@staff0rd/assist 0.416.0 → 0.417.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 +1 -1
- package/claude/commands/pr.md +1 -67
- package/dist/commands/sessions/web/bundle.js +382 -382
- package/dist/index.js +319 -42
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Command } from "commander";
|
|
|
6
6
|
// package.json
|
|
7
7
|
var package_default = {
|
|
8
8
|
name: "@staff0rd/assist",
|
|
9
|
-
version: "0.
|
|
9
|
+
version: "0.417.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -6431,6 +6431,20 @@ function sendToDaemon(message) {
|
|
|
6431
6431
|
});
|
|
6432
6432
|
}
|
|
6433
6433
|
|
|
6434
|
+
// src/commands/sessions/daemon/readSocketLines.ts
|
|
6435
|
+
function readSocketLines(socket, onLine) {
|
|
6436
|
+
let buffer = "";
|
|
6437
|
+
socket.on("data", (chunk) => {
|
|
6438
|
+
buffer += chunk.toString("utf8");
|
|
6439
|
+
let newline = buffer.indexOf("\n");
|
|
6440
|
+
while (newline !== -1) {
|
|
6441
|
+
onLine(buffer.slice(0, newline));
|
|
6442
|
+
buffer = buffer.slice(newline + 1);
|
|
6443
|
+
newline = buffer.indexOf("\n");
|
|
6444
|
+
}
|
|
6445
|
+
});
|
|
6446
|
+
}
|
|
6447
|
+
|
|
6434
6448
|
// src/commands/sessions/daemon/sendToDaemonAwaitAck.ts
|
|
6435
6449
|
var ACK_TIMEOUT_MS = 1e3;
|
|
6436
6450
|
function sendToDaemonAwaitAck(message) {
|
|
@@ -6449,16 +6463,8 @@ function sendToDaemonAwaitAck(message) {
|
|
|
6449
6463
|
() => finish(new Error("timed out awaiting daemon ack")),
|
|
6450
6464
|
ACK_TIMEOUT_MS
|
|
6451
6465
|
);
|
|
6452
|
-
|
|
6453
|
-
|
|
6454
|
-
buffer += chunk.toString("utf8");
|
|
6455
|
-
let newline = buffer.indexOf("\n");
|
|
6456
|
-
while (newline !== -1) {
|
|
6457
|
-
const line = buffer.slice(0, newline);
|
|
6458
|
-
buffer = buffer.slice(newline + 1);
|
|
6459
|
-
if (isAck(line)) return finish();
|
|
6460
|
-
newline = buffer.indexOf("\n");
|
|
6461
|
-
}
|
|
6466
|
+
readSocketLines(socket, (line) => {
|
|
6467
|
+
if (isAck(line)) finish();
|
|
6462
6468
|
});
|
|
6463
6469
|
socket.on("error", (error) => finish(error));
|
|
6464
6470
|
socket.on(
|
|
@@ -18123,7 +18129,23 @@ async function prs(options2) {
|
|
|
18123
18129
|
}
|
|
18124
18130
|
}
|
|
18125
18131
|
|
|
18126
|
-
// src/commands/prs/
|
|
18132
|
+
// src/commands/prs/buildValidatedBody.ts
|
|
18133
|
+
function buildValidatedBody(options2, usage) {
|
|
18134
|
+
if (!options2.title || !options2.what || !options2.why) {
|
|
18135
|
+
console.error(usage);
|
|
18136
|
+
process.exit(1);
|
|
18137
|
+
}
|
|
18138
|
+
const body = buildPrBody({
|
|
18139
|
+
what: options2.what,
|
|
18140
|
+
why: options2.why,
|
|
18141
|
+
how: options2.how,
|
|
18142
|
+
resolves: options2.resolves
|
|
18143
|
+
});
|
|
18144
|
+
validatePrContent(options2.title, body);
|
|
18145
|
+
return { title: options2.title, body };
|
|
18146
|
+
}
|
|
18147
|
+
|
|
18148
|
+
// src/commands/prs/placePr.ts
|
|
18127
18149
|
import { execFileSync as execFileSync7 } from "child_process";
|
|
18128
18150
|
|
|
18129
18151
|
// src/commands/prs/buildCreateArgs.ts
|
|
@@ -18181,40 +18203,138 @@ function readSessionPrRef() {
|
|
|
18181
18203
|
}
|
|
18182
18204
|
}
|
|
18183
18205
|
|
|
18184
|
-
// src/commands/prs/
|
|
18185
|
-
async function
|
|
18186
|
-
if (
|
|
18187
|
-
|
|
18188
|
-
|
|
18206
|
+
// src/commands/prs/recordPrActivity.ts
|
|
18207
|
+
async function recordPrActivity() {
|
|
18208
|
+
if (resolveSessionItemId() === null) return;
|
|
18209
|
+
const pr = readSessionPrRef();
|
|
18210
|
+
if (pr) await recordSessionRefs([pr]);
|
|
18211
|
+
}
|
|
18212
|
+
|
|
18213
|
+
// src/commands/prs/placePr.ts
|
|
18214
|
+
function hasUpstream() {
|
|
18215
|
+
try {
|
|
18216
|
+
execFileSync7(
|
|
18217
|
+
"git",
|
|
18218
|
+
["rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"],
|
|
18219
|
+
{ stdio: "pipe" }
|
|
18189
18220
|
);
|
|
18221
|
+
return true;
|
|
18222
|
+
} catch {
|
|
18223
|
+
return false;
|
|
18224
|
+
}
|
|
18225
|
+
}
|
|
18226
|
+
function ensureBranchPushed() {
|
|
18227
|
+
const args = hasUpstream() ? ["push"] : ["push", "--set-upstream", "origin", "HEAD"];
|
|
18228
|
+
execFileSync7("git", args, { stdio: "inherit" });
|
|
18229
|
+
}
|
|
18230
|
+
async function placePr(prNumber, title, body, options2) {
|
|
18231
|
+
const args = prNumber !== null ? buildEditArgs(prNumber, title, body) : buildCreateArgs(title, body, options2);
|
|
18232
|
+
try {
|
|
18233
|
+
if (prNumber === null && !options2.head) ensureBranchPushed();
|
|
18234
|
+
execFileSync7("gh", args, { stdio: "inherit" });
|
|
18235
|
+
} catch {
|
|
18190
18236
|
process.exit(1);
|
|
18191
18237
|
}
|
|
18192
|
-
|
|
18193
|
-
|
|
18194
|
-
|
|
18195
|
-
|
|
18196
|
-
|
|
18238
|
+
await recordPrActivity();
|
|
18239
|
+
}
|
|
18240
|
+
|
|
18241
|
+
// src/commands/prs/previewAndPlace.ts
|
|
18242
|
+
import { randomUUID as randomUUID4 } from "crypto";
|
|
18243
|
+
|
|
18244
|
+
// src/commands/prs/requestPrDecision.ts
|
|
18245
|
+
function parseIncoming(line, requestId) {
|
|
18246
|
+
try {
|
|
18247
|
+
const msg = JSON.parse(line);
|
|
18248
|
+
if (msg.type === "error" && (msg.message ?? "").includes("pr-preview"))
|
|
18249
|
+
return { kind: "error", message: msg.message ?? "pr-preview failed" };
|
|
18250
|
+
if (msg.type !== "pr-decision" || msg.requestId !== requestId) return null;
|
|
18251
|
+
if (msg.decision !== "approve" && msg.decision !== "reject") return null;
|
|
18252
|
+
return {
|
|
18253
|
+
kind: "decision",
|
|
18254
|
+
decision: { decision: msg.decision, reason: msg.reason }
|
|
18255
|
+
};
|
|
18256
|
+
} catch {
|
|
18257
|
+
return null;
|
|
18258
|
+
}
|
|
18259
|
+
}
|
|
18260
|
+
function requestPrDecision(request) {
|
|
18261
|
+
return new Promise((resolve19, reject) => {
|
|
18262
|
+
connectToDaemon().then((socket) => {
|
|
18263
|
+
let settled = false;
|
|
18264
|
+
const finish = (error, decision) => {
|
|
18265
|
+
if (settled) return;
|
|
18266
|
+
settled = true;
|
|
18267
|
+
socket.destroy();
|
|
18268
|
+
if (error) reject(error);
|
|
18269
|
+
else resolve19(decision);
|
|
18270
|
+
};
|
|
18271
|
+
readSocketLines(socket, (line) => {
|
|
18272
|
+
const incoming = parseIncoming(line, request.requestId);
|
|
18273
|
+
if (!incoming) return;
|
|
18274
|
+
if (incoming.kind === "error") finish(new Error(incoming.message));
|
|
18275
|
+
else finish(void 0, incoming.decision);
|
|
18276
|
+
});
|
|
18277
|
+
socket.on("error", (error) => finish(error));
|
|
18278
|
+
socket.on(
|
|
18279
|
+
"close",
|
|
18280
|
+
() => finish(new Error("daemon closed before a decision was made"))
|
|
18281
|
+
);
|
|
18282
|
+
socket.write(`${JSON.stringify({ type: "pr-preview", ...request })}
|
|
18283
|
+
`);
|
|
18284
|
+
}, reject);
|
|
18197
18285
|
});
|
|
18198
|
-
|
|
18199
|
-
|
|
18200
|
-
|
|
18286
|
+
}
|
|
18287
|
+
|
|
18288
|
+
// src/commands/prs/previewAndPlace.ts
|
|
18289
|
+
async function previewAndPlace(args) {
|
|
18290
|
+
console.log("Awaiting your approval in the assist web UI preview pane\u2026");
|
|
18291
|
+
let decision;
|
|
18292
|
+
try {
|
|
18293
|
+
decision = await requestPrDecision({
|
|
18294
|
+
sessionId: args.sessionId,
|
|
18295
|
+
requestId: randomUUID4(),
|
|
18296
|
+
title: args.title,
|
|
18297
|
+
body: args.body,
|
|
18298
|
+
prNumber: args.prNumber
|
|
18299
|
+
});
|
|
18300
|
+
} catch (error) {
|
|
18201
18301
|
console.error(
|
|
18202
|
-
`Error:
|
|
18302
|
+
`Error: ${error instanceof Error ? error.message : String(error)}`
|
|
18203
18303
|
);
|
|
18204
18304
|
process.exit(1);
|
|
18205
18305
|
}
|
|
18206
|
-
|
|
18207
|
-
|
|
18208
|
-
|
|
18209
|
-
|
|
18306
|
+
if (decision.decision === "reject") {
|
|
18307
|
+
console.error(
|
|
18308
|
+
`PR preview rejected${decision.reason ? `: ${decision.reason}` : "."}`
|
|
18309
|
+
);
|
|
18210
18310
|
process.exit(1);
|
|
18211
18311
|
}
|
|
18212
|
-
await
|
|
18312
|
+
await placePr(args.prNumber, args.title, args.body, args.options);
|
|
18213
18313
|
}
|
|
18214
|
-
|
|
18215
|
-
|
|
18216
|
-
|
|
18217
|
-
|
|
18314
|
+
|
|
18315
|
+
// src/commands/prs/raise.ts
|
|
18316
|
+
var USAGE = "Usage: assist prs raise --title <title> --what <what> --why <why> [--how <how>] [--resolves <key>] [--force]";
|
|
18317
|
+
async function raise(options2) {
|
|
18318
|
+
const { title, body } = buildValidatedBody(options2, USAGE);
|
|
18319
|
+
const existing = findCurrentPrNumber();
|
|
18320
|
+
const sessionId = process.env.ASSIST_SESSION_ID;
|
|
18321
|
+
if (process.env.ASSIST_SESSION === "1" && sessionId) {
|
|
18322
|
+
await previewAndPlace({
|
|
18323
|
+
sessionId,
|
|
18324
|
+
title,
|
|
18325
|
+
body,
|
|
18326
|
+
prNumber: existing,
|
|
18327
|
+
options: options2
|
|
18328
|
+
});
|
|
18329
|
+
return;
|
|
18330
|
+
}
|
|
18331
|
+
if (existing !== null && !options2.force) {
|
|
18332
|
+
console.error(
|
|
18333
|
+
`Error: A pull request already exists for this branch (#${existing}). Pass --force to overwrite it, or use 'assist prs edit' to update individual sections.`
|
|
18334
|
+
);
|
|
18335
|
+
process.exit(1);
|
|
18336
|
+
}
|
|
18337
|
+
await placePr(existing, title, body, options2);
|
|
18218
18338
|
}
|
|
18219
18339
|
|
|
18220
18340
|
// src/commands/prs/reply.ts
|
|
@@ -18316,6 +18436,86 @@ function registerPrsEdit(prsCommand) {
|
|
|
18316
18436
|
).action(edit);
|
|
18317
18437
|
}
|
|
18318
18438
|
|
|
18439
|
+
// src/commands/prs/raiseHelpText.ts
|
|
18440
|
+
var GUIDANCE = `Raise a pull request for the current branch. Use a concise description with no
|
|
18441
|
+
headers, and do not reference Claude or any AI assistance in the title or body.
|
|
18442
|
+
|
|
18443
|
+
The body is assembled from discrete section options; supply at minimum --title,
|
|
18444
|
+
--what, and --why:
|
|
18445
|
+
|
|
18446
|
+
--title <title> short PR title.
|
|
18447
|
+
--what <what> what the change does (rendered as ## What).
|
|
18448
|
+
--why <why> why the change is needed (rendered as ## Why).
|
|
18449
|
+
--how <how> optional; how the change works (rendered as ## How). Omit it
|
|
18450
|
+
unless the approach genuinely needs explaining.
|
|
18451
|
+
--resolves <key> Jira issue key resolved by this PR; repeatable. Each key's
|
|
18452
|
+
browse URL is appended inline to ## Why. Unless a Jira key is
|
|
18453
|
+
already known from the session, ask the user whether this PR
|
|
18454
|
+
resolves a Jira issue and for the key before raising; omit
|
|
18455
|
+
--resolves only if they say there isn't one.
|
|
18456
|
+
|
|
18457
|
+
Wrap symbols, file paths, function names, class names, variable names, config
|
|
18458
|
+
keys, CLI commands, and flag names in backticks.
|
|
18459
|
+
|
|
18460
|
+
One section, one question. Each section answers exactly one thing, and
|
|
18461
|
+
implementation detail lives only in ## How:
|
|
18462
|
+
|
|
18463
|
+
## What what is observably different for someone using or calling this, and
|
|
18464
|
+
nothing else. Not how it's built, not which functions/files changed.
|
|
18465
|
+
## Why the problem or motivation that made the change worth doing. Not how
|
|
18466
|
+
the solution works.
|
|
18467
|
+
## How only the non-obvious decisions the diff alone won't explain: a
|
|
18468
|
+
deliberate trade-off, a workaround, a reason the obvious approach was
|
|
18469
|
+
rejected. Omit it entirely by default. Never restate ## What as
|
|
18470
|
+
mechanism, and never walk through the diff.
|
|
18471
|
+
|
|
18472
|
+
The most common failure is altitude bleed: an implementation detail gets sprayed
|
|
18473
|
+
into whichever section is being written \u2014 ## What narrates the diff, ## How
|
|
18474
|
+
restates ## What, ## Why smuggles in mechanism. If a sentence describes a
|
|
18475
|
+
mechanism, it belongs in ## How, and probably shouldn't exist at all unless it's
|
|
18476
|
+
a genuine non-obvious decision. Litmus \u2014 a sentence is almost certainly mechanism
|
|
18477
|
+
(so ## How, or cut it) if it contains "by \u2026ing", "so that it can", "because the
|
|
18478
|
+
X filters/needs/uses", or names an internal component, property, function, or
|
|
18479
|
+
file.
|
|
18480
|
+
|
|
18481
|
+
Brevity budget \u2014 keep each section within these limits:
|
|
18482
|
+
|
|
18483
|
+
## What a few sentences (2\u20133).
|
|
18484
|
+
## Why 1\u20132 sentences.
|
|
18485
|
+
## How omit by default; a sentence or two, only for non-obvious decisions.
|
|
18486
|
+
|
|
18487
|
+
Write prose. A short paragraph is the natural form for ## What and ## Why \u2014
|
|
18488
|
+
bullets in ## What are a smell. Use bullets only when there are genuinely several
|
|
18489
|
+
independent, parallel items (3+); a single bullet is never right. A single
|
|
18490
|
+
non-list paragraph over ~600 characters or ~4 sentences is a wall of text and
|
|
18491
|
+
will be rejected.
|
|
18492
|
+
|
|
18493
|
+
If a pull request already exists for the branch, this command errors \u2014 pass
|
|
18494
|
+
--force to fully overwrite its title and body, or use 'assist prs edit' to update
|
|
18495
|
+
only individual sections (every other section of the existing body is preserved).`;
|
|
18496
|
+
var TERMINAL_CONFIRM = `Before running this command, the user must see the full proposed title and body \u2014
|
|
18497
|
+
do not assume they can see your reasoning or earlier tool output. Write the
|
|
18498
|
+
complete title and body verbatim in your visible reply, then use the
|
|
18499
|
+
AskUserQuestion tool to ask whether to create the PR, putting the full title and
|
|
18500
|
+
body in the approve option's preview field. This confirmation is mandatory in
|
|
18501
|
+
every permission mode, including auto-accept and bypass-permissions. If the user
|
|
18502
|
+
requests changes, revise and confirm again before running.`;
|
|
18503
|
+
var WEB_CONFIRM = `You are running inside an assist web session. When you run this command the
|
|
18504
|
+
drafted title and body are shown automatically in a preview pane beside the
|
|
18505
|
+
terminal in the web UI, for the user to approve or reject there \u2014 do NOT display
|
|
18506
|
+
the title and body or ask for confirmation in the terminal. The command blocks
|
|
18507
|
+
until the user decides: on approval it creates or updates the PR and reports it;
|
|
18508
|
+
on rejection it exits non-zero with the reason, which you must address before
|
|
18509
|
+
running again. Just compose the sections and run the command.`;
|
|
18510
|
+
function raiseHelpText() {
|
|
18511
|
+
const confirm = process.env.ASSIST_SESSION === "1" ? WEB_CONFIRM : TERMINAL_CONFIRM;
|
|
18512
|
+
return `
|
|
18513
|
+
${GUIDANCE}
|
|
18514
|
+
|
|
18515
|
+
${confirm}
|
|
18516
|
+
`;
|
|
18517
|
+
}
|
|
18518
|
+
|
|
18319
18519
|
// src/commands/registerPrsRaise.ts
|
|
18320
18520
|
function collect5(value, previous) {
|
|
18321
18521
|
return previous.concat([value]);
|
|
@@ -18341,7 +18541,7 @@ function registerPrsRaise(prsCommand) {
|
|
|
18341
18541
|
"Request a review (repeatable)",
|
|
18342
18542
|
collect5,
|
|
18343
18543
|
[]
|
|
18344
|
-
).option("-m, --milestone <name>", "Add the pull request to a milestone").action(raise);
|
|
18544
|
+
).option("-m, --milestone <name>", "Add the pull request to a milestone").addHelpText("after", () => raiseHelpText()).action(raise);
|
|
18345
18545
|
}
|
|
18346
18546
|
|
|
18347
18547
|
// src/commands/registerPrs.ts
|
|
@@ -24838,7 +25038,8 @@ function toSessionInfo({
|
|
|
24838
25038
|
autoAdvance,
|
|
24839
25039
|
starred,
|
|
24840
25040
|
usedPct,
|
|
24841
|
-
design
|
|
25041
|
+
design,
|
|
25042
|
+
pendingPrPreview
|
|
24842
25043
|
}) {
|
|
24843
25044
|
return {
|
|
24844
25045
|
id,
|
|
@@ -24865,7 +25066,8 @@ function toSessionInfo({
|
|
|
24865
25066
|
autoAdvance,
|
|
24866
25067
|
starred,
|
|
24867
25068
|
usedPct,
|
|
24868
|
-
design
|
|
25069
|
+
design,
|
|
25070
|
+
pendingPrPreview
|
|
24869
25071
|
};
|
|
24870
25072
|
}
|
|
24871
25073
|
|
|
@@ -25026,7 +25228,7 @@ function createAssistSession(id, assistArgs, cwd, meta) {
|
|
|
25026
25228
|
}
|
|
25027
25229
|
|
|
25028
25230
|
// src/commands/sessions/daemon/createSession.ts
|
|
25029
|
-
import { randomUUID as
|
|
25231
|
+
import { randomUUID as randomUUID5 } from "crypto";
|
|
25030
25232
|
|
|
25031
25233
|
// src/commands/sessions/daemon/resolveRunConfig.ts
|
|
25032
25234
|
function resolveRunConfig(name, cwd) {
|
|
@@ -25107,7 +25309,7 @@ function sessionBase(id, status3) {
|
|
|
25107
25309
|
}
|
|
25108
25310
|
function createSession(id, prompt, cwd, design, harness) {
|
|
25109
25311
|
if (harness === "pi") return createPiSession(id, prompt, cwd);
|
|
25110
|
-
const claudeSessionId =
|
|
25312
|
+
const claudeSessionId = randomUUID5();
|
|
25111
25313
|
return {
|
|
25112
25314
|
...sessionBase(id, prompt ? "running" : "waiting"),
|
|
25113
25315
|
name: prompt?.slice(0, 40) || `Session ${id}`,
|
|
@@ -25258,6 +25460,74 @@ function logSpawnedSession(session) {
|
|
|
25258
25460
|
);
|
|
25259
25461
|
}
|
|
25260
25462
|
|
|
25463
|
+
// src/commands/sessions/daemon/PrPreviewCoordinator.ts
|
|
25464
|
+
var PrPreviewCoordinator = class {
|
|
25465
|
+
constructor(sessions, notify2) {
|
|
25466
|
+
this.sessions = sessions;
|
|
25467
|
+
this.notify = notify2;
|
|
25468
|
+
}
|
|
25469
|
+
waiters = /* @__PURE__ */ new Map();
|
|
25470
|
+
set(client, d) {
|
|
25471
|
+
const id = d.sessionId;
|
|
25472
|
+
const session = this.sessions.get(id);
|
|
25473
|
+
if (!session) {
|
|
25474
|
+
daemonLog(`pr-preview for unknown session id=${id} (ignoring)`);
|
|
25475
|
+
sendTo(client, {
|
|
25476
|
+
type: "error",
|
|
25477
|
+
message: `No live session ${id} for pr-preview`
|
|
25478
|
+
});
|
|
25479
|
+
return;
|
|
25480
|
+
}
|
|
25481
|
+
const prNumber = typeof d.prNumber === "number" ? d.prNumber : null;
|
|
25482
|
+
session.pendingPrPreview = {
|
|
25483
|
+
requestId: d.requestId,
|
|
25484
|
+
title: d.title,
|
|
25485
|
+
body: d.body,
|
|
25486
|
+
prNumber
|
|
25487
|
+
};
|
|
25488
|
+
this.waiters.set(id, client);
|
|
25489
|
+
daemonLog(
|
|
25490
|
+
`pr-preview set: id=${id} requestId=${d.requestId} target=${prNumber === null ? "create" : `edit #${prNumber}`}`
|
|
25491
|
+
);
|
|
25492
|
+
this.notify();
|
|
25493
|
+
}
|
|
25494
|
+
decide(d) {
|
|
25495
|
+
const id = d.sessionId;
|
|
25496
|
+
const requestId = d.requestId;
|
|
25497
|
+
const session = this.sessions.get(id);
|
|
25498
|
+
if (!session || session.pendingPrPreview?.requestId !== requestId) {
|
|
25499
|
+
daemonLog(
|
|
25500
|
+
`pr-decision for stale/unknown preview id=${id} requestId=${requestId} (ignoring)`
|
|
25501
|
+
);
|
|
25502
|
+
return;
|
|
25503
|
+
}
|
|
25504
|
+
daemonLog(
|
|
25505
|
+
`pr-decision received: id=${id} requestId=${requestId} decision=${d.decision}`
|
|
25506
|
+
);
|
|
25507
|
+
const waiter = this.waiters.get(id);
|
|
25508
|
+
if (waiter)
|
|
25509
|
+
sendTo(waiter, {
|
|
25510
|
+
type: "pr-decision",
|
|
25511
|
+
requestId,
|
|
25512
|
+
decision: d.decision,
|
|
25513
|
+
reason: d.reason
|
|
25514
|
+
});
|
|
25515
|
+
this.waiters.delete(id);
|
|
25516
|
+
session.pendingPrPreview = void 0;
|
|
25517
|
+
this.notify();
|
|
25518
|
+
}
|
|
25519
|
+
clearWaiter(client) {
|
|
25520
|
+
for (const [id, waiter] of this.waiters) {
|
|
25521
|
+
if (waiter !== client) continue;
|
|
25522
|
+
this.waiters.delete(id);
|
|
25523
|
+
const session = this.sessions.get(id);
|
|
25524
|
+
if (session) session.pendingPrPreview = void 0;
|
|
25525
|
+
daemonLog(`pr-preview cleared: id=${id} (waiting client disconnected)`);
|
|
25526
|
+
this.notify();
|
|
25527
|
+
}
|
|
25528
|
+
}
|
|
25529
|
+
};
|
|
25530
|
+
|
|
25261
25531
|
// src/commands/sessions/daemon/applySetStatus.ts
|
|
25262
25532
|
function applySetStatus(sessions, id, status3, source, onStatusChange) {
|
|
25263
25533
|
const session = sessions.get(id);
|
|
@@ -25698,7 +25968,7 @@ function respawnSession(session, respawn, status3, clients, onStatusChange) {
|
|
|
25698
25968
|
}
|
|
25699
25969
|
|
|
25700
25970
|
// src/commands/sessions/daemon/respawnPlan.ts
|
|
25701
|
-
import { randomUUID as
|
|
25971
|
+
import { randomUUID as randomUUID6 } from "crypto";
|
|
25702
25972
|
|
|
25703
25973
|
// src/commands/sessions/daemon/assistResumeArgs.ts
|
|
25704
25974
|
function assistResumeArgs(session) {
|
|
@@ -25737,7 +26007,7 @@ function respawnPlan(session) {
|
|
|
25737
26007
|
return null;
|
|
25738
26008
|
}
|
|
25739
26009
|
function freshClaudePlan(session, prompt, cwd) {
|
|
25740
|
-
const claudeSessionId =
|
|
26010
|
+
const claudeSessionId = randomUUID6();
|
|
25741
26011
|
return {
|
|
25742
26012
|
spawn: () => {
|
|
25743
26013
|
session.claudeSessionId = claudeSessionId;
|
|
@@ -27144,6 +27414,10 @@ var SessionManager = class {
|
|
|
27144
27414
|
this.onIdleChange = onIdleChange;
|
|
27145
27415
|
}
|
|
27146
27416
|
sessions = /* @__PURE__ */ new Map();
|
|
27417
|
+
prPreview = new PrPreviewCoordinator(
|
|
27418
|
+
this.sessions,
|
|
27419
|
+
() => this.notify()
|
|
27420
|
+
);
|
|
27147
27421
|
// why: dispatch calls active.set() on card click; broadcasts include active.toJSON()
|
|
27148
27422
|
active = new ActiveSelection(() => this.notify());
|
|
27149
27423
|
clients = new ClientHub(persistUsagePeak);
|
|
@@ -27159,6 +27433,7 @@ var SessionManager = class {
|
|
|
27159
27433
|
removeClient(client) {
|
|
27160
27434
|
this.clients.delete(client);
|
|
27161
27435
|
this.clients.unsubscribeLogs(client);
|
|
27436
|
+
this.prPreview.clearWaiter(client);
|
|
27162
27437
|
this.onIdleChange?.(this.isIdle());
|
|
27163
27438
|
}
|
|
27164
27439
|
isIdle = () => this.sessions.size === 0 && this.clients.size === 0;
|
|
@@ -27531,6 +27806,8 @@ var messageHandlers = {
|
|
|
27531
27806
|
),
|
|
27532
27807
|
"set-active": (_client, m, d) => m.active.set(d.cwd, d.sessionId),
|
|
27533
27808
|
"set-status": handleSetStatus,
|
|
27809
|
+
"pr-preview": (client, m, d) => m.prPreview.set(client, d),
|
|
27810
|
+
"pr-decision": (_client, m, d) => m.prPreview.decide(d),
|
|
27534
27811
|
"ui-status": (_client, _m, d) => daemonLog(`ui rendered: id=${d.sessionId} status=${d.status}`)
|
|
27535
27812
|
};
|
|
27536
27813
|
|