@punkcode/cli 0.1.21 → 0.1.23
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.
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
signIn,
|
|
11
11
|
usePunkStore,
|
|
12
12
|
version
|
|
13
|
-
} from "./chunk-
|
|
13
|
+
} from "./chunk-2M6GXAAB.js";
|
|
14
14
|
|
|
15
15
|
// src/ui/App.tsx
|
|
16
16
|
import { useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
|
|
@@ -221,7 +221,7 @@ function PasswordInput({ onSubmit }) {
|
|
|
221
221
|
}
|
|
222
222
|
|
|
223
223
|
// src/ui/Dashboard.tsx
|
|
224
|
-
import { useState as useState2, useEffect as useEffect2, useRef } from "react";
|
|
224
|
+
import { useState as useState2, useEffect as useEffect2, useRef, useMemo } from "react";
|
|
225
225
|
import { Box as Box2, Text as Text2, useApp, useInput as useInput2, useStdout } from "ink";
|
|
226
226
|
import { Badge } from "@inkjs/ui";
|
|
227
227
|
import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
@@ -239,6 +239,7 @@ var LOGO = [
|
|
|
239
239
|
"\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u255A\u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2557",
|
|
240
240
|
"\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D"
|
|
241
241
|
];
|
|
242
|
+
var LOGO_JSX = LOGO.map((line, i) => /* @__PURE__ */ jsx2(Text2, { color: theme.logo, children: line }, i));
|
|
242
243
|
function Dashboard({ store, connection, overlay }) {
|
|
243
244
|
const { exit } = useApp();
|
|
244
245
|
const { stdout } = useStdout();
|
|
@@ -250,20 +251,17 @@ function Dashboard({ store, connection, overlay }) {
|
|
|
250
251
|
const sessions = usePunkStore(store, (s) => s.sessions);
|
|
251
252
|
const activityLog = usePunkStore(store, (s) => s.activityLog);
|
|
252
253
|
const server = usePunkStore(store, (s) => s.server);
|
|
253
|
-
const connectedAt = usePunkStore(store, (s) => s.connectedAt);
|
|
254
254
|
const auth = usePunkStore(store, (s) => s.auth);
|
|
255
255
|
const sessionProjects = usePunkStore(store, (s) => s.sessionProjects);
|
|
256
256
|
const [focusMode, setFocusMode] = useState2(false);
|
|
257
257
|
const [focusedSessionIdx, setFocusedSessionIdx] = useState2(0);
|
|
258
|
-
const knownSessionIds = Object.keys(sessionProjects);
|
|
258
|
+
const knownSessionIds = useMemo(() => Object.keys(sessionProjects), [sessionProjects]);
|
|
259
259
|
const focusedSessionId = focusMode ? knownSessionIds[focusedSessionIdx] : null;
|
|
260
260
|
const hasMultipleSessions = knownSessionIds.length > 1;
|
|
261
|
-
const filteredActivity =
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
return () => clearInterval(timer);
|
|
266
|
-
}, []);
|
|
261
|
+
const filteredActivity = useMemo(
|
|
262
|
+
() => focusedSessionId ? activityLog.filter((e) => e.sessionId === focusedSessionId) : activityLog,
|
|
263
|
+
[focusedSessionId, activityLog]
|
|
264
|
+
);
|
|
267
265
|
const [selectedIdx, setSelectedIdx] = useState2(-1);
|
|
268
266
|
const [userScrolled, setUserScrolled] = useState2(false);
|
|
269
267
|
const prevLogLength = useRef(filteredActivity.length);
|
|
@@ -284,7 +282,8 @@ function Dashboard({ store, connection, overlay }) {
|
|
|
284
282
|
connection?.disconnect();
|
|
285
283
|
exit();
|
|
286
284
|
}
|
|
287
|
-
|
|
285
|
+
});
|
|
286
|
+
useInput2((input, key) => {
|
|
288
287
|
if (input === "r") connection?.reconnect();
|
|
289
288
|
if (input === "c" && !key.ctrl) {
|
|
290
289
|
store.getState().clearActivity();
|
|
@@ -328,9 +327,8 @@ function Dashboard({ store, connection, overlay }) {
|
|
|
328
327
|
setSelectedIdx(next);
|
|
329
328
|
}
|
|
330
329
|
}
|
|
331
|
-
});
|
|
330
|
+
}, { isActive: !overlay });
|
|
332
331
|
const sessionList = Object.values(sessions);
|
|
333
|
-
const uptime = connectedAt ? formatDuration(now - connectedAt) : "-";
|
|
334
332
|
const boxWidth = termWidth - 2;
|
|
335
333
|
const col = getColumns(termWidth);
|
|
336
334
|
const headerHeight = 8;
|
|
@@ -355,7 +353,7 @@ function Dashboard({ store, connection, overlay }) {
|
|
|
355
353
|
/* @__PURE__ */ jsx2(Text2, { children: stripProtocol(server) })
|
|
356
354
|
] })
|
|
357
355
|
] }),
|
|
358
|
-
termWidth >= 120 && /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", alignItems: "flex-end", justifyContent: "center", children:
|
|
356
|
+
termWidth >= 120 && /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", alignItems: "flex-end", justifyContent: "center", children: LOGO_JSX })
|
|
359
357
|
] })
|
|
360
358
|
) : (
|
|
361
359
|
/* Full header when connected */
|
|
@@ -373,10 +371,6 @@ function Dashboard({ store, connection, overlay }) {
|
|
|
373
371
|
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Status: ".padEnd(12) }),
|
|
374
372
|
/* @__PURE__ */ jsx2(StatusIndicator, { status: connectionStatus, error: connectionError })
|
|
375
373
|
] }),
|
|
376
|
-
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
377
|
-
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Uptime: ".padEnd(12) }),
|
|
378
|
-
/* @__PURE__ */ jsx2(Text2, { children: uptime })
|
|
379
|
-
] }),
|
|
380
374
|
deviceInfo && /* @__PURE__ */ jsxs2(Box2, { children: [
|
|
381
375
|
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Device: ".padEnd(12) }),
|
|
382
376
|
/* @__PURE__ */ jsx2(Text2, { children: deviceInfo.name })
|
|
@@ -446,7 +440,7 @@ function Dashboard({ store, connection, overlay }) {
|
|
|
446
440
|
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " details" })
|
|
447
441
|
] })
|
|
448
442
|
] }) }),
|
|
449
|
-
termWidth >= 120 && /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", alignItems: "flex-end", justifyContent: "center", children:
|
|
443
|
+
termWidth >= 120 && /* @__PURE__ */ jsx2(Box2, { flexDirection: "column", alignItems: "flex-end", justifyContent: "center", children: LOGO_JSX })
|
|
450
444
|
] })
|
|
451
445
|
),
|
|
452
446
|
!overlay && /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginX: 1, marginTop: 1, children: [
|
|
@@ -465,13 +459,13 @@ function Dashboard({ store, connection, overlay }) {
|
|
|
465
459
|
"ID".padEnd(col.id),
|
|
466
460
|
"PROJECT".padEnd(col.project),
|
|
467
461
|
"STATUS".padEnd(col.status),
|
|
468
|
-
"
|
|
462
|
+
"RUNNING".padEnd(col.started),
|
|
469
463
|
col.showExtras ? "MODEL".padEnd(col.model) + "EFFORT" : ""
|
|
470
464
|
] }) }),
|
|
471
465
|
sessionList.length === 0 ? /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
|
|
472
466
|
"\u25CB",
|
|
473
467
|
" Waiting for sessions from the Punk app..."
|
|
474
|
-
] }) : sessionList.map((session) => /* @__PURE__ */ jsx2(SessionRow, { session,
|
|
468
|
+
] }) : sessionList.map((session) => /* @__PURE__ */ jsx2(SessionRow, { session, col }, session.requestId))
|
|
475
469
|
]
|
|
476
470
|
}
|
|
477
471
|
)
|
|
@@ -632,10 +626,17 @@ function StatusIndicator({ status, error }) {
|
|
|
632
626
|
" Disconnected"
|
|
633
627
|
] });
|
|
634
628
|
}
|
|
635
|
-
function SessionRow({ session,
|
|
629
|
+
function SessionRow({ session, col }) {
|
|
630
|
+
const [elapsed, setElapsed] = useState2(Date.now() - session.startedAt);
|
|
631
|
+
useEffect2(() => {
|
|
632
|
+
const timer = setInterval(() => {
|
|
633
|
+
setElapsed(Date.now() - session.startedAt);
|
|
634
|
+
}, 1e3);
|
|
635
|
+
return () => clearInterval(timer);
|
|
636
|
+
}, [session.startedAt]);
|
|
636
637
|
const id = session.requestId.slice(0, col.id - 2);
|
|
637
638
|
const project = session.workingDirectory ? session.workingDirectory.split("/").pop() ?? "" : "";
|
|
638
|
-
const started = formatDuration(
|
|
639
|
+
const started = formatDuration(elapsed);
|
|
639
640
|
return /* @__PURE__ */ jsxs2(Box2, { children: [
|
|
640
641
|
/* @__PURE__ */ jsxs2(Text2, { children: [
|
|
641
642
|
id.padEnd(col.id),
|
|
@@ -752,7 +753,7 @@ function formatDuration(ms) {
|
|
|
752
753
|
const seconds = Math.floor(ms / 1e3);
|
|
753
754
|
if (seconds < 60) return `${seconds}s`;
|
|
754
755
|
const minutes = Math.floor(seconds / 60);
|
|
755
|
-
if (minutes < 60) return `${minutes}m
|
|
756
|
+
if (minutes < 60) return `${minutes}m`;
|
|
756
757
|
const hours = Math.floor(minutes / 60);
|
|
757
758
|
return `${hours}h ${minutes % 60}m`;
|
|
758
759
|
}
|
|
@@ -795,6 +796,15 @@ function App({ server, idToken, options }) {
|
|
|
795
796
|
connectionRef.current?.disconnect();
|
|
796
797
|
};
|
|
797
798
|
}, []);
|
|
799
|
+
useEffect3(() => {
|
|
800
|
+
const onSigcont = () => {
|
|
801
|
+
connectionRef.current?.reconnect();
|
|
802
|
+
};
|
|
803
|
+
process.on("SIGCONT", onSigcont);
|
|
804
|
+
return () => {
|
|
805
|
+
process.removeListener("SIGCONT", onSigcont);
|
|
806
|
+
};
|
|
807
|
+
}, []);
|
|
798
808
|
const loginOverlay = screen === "login" ? /* @__PURE__ */ jsx3(LoginDialog, { store, server }) : void 0;
|
|
799
809
|
return /* @__PURE__ */ jsx3(
|
|
800
810
|
Dashboard,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/version.ts
|
|
4
|
-
var version = "0.1.
|
|
4
|
+
var version = "0.1.23";
|
|
5
5
|
|
|
6
6
|
// src/lib/auth.ts
|
|
7
7
|
import fs from "fs";
|
|
@@ -643,6 +643,13 @@ async function listSessions(workingDirectory) {
|
|
|
643
643
|
return [];
|
|
644
644
|
}
|
|
645
645
|
}
|
|
646
|
+
async function listRecentSessions(limit = 200) {
|
|
647
|
+
try {
|
|
648
|
+
return await sdkListSessions({ limit });
|
|
649
|
+
} catch {
|
|
650
|
+
return [];
|
|
651
|
+
}
|
|
652
|
+
}
|
|
646
653
|
var TOOL_RESULT_PREVIEW_BYTES = 2048;
|
|
647
654
|
var ANSI_RE = /\u001b\[\d*m/g;
|
|
648
655
|
function stripAnsi(text) {
|
|
@@ -1175,7 +1182,6 @@ var PunkConnection = class {
|
|
|
1175
1182
|
}
|
|
1176
1183
|
}, 50 * 60 * 1e3);
|
|
1177
1184
|
this.attachSocketHandlers();
|
|
1178
|
-
this.attachSignalHandlers();
|
|
1179
1185
|
}
|
|
1180
1186
|
disconnect() {
|
|
1181
1187
|
this.cleanup();
|
|
@@ -1242,6 +1248,9 @@ var PunkConnection = class {
|
|
|
1242
1248
|
socket.on("list-sessions", (msg) => {
|
|
1243
1249
|
if (msg.type === "list-sessions") this.handleListSessions(msg);
|
|
1244
1250
|
});
|
|
1251
|
+
socket.on("session:list-recent", (msg) => {
|
|
1252
|
+
if (msg.type === "session:list-recent") void this.handleListRecentSessions(msg);
|
|
1253
|
+
});
|
|
1245
1254
|
socket.on("get-context", (msg) => {
|
|
1246
1255
|
if (msg.type === "get-context") this.handleGetContext(msg);
|
|
1247
1256
|
});
|
|
@@ -1273,18 +1282,6 @@ var PunkConnection = class {
|
|
|
1273
1282
|
this.resolvePermission(msg.requestId, msg.toolUseId, msg.allow, msg.answers, msg.feedback, msg.permissionMode);
|
|
1274
1283
|
});
|
|
1275
1284
|
}
|
|
1276
|
-
attachSignalHandlers() {
|
|
1277
|
-
const onShutdown = () => {
|
|
1278
|
-
this.store.getState().addActivity({ icon: "\u25CF", message: "Shutting down..." });
|
|
1279
|
-
this.cleanup();
|
|
1280
|
-
process.exit(0);
|
|
1281
|
-
};
|
|
1282
|
-
process.on("SIGINT", onShutdown);
|
|
1283
|
-
process.on("SIGTERM", onShutdown);
|
|
1284
|
-
process.on("SIGCONT", () => {
|
|
1285
|
-
this.reconnect();
|
|
1286
|
-
});
|
|
1287
|
-
}
|
|
1288
1285
|
send(event, msg) {
|
|
1289
1286
|
if (!this.socket.connected) return;
|
|
1290
1287
|
this.socket.emit(event, msg);
|
|
@@ -1385,6 +1382,10 @@ var PunkConnection = class {
|
|
|
1385
1382
|
this.store.getState().addActivity({ icon: "\u2717", message: "Session cancelled", sessionId: id });
|
|
1386
1383
|
}
|
|
1387
1384
|
}
|
|
1385
|
+
async handleListRecentSessions(msg) {
|
|
1386
|
+
const sessions = await listRecentSessions(msg.limit);
|
|
1387
|
+
this.send("response", { type: "session:recent", sessions, requestId: msg.id });
|
|
1388
|
+
}
|
|
1388
1389
|
async handleListSessions(msg) {
|
|
1389
1390
|
const workingDirectory = msg.workingDirectory ?? this.defaultCwd;
|
|
1390
1391
|
const sessions = await listSessions(workingDirectory);
|
|
@@ -1592,9 +1593,11 @@ var createPunkStore = (server) => createStore((set) => ({
|
|
|
1592
1593
|
return { sessions: { ...s.sessions, [id]: { ...existing, ...updates } } };
|
|
1593
1594
|
}),
|
|
1594
1595
|
removeSession: (id) => set((s) => {
|
|
1595
|
-
const
|
|
1596
|
-
delete
|
|
1597
|
-
|
|
1596
|
+
const sessions = { ...s.sessions };
|
|
1597
|
+
delete sessions[id];
|
|
1598
|
+
const sessionProjects = { ...s.sessionProjects };
|
|
1599
|
+
delete sessionProjects[id];
|
|
1600
|
+
return { sessions, sessionProjects };
|
|
1598
1601
|
}),
|
|
1599
1602
|
addActivity: (entry) => set((s) => ({
|
|
1600
1603
|
activityLog: [
|
package/dist/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
refreshIdToken,
|
|
9
9
|
signIn,
|
|
10
10
|
version
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-2M6GXAAB.js";
|
|
12
12
|
|
|
13
13
|
// src/cli.ts
|
|
14
14
|
import { program } from "commander";
|
|
@@ -128,23 +128,32 @@ async function runHeadless(server, idToken, options) {
|
|
|
128
128
|
}
|
|
129
129
|
}
|
|
130
130
|
});
|
|
131
|
-
new PunkConnection(server, idToken, options, store);
|
|
131
|
+
const connection = new PunkConnection(server, idToken, options, store);
|
|
132
|
+
const shutdown = () => {
|
|
133
|
+
connection.disconnect();
|
|
134
|
+
process.exit(0);
|
|
135
|
+
};
|
|
136
|
+
process.on("SIGINT", shutdown);
|
|
137
|
+
process.on("SIGTERM", shutdown);
|
|
132
138
|
await new Promise(() => {
|
|
133
139
|
});
|
|
134
140
|
}
|
|
135
141
|
async function runTui(server, options) {
|
|
136
142
|
const { render } = await import("ink");
|
|
137
143
|
const { createElement } = await import("react");
|
|
138
|
-
const { App } = await import("./App-
|
|
144
|
+
const { App } = await import("./App-5XKHGVXM.js");
|
|
139
145
|
const idToken = options.token ? options.token : void 0;
|
|
140
146
|
process.stdout.write("\x1B[?1049h");
|
|
141
147
|
process.stdout.write("\x1B[H");
|
|
142
|
-
const { waitUntilExit } = render(
|
|
148
|
+
const { waitUntilExit, unmount } = render(
|
|
143
149
|
createElement(App, { server, idToken, options })
|
|
144
150
|
);
|
|
151
|
+
const onSigterm = () => unmount();
|
|
152
|
+
process.once("SIGTERM", onSigterm);
|
|
145
153
|
try {
|
|
146
154
|
await waitUntilExit();
|
|
147
155
|
} finally {
|
|
156
|
+
process.removeListener("SIGTERM", onSigterm);
|
|
148
157
|
process.stdout.write("\x1B[?1049l");
|
|
149
158
|
}
|
|
150
159
|
}
|