@punkcode/cli 0.1.20 → 0.1.22
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-4FFAG2HK.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,6 +282,8 @@ function Dashboard({ store, connection, overlay }) {
|
|
|
284
282
|
connection?.disconnect();
|
|
285
283
|
exit();
|
|
286
284
|
}
|
|
285
|
+
});
|
|
286
|
+
useInput2((input, key) => {
|
|
287
287
|
if (input === "r") connection?.reconnect();
|
|
288
288
|
if (input === "c" && !key.ctrl) {
|
|
289
289
|
store.getState().clearActivity();
|
|
@@ -327,9 +327,8 @@ function Dashboard({ store, connection, overlay }) {
|
|
|
327
327
|
setSelectedIdx(next);
|
|
328
328
|
}
|
|
329
329
|
}
|
|
330
|
-
});
|
|
330
|
+
}, { isActive: !overlay });
|
|
331
331
|
const sessionList = Object.values(sessions);
|
|
332
|
-
const uptime = connectedAt ? formatDuration(now - connectedAt) : "-";
|
|
333
332
|
const boxWidth = termWidth - 2;
|
|
334
333
|
const col = getColumns(termWidth);
|
|
335
334
|
const headerHeight = 8;
|
|
@@ -354,7 +353,7 @@ function Dashboard({ store, connection, overlay }) {
|
|
|
354
353
|
/* @__PURE__ */ jsx2(Text2, { children: stripProtocol(server) })
|
|
355
354
|
] })
|
|
356
355
|
] }),
|
|
357
|
-
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 })
|
|
358
357
|
] })
|
|
359
358
|
) : (
|
|
360
359
|
/* Full header when connected */
|
|
@@ -372,10 +371,6 @@ function Dashboard({ store, connection, overlay }) {
|
|
|
372
371
|
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Status: ".padEnd(12) }),
|
|
373
372
|
/* @__PURE__ */ jsx2(StatusIndicator, { status: connectionStatus, error: connectionError })
|
|
374
373
|
] }),
|
|
375
|
-
/* @__PURE__ */ jsxs2(Box2, { children: [
|
|
376
|
-
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Uptime: ".padEnd(12) }),
|
|
377
|
-
/* @__PURE__ */ jsx2(Text2, { children: uptime })
|
|
378
|
-
] }),
|
|
379
374
|
deviceInfo && /* @__PURE__ */ jsxs2(Box2, { children: [
|
|
380
375
|
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: "Device: ".padEnd(12) }),
|
|
381
376
|
/* @__PURE__ */ jsx2(Text2, { children: deviceInfo.name })
|
|
@@ -445,7 +440,7 @@ function Dashboard({ store, connection, overlay }) {
|
|
|
445
440
|
/* @__PURE__ */ jsx2(Text2, { dimColor: true, children: " details" })
|
|
446
441
|
] })
|
|
447
442
|
] }) }),
|
|
448
|
-
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 })
|
|
449
444
|
] })
|
|
450
445
|
),
|
|
451
446
|
!overlay && /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", marginX: 1, marginTop: 1, children: [
|
|
@@ -464,13 +459,13 @@ function Dashboard({ store, connection, overlay }) {
|
|
|
464
459
|
"ID".padEnd(col.id),
|
|
465
460
|
"PROJECT".padEnd(col.project),
|
|
466
461
|
"STATUS".padEnd(col.status),
|
|
467
|
-
"
|
|
462
|
+
"RUNNING".padEnd(col.started),
|
|
468
463
|
col.showExtras ? "MODEL".padEnd(col.model) + "EFFORT" : ""
|
|
469
464
|
] }) }),
|
|
470
465
|
sessionList.length === 0 ? /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
|
|
471
466
|
"\u25CB",
|
|
472
467
|
" Waiting for sessions from the Punk app..."
|
|
473
|
-
] }) : sessionList.map((session) => /* @__PURE__ */ jsx2(SessionRow, { session,
|
|
468
|
+
] }) : sessionList.map((session) => /* @__PURE__ */ jsx2(SessionRow, { session, col }, session.requestId))
|
|
474
469
|
]
|
|
475
470
|
}
|
|
476
471
|
)
|
|
@@ -631,10 +626,17 @@ function StatusIndicator({ status, error }) {
|
|
|
631
626
|
" Disconnected"
|
|
632
627
|
] });
|
|
633
628
|
}
|
|
634
|
-
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]);
|
|
635
637
|
const id = session.requestId.slice(0, col.id - 2);
|
|
636
638
|
const project = session.workingDirectory ? session.workingDirectory.split("/").pop() ?? "" : "";
|
|
637
|
-
const started = formatDuration(
|
|
639
|
+
const started = formatDuration(elapsed);
|
|
638
640
|
return /* @__PURE__ */ jsxs2(Box2, { children: [
|
|
639
641
|
/* @__PURE__ */ jsxs2(Text2, { children: [
|
|
640
642
|
id.padEnd(col.id),
|
|
@@ -751,7 +753,7 @@ function formatDuration(ms) {
|
|
|
751
753
|
const seconds = Math.floor(ms / 1e3);
|
|
752
754
|
if (seconds < 60) return `${seconds}s`;
|
|
753
755
|
const minutes = Math.floor(seconds / 60);
|
|
754
|
-
if (minutes < 60) return `${minutes}m
|
|
756
|
+
if (minutes < 60) return `${minutes}m`;
|
|
755
757
|
const hours = Math.floor(minutes / 60);
|
|
756
758
|
return `${hours}h ${minutes % 60}m`;
|
|
757
759
|
}
|
|
@@ -794,6 +796,15 @@ function App({ server, idToken, options }) {
|
|
|
794
796
|
connectionRef.current?.disconnect();
|
|
795
797
|
};
|
|
796
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
|
+
}, []);
|
|
797
808
|
const loginOverlay = screen === "login" ? /* @__PURE__ */ jsx3(LoginDialog, { store, server }) : void 0;
|
|
798
809
|
return /* @__PURE__ */ jsx3(
|
|
799
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.22";
|
|
5
5
|
|
|
6
6
|
// src/lib/auth.ts
|
|
7
7
|
import fs from "fs";
|
|
@@ -1175,7 +1175,6 @@ var PunkConnection = class {
|
|
|
1175
1175
|
}
|
|
1176
1176
|
}, 50 * 60 * 1e3);
|
|
1177
1177
|
this.attachSocketHandlers();
|
|
1178
|
-
this.attachSignalHandlers();
|
|
1179
1178
|
}
|
|
1180
1179
|
disconnect() {
|
|
1181
1180
|
this.cleanup();
|
|
@@ -1273,18 +1272,6 @@ var PunkConnection = class {
|
|
|
1273
1272
|
this.resolvePermission(msg.requestId, msg.toolUseId, msg.allow, msg.answers, msg.feedback, msg.permissionMode);
|
|
1274
1273
|
});
|
|
1275
1274
|
}
|
|
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
1275
|
send(event, msg) {
|
|
1289
1276
|
if (!this.socket.connected) return;
|
|
1290
1277
|
this.socket.emit(event, msg);
|
|
@@ -1592,9 +1579,11 @@ var createPunkStore = (server) => createStore((set) => ({
|
|
|
1592
1579
|
return { sessions: { ...s.sessions, [id]: { ...existing, ...updates } } };
|
|
1593
1580
|
}),
|
|
1594
1581
|
removeSession: (id) => set((s) => {
|
|
1595
|
-
const
|
|
1596
|
-
delete
|
|
1597
|
-
|
|
1582
|
+
const sessions = { ...s.sessions };
|
|
1583
|
+
delete sessions[id];
|
|
1584
|
+
const sessionProjects = { ...s.sessionProjects };
|
|
1585
|
+
delete sessionProjects[id];
|
|
1586
|
+
return { sessions, sessionProjects };
|
|
1598
1587
|
}),
|
|
1599
1588
|
addActivity: (entry) => set((s) => ({
|
|
1600
1589
|
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-4FFAG2HK.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-RF23NIE6.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
|
}
|