@staff0rd/assist 0.551.0 → 0.552.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/commands/sessions/web/bundle.js +295 -295
- package/dist/index.js +105 -36
- 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.552.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -7564,7 +7564,7 @@ var BACKLOG_MARKERS = [
|
|
|
7564
7564
|
function findBacklogUp(startDir) {
|
|
7565
7565
|
let current = startDir;
|
|
7566
7566
|
while (current !== dirname14(current)) {
|
|
7567
|
-
if (BACKLOG_MARKERS.some((
|
|
7567
|
+
if (BACKLOG_MARKERS.some((marker2) => existsSync21(join17(current, marker2)))) {
|
|
7568
7568
|
return current;
|
|
7569
7569
|
}
|
|
7570
7570
|
current = dirname14(current);
|
|
@@ -9376,9 +9376,9 @@ function printPhaseTasks(phase) {
|
|
|
9376
9376
|
// src/commands/backlog/show/printPlan.ts
|
|
9377
9377
|
function phaseHeader(index3, name, isCurrent) {
|
|
9378
9378
|
const phaseNumber = index3 + 1;
|
|
9379
|
-
const
|
|
9379
|
+
const marker2 = isCurrent ? chalk56.green("\u25B6 ") : " ";
|
|
9380
9380
|
const label2 = isCurrent ? chalk56.green.bold(`Phase ${phaseNumber}: ${name}`) : `${chalk56.bold(`Phase ${phaseNumber}:`)} ${name}`;
|
|
9381
|
-
return `${
|
|
9381
|
+
return `${marker2}${label2}`;
|
|
9382
9382
|
}
|
|
9383
9383
|
function printPhaseSessions(sessions) {
|
|
9384
9384
|
if (sessions.length === 0) return;
|
|
@@ -14678,12 +14678,12 @@ async function launchMode(slashCommand, options2) {
|
|
|
14678
14678
|
resumeSessionId,
|
|
14679
14679
|
cwd: process.cwd()
|
|
14680
14680
|
});
|
|
14681
|
-
const
|
|
14681
|
+
const marker2 = watchForMarker(child, { actOnDone: options2?.once });
|
|
14682
14682
|
const exitCode = await awaitClaude(done2, `/${slashCommand}`);
|
|
14683
14683
|
stopWatching();
|
|
14684
14684
|
if (exitCode === CLAUDE_SPAWN_FAILED) return;
|
|
14685
14685
|
await handleLaunchSignal(slashCommand, options2?.once);
|
|
14686
|
-
if (exitCode !== 0 && !
|
|
14686
|
+
if (exitCode !== 0 && !marker2.killedOnMarker()) process.exitCode = exitCode;
|
|
14687
14687
|
}
|
|
14688
14688
|
|
|
14689
14689
|
// src/commands/backlog/refine.ts
|
|
@@ -17262,15 +17262,15 @@ function codeCommentConfirm(pin) {
|
|
|
17262
17262
|
process.exitCode = 1;
|
|
17263
17263
|
return;
|
|
17264
17264
|
}
|
|
17265
|
-
const
|
|
17265
|
+
const marker2 = isHashCommentFile(state.file) ? "#" : "//";
|
|
17266
17266
|
const indentSource = lines2[index3] ?? "";
|
|
17267
17267
|
const indent3 = indentSource.match(/^\s*/)?.[0] ?? "";
|
|
17268
|
-
lines2.splice(index3, 0, `${indent3}${
|
|
17268
|
+
lines2.splice(index3, 0, `${indent3}${marker2} ${state.text}`);
|
|
17269
17269
|
writeFileSync24(state.file, lines2.join("\n"));
|
|
17270
17270
|
unlinkSync8(getPinStatePath(pin));
|
|
17271
17271
|
console.log(
|
|
17272
17272
|
chalk121.green(
|
|
17273
|
-
`Inserted "${
|
|
17273
|
+
`Inserted "${marker2} ${state.text}" at ${state.file}:${state.line}`
|
|
17274
17274
|
)
|
|
17275
17275
|
);
|
|
17276
17276
|
}
|
|
@@ -17332,7 +17332,7 @@ function codeCommentSet(file, line, text17) {
|
|
|
17332
17332
|
return;
|
|
17333
17333
|
}
|
|
17334
17334
|
const hash = isHashCommentFile(file);
|
|
17335
|
-
const
|
|
17335
|
+
const marker2 = hash ? "#" : "//";
|
|
17336
17336
|
const validation = validateCommentText(text17, hash);
|
|
17337
17337
|
if (!validation.ok) {
|
|
17338
17338
|
console.error(chalk122.red(`Refused: ${validation.reason}`));
|
|
@@ -17357,7 +17357,7 @@ function codeCommentSet(file, line, text17) {
|
|
|
17357
17357
|
}
|
|
17358
17358
|
console.log(
|
|
17359
17359
|
`A confirmation pin was sent to your desktop notifications.
|
|
17360
|
-
To insert "${
|
|
17360
|
+
To insert "${marker2} ${validation.text}" at ${file}:${lineNumber}, run:
|
|
17361
17361
|
${chalk122.cyan(" assist code-comment confirm <PIN>")}
|
|
17362
17362
|
using the pin from that notification.`
|
|
17363
17363
|
);
|
|
@@ -19826,9 +19826,9 @@ function selectCommentExtractor(filePath) {
|
|
|
19826
19826
|
}
|
|
19827
19827
|
|
|
19828
19828
|
// src/commands/editHook/decideCommentGuard.ts
|
|
19829
|
-
function denyReason(
|
|
19830
|
-
const blockClause =
|
|
19831
|
-
return `This edit introduces a code comment (${
|
|
19829
|
+
function denyReason(marker2) {
|
|
19830
|
+
const blockClause = marker2 === "//" ? ", no block comments" : "";
|
|
19831
|
+
return `This edit introduces a code comment (${marker2}), which is blocked by the comment gate. Comments are a last resort \u2014 prefer a clearer name, a smaller function, or a test that makes the comment unnecessary. The comment must not appear in your edit itself. If this one line genuinely earns its keep, use the escape hatch: run \`assist code-comment set <file> <line> "<text>"\` (single line, max 50 chars${blockClause}) to get a pin, then \`assist code-comment confirm <pin>\` to insert it.`;
|
|
19832
19832
|
}
|
|
19833
19833
|
function decideCommentGuard(input, existingContent) {
|
|
19834
19834
|
const { file_path, content } = input.tool_input;
|
|
@@ -20439,15 +20439,15 @@ function renderNodes(nodes, indent3) {
|
|
|
20439
20439
|
function isListNode(node) {
|
|
20440
20440
|
return node.type === "orderedList" || node.type === "bulletList";
|
|
20441
20441
|
}
|
|
20442
|
-
function renderListChild(child, indent3, pad,
|
|
20442
|
+
function renderListChild(child, indent3, pad, marker2, isFirst) {
|
|
20443
20443
|
if (isListNode(child)) return renderNodes([child], indent3 + 1);
|
|
20444
20444
|
if (child.type !== "paragraph") return renderNode(child, indent3);
|
|
20445
20445
|
const text17 = renderChildren(child, indent3);
|
|
20446
|
-
return isFirst ? `${pad}${
|
|
20446
|
+
return isFirst ? `${pad}${marker2} ${text17}` : `${pad} ${text17}`;
|
|
20447
20447
|
}
|
|
20448
|
-
function renderListItem(node, indent3,
|
|
20448
|
+
function renderListItem(node, indent3, marker2) {
|
|
20449
20449
|
const pad = " ".repeat(indent3);
|
|
20450
|
-
return (node.content ?? []).map((child, i) => renderListChild(child, indent3, pad,
|
|
20450
|
+
return (node.content ?? []).map((child, i) => renderListChild(child, indent3, pad, marker2, i === 0)).join("\n");
|
|
20451
20451
|
}
|
|
20452
20452
|
function adfToText(doc) {
|
|
20453
20453
|
return renderNodes([doc], 0);
|
|
@@ -29545,9 +29545,9 @@ function renderWatchReport({
|
|
|
29545
29545
|
} else {
|
|
29546
29546
|
lines2.push("| SHA | When | Subject |", "| --- | --- | --- |");
|
|
29547
29547
|
for (const commit2 of commits2) {
|
|
29548
|
-
const
|
|
29548
|
+
const marker2 = isNew.has(commit2.sha) ? " \u2190 new" : "";
|
|
29549
29549
|
lines2.push(
|
|
29550
|
-
`| \`${commit2.short}\` | ${commit2.when} | ${escapeCell(commit2.subject)}${
|
|
29550
|
+
`| \`${commit2.short}\` | ${commit2.when} | ${escapeCell(commit2.subject)}${marker2} |`
|
|
29551
29551
|
);
|
|
29552
29552
|
}
|
|
29553
29553
|
}
|
|
@@ -31079,7 +31079,8 @@ function toSessionInfo(session) {
|
|
|
31079
31079
|
design,
|
|
31080
31080
|
verifying,
|
|
31081
31081
|
pendingPrPreview,
|
|
31082
|
-
undurable
|
|
31082
|
+
undurable,
|
|
31083
|
+
lastUserMessage
|
|
31083
31084
|
} = session;
|
|
31084
31085
|
return {
|
|
31085
31086
|
...toSessionRunInfo(session),
|
|
@@ -31103,6 +31104,7 @@ function toSessionInfo(session) {
|
|
|
31103
31104
|
verifying,
|
|
31104
31105
|
pendingPrPreview,
|
|
31105
31106
|
undurable,
|
|
31107
|
+
lastUserMessage,
|
|
31106
31108
|
joinable: joinRefusal(session) === void 0
|
|
31107
31109
|
};
|
|
31108
31110
|
}
|
|
@@ -32549,6 +32551,61 @@ function resolvedToolUseIds(events, afterIdx) {
|
|
|
32549
32551
|
return ids;
|
|
32550
32552
|
}
|
|
32551
32553
|
|
|
32554
|
+
// src/commands/sessions/shared/extractLastUserMessage.ts
|
|
32555
|
+
var MAX_LENGTH2 = 2048;
|
|
32556
|
+
var INTERRUPT_PREFIX2 = "[Request interrupted";
|
|
32557
|
+
function extractLastUserMessage(entries, maxLength = MAX_LENGTH2) {
|
|
32558
|
+
for (let i = entries.length - 1; i >= 0; i--) {
|
|
32559
|
+
const entry = entries[i];
|
|
32560
|
+
if (entry.isSidechain || entry.isMeta) continue;
|
|
32561
|
+
if (entry.type !== "user") continue;
|
|
32562
|
+
const raw = promptTextOrNull(entry);
|
|
32563
|
+
if (raw === null) continue;
|
|
32564
|
+
const message3 = renderPrompt(raw);
|
|
32565
|
+
if (message3) return cap(message3, maxLength);
|
|
32566
|
+
}
|
|
32567
|
+
return void 0;
|
|
32568
|
+
}
|
|
32569
|
+
function promptTextOrNull(entry) {
|
|
32570
|
+
const content = asRecord3(entry.message)?.content;
|
|
32571
|
+
if (typeof content === "string") return isInterrupt(content) ? null : content;
|
|
32572
|
+
if (!Array.isArray(content)) return null;
|
|
32573
|
+
const parts = [];
|
|
32574
|
+
for (const block of content) {
|
|
32575
|
+
const b = asRecord3(block);
|
|
32576
|
+
if (b?.type !== "text") continue;
|
|
32577
|
+
const text17 = typeof b.text === "string" ? b.text : "";
|
|
32578
|
+
if (isInterrupt(text17)) return null;
|
|
32579
|
+
parts.push(text17);
|
|
32580
|
+
}
|
|
32581
|
+
return parts.length === 0 ? null : parts.join("\n");
|
|
32582
|
+
}
|
|
32583
|
+
function renderPrompt(raw) {
|
|
32584
|
+
const command = marker(raw, "command-name");
|
|
32585
|
+
if (command) {
|
|
32586
|
+
const args = marker(raw, "command-args");
|
|
32587
|
+
const name = `/${command.replace(/^\/+/, "")}`;
|
|
32588
|
+
return args ? `${name} ${args}` : name;
|
|
32589
|
+
}
|
|
32590
|
+
return stripBlocks(raw);
|
|
32591
|
+
}
|
|
32592
|
+
function stripBlocks(raw) {
|
|
32593
|
+
return raw.replace(/<system-reminder>[\s\S]*?<\/system-reminder>/g, "").replace(/<command-[^>]*>[\s\S]*?<\/command-[^>]*>/g, "").replace(/<local-command-[^>]*>[\s\S]*?<\/local-command-[^>]*>/g, "").trim();
|
|
32594
|
+
}
|
|
32595
|
+
function marker(raw, tag) {
|
|
32596
|
+
const match = raw.match(new RegExp(`<${tag}>([\\s\\S]*?)</${tag}>`));
|
|
32597
|
+
return match ? match[1].trim() : "";
|
|
32598
|
+
}
|
|
32599
|
+
function cap(message3, maxLength) {
|
|
32600
|
+
return message3.length <= maxLength ? message3 : `${message3.slice(0, maxLength).trimEnd()}\u2026`;
|
|
32601
|
+
}
|
|
32602
|
+
function isInterrupt(value) {
|
|
32603
|
+
return value.trimStart().startsWith(INTERRUPT_PREFIX2);
|
|
32604
|
+
}
|
|
32605
|
+
function asRecord3(value) {
|
|
32606
|
+
return value && typeof value === "object" ? value : null;
|
|
32607
|
+
}
|
|
32608
|
+
|
|
32552
32609
|
// src/commands/sessions/shared/readTranscriptTail.ts
|
|
32553
32610
|
import * as fs46 from "fs";
|
|
32554
32611
|
var DEFAULT_MAX_BYTES = 256 * 1024;
|
|
@@ -32632,9 +32689,19 @@ async function resolveTranscriptPath(session) {
|
|
|
32632
32689
|
if (filePath) session.transcriptPath = filePath;
|
|
32633
32690
|
return filePath;
|
|
32634
32691
|
}
|
|
32635
|
-
|
|
32636
|
-
|
|
32637
|
-
|
|
32692
|
+
function updateLastUserMessage(session, entries, notify2) {
|
|
32693
|
+
const message3 = extractLastUserMessage(entries);
|
|
32694
|
+
if (message3 === session.lastUserMessage) return;
|
|
32695
|
+
session.lastUserMessage = message3;
|
|
32696
|
+
daemonLog(
|
|
32697
|
+
`session ${session.id} last user message: ${JSON.stringify(message3?.slice(0, 120) ?? null)}`
|
|
32698
|
+
);
|
|
32699
|
+
notify2?.();
|
|
32700
|
+
}
|
|
32701
|
+
function isFinished(session) {
|
|
32702
|
+
return session.status === "done" || session.status === "error" || session.status === "stopped";
|
|
32703
|
+
}
|
|
32704
|
+
async function reconcileTranscriptStatus(session, onStatusChange, notify2) {
|
|
32638
32705
|
const filePath = await resolveTranscriptPath(session);
|
|
32639
32706
|
if (!filePath) return;
|
|
32640
32707
|
const entries = await readTranscriptTail(filePath);
|
|
@@ -32642,6 +32709,8 @@ async function reconcileTranscriptStatus(session, onStatusChange) {
|
|
|
32642
32709
|
if (fingerprint !== null && fingerprint === session.transcriptFingerprint)
|
|
32643
32710
|
return;
|
|
32644
32711
|
session.transcriptFingerprint = fingerprint ?? void 0;
|
|
32712
|
+
updateLastUserMessage(session, entries, notify2);
|
|
32713
|
+
if (isFinished(session)) return;
|
|
32645
32714
|
const derived = deriveTranscriptStatus(entries, {
|
|
32646
32715
|
permissionActive: session.permissionActive
|
|
32647
32716
|
});
|
|
@@ -32812,7 +32881,7 @@ function watchTranscript(session, notify2, onStatusChange) {
|
|
|
32812
32881
|
let timer = null;
|
|
32813
32882
|
const run4 = () => {
|
|
32814
32883
|
timer = null;
|
|
32815
|
-
void reconcileTranscriptStatus(session, onStatusChange);
|
|
32884
|
+
void reconcileTranscriptStatus(session, onStatusChange, notify2);
|
|
32816
32885
|
startTranscriptTitleGeneration(session, notify2);
|
|
32817
32886
|
};
|
|
32818
32887
|
try {
|
|
@@ -33421,7 +33490,7 @@ function restoreBase(id, persisted) {
|
|
|
33421
33490
|
}
|
|
33422
33491
|
|
|
33423
33492
|
// src/commands/sessions/daemon/deferredSession.ts
|
|
33424
|
-
function deferredSession(id, persisted,
|
|
33493
|
+
function deferredSession(id, persisted, cap2) {
|
|
33425
33494
|
return {
|
|
33426
33495
|
...restoreBase(id, persisted),
|
|
33427
33496
|
status: "stopped",
|
|
@@ -33435,13 +33504,13 @@ function deferredSession(id, persisted, cap) {
|
|
|
33435
33504
|
runArgs: persisted.runArgs,
|
|
33436
33505
|
activity: persisted.activity,
|
|
33437
33506
|
restored: false,
|
|
33438
|
-
scrollback: deferralNotice(persisted,
|
|
33507
|
+
scrollback: deferralNotice(persisted, cap2)
|
|
33439
33508
|
};
|
|
33440
33509
|
}
|
|
33441
|
-
function deferralNotice(persisted,
|
|
33510
|
+
function deferralNotice(persisted, cap2) {
|
|
33442
33511
|
return [
|
|
33443
33512
|
`\r
|
|
33444
|
-
\x1B[33mNot resumed: restore was already at its cap of ${
|
|
33513
|
+
\x1B[33mNot resumed: restore was already at its cap of ${cap2} session(s) (raise it with: assist config set sessions.maxLive <n> -g)\x1B[0m\r
|
|
33445
33514
|
`,
|
|
33446
33515
|
`This card is the handle for it. Its command, working directory (${persisted.cwd})\r
|
|
33447
33516
|
`,
|
|
@@ -33677,23 +33746,23 @@ function logRestoreError(persisted, error) {
|
|
|
33677
33746
|
// src/commands/sessions/daemon/restoreAll.ts
|
|
33678
33747
|
function restoreAll(spawner, sessions) {
|
|
33679
33748
|
const persisted = loadPersistedSessions();
|
|
33680
|
-
const
|
|
33749
|
+
const cap2 = sessionLimits.maxRestore();
|
|
33681
33750
|
const restoredIds = /* @__PURE__ */ new Map();
|
|
33682
|
-
const names = persisted.slice(0,
|
|
33751
|
+
const names = persisted.slice(0, cap2).map((entry) => {
|
|
33683
33752
|
const id = restoreOne(entry, spawner, sessions);
|
|
33684
33753
|
if (entry.id != null && id != null) restoredIds.set(entry.id, id);
|
|
33685
33754
|
return entry.name;
|
|
33686
33755
|
});
|
|
33687
|
-
for (const over of persisted.slice(
|
|
33688
|
-
deferOne(over, spawner.recoveryCard,
|
|
33756
|
+
for (const over of persisted.slice(cap2))
|
|
33757
|
+
deferOne(over, spawner.recoveryCard, cap2);
|
|
33689
33758
|
remapLaunchedFrom(sessions, restoredIds);
|
|
33690
33759
|
return names;
|
|
33691
33760
|
}
|
|
33692
|
-
function deferOne(persisted, spawnRecoveryCard,
|
|
33761
|
+
function deferOne(persisted, spawnRecoveryCard, cap2) {
|
|
33693
33762
|
try {
|
|
33694
|
-
const id = spawnRecoveryCard((sid) => deferredSession(sid, persisted,
|
|
33763
|
+
const id = spawnRecoveryCard((sid) => deferredSession(sid, persisted, cap2));
|
|
33695
33764
|
daemonLog(
|
|
33696
|
-
`restore capped at ${
|
|
33765
|
+
`restore capped at ${cap2} (sessions.maxLive): ${describePersistedSession(persisted)} deferred to stopped card ${id}`
|
|
33697
33766
|
);
|
|
33698
33767
|
} catch (error) {
|
|
33699
33768
|
logDroppedSession(persisted, error);
|