@staff0rd/assist 0.767.0 → 0.767.1
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/dist/commands/sessions/web/bundle.js +332 -332
- package/dist/index.js +110 -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.767.
|
|
9
|
+
version: "0.767.1",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -13696,8 +13696,8 @@ function subsequenceScore(text17, query) {
|
|
|
13696
13696
|
function scoreFilePath(path106, query) {
|
|
13697
13697
|
const needle = query.trim().toLowerCase();
|
|
13698
13698
|
if (!needle) return 0;
|
|
13699
|
-
const
|
|
13700
|
-
const inBasename = subsequenceScore(
|
|
13699
|
+
const basename33 = path106.slice(path106.lastIndexOf("/") + 1);
|
|
13700
|
+
const inBasename = subsequenceScore(basename33, needle);
|
|
13701
13701
|
if (inBasename !== null) return BASENAME_WEIGHT + inBasename;
|
|
13702
13702
|
return subsequenceScore(path106, needle);
|
|
13703
13703
|
}
|
|
@@ -15211,12 +15211,9 @@ var attachmentMimeTypes = {
|
|
|
15211
15211
|
"image/gif": "gif",
|
|
15212
15212
|
"image/webp": "webp",
|
|
15213
15213
|
"image/svg+xml": "svg",
|
|
15214
|
-
"image/bmp": "bmp",
|
|
15215
|
-
"image/avif": "avif",
|
|
15216
15214
|
"video/mp4": "mp4",
|
|
15217
15215
|
"video/webm": "webm",
|
|
15218
|
-
"video/quicktime": "mov"
|
|
15219
|
-
"video/ogg": "ogv"
|
|
15216
|
+
"video/quicktime": "mov"
|
|
15220
15217
|
};
|
|
15221
15218
|
|
|
15222
15219
|
// src/commands/sessions/web/attachmentContentType.ts
|
|
@@ -16972,20 +16969,29 @@ function extensionFromMime(contentType) {
|
|
|
16972
16969
|
const subtype = mime.split("/")[1]?.replace(/^x-/, "").replace(/\+.*$/, "");
|
|
16973
16970
|
return subtype && /^[a-z0-9]+$/.test(subtype) ? subtype : void 0;
|
|
16974
16971
|
}
|
|
16972
|
+
var ghAttachableExtensions = /* @__PURE__ */ new Set([
|
|
16973
|
+
...Object.values(attachmentMimeTypes),
|
|
16974
|
+
"jpeg"
|
|
16975
|
+
]);
|
|
16975
16976
|
function pickExtension(name, contentType) {
|
|
16976
16977
|
const fromName = extname2(name).replace(/^\./, "").toLowerCase();
|
|
16977
|
-
|
|
16978
|
-
|
|
16978
|
+
const ext = /^[a-z0-9]+$/.test(fromName) ? fromName : extensionFromMime(contentType) ?? "png";
|
|
16979
|
+
if (!ghAttachableExtensions.has(ext))
|
|
16980
|
+
throw new Error(
|
|
16981
|
+
`gh cannot attach .${ext} files (supported: ${[...ghAttachableExtensions].join(", ")}).`
|
|
16982
|
+
);
|
|
16983
|
+
return ext;
|
|
16979
16984
|
}
|
|
16980
16985
|
function safeBaseName(name) {
|
|
16981
16986
|
const base = name.replace(/\.[^.]+$/, "").replace(/[^a-zA-Z0-9_-]+/g, "-");
|
|
16982
16987
|
return base.replace(/^-+|-+$/g, "").slice(0, 60) || "screenshot";
|
|
16983
16988
|
}
|
|
16984
16989
|
async function stageAttachment(name, contentType, body) {
|
|
16990
|
+
const ext = pickExtension(name, contentType);
|
|
16985
16991
|
await mkdir4(stagedAttachmentsDir, { recursive: true });
|
|
16986
16992
|
const dir = await mkdtemp(join41(stagedAttachmentsDir, "upload-"));
|
|
16987
16993
|
const alt = safeBaseName(name);
|
|
16988
|
-
const filePath = join41(dir, `${alt}.${
|
|
16994
|
+
const filePath = join41(dir, `${alt}.${ext}`);
|
|
16989
16995
|
await writeFile2(filePath, body);
|
|
16990
16996
|
return { dir, filePath, alt };
|
|
16991
16997
|
}
|
|
@@ -24631,10 +24637,7 @@ async function reviewProposedIssue(title, body, metadata2 = []) {
|
|
|
24631
24637
|
|
|
24632
24638
|
// src/commands/prs/attachArgs.ts
|
|
24633
24639
|
function attachArgs(attachments) {
|
|
24634
|
-
return attachments.flatMap(({ path: path106
|
|
24635
|
-
"--attach",
|
|
24636
|
-
alt ? `${path106}#${alt}` : path106
|
|
24637
|
-
]);
|
|
24640
|
+
return attachments.flatMap(({ path: path106 }) => ["--attach", path106]);
|
|
24638
24641
|
}
|
|
24639
24642
|
|
|
24640
24643
|
// src/commands/prs/runGhWithAttachments.ts
|
|
@@ -41014,7 +41017,7 @@ function requestDrain(socket, lines2) {
|
|
|
41014
41017
|
}
|
|
41015
41018
|
|
|
41016
41019
|
// src/commands/sessions/daemon/runDaemon.ts
|
|
41017
|
-
import { mkdirSync as
|
|
41020
|
+
import { mkdirSync as mkdirSync38 } from "fs";
|
|
41018
41021
|
|
|
41019
41022
|
// src/commands/sessions/daemon/createAutoExit.ts
|
|
41020
41023
|
var DEFAULT_GRACE_MS = 6e4;
|
|
@@ -41249,6 +41252,10 @@ function resizeSession(sessions, id, cols, rows, viewer = {}) {
|
|
|
41249
41252
|
if (isInactiveViewer(s, viewer)) return;
|
|
41250
41253
|
claimViewer(s, viewer, "resize");
|
|
41251
41254
|
const unchanged = s.cols === cols && s.rows === rows;
|
|
41255
|
+
if (!unchanged || viewer.claim)
|
|
41256
|
+
daemonLog(
|
|
41257
|
+
`session ${id} resize ${s.cols}x${s.rows} -> ${cols}x${rows} by ${viewer.viewerId ?? "unknown viewer"} on ${viewer.viewerNode ?? "unknown node"}${viewer.claim ? " (takeover)" : ""}`
|
|
41258
|
+
);
|
|
41252
41259
|
s.cols = cols;
|
|
41253
41260
|
s.rows = rows;
|
|
41254
41261
|
const resize = (c, r) => resizePty(s, c, r);
|
|
@@ -42719,10 +42726,37 @@ function startSessionTitleGeneration(session, notify2) {
|
|
|
42719
42726
|
runSessionTitleGeneration(session, prompt, notify2, singleLineTitle(prompt));
|
|
42720
42727
|
}
|
|
42721
42728
|
|
|
42729
|
+
// src/commands/sessions/daemon/worktree/appendWatcherLog.ts
|
|
42730
|
+
import { appendFileSync as appendFileSync3, mkdirSync as mkdirSync34 } from "fs";
|
|
42731
|
+
import { dirname as dirname42 } from "path";
|
|
42732
|
+
|
|
42733
|
+
// src/commands/sessions/daemon/worktree/watcherLogPath.ts
|
|
42734
|
+
import { createHash as createHash4 } from "crypto";
|
|
42735
|
+
import { homedir as homedir26 } from "os";
|
|
42736
|
+
import { basename as basename29, join as join102 } from "path";
|
|
42737
|
+
function watcherLogPath(cwd) {
|
|
42738
|
+
const clone = canonicalTreePath(cwd);
|
|
42739
|
+
const key = createHash4("sha1").update(clone).digest("hex").slice(0, 8);
|
|
42740
|
+
const dir = process.env.ASSIST_WATCHER_LOG_DIR ?? join102(homedir26(), ".assist", "watchers");
|
|
42741
|
+
return join102(dir, `${basename29(clone) || "root"}-${key}.log`);
|
|
42742
|
+
}
|
|
42743
|
+
|
|
42744
|
+
// src/commands/sessions/daemon/worktree/appendWatcherLog.ts
|
|
42745
|
+
function appendWatcherLog(session, data) {
|
|
42746
|
+
if (session.watcher !== true || !session.cwd) return;
|
|
42747
|
+
try {
|
|
42748
|
+
const path106 = watcherLogPath(session.cwd);
|
|
42749
|
+
mkdirSync34(dirname42(path106), { recursive: true });
|
|
42750
|
+
appendFileSync3(path106, data);
|
|
42751
|
+
} catch {
|
|
42752
|
+
}
|
|
42753
|
+
}
|
|
42754
|
+
|
|
42722
42755
|
// src/commands/sessions/daemon/emitSessionOutput.ts
|
|
42723
42756
|
var MAX_SCROLLBACK = 256 * 1024;
|
|
42724
42757
|
function emitSessionOutput(session, clients, data) {
|
|
42725
42758
|
session.scrollback += data;
|
|
42759
|
+
appendWatcherLog(session, data);
|
|
42726
42760
|
if (session.scrollback.length > MAX_SCROLLBACK) {
|
|
42727
42761
|
session.scrollback = session.scrollback.slice(-MAX_SCROLLBACK);
|
|
42728
42762
|
}
|
|
@@ -42795,8 +42829,8 @@ function handleRefusedRun(session, exitCode, onStatusChange) {
|
|
|
42795
42829
|
}
|
|
42796
42830
|
|
|
42797
42831
|
// src/commands/sessions/daemon/watchActivity.ts
|
|
42798
|
-
import { existsSync as existsSync90, mkdirSync as
|
|
42799
|
-
import { dirname as
|
|
42832
|
+
import { existsSync as existsSync90, mkdirSync as mkdirSync35, watch as watch2 } from "fs";
|
|
42833
|
+
import { dirname as dirname43 } from "path";
|
|
42800
42834
|
|
|
42801
42835
|
// src/commands/sessions/daemon/applyActivityToSession.ts
|
|
42802
42836
|
function applyActivityToSession(session, activity2) {
|
|
@@ -42858,9 +42892,9 @@ var DEBOUNCE_MS2 = 50;
|
|
|
42858
42892
|
function watchActivity(session, notify2, onClaudeSessionId) {
|
|
42859
42893
|
if (session.commandType !== "assist" || !session.cwd) return;
|
|
42860
42894
|
const path106 = activityPath(session.id);
|
|
42861
|
-
const dir =
|
|
42895
|
+
const dir = dirname43(path106);
|
|
42862
42896
|
try {
|
|
42863
|
-
|
|
42897
|
+
mkdirSync35(dir, { recursive: true });
|
|
42864
42898
|
} catch {
|
|
42865
42899
|
return;
|
|
42866
42900
|
}
|
|
@@ -43064,10 +43098,10 @@ function headContainsSessionId(filePath, claudeSessionId) {
|
|
|
43064
43098
|
}
|
|
43065
43099
|
|
|
43066
43100
|
// src/commands/sessions/daemon/ensureProjectDirExists.ts
|
|
43067
|
-
import { mkdirSync as
|
|
43101
|
+
import { mkdirSync as mkdirSync36 } from "fs";
|
|
43068
43102
|
function ensureProjectDirExists(dir, sessionId) {
|
|
43069
43103
|
try {
|
|
43070
|
-
|
|
43104
|
+
mkdirSync36(dir, { recursive: true });
|
|
43071
43105
|
return true;
|
|
43072
43106
|
} catch (error) {
|
|
43073
43107
|
daemonLog(
|
|
@@ -44046,12 +44080,42 @@ function createAssistSession(id, assistArgs, cwd, meta, holdPty) {
|
|
|
44046
44080
|
};
|
|
44047
44081
|
}
|
|
44048
44082
|
|
|
44083
|
+
// src/commands/sessions/daemon/worktree/seedWatcherScrollback.ts
|
|
44084
|
+
import { readFileSync as readFileSync65, writeFileSync as writeFileSync54 } from "fs";
|
|
44085
|
+
var SCROLLBACK_TAIL = 256 * 1024;
|
|
44086
|
+
var MAX_LOG_SIZE = 4 * 1024 * 1024;
|
|
44087
|
+
function readLogTail2(path106) {
|
|
44088
|
+
let log2;
|
|
44089
|
+
try {
|
|
44090
|
+
log2 = readFileSync65(path106, "utf8");
|
|
44091
|
+
} catch {
|
|
44092
|
+
return "";
|
|
44093
|
+
}
|
|
44094
|
+
if (log2.length > MAX_LOG_SIZE) {
|
|
44095
|
+
log2 = log2.slice(-SCROLLBACK_TAIL);
|
|
44096
|
+
writeFileSync54(path106, log2);
|
|
44097
|
+
daemonLog(`watcher log ${path106} trimmed to its last ${log2.length} chars`);
|
|
44098
|
+
}
|
|
44099
|
+
return log2.slice(-SCROLLBACK_TAIL);
|
|
44100
|
+
}
|
|
44101
|
+
function seedWatcherScrollback(cwd, event) {
|
|
44102
|
+
const path106 = watcherLogPath(cwd);
|
|
44103
|
+
const history = readLogTail2(path106);
|
|
44104
|
+
const note = watcherNote(`${event} at ${(/* @__PURE__ */ new Date()).toLocaleString()}`);
|
|
44105
|
+
appendWatcherLog({ watcher: true, cwd }, note);
|
|
44106
|
+
daemonLog(
|
|
44107
|
+
`watcher in ${cwd} seeded with ${history.length} chars of history from ${path106} (${event})`
|
|
44108
|
+
);
|
|
44109
|
+
return history + note;
|
|
44110
|
+
}
|
|
44111
|
+
|
|
44049
44112
|
// src/commands/sessions/daemon/createWatcherSession.ts
|
|
44050
44113
|
var WATCHER_ARGS = ["watch", "loop"];
|
|
44051
44114
|
function createWatcherSession(id, cwd) {
|
|
44052
44115
|
return {
|
|
44053
44116
|
...createAssistSession(id, WATCHER_ARGS, cwd),
|
|
44054
|
-
watcher: true
|
|
44117
|
+
watcher: true,
|
|
44118
|
+
scrollback: seedWatcherScrollback(cwd, "watcher started")
|
|
44055
44119
|
};
|
|
44056
44120
|
}
|
|
44057
44121
|
|
|
@@ -45030,7 +45094,17 @@ function relaunchConsoleWatcher(id, persisted, base) {
|
|
|
45030
45094
|
daemonLog(
|
|
45031
45095
|
`relaunching watcher session ${id} running ${command.join(" ")} in ${persisted.cwd ?? "(no cwd)"}`
|
|
45032
45096
|
);
|
|
45033
|
-
|
|
45097
|
+
const session = runningSession(
|
|
45098
|
+
base,
|
|
45099
|
+
persisted,
|
|
45100
|
+
spawnPty(command, persisted.cwd, id)
|
|
45101
|
+
);
|
|
45102
|
+
if (persisted.cwd)
|
|
45103
|
+
session.scrollback = seedWatcherScrollback(
|
|
45104
|
+
persisted.cwd,
|
|
45105
|
+
"daemon restarted; watcher relaunched"
|
|
45106
|
+
);
|
|
45107
|
+
return session;
|
|
45034
45108
|
}
|
|
45035
45109
|
|
|
45036
45110
|
// src/commands/sessions/daemon/restoreSession.ts
|
|
@@ -45137,7 +45211,7 @@ function rearmStoppedSessions(sessions, notify2) {
|
|
|
45137
45211
|
|
|
45138
45212
|
// src/commands/sessions/daemon/worktree/reconcileWorktreesOnRestore.ts
|
|
45139
45213
|
import { existsSync as existsSync93 } from "fs";
|
|
45140
|
-
import { basename as
|
|
45214
|
+
import { basename as basename31 } from "path";
|
|
45141
45215
|
|
|
45142
45216
|
// src/commands/sessions/daemon/worktree/accountedTrees.ts
|
|
45143
45217
|
function accountedTrees(sessions) {
|
|
@@ -45245,7 +45319,7 @@ function capped2(lines2) {
|
|
|
45245
45319
|
}
|
|
45246
45320
|
|
|
45247
45321
|
// src/commands/sessions/daemon/worktree/resurfaceOrphanedWorktree.ts
|
|
45248
|
-
import { basename as
|
|
45322
|
+
import { basename as basename30 } from "path";
|
|
45249
45323
|
function resurfaceOrphanedWorktree(sessions, spawnWith, recovered, notify2) {
|
|
45250
45324
|
const { orphan, reason: reason4, held } = recovered;
|
|
45251
45325
|
let id;
|
|
@@ -45268,7 +45342,7 @@ function orphanedSession(id, recovered) {
|
|
|
45268
45342
|
const { orphan, reason: reason4, held } = recovered;
|
|
45269
45343
|
return {
|
|
45270
45344
|
...sessionBase(id, "stopped"),
|
|
45271
|
-
name: `recovered ${
|
|
45345
|
+
name: `recovered ${basename30(orphan.path)}`,
|
|
45272
45346
|
subtitle: `${held.summary} in ${orphan.path}`,
|
|
45273
45347
|
commandType: "claude",
|
|
45274
45348
|
pty: null,
|
|
@@ -45329,7 +45403,7 @@ async function recoverOrphanedWorktrees(sessions, spawnWith, notify2) {
|
|
|
45329
45403
|
logVanishedTree(sessions, path106);
|
|
45330
45404
|
vanished.set(clone, [
|
|
45331
45405
|
...vanished.get(clone) ?? [],
|
|
45332
|
-
{ path: path106, branch:
|
|
45406
|
+
{ path: path106, branch: basename31(path106) }
|
|
45333
45407
|
]);
|
|
45334
45408
|
continue;
|
|
45335
45409
|
}
|
|
@@ -46449,8 +46523,8 @@ function resumeSession(id, sessionId, cwd, name, holdPty, harness) {
|
|
|
46449
46523
|
import { existsSync as existsSync95 } from "fs";
|
|
46450
46524
|
|
|
46451
46525
|
// src/commands/sessions/daemon/worktree/carryTranscriptToTree.ts
|
|
46452
|
-
import { copyFileSync as copyFileSync5, existsSync as existsSync94, mkdirSync as
|
|
46453
|
-
import { join as
|
|
46526
|
+
import { copyFileSync as copyFileSync5, existsSync as existsSync94, mkdirSync as mkdirSync37 } from "fs";
|
|
46527
|
+
import { join as join104 } from "path";
|
|
46454
46528
|
function carryTranscriptToTree(claudeSessionId, fromCwd, toCwd) {
|
|
46455
46529
|
const dir = projectDirForCwd(toCwd);
|
|
46456
46530
|
if (dir === projectDirForCwd(fromCwd)) {
|
|
@@ -46459,7 +46533,7 @@ function carryTranscriptToTree(claudeSessionId, fromCwd, toCwd) {
|
|
|
46459
46533
|
);
|
|
46460
46534
|
return;
|
|
46461
46535
|
}
|
|
46462
|
-
const dest =
|
|
46536
|
+
const dest = join104(dir, `${claudeSessionId}.jsonl`);
|
|
46463
46537
|
if (existsSync94(dest)) {
|
|
46464
46538
|
daemonLog(`transcript ${claudeSessionId} already present in ${dir}`);
|
|
46465
46539
|
return;
|
|
@@ -46472,7 +46546,7 @@ function carryTranscriptToTree(claudeSessionId, fromCwd, toCwd) {
|
|
|
46472
46546
|
return;
|
|
46473
46547
|
}
|
|
46474
46548
|
try {
|
|
46475
|
-
|
|
46549
|
+
mkdirSync37(dir, { recursive: true });
|
|
46476
46550
|
copyFileSync5(source, dest);
|
|
46477
46551
|
daemonLog(
|
|
46478
46552
|
`transcript ${source} copied to ${dest} so ${toCwd} can resume it`
|
|
@@ -47347,10 +47421,10 @@ function handleConnection(socket, manager) {
|
|
|
47347
47421
|
}
|
|
47348
47422
|
|
|
47349
47423
|
// src/commands/sessions/daemon/onListening.ts
|
|
47350
|
-
import { unlinkSync as unlinkSync22, writeFileSync as
|
|
47424
|
+
import { unlinkSync as unlinkSync22, writeFileSync as writeFileSync55 } from "fs";
|
|
47351
47425
|
|
|
47352
47426
|
// src/commands/sessions/daemon/startPidFileWatchdog.ts
|
|
47353
|
-
import { readFileSync as
|
|
47427
|
+
import { readFileSync as readFileSync66 } from "fs";
|
|
47354
47428
|
var WATCHDOG_INTERVAL_MS = 5e3;
|
|
47355
47429
|
function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
|
|
47356
47430
|
const timer = setInterval(() => {
|
|
@@ -47361,7 +47435,7 @@ function startPidFileWatchdog(onLost, intervalMs = WATCHDOG_INTERVAL_MS) {
|
|
|
47361
47435
|
}
|
|
47362
47436
|
function ownsPidFile() {
|
|
47363
47437
|
try {
|
|
47364
|
-
return
|
|
47438
|
+
return readFileSync66(daemonPaths.pid, "utf8").trim() === String(process.pid);
|
|
47365
47439
|
} catch {
|
|
47366
47440
|
return false;
|
|
47367
47441
|
}
|
|
@@ -47369,7 +47443,7 @@ function ownsPidFile() {
|
|
|
47369
47443
|
|
|
47370
47444
|
// src/commands/sessions/daemon/onListening.ts
|
|
47371
47445
|
function onListening(manager, checkAutoExit) {
|
|
47372
|
-
|
|
47446
|
+
writeFileSync55(daemonPaths.pid, String(process.pid));
|
|
47373
47447
|
startPidFileWatchdog(() => {
|
|
47374
47448
|
daemonLog("lost daemon.pid ownership; shutting down sessions and exiting");
|
|
47375
47449
|
void manager.flushActiveMs().finally(() => {
|
|
@@ -47457,7 +47531,7 @@ async function recoverFromAddrInUse(server, manager, checkAutoExit) {
|
|
|
47457
47531
|
|
|
47458
47532
|
// src/commands/sessions/daemon/runDaemon.ts
|
|
47459
47533
|
async function runDaemon() {
|
|
47460
|
-
|
|
47534
|
+
mkdirSync38(daemonPaths.dir, { recursive: true });
|
|
47461
47535
|
daemonLog(
|
|
47462
47536
|
`starting (reason: ${process.env.ASSIST_DAEMON_SPAWN_REASON ?? "manual"})`
|
|
47463
47537
|
);
|