@staff0rd/assist 0.193.1 → 0.195.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/backlog/web/bundle.js +26 -26
- package/dist/commands/sessions/web/bundle.js +20 -20
- package/dist/index.js +131 -55
- 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.195.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -1674,6 +1674,48 @@ async function parseItemBody(req) {
|
|
|
1674
1674
|
async function parseStatusBody(req) {
|
|
1675
1675
|
return JSON.parse(await readBody(req));
|
|
1676
1676
|
}
|
|
1677
|
+
async function parseRewindBody(req) {
|
|
1678
|
+
return JSON.parse(await readBody(req));
|
|
1679
|
+
}
|
|
1680
|
+
|
|
1681
|
+
// src/commands/backlog/web/rewindItemPhase.ts
|
|
1682
|
+
async function rewindItemPhase(req, res, id) {
|
|
1683
|
+
const { phase, reason } = await parseRewindBody(req);
|
|
1684
|
+
const items = loadBacklog();
|
|
1685
|
+
const item = items.find((i) => i.id === id);
|
|
1686
|
+
if (!item) {
|
|
1687
|
+
respondJson(res, 404, { error: "Not found" });
|
|
1688
|
+
return;
|
|
1689
|
+
}
|
|
1690
|
+
const error = validateRewind(item, phase);
|
|
1691
|
+
if (error) {
|
|
1692
|
+
respondJson(res, 400, { error });
|
|
1693
|
+
return;
|
|
1694
|
+
}
|
|
1695
|
+
const phaseName = item.plan?.[phase - 1].name;
|
|
1696
|
+
addComment(
|
|
1697
|
+
item,
|
|
1698
|
+
`Rewound to phase ${phase} (${phaseName}): ${reason}`,
|
|
1699
|
+
phase
|
|
1700
|
+
);
|
|
1701
|
+
item.currentPhase = phase;
|
|
1702
|
+
item.status = "in-progress";
|
|
1703
|
+
saveBacklog(items);
|
|
1704
|
+
respondJson(res, 200, item);
|
|
1705
|
+
}
|
|
1706
|
+
function validateRewind(item, phase) {
|
|
1707
|
+
if (!item.plan || item.plan.length === 0) {
|
|
1708
|
+
return "Item has no plan phases.";
|
|
1709
|
+
}
|
|
1710
|
+
if (phase < 1 || phase > item.plan.length) {
|
|
1711
|
+
return `Phase ${phase} does not exist. Valid range: 1\u2013${item.plan.length}.`;
|
|
1712
|
+
}
|
|
1713
|
+
const currentPhase = item.currentPhase ?? 1;
|
|
1714
|
+
if (phase >= currentPhase) {
|
|
1715
|
+
return `Phase ${phase} is not earlier than the current phase (${currentPhase}).`;
|
|
1716
|
+
}
|
|
1717
|
+
return void 0;
|
|
1718
|
+
}
|
|
1677
1719
|
|
|
1678
1720
|
// src/commands/backlog/web/shared.ts
|
|
1679
1721
|
function listItems(req, res) {
|
|
@@ -1755,6 +1797,11 @@ var itemRoutes = {
|
|
|
1755
1797
|
DELETE: (_req, res, id) => deleteItem2(res, id)
|
|
1756
1798
|
};
|
|
1757
1799
|
async function handleItemRoute(req, res, pathname) {
|
|
1800
|
+
const rewindMatch = pathname.match(/^\/api\/items\/(\d+)\/rewind$/);
|
|
1801
|
+
if (rewindMatch && req.method === "POST") {
|
|
1802
|
+
await rewindItemPhase(req, res, Number.parseInt(rewindMatch[1], 10));
|
|
1803
|
+
return true;
|
|
1804
|
+
}
|
|
1758
1805
|
const match = pathname.match(/^\/api\/items\/(\d+)$/);
|
|
1759
1806
|
if (!match) return false;
|
|
1760
1807
|
const handler = itemRoutes[req.method ?? "GET"];
|
|
@@ -4403,7 +4450,7 @@ function registerLinkCommands(cmd) {
|
|
|
4403
4450
|
|
|
4404
4451
|
// src/commands/backlog/rewindPhase.ts
|
|
4405
4452
|
import chalk53 from "chalk";
|
|
4406
|
-
function
|
|
4453
|
+
function validateRewind2(item, phaseNumber) {
|
|
4407
4454
|
if (!item.plan || item.plan.length === 0) {
|
|
4408
4455
|
return `Item #${item.id} has no plan phases.`;
|
|
4409
4456
|
}
|
|
@@ -4422,7 +4469,7 @@ function rewindPhase(id, phase, opts) {
|
|
|
4422
4469
|
const result = loadAndFindItem(id);
|
|
4423
4470
|
if (!result) return;
|
|
4424
4471
|
const { item } = result;
|
|
4425
|
-
const error =
|
|
4472
|
+
const error = validateRewind2(item, phaseNumber);
|
|
4426
4473
|
if (error) {
|
|
4427
4474
|
console.log(chalk53.red(error));
|
|
4428
4475
|
process.exitCode = 1;
|
|
@@ -12446,6 +12493,45 @@ var routes3 = {
|
|
|
12446
12493
|
var handleRequest3 = createFallbackHandler(routes3, htmlHandler2);
|
|
12447
12494
|
|
|
12448
12495
|
// src/commands/sessions/web/handleSocket.ts
|
|
12496
|
+
function dispatch(ws, manager, data) {
|
|
12497
|
+
switch (data.type) {
|
|
12498
|
+
case "create": {
|
|
12499
|
+
const id = manager.spawn(
|
|
12500
|
+
data.prompt,
|
|
12501
|
+
data.cwd
|
|
12502
|
+
);
|
|
12503
|
+
ws.send(JSON.stringify({ type: "created", sessionId: id }));
|
|
12504
|
+
break;
|
|
12505
|
+
}
|
|
12506
|
+
case "input":
|
|
12507
|
+
manager.writeToSession(data.sessionId, data.data);
|
|
12508
|
+
break;
|
|
12509
|
+
case "resize":
|
|
12510
|
+
manager.resizeSession(
|
|
12511
|
+
data.sessionId,
|
|
12512
|
+
data.cols,
|
|
12513
|
+
data.rows
|
|
12514
|
+
);
|
|
12515
|
+
break;
|
|
12516
|
+
case "resume": {
|
|
12517
|
+
const id = manager.resume(
|
|
12518
|
+
data.sessionId,
|
|
12519
|
+
data.cwd,
|
|
12520
|
+
data.name
|
|
12521
|
+
);
|
|
12522
|
+
ws.send(JSON.stringify({ type: "created", sessionId: id }));
|
|
12523
|
+
break;
|
|
12524
|
+
}
|
|
12525
|
+
case "dismiss":
|
|
12526
|
+
manager.dismissSession(data.sessionId);
|
|
12527
|
+
break;
|
|
12528
|
+
case "history":
|
|
12529
|
+
manager.getHistory().then((history) => {
|
|
12530
|
+
ws.send(JSON.stringify({ type: "history", sessions: history }));
|
|
12531
|
+
});
|
|
12532
|
+
break;
|
|
12533
|
+
}
|
|
12534
|
+
}
|
|
12449
12535
|
function handleSocket(ws, manager) {
|
|
12450
12536
|
manager.addClient(ws);
|
|
12451
12537
|
ws.on("message", (msg) => {
|
|
@@ -12455,40 +12541,7 @@ function handleSocket(ws, manager) {
|
|
|
12455
12541
|
} catch {
|
|
12456
12542
|
return;
|
|
12457
12543
|
}
|
|
12458
|
-
|
|
12459
|
-
case "create": {
|
|
12460
|
-
const id = manager.spawn(data.prompt);
|
|
12461
|
-
ws.send(JSON.stringify({ type: "created", sessionId: id }));
|
|
12462
|
-
break;
|
|
12463
|
-
}
|
|
12464
|
-
case "input":
|
|
12465
|
-
manager.writeToSession(data.sessionId, data.data);
|
|
12466
|
-
break;
|
|
12467
|
-
case "resize":
|
|
12468
|
-
manager.resizeSession(
|
|
12469
|
-
data.sessionId,
|
|
12470
|
-
data.cols,
|
|
12471
|
-
data.rows
|
|
12472
|
-
);
|
|
12473
|
-
break;
|
|
12474
|
-
case "resume": {
|
|
12475
|
-
const id = manager.resume(
|
|
12476
|
-
data.sessionId,
|
|
12477
|
-
data.cwd,
|
|
12478
|
-
data.name
|
|
12479
|
-
);
|
|
12480
|
-
ws.send(JSON.stringify({ type: "created", sessionId: id }));
|
|
12481
|
-
break;
|
|
12482
|
-
}
|
|
12483
|
-
case "dismiss":
|
|
12484
|
-
manager.dismissSession(data.sessionId);
|
|
12485
|
-
break;
|
|
12486
|
-
case "history":
|
|
12487
|
-
manager.getHistory().then((history) => {
|
|
12488
|
-
ws.send(JSON.stringify({ type: "history", sessions: history }));
|
|
12489
|
-
});
|
|
12490
|
-
break;
|
|
12491
|
-
}
|
|
12544
|
+
dispatch(ws, manager, data);
|
|
12492
12545
|
});
|
|
12493
12546
|
ws.on("close", () => {
|
|
12494
12547
|
manager.removeClient(ws);
|
|
@@ -12520,13 +12573,13 @@ function shellEscape(s) {
|
|
|
12520
12573
|
}
|
|
12521
12574
|
|
|
12522
12575
|
// src/commands/sessions/web/createSession.ts
|
|
12523
|
-
function createSession(id, prompt) {
|
|
12576
|
+
function createSession(id, prompt, cwd) {
|
|
12524
12577
|
return {
|
|
12525
12578
|
id,
|
|
12526
12579
|
name: prompt?.slice(0, 40) || `Session ${id}`,
|
|
12527
12580
|
status: "running",
|
|
12528
12581
|
startedAt: Date.now(),
|
|
12529
|
-
pty: spawnClaude2({ prompt }),
|
|
12582
|
+
pty: spawnClaude2({ prompt, cwd }),
|
|
12530
12583
|
scrollback: "",
|
|
12531
12584
|
idleTimer: null,
|
|
12532
12585
|
lastResizeAt: 0
|
|
@@ -12702,14 +12755,47 @@ function wirePtyEvents(session, clients, onStatusChange) {
|
|
|
12702
12755
|
});
|
|
12703
12756
|
}
|
|
12704
12757
|
|
|
12758
|
+
// src/commands/sessions/web/writeToSession.ts
|
|
12759
|
+
function writeToSession(sessions, id, data) {
|
|
12760
|
+
const s = sessions.get(id);
|
|
12761
|
+
if (s && s.status !== "done") s.pty.write(data);
|
|
12762
|
+
}
|
|
12763
|
+
function resizeSession(sessions, id, cols, rows) {
|
|
12764
|
+
const s = sessions.get(id);
|
|
12765
|
+
if (s && s.status !== "done") {
|
|
12766
|
+
s.lastResizeAt = Date.now();
|
|
12767
|
+
s.pty.resize(cols, rows);
|
|
12768
|
+
}
|
|
12769
|
+
}
|
|
12770
|
+
function dismissSession(sessions, id) {
|
|
12771
|
+
const s = sessions.get(id);
|
|
12772
|
+
if (!s) return false;
|
|
12773
|
+
if (s.status !== "done") s.pty.kill();
|
|
12774
|
+
clearIdle(s);
|
|
12775
|
+
sessions.delete(id);
|
|
12776
|
+
return true;
|
|
12777
|
+
}
|
|
12778
|
+
|
|
12705
12779
|
// src/commands/sessions/web/SessionManager.ts
|
|
12706
12780
|
var SessionManager = class {
|
|
12707
12781
|
sessions = /* @__PURE__ */ new Map();
|
|
12708
12782
|
clients = /* @__PURE__ */ new Set();
|
|
12709
12783
|
nextId = 1;
|
|
12784
|
+
repoCwd;
|
|
12785
|
+
constructor() {
|
|
12786
|
+
const cwd = process.cwd();
|
|
12787
|
+
this.repoCwd = isGitRepo(cwd) ? cwd : void 0;
|
|
12788
|
+
}
|
|
12710
12789
|
addClient(ws) {
|
|
12711
12790
|
this.clients.add(ws);
|
|
12712
|
-
wsSend(ws, {
|
|
12791
|
+
wsSend(ws, {
|
|
12792
|
+
type: "sessions",
|
|
12793
|
+
cwd: this.repoCwd,
|
|
12794
|
+
sessions: this.listSessions()
|
|
12795
|
+
});
|
|
12796
|
+
this.replayScrollback(ws);
|
|
12797
|
+
}
|
|
12798
|
+
replayScrollback(ws) {
|
|
12713
12799
|
for (const s of this.sessions.values()) {
|
|
12714
12800
|
if (s.scrollback)
|
|
12715
12801
|
wsSend(ws, { type: "output", sessionId: s.id, data: s.scrollback });
|
|
@@ -12718,9 +12804,9 @@ var SessionManager = class {
|
|
|
12718
12804
|
removeClient(ws) {
|
|
12719
12805
|
this.clients.delete(ws);
|
|
12720
12806
|
}
|
|
12721
|
-
spawn(prompt) {
|
|
12807
|
+
spawn(prompt, cwd) {
|
|
12722
12808
|
const id = String(this.nextId++);
|
|
12723
|
-
const session = createSession(id, prompt);
|
|
12809
|
+
const session = createSession(id, prompt, cwd);
|
|
12724
12810
|
this.wire(session);
|
|
12725
12811
|
return id;
|
|
12726
12812
|
}
|
|
@@ -12743,23 +12829,13 @@ var SessionManager = class {
|
|
|
12743
12829
|
this.notify();
|
|
12744
12830
|
}
|
|
12745
12831
|
writeToSession(id, data) {
|
|
12746
|
-
|
|
12747
|
-
if (s && s.status !== "done") s.pty.write(data);
|
|
12832
|
+
writeToSession(this.sessions, id, data);
|
|
12748
12833
|
}
|
|
12749
12834
|
resizeSession(id, cols, rows) {
|
|
12750
|
-
|
|
12751
|
-
if (s && s.status !== "done") {
|
|
12752
|
-
s.lastResizeAt = Date.now();
|
|
12753
|
-
s.pty.resize(cols, rows);
|
|
12754
|
-
}
|
|
12835
|
+
resizeSession(this.sessions, id, cols, rows);
|
|
12755
12836
|
}
|
|
12756
12837
|
dismissSession(id) {
|
|
12757
|
-
|
|
12758
|
-
if (!s) return;
|
|
12759
|
-
if (s.status !== "done") s.pty.kill();
|
|
12760
|
-
clearIdle(s);
|
|
12761
|
-
this.sessions.delete(id);
|
|
12762
|
-
this.notify();
|
|
12838
|
+
if (dismissSession(this.sessions, id)) this.notify();
|
|
12763
12839
|
}
|
|
12764
12840
|
listSessions() {
|
|
12765
12841
|
return [...this.sessions.values()].map(
|