@staff0rd/assist 0.191.2 → 0.192.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 +2 -0
- package/dist/commands/sessions/web/bundle.js +116 -0
- package/dist/index.js +304 -24
- package/package.json +6 -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.192.0",
|
|
10
10
|
type: "module",
|
|
11
11
|
main: "dist/index.js",
|
|
12
12
|
bin: {
|
|
@@ -49,10 +49,12 @@ var package_default = {
|
|
|
49
49
|
"is-wsl": "^3.1.0",
|
|
50
50
|
minimatch: "^10.1.1",
|
|
51
51
|
"node-notifier": "^10.0.1",
|
|
52
|
+
"node-pty": "^1.1.0",
|
|
52
53
|
semver: "^7.7.3",
|
|
53
54
|
"shell-quote": "^1.8.3",
|
|
54
55
|
"ts-morph": "^27.0.2",
|
|
55
56
|
typescript: "^5.9.3",
|
|
57
|
+
ws: "^8.20.0",
|
|
56
58
|
yaml: "^2.8.2",
|
|
57
59
|
zod: "^4.3.6"
|
|
58
60
|
},
|
|
@@ -70,7 +72,10 @@ var package_default = {
|
|
|
70
72
|
"@types/react-dom": "^19.2.3",
|
|
71
73
|
"@types/semver": "^7.7.1",
|
|
72
74
|
"@types/shell-quote": "^1.7.5",
|
|
75
|
+
"@types/ws": "^8.18.1",
|
|
73
76
|
"@vitest/coverage-v8": "^4.1.2",
|
|
77
|
+
"@xterm/addon-fit": "^0.11.0",
|
|
78
|
+
"@xterm/xterm": "^6.0.0",
|
|
74
79
|
esbuild: "^0.27.3",
|
|
75
80
|
jotai: "^2.18.0",
|
|
76
81
|
jscpd: "^4.0.5",
|
|
@@ -1175,7 +1180,7 @@ function getTranscriptConfig() {
|
|
|
1175
1180
|
// src/commands/backlog/spawnClaude.ts
|
|
1176
1181
|
function spawnClaude(prompt, options2 = {}) {
|
|
1177
1182
|
const config = loadConfig();
|
|
1178
|
-
const finalPrompt = config.caveman ? `/caveman
|
|
1183
|
+
const finalPrompt = config.caveman ? `/caveman:caveman
|
|
1179
1184
|
|
|
1180
1185
|
${prompt}` : prompt;
|
|
1181
1186
|
const args = [finalPrompt];
|
|
@@ -1573,20 +1578,20 @@ function createBundleHandler(importMetaUrl, bundlePath) {
|
|
|
1573
1578
|
res.end(cache);
|
|
1574
1579
|
};
|
|
1575
1580
|
}
|
|
1576
|
-
function createHtmlHandler(
|
|
1581
|
+
function createHtmlHandler(getHtml4) {
|
|
1577
1582
|
return (_req, res) => {
|
|
1578
1583
|
res.writeHead(200, { "Content-Type": "text/html" });
|
|
1579
|
-
res.end(
|
|
1584
|
+
res.end(getHtml4());
|
|
1580
1585
|
};
|
|
1581
1586
|
}
|
|
1582
1587
|
function parseRoute(req, port) {
|
|
1583
1588
|
const url = new URL(req.url ?? "/", `http://localhost:${port}`);
|
|
1584
1589
|
return { method: req.method ?? "GET", pathname: url.pathname };
|
|
1585
1590
|
}
|
|
1586
|
-
function createRouteHandler(
|
|
1591
|
+
function createRouteHandler(routes4) {
|
|
1587
1592
|
return async (req, res, port) => {
|
|
1588
1593
|
const { method, pathname } = parseRoute(req, port);
|
|
1589
|
-
const handler =
|
|
1594
|
+
const handler = routes4[`${method} ${pathname}`];
|
|
1590
1595
|
if (handler) {
|
|
1591
1596
|
await handler(req, res);
|
|
1592
1597
|
return;
|
|
@@ -1605,6 +1610,25 @@ function startWebServer(label2, port, handler) {
|
|
|
1605
1610
|
console.log(chalk16.dim("Press Ctrl+C to stop"));
|
|
1606
1611
|
exec(`open ${url}`);
|
|
1607
1612
|
});
|
|
1613
|
+
return server;
|
|
1614
|
+
}
|
|
1615
|
+
|
|
1616
|
+
// src/shared/createFallbackHandler.ts
|
|
1617
|
+
function createFallbackHandler(routes4, htmlHandler3, extra) {
|
|
1618
|
+
const baseHandler = createRouteHandler(routes4);
|
|
1619
|
+
return async (req, res, port) => {
|
|
1620
|
+
const { method, pathname } = parseRoute(req, port);
|
|
1621
|
+
if (extra && await extra(req, res, pathname)) return;
|
|
1622
|
+
if (routes4[`${method} ${pathname}`]) {
|
|
1623
|
+
await baseHandler(req, res, port);
|
|
1624
|
+
return;
|
|
1625
|
+
}
|
|
1626
|
+
if (method === "GET" && !pathname.startsWith("/api/")) {
|
|
1627
|
+
await htmlHandler3(req, res);
|
|
1628
|
+
return;
|
|
1629
|
+
}
|
|
1630
|
+
await baseHandler(req, res, port);
|
|
1631
|
+
};
|
|
1608
1632
|
}
|
|
1609
1633
|
|
|
1610
1634
|
// src/commands/backlog/web/getHtml.ts
|
|
@@ -1711,8 +1735,9 @@ async function patchItemStatus(req, res, id) {
|
|
|
1711
1735
|
}
|
|
1712
1736
|
|
|
1713
1737
|
// src/commands/backlog/web/handleRequest.ts
|
|
1738
|
+
var htmlHandler = createHtmlHandler(getHtml);
|
|
1714
1739
|
var routes = {
|
|
1715
|
-
"GET /":
|
|
1740
|
+
"GET /": htmlHandler,
|
|
1716
1741
|
"GET /bundle.js": createBundleHandler(
|
|
1717
1742
|
import.meta.url,
|
|
1718
1743
|
"commands/backlog/web/bundle.js"
|
|
@@ -1726,8 +1751,6 @@ var itemRoutes = {
|
|
|
1726
1751
|
PATCH: (req, res, id) => patchItemStatus(req, res, id),
|
|
1727
1752
|
DELETE: (_req, res, id) => deleteItem2(res, id)
|
|
1728
1753
|
};
|
|
1729
|
-
var serveHtml = createHtmlHandler(getHtml);
|
|
1730
|
-
var baseHandler = createRouteHandler(routes);
|
|
1731
1754
|
async function handleItemRoute(req, res, pathname) {
|
|
1732
1755
|
const match = pathname.match(/^\/api\/items\/(\d+)$/);
|
|
1733
1756
|
if (!match) return false;
|
|
@@ -1736,21 +1759,11 @@ async function handleItemRoute(req, res, pathname) {
|
|
|
1736
1759
|
await handler(req, res, Number.parseInt(match[1], 10));
|
|
1737
1760
|
return true;
|
|
1738
1761
|
}
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
if (routes[`${method} ${pathname}`]) {
|
|
1745
|
-
await baseHandler(req, res, port);
|
|
1746
|
-
return;
|
|
1747
|
-
}
|
|
1748
|
-
if (method === "GET" && !pathname.startsWith("/api/")) {
|
|
1749
|
-
await serveHtml(req, res);
|
|
1750
|
-
return;
|
|
1751
|
-
}
|
|
1752
|
-
await baseHandler(req, res, port);
|
|
1753
|
-
}
|
|
1762
|
+
var handleRequest = createFallbackHandler(
|
|
1763
|
+
routes,
|
|
1764
|
+
htmlHandler,
|
|
1765
|
+
handleItemRoute
|
|
1766
|
+
);
|
|
1754
1767
|
|
|
1755
1768
|
// src/commands/backlog/web/index.ts
|
|
1756
1769
|
async function web(options2) {
|
|
@@ -12373,6 +12386,272 @@ function screenshot(processName) {
|
|
|
12373
12386
|
}
|
|
12374
12387
|
}
|
|
12375
12388
|
|
|
12389
|
+
// src/commands/sessions/web/index.ts
|
|
12390
|
+
import { WebSocketServer } from "ws";
|
|
12391
|
+
|
|
12392
|
+
// src/commands/sessions/web/handleRequest.ts
|
|
12393
|
+
import { readFileSync as readFileSync34 } from "fs";
|
|
12394
|
+
import { createRequire as createRequire2 } from "module";
|
|
12395
|
+
|
|
12396
|
+
// src/commands/sessions/web/getHtml.ts
|
|
12397
|
+
function getHtml3() {
|
|
12398
|
+
return `<!DOCTYPE html>
|
|
12399
|
+
<html lang="en">
|
|
12400
|
+
<head>
|
|
12401
|
+
<meta charset="UTF-8">
|
|
12402
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
12403
|
+
<title>Sessions</title>
|
|
12404
|
+
<link rel="stylesheet" href="/xterm.css">
|
|
12405
|
+
<style>
|
|
12406
|
+
* { margin: 0; padding: 0; box-sizing: border-box; }
|
|
12407
|
+
html, body, #app { width: 100%; height: 100%; overflow: hidden; background: #1e1e1e; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
|
|
12408
|
+
::-webkit-scrollbar { width: 6px; }
|
|
12409
|
+
::-webkit-scrollbar-track { background: transparent; }
|
|
12410
|
+
::-webkit-scrollbar-thumb { background: #555; border-radius: 3px; }
|
|
12411
|
+
::-webkit-scrollbar-thumb:hover { background: #777; }
|
|
12412
|
+
</style>
|
|
12413
|
+
</head>
|
|
12414
|
+
<body>
|
|
12415
|
+
<div id="app"></div>
|
|
12416
|
+
<script src="/bundle.js"></script>
|
|
12417
|
+
</body>
|
|
12418
|
+
</html>`;
|
|
12419
|
+
}
|
|
12420
|
+
|
|
12421
|
+
// src/commands/sessions/web/handleRequest.ts
|
|
12422
|
+
var require3 = createRequire2(import.meta.url);
|
|
12423
|
+
function createCssHandler(packageEntry) {
|
|
12424
|
+
let cache;
|
|
12425
|
+
return (_req, res) => {
|
|
12426
|
+
if (!cache) {
|
|
12427
|
+
const resolved = require3.resolve(packageEntry);
|
|
12428
|
+
cache = readFileSync34(resolved, "utf-8");
|
|
12429
|
+
}
|
|
12430
|
+
res.writeHead(200, { "Content-Type": "text/css" });
|
|
12431
|
+
res.end(cache);
|
|
12432
|
+
};
|
|
12433
|
+
}
|
|
12434
|
+
var htmlHandler2 = createHtmlHandler(getHtml3);
|
|
12435
|
+
var routes3 = {
|
|
12436
|
+
"GET /": htmlHandler2,
|
|
12437
|
+
"GET /bundle.js": createBundleHandler(
|
|
12438
|
+
import.meta.url,
|
|
12439
|
+
"commands/sessions/web/bundle.js"
|
|
12440
|
+
),
|
|
12441
|
+
"GET /xterm.css": createCssHandler("@xterm/xterm/css/xterm.css")
|
|
12442
|
+
};
|
|
12443
|
+
var handleRequest3 = createFallbackHandler(routes3, htmlHandler2);
|
|
12444
|
+
|
|
12445
|
+
// src/commands/sessions/web/handleSocket.ts
|
|
12446
|
+
function handleSocket(ws, manager) {
|
|
12447
|
+
manager.addClient(ws);
|
|
12448
|
+
ws.on("message", (msg) => {
|
|
12449
|
+
let data;
|
|
12450
|
+
try {
|
|
12451
|
+
data = JSON.parse(msg.toString());
|
|
12452
|
+
} catch {
|
|
12453
|
+
return;
|
|
12454
|
+
}
|
|
12455
|
+
switch (data.type) {
|
|
12456
|
+
case "create": {
|
|
12457
|
+
const id = manager.spawn(data.prompt);
|
|
12458
|
+
ws.send(JSON.stringify({ type: "created", sessionId: id }));
|
|
12459
|
+
break;
|
|
12460
|
+
}
|
|
12461
|
+
case "input":
|
|
12462
|
+
manager.writeToSession(data.sessionId, data.data);
|
|
12463
|
+
break;
|
|
12464
|
+
case "resize":
|
|
12465
|
+
manager.resizeSession(
|
|
12466
|
+
data.sessionId,
|
|
12467
|
+
data.cols,
|
|
12468
|
+
data.rows
|
|
12469
|
+
);
|
|
12470
|
+
break;
|
|
12471
|
+
case "dismiss":
|
|
12472
|
+
manager.dismissSession(data.sessionId);
|
|
12473
|
+
break;
|
|
12474
|
+
}
|
|
12475
|
+
});
|
|
12476
|
+
ws.on("close", () => {
|
|
12477
|
+
manager.removeClient(ws);
|
|
12478
|
+
});
|
|
12479
|
+
}
|
|
12480
|
+
|
|
12481
|
+
// src/commands/sessions/web/spawnClaude.ts
|
|
12482
|
+
import * as pty from "node-pty";
|
|
12483
|
+
function spawnClaude2(prompt) {
|
|
12484
|
+
const shell = process.platform === "win32" ? "cmd.exe" : process.env.SHELL ?? "bash";
|
|
12485
|
+
const args = buildArgs(prompt);
|
|
12486
|
+
return pty.spawn(shell, args, {
|
|
12487
|
+
name: "xterm-256color",
|
|
12488
|
+
cols: 120,
|
|
12489
|
+
rows: 30,
|
|
12490
|
+
cwd: process.cwd(),
|
|
12491
|
+
env: { ...process.env }
|
|
12492
|
+
});
|
|
12493
|
+
}
|
|
12494
|
+
function buildArgs(prompt) {
|
|
12495
|
+
if (process.platform === "win32") {
|
|
12496
|
+
return prompt ? ["/c", "claude", prompt] : ["/c", "claude"];
|
|
12497
|
+
}
|
|
12498
|
+
return prompt ? ["-c", 'exec claude "$0"', prompt] : ["-c", "claude"];
|
|
12499
|
+
}
|
|
12500
|
+
|
|
12501
|
+
// src/commands/sessions/web/createSession.ts
|
|
12502
|
+
function createSession(id, prompt) {
|
|
12503
|
+
return {
|
|
12504
|
+
id,
|
|
12505
|
+
name: prompt?.slice(0, 40) || `Session ${id}`,
|
|
12506
|
+
status: "running",
|
|
12507
|
+
startedAt: Date.now(),
|
|
12508
|
+
pty: spawnClaude2(prompt),
|
|
12509
|
+
scrollback: "",
|
|
12510
|
+
idleTimer: null,
|
|
12511
|
+
lastResizeAt: 0
|
|
12512
|
+
};
|
|
12513
|
+
}
|
|
12514
|
+
|
|
12515
|
+
// src/commands/sessions/web/scheduleIdle.ts
|
|
12516
|
+
var IDLE_MS = 3e3;
|
|
12517
|
+
function scheduleIdle(session, onIdle) {
|
|
12518
|
+
if (session.idleTimer) clearTimeout(session.idleTimer);
|
|
12519
|
+
if (session.status === "done") return;
|
|
12520
|
+
session.idleTimer = setTimeout(() => {
|
|
12521
|
+
if (session.status === "running") onIdle();
|
|
12522
|
+
}, IDLE_MS);
|
|
12523
|
+
}
|
|
12524
|
+
function clearIdle(session) {
|
|
12525
|
+
if (session.idleTimer) clearTimeout(session.idleTimer);
|
|
12526
|
+
}
|
|
12527
|
+
|
|
12528
|
+
// src/commands/sessions/web/wsBroadcast.ts
|
|
12529
|
+
function wsSend(ws, msg) {
|
|
12530
|
+
if (ws.readyState === ws.OPEN) ws.send(JSON.stringify(msg));
|
|
12531
|
+
}
|
|
12532
|
+
function wsBroadcast(clients, msg) {
|
|
12533
|
+
const json = JSON.stringify(msg);
|
|
12534
|
+
for (const ws of clients) {
|
|
12535
|
+
if (ws.readyState === ws.OPEN) ws.send(json);
|
|
12536
|
+
}
|
|
12537
|
+
}
|
|
12538
|
+
|
|
12539
|
+
// src/commands/sessions/web/wirePtyEvents.ts
|
|
12540
|
+
var MAX_SCROLLBACK = 256 * 1024;
|
|
12541
|
+
var RESIZE_GRACE_MS = 500;
|
|
12542
|
+
function appendScrollback(session, data) {
|
|
12543
|
+
session.scrollback += data;
|
|
12544
|
+
if (session.scrollback.length > MAX_SCROLLBACK) {
|
|
12545
|
+
session.scrollback = session.scrollback.slice(-MAX_SCROLLBACK);
|
|
12546
|
+
}
|
|
12547
|
+
}
|
|
12548
|
+
function wirePtyEvents(session, clients, onStatusChange) {
|
|
12549
|
+
session.pty.onData((data) => {
|
|
12550
|
+
appendScrollback(session, data);
|
|
12551
|
+
const isRedraw = Date.now() - session.lastResizeAt < RESIZE_GRACE_MS;
|
|
12552
|
+
if (!isRedraw && session.status !== "running")
|
|
12553
|
+
onStatusChange(session, "running");
|
|
12554
|
+
if (!isRedraw)
|
|
12555
|
+
scheduleIdle(session, () => onStatusChange(session, "waiting"));
|
|
12556
|
+
wsBroadcast(clients, { type: "output", sessionId: session.id, data });
|
|
12557
|
+
});
|
|
12558
|
+
session.pty.onExit(() => {
|
|
12559
|
+
clearIdle(session);
|
|
12560
|
+
onStatusChange(session, "done");
|
|
12561
|
+
});
|
|
12562
|
+
}
|
|
12563
|
+
|
|
12564
|
+
// src/commands/sessions/web/SessionManager.ts
|
|
12565
|
+
var SessionManager = class {
|
|
12566
|
+
sessions = /* @__PURE__ */ new Map();
|
|
12567
|
+
clients = /* @__PURE__ */ new Set();
|
|
12568
|
+
nextId = 1;
|
|
12569
|
+
addClient(ws) {
|
|
12570
|
+
this.clients.add(ws);
|
|
12571
|
+
wsSend(ws, { type: "sessions", sessions: this.listSessions() });
|
|
12572
|
+
for (const s of this.sessions.values()) {
|
|
12573
|
+
if (s.scrollback)
|
|
12574
|
+
wsSend(ws, { type: "output", sessionId: s.id, data: s.scrollback });
|
|
12575
|
+
}
|
|
12576
|
+
}
|
|
12577
|
+
removeClient(ws) {
|
|
12578
|
+
this.clients.delete(ws);
|
|
12579
|
+
}
|
|
12580
|
+
spawn(prompt) {
|
|
12581
|
+
const id = String(this.nextId++);
|
|
12582
|
+
const session = createSession(id, prompt);
|
|
12583
|
+
this.sessions.set(id, session);
|
|
12584
|
+
wirePtyEvents(session, this.clients, (s, status2) => {
|
|
12585
|
+
s.status = status2;
|
|
12586
|
+
this.notify();
|
|
12587
|
+
});
|
|
12588
|
+
scheduleIdle(session, () => {
|
|
12589
|
+
session.status = "waiting";
|
|
12590
|
+
this.notify();
|
|
12591
|
+
});
|
|
12592
|
+
this.notify();
|
|
12593
|
+
return id;
|
|
12594
|
+
}
|
|
12595
|
+
writeToSession(id, data) {
|
|
12596
|
+
const s = this.sessions.get(id);
|
|
12597
|
+
if (s && s.status !== "done") s.pty.write(data);
|
|
12598
|
+
}
|
|
12599
|
+
resizeSession(id, cols, rows) {
|
|
12600
|
+
const s = this.sessions.get(id);
|
|
12601
|
+
if (s && s.status !== "done") {
|
|
12602
|
+
s.lastResizeAt = Date.now();
|
|
12603
|
+
s.pty.resize(cols, rows);
|
|
12604
|
+
}
|
|
12605
|
+
}
|
|
12606
|
+
dismissSession(id) {
|
|
12607
|
+
const s = this.sessions.get(id);
|
|
12608
|
+
if (!s) return;
|
|
12609
|
+
if (s.status !== "done") s.pty.kill();
|
|
12610
|
+
clearIdle(s);
|
|
12611
|
+
this.sessions.delete(id);
|
|
12612
|
+
this.notify();
|
|
12613
|
+
}
|
|
12614
|
+
listSessions() {
|
|
12615
|
+
return [...this.sessions.values()].map(
|
|
12616
|
+
({ id, name, status: status2, startedAt }) => ({
|
|
12617
|
+
id,
|
|
12618
|
+
name,
|
|
12619
|
+
status: status2,
|
|
12620
|
+
startedAt
|
|
12621
|
+
})
|
|
12622
|
+
);
|
|
12623
|
+
}
|
|
12624
|
+
notify() {
|
|
12625
|
+
wsBroadcast(this.clients, {
|
|
12626
|
+
type: "sessions",
|
|
12627
|
+
sessions: this.listSessions()
|
|
12628
|
+
});
|
|
12629
|
+
}
|
|
12630
|
+
};
|
|
12631
|
+
|
|
12632
|
+
// src/commands/sessions/web/index.ts
|
|
12633
|
+
async function web3(options2) {
|
|
12634
|
+
const port = Number.parseInt(options2.port, 10);
|
|
12635
|
+
const server = startWebServer("Sessions", port, handleRequest3);
|
|
12636
|
+
const manager = new SessionManager();
|
|
12637
|
+
const wss = new WebSocketServer({ noServer: true });
|
|
12638
|
+
server.on("upgrade", (req, socket, head) => {
|
|
12639
|
+
if (req.url === "/ws") {
|
|
12640
|
+
wss.handleUpgrade(req, socket, head, (ws) => {
|
|
12641
|
+
handleSocket(ws, manager);
|
|
12642
|
+
});
|
|
12643
|
+
} else {
|
|
12644
|
+
socket.destroy();
|
|
12645
|
+
}
|
|
12646
|
+
});
|
|
12647
|
+
}
|
|
12648
|
+
|
|
12649
|
+
// src/commands/sessions/registerSessions.ts
|
|
12650
|
+
function registerSessions(program2) {
|
|
12651
|
+
const cmd = program2.command("sessions").description("Web dashboard for Claude Code sessions").action(() => web3({ port: "3100" }));
|
|
12652
|
+
cmd.command("web").description("Start the sessions web dashboard").option("-p, --port <number>", "Port to listen on", "3100").action(web3);
|
|
12653
|
+
}
|
|
12654
|
+
|
|
12376
12655
|
// src/commands/statusLine.ts
|
|
12377
12656
|
import chalk134 from "chalk";
|
|
12378
12657
|
|
|
@@ -12627,6 +12906,7 @@ registerRavendb(program);
|
|
|
12627
12906
|
registerSeq(program);
|
|
12628
12907
|
registerTranscript(program);
|
|
12629
12908
|
registerVoice(program);
|
|
12909
|
+
registerSessions(program);
|
|
12630
12910
|
registerDeny(program);
|
|
12631
12911
|
program.command("next").description("Alias for backlog next -w").action(() => next({ allowEdits: true }));
|
|
12632
12912
|
program.command("draft").alias("feat").description("Launch Claude in /draft mode, chain into next on /next signal").action(() => launchMode("draft"));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@staff0rd/assist",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.192.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -43,10 +43,12 @@
|
|
|
43
43
|
"is-wsl": "^3.1.0",
|
|
44
44
|
"minimatch": "^10.1.1",
|
|
45
45
|
"node-notifier": "^10.0.1",
|
|
46
|
+
"node-pty": "^1.1.0",
|
|
46
47
|
"semver": "^7.7.3",
|
|
47
48
|
"shell-quote": "^1.8.3",
|
|
48
49
|
"ts-morph": "^27.0.2",
|
|
49
50
|
"typescript": "^5.9.3",
|
|
51
|
+
"ws": "^8.20.0",
|
|
50
52
|
"yaml": "^2.8.2",
|
|
51
53
|
"zod": "^4.3.6"
|
|
52
54
|
},
|
|
@@ -64,7 +66,10 @@
|
|
|
64
66
|
"@types/react-dom": "^19.2.3",
|
|
65
67
|
"@types/semver": "^7.7.1",
|
|
66
68
|
"@types/shell-quote": "^1.7.5",
|
|
69
|
+
"@types/ws": "^8.18.1",
|
|
67
70
|
"@vitest/coverage-v8": "^4.1.2",
|
|
71
|
+
"@xterm/addon-fit": "^0.11.0",
|
|
72
|
+
"@xterm/xterm": "^6.0.0",
|
|
68
73
|
"esbuild": "^0.27.3",
|
|
69
74
|
"jotai": "^2.18.0",
|
|
70
75
|
"jscpd": "^4.0.5",
|