@staff0rd/assist 0.321.0 → 0.322.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 +114 -31
- 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.322.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -1556,19 +1556,19 @@ function moveCaseInsensitive(absSource, absDest) {
|
|
|
1556
1556
|
fs9.renameSync(absSource, tmp);
|
|
1557
1557
|
fs9.renameSync(tmp, absDest);
|
|
1558
1558
|
}
|
|
1559
|
-
function applyMoves(project, moves, cwd,
|
|
1559
|
+
function applyMoves(project, moves, cwd, emit4) {
|
|
1560
1560
|
for (const { sourcePath, destPath } of moves) {
|
|
1561
1561
|
const start3 = performance.now();
|
|
1562
1562
|
const absSource = path15.resolve(sourcePath);
|
|
1563
1563
|
const absDest = path15.resolve(destPath);
|
|
1564
1564
|
for (const r of renameExports(project, absSource, absDest)) {
|
|
1565
|
-
|
|
1565
|
+
emit4(` Renamed export ${r} in ${sourcePath}`);
|
|
1566
1566
|
}
|
|
1567
1567
|
const sourceFile = project.getSourceFile(absSource);
|
|
1568
1568
|
if (sourceFile) sourceFile.move(absDest);
|
|
1569
1569
|
const ms = (performance.now() - start3).toFixed(0);
|
|
1570
1570
|
const rel = `${path15.relative(cwd, absSource)} \u2192 ${path15.relative(cwd, absDest)}`;
|
|
1571
|
-
|
|
1571
|
+
emit4(` Renamed ${rel} (${ms}ms)`);
|
|
1572
1572
|
}
|
|
1573
1573
|
project.saveSync();
|
|
1574
1574
|
for (const { sourcePath, destPath } of moves) {
|
|
@@ -6728,6 +6728,44 @@ function installRestartMenu(options2 = {}) {
|
|
|
6728
6728
|
return cleanup;
|
|
6729
6729
|
}
|
|
6730
6730
|
|
|
6731
|
+
// src/commands/sessions/web/streamDaemonLogs.ts
|
|
6732
|
+
import { createInterface as createInterface3 } from "readline";
|
|
6733
|
+
var RECONNECT_MS = 3e3;
|
|
6734
|
+
function streamDaemonLogs() {
|
|
6735
|
+
void connect2();
|
|
6736
|
+
}
|
|
6737
|
+
async function connect2() {
|
|
6738
|
+
try {
|
|
6739
|
+
await ensureDaemonRunning("web log stream");
|
|
6740
|
+
const socket = await connectToDaemon();
|
|
6741
|
+
wire(socket);
|
|
6742
|
+
socket.write(`${JSON.stringify({ type: "subscribe-logs" })}
|
|
6743
|
+
`);
|
|
6744
|
+
} catch {
|
|
6745
|
+
scheduleReconnect();
|
|
6746
|
+
}
|
|
6747
|
+
}
|
|
6748
|
+
function wire(socket) {
|
|
6749
|
+
const lines = createInterface3({ input: socket });
|
|
6750
|
+
lines.on("error", () => {
|
|
6751
|
+
});
|
|
6752
|
+
lines.on("line", emit);
|
|
6753
|
+
socket.on("error", () => {
|
|
6754
|
+
});
|
|
6755
|
+
socket.on("close", scheduleReconnect);
|
|
6756
|
+
}
|
|
6757
|
+
function emit(line) {
|
|
6758
|
+
try {
|
|
6759
|
+
const data = JSON.parse(line);
|
|
6760
|
+
if (data.type === "log" && typeof data.line === "string")
|
|
6761
|
+
console.log(data.line);
|
|
6762
|
+
} catch {
|
|
6763
|
+
}
|
|
6764
|
+
}
|
|
6765
|
+
function scheduleReconnect() {
|
|
6766
|
+
setTimeout(() => void connect2(), RECONNECT_MS).unref();
|
|
6767
|
+
}
|
|
6768
|
+
|
|
6731
6769
|
// src/commands/sessions/web/index.ts
|
|
6732
6770
|
async function web(options2) {
|
|
6733
6771
|
const port = Number.parseInt(options2.port, 10);
|
|
@@ -6754,6 +6792,7 @@ async function web(options2) {
|
|
|
6754
6792
|
}
|
|
6755
6793
|
});
|
|
6756
6794
|
installRestartMenu();
|
|
6795
|
+
streamDaemonLogs();
|
|
6757
6796
|
void ensureDaemonRunning("web server start").catch((error) => {
|
|
6758
6797
|
console.error(
|
|
6759
6798
|
chalk55.yellow(
|
|
@@ -11669,7 +11708,7 @@ function advisory(count6) {
|
|
|
11669
11708
|
const noun = count6 === 1 ? "handover" : "handovers";
|
|
11670
11709
|
return `${count6} unrecalled ${noun} for this repo. Run /recall to load.`;
|
|
11671
11710
|
}
|
|
11672
|
-
function
|
|
11711
|
+
function emit2(message) {
|
|
11673
11712
|
const json = JSON.stringify({
|
|
11674
11713
|
hookSpecificOutput: { hookEventName: "SessionStart" },
|
|
11675
11714
|
systemMessage: message
|
|
@@ -11686,7 +11725,7 @@ async function load2(options2 = {}) {
|
|
|
11686
11725
|
await migrateDiskHandovers(orm, origin, cwd);
|
|
11687
11726
|
const count6 = await countPendingHandovers(orm, origin);
|
|
11688
11727
|
if (count6 === 0) return null;
|
|
11689
|
-
return
|
|
11728
|
+
return emit2(advisory(count6));
|
|
11690
11729
|
}
|
|
11691
11730
|
|
|
11692
11731
|
// src/commands/handover/listPendingHandovers.ts
|
|
@@ -12401,25 +12440,25 @@ function isVisibleText(t) {
|
|
|
12401
12440
|
return /[a-zA-Z]{3,}/.test(t);
|
|
12402
12441
|
}
|
|
12403
12442
|
var isHashtag = (t) => /^#[A-Za-z0-9_]+$/.test(t);
|
|
12404
|
-
function collectRscText(v, resolve17,
|
|
12443
|
+
function collectRscText(v, resolve17, sink2, seen) {
|
|
12405
12444
|
if (v == null) return;
|
|
12406
12445
|
if (typeof v === "string") {
|
|
12407
12446
|
if (isRscRef(v)) {
|
|
12408
12447
|
if (!seen.has(v)) {
|
|
12409
12448
|
seen.add(v);
|
|
12410
|
-
collectRscText(resolve17(v), resolve17,
|
|
12449
|
+
collectRscText(resolve17(v), resolve17, sink2, seen);
|
|
12411
12450
|
}
|
|
12412
|
-
} else if (isHashtag(v))
|
|
12413
|
-
else if (isVisibleText(v))
|
|
12451
|
+
} else if (isHashtag(v)) sink2.hashtags.push(v);
|
|
12452
|
+
else if (isVisibleText(v)) sink2.text.push(v);
|
|
12414
12453
|
return;
|
|
12415
12454
|
}
|
|
12416
12455
|
if (Array.isArray(v)) {
|
|
12417
|
-
for (const x of v) collectRscText(x, resolve17,
|
|
12456
|
+
for (const x of v) collectRscText(x, resolve17, sink2, seen);
|
|
12418
12457
|
return;
|
|
12419
12458
|
}
|
|
12420
12459
|
if (typeof v === "object") {
|
|
12421
12460
|
for (const val of Object.values(v)) {
|
|
12422
|
-
collectRscText(val, resolve17,
|
|
12461
|
+
collectRscText(val, resolve17, sink2, seen);
|
|
12423
12462
|
}
|
|
12424
12463
|
}
|
|
12425
12464
|
}
|
|
@@ -12458,9 +12497,9 @@ function buildMentionMap(rows, resolve17) {
|
|
|
12458
12497
|
if (!url || o.children == null) return;
|
|
12459
12498
|
const slug = slugFromProfileUrl(url);
|
|
12460
12499
|
if (!slug || map.has(slug)) return;
|
|
12461
|
-
const
|
|
12462
|
-
collectRscText(o.children, resolve17,
|
|
12463
|
-
const name =
|
|
12500
|
+
const sink2 = { text: [], hashtags: [] };
|
|
12501
|
+
collectRscText(o.children, resolve17, sink2, /* @__PURE__ */ new Set());
|
|
12502
|
+
const name = sink2.text.join(" ").replace(/\s+/g, " ").trim();
|
|
12464
12503
|
map.set(slug, name ? { slug, name, url } : { slug, url });
|
|
12465
12504
|
});
|
|
12466
12505
|
return map;
|
|
@@ -12561,8 +12600,8 @@ function walkPostRow(v, resolve17, raw) {
|
|
|
12561
12600
|
if (a) raw.related.push(a[0]);
|
|
12562
12601
|
}
|
|
12563
12602
|
if (isCommentary(o)) {
|
|
12564
|
-
const
|
|
12565
|
-
collectRscText(o.children, resolve17,
|
|
12603
|
+
const sink2 = { text: raw.text, hashtags: raw.hashtags };
|
|
12604
|
+
collectRscText(o.children, resolve17, sink2, /* @__PURE__ */ new Set());
|
|
12566
12605
|
}
|
|
12567
12606
|
for (const val of Object.values(o)) walkPostRow(val, resolve17, raw);
|
|
12568
12607
|
}
|
|
@@ -19985,7 +20024,7 @@ function listDaemonPids() {
|
|
|
19985
20024
|
}
|
|
19986
20025
|
|
|
19987
20026
|
// src/commands/sessions/daemon/queryDaemon.ts
|
|
19988
|
-
import { createInterface as
|
|
20027
|
+
import { createInterface as createInterface5 } from "readline";
|
|
19989
20028
|
var STATUS_TIMEOUT_MS = 5e3;
|
|
19990
20029
|
function queryDaemon(socket) {
|
|
19991
20030
|
socket.write(`${JSON.stringify({ type: "ping" })}
|
|
@@ -19994,7 +20033,7 @@ function queryDaemon(socket) {
|
|
|
19994
20033
|
const result = { sessions: [] };
|
|
19995
20034
|
const pending = /* @__PURE__ */ new Set(["sessions", "pong"]);
|
|
19996
20035
|
const timer = setTimeout(() => resolve17(result), STATUS_TIMEOUT_MS);
|
|
19997
|
-
const lines =
|
|
20036
|
+
const lines = createInterface5({ input: socket });
|
|
19998
20037
|
lines.on("error", () => {
|
|
19999
20038
|
});
|
|
20000
20039
|
lines.on("line", (line) => {
|
|
@@ -20074,14 +20113,32 @@ function reportStrays(pids) {
|
|
|
20074
20113
|
}
|
|
20075
20114
|
|
|
20076
20115
|
// src/commands/sessions/daemon/drainDaemon.ts
|
|
20077
|
-
import { createInterface as
|
|
20116
|
+
import { createInterface as createInterface6 } from "readline";
|
|
20078
20117
|
|
|
20079
20118
|
// src/commands/sessions/daemon/loadPersistedSessions.ts
|
|
20080
20119
|
import { z as z5 } from "zod";
|
|
20081
20120
|
|
|
20082
20121
|
// src/commands/sessions/daemon/daemonLog.ts
|
|
20122
|
+
var RING_CAPACITY = 1e3;
|
|
20123
|
+
var ring = [];
|
|
20124
|
+
var sink;
|
|
20083
20125
|
function daemonLog(message) {
|
|
20084
|
-
|
|
20126
|
+
emit3(`${(/* @__PURE__ */ new Date()).toISOString()} [${process.pid}] ${message}`);
|
|
20127
|
+
}
|
|
20128
|
+
function relayDaemonLog(line) {
|
|
20129
|
+
emit3(`[windows] ${line}`);
|
|
20130
|
+
}
|
|
20131
|
+
function emit3(line) {
|
|
20132
|
+
console.log(line);
|
|
20133
|
+
ring.push(line);
|
|
20134
|
+
if (ring.length > RING_CAPACITY) ring.shift();
|
|
20135
|
+
sink?.(line);
|
|
20136
|
+
}
|
|
20137
|
+
function setDaemonLogSink(next3) {
|
|
20138
|
+
sink = next3;
|
|
20139
|
+
}
|
|
20140
|
+
function recentDaemonLogLines() {
|
|
20141
|
+
return [...ring];
|
|
20085
20142
|
}
|
|
20086
20143
|
|
|
20087
20144
|
// src/commands/sessions/daemon/loadPersistedSessions.ts
|
|
@@ -20163,7 +20220,7 @@ function requestDrain(socket) {
|
|
|
20163
20220
|
`);
|
|
20164
20221
|
return new Promise((resolve17) => {
|
|
20165
20222
|
const timer = setTimeout(() => resolve17(0), DRAIN_TIMEOUT_MS);
|
|
20166
|
-
const lines =
|
|
20223
|
+
const lines = createInterface6({ input: socket });
|
|
20167
20224
|
lines.on("error", () => {
|
|
20168
20225
|
});
|
|
20169
20226
|
lines.on("line", (line) => {
|
|
@@ -20324,6 +20381,8 @@ var ClientHub = class extends Set {
|
|
|
20324
20381
|
this.persistPeak = persistPeak;
|
|
20325
20382
|
}
|
|
20326
20383
|
latestLimits;
|
|
20384
|
+
// why: log delivery is opt-in so browser tabs aren't spammed; only connections that ask via subscribe-logs receive daemonLog lines.
|
|
20385
|
+
logSubscribers = /* @__PURE__ */ new Set();
|
|
20327
20386
|
updateLimits(rateLimits) {
|
|
20328
20387
|
this.latestLimits = rateLimits;
|
|
20329
20388
|
broadcast(this, { type: "limits", rateLimits });
|
|
@@ -20334,6 +20393,21 @@ var ClientHub = class extends Set {
|
|
|
20334
20393
|
sendTo(client, { type: "limits", rateLimits: this.latestLimits });
|
|
20335
20394
|
}
|
|
20336
20395
|
}
|
|
20396
|
+
subscribeLogs(client) {
|
|
20397
|
+
for (const line of recentDaemonLogLines()) {
|
|
20398
|
+
sendTo(client, { type: "log", line });
|
|
20399
|
+
}
|
|
20400
|
+
this.logSubscribers.add(client);
|
|
20401
|
+
}
|
|
20402
|
+
unsubscribeLogs(client) {
|
|
20403
|
+
this.logSubscribers.delete(client);
|
|
20404
|
+
}
|
|
20405
|
+
// why: bound so it can be handed to setDaemonLogSink as a bare reference.
|
|
20406
|
+
emitLog = (line) => {
|
|
20407
|
+
for (const client of this.logSubscribers) {
|
|
20408
|
+
sendTo(client, { type: "log", line });
|
|
20409
|
+
}
|
|
20410
|
+
};
|
|
20337
20411
|
};
|
|
20338
20412
|
|
|
20339
20413
|
// src/commands/sessions/daemon/spawnPty.ts
|
|
@@ -20940,10 +21014,10 @@ async function isWindowsDaemonRunning() {
|
|
|
20940
21014
|
import { spawn as spawn10 } from "child_process";
|
|
20941
21015
|
|
|
20942
21016
|
// src/commands/sessions/daemon/logChildStream.ts
|
|
20943
|
-
import { createInterface as
|
|
21017
|
+
import { createInterface as createInterface7 } from "readline";
|
|
20944
21018
|
function logChildStream(stream, label2) {
|
|
20945
21019
|
if (!stream) return;
|
|
20946
|
-
const lines =
|
|
21020
|
+
const lines = createInterface7({ input: stream });
|
|
20947
21021
|
lines.on("line", (line) => daemonLog(`[${label2}] ${line}`));
|
|
20948
21022
|
lines.on("error", () => {
|
|
20949
21023
|
});
|
|
@@ -21099,6 +21173,10 @@ var inbound = {
|
|
|
21099
21173
|
created: handleCreated,
|
|
21100
21174
|
sessions: handleSessions,
|
|
21101
21175
|
output: handleOutput,
|
|
21176
|
+
// why: relay the Windows daemon's own log lines into this daemon's stream (ring + subscribers) so assist.log shows both daemons; not state.broadcast — browsers must not receive log spam.
|
|
21177
|
+
log: (_state, msg) => {
|
|
21178
|
+
if (typeof msg.line === "string") relayDaemonLog(msg.line);
|
|
21179
|
+
},
|
|
21102
21180
|
clear: relayWithSessionId,
|
|
21103
21181
|
error: (state, msg) => {
|
|
21104
21182
|
daemonLog(`windows daemon: inbound error: ${msg.message}`);
|
|
@@ -21215,7 +21293,7 @@ function isWindowsIo(data) {
|
|
|
21215
21293
|
}
|
|
21216
21294
|
|
|
21217
21295
|
// src/commands/sessions/daemon/WindowsConnection.ts
|
|
21218
|
-
import { createInterface as
|
|
21296
|
+
import { createInterface as createInterface8 } from "readline";
|
|
21219
21297
|
|
|
21220
21298
|
// src/commands/sessions/daemon/LaunchCircuitBreaker.ts
|
|
21221
21299
|
var MAX_FAILURES = 3;
|
|
@@ -21292,10 +21370,11 @@ var WindowsConnection = class {
|
|
|
21292
21370
|
this.socket = socket;
|
|
21293
21371
|
this.wire(socket);
|
|
21294
21372
|
this.write(buildHello());
|
|
21373
|
+
this.write({ type: "subscribe-logs" });
|
|
21295
21374
|
return socket;
|
|
21296
21375
|
}
|
|
21297
21376
|
wire(socket) {
|
|
21298
|
-
const lines =
|
|
21377
|
+
const lines = createInterface8({ input: socket });
|
|
21299
21378
|
lines.on("error", () => {
|
|
21300
21379
|
});
|
|
21301
21380
|
lines.on("line", (line) => this.deps.onLine(line));
|
|
@@ -21382,14 +21461,14 @@ var WindowsProxy = class {
|
|
|
21382
21461
|
state;
|
|
21383
21462
|
conn;
|
|
21384
21463
|
healer;
|
|
21385
|
-
constructor(clients, onSessionsChanged,
|
|
21464
|
+
constructor(clients, onSessionsChanged, connect4 = defaultConnect, heal = healWindowsDaemon) {
|
|
21386
21465
|
this.state = createState(
|
|
21387
21466
|
(msg) => broadcast(clients, msg),
|
|
21388
21467
|
onSessionsChanged,
|
|
21389
21468
|
(version2) => void this.healer.onMismatch(version2)
|
|
21390
21469
|
);
|
|
21391
21470
|
this.conn = new WindowsConnection({
|
|
21392
|
-
connect:
|
|
21471
|
+
connect: connect4,
|
|
21393
21472
|
onLine: (line) => handleInbound(this.state, line),
|
|
21394
21473
|
onClose: () => this.handleClose()
|
|
21395
21474
|
});
|
|
@@ -21486,6 +21565,7 @@ var SessionManager = class {
|
|
|
21486
21565
|
}
|
|
21487
21566
|
removeClient(client) {
|
|
21488
21567
|
this.clients.delete(client);
|
|
21568
|
+
this.clients.unsubscribeLogs(client);
|
|
21489
21569
|
this.onIdleChange?.(this.isIdle());
|
|
21490
21570
|
}
|
|
21491
21571
|
isIdle = () => this.sessions.size === 0 && this.clients.size === 0;
|
|
@@ -21566,7 +21646,7 @@ import { unlinkSync as unlinkSync19 } from "fs";
|
|
|
21566
21646
|
import * as net3 from "net";
|
|
21567
21647
|
|
|
21568
21648
|
// src/commands/sessions/daemon/handleConnection.ts
|
|
21569
|
-
import { createInterface as
|
|
21649
|
+
import { createInterface as createInterface9 } from "readline";
|
|
21570
21650
|
|
|
21571
21651
|
// src/commands/sessions/shared/discoverSessions.ts
|
|
21572
21652
|
import * as fs31 from "fs";
|
|
@@ -21875,6 +21955,7 @@ function routed(local) {
|
|
|
21875
21955
|
}
|
|
21876
21956
|
var messageHandlers = {
|
|
21877
21957
|
ping: (client) => sendTo(client, { type: "pong", pid: process.pid }),
|
|
21958
|
+
"subscribe-logs": (client, m) => m.clients.subscribeLogs(client),
|
|
21878
21959
|
hello: (client) => sendTo(client, buildHello()),
|
|
21879
21960
|
create: creator(
|
|
21880
21961
|
true,
|
|
@@ -21943,7 +22024,7 @@ function handleConnection(socket, manager) {
|
|
|
21943
22024
|
};
|
|
21944
22025
|
manager.addClient(client);
|
|
21945
22026
|
manager.clients.greet(client);
|
|
21946
|
-
const lines =
|
|
22027
|
+
const lines = createInterface9({ input: socket });
|
|
21947
22028
|
lines.on("error", () => {
|
|
21948
22029
|
});
|
|
21949
22030
|
lines.on("line", (line) => {
|
|
@@ -22079,7 +22160,9 @@ async function runDaemon() {
|
|
|
22079
22160
|
daemonLog("no sessions and no connected server; exiting");
|
|
22080
22161
|
process.exit(0);
|
|
22081
22162
|
});
|
|
22082
|
-
|
|
22163
|
+
const manager = new SessionManager(checkAutoExit);
|
|
22164
|
+
setDaemonLogSink(manager.clients.emitLog);
|
|
22165
|
+
startDaemonServer(manager, checkAutoExit);
|
|
22083
22166
|
}
|
|
22084
22167
|
|
|
22085
22168
|
// src/commands/sessions/daemon/registerDaemon.ts
|