codex-devtools 0.1.2 → 0.1.5
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 +11 -1
- package/bin/codex-devtools.cjs +73 -11
- package/dist-electron/main/index.cjs +20 -0
- package/dist-electron/main/standalone.cjs +2 -1
- package/out/renderer/assets/{index-r_pK0Xle.css → index-BTmVA30y.css} +8 -8
- package/out/renderer/assets/{index-CR8-JZrV.js → index-C1DUQHyp.js} +12 -2
- package/out/renderer/index.html +3 -3
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -38,7 +38,17 @@ npx codex-devtools
|
|
|
38
38
|
bunx codex-devtools
|
|
39
39
|
```
|
|
40
40
|
|
|
41
|
-
This
|
|
41
|
+
This launches the native Electron app window.
|
|
42
|
+
|
|
43
|
+
To run web/HTTP mode explicitly:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
npx codex-devtools --web
|
|
47
|
+
# or
|
|
48
|
+
bunx codex-devtools --web
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Standalone mode serves at `http://localhost:3456`.
|
|
42
52
|
|
|
43
53
|
## Standalone mode
|
|
44
54
|
|
package/bin/codex-devtools.cjs
CHANGED
|
@@ -3,21 +3,83 @@
|
|
|
3
3
|
|
|
4
4
|
const { existsSync } = require('node:fs');
|
|
5
5
|
const { join } = require('node:path');
|
|
6
|
+
const { spawn } = require('node:child_process');
|
|
6
7
|
|
|
7
|
-
const
|
|
8
|
+
const APP_ROOT = join(__dirname, '..');
|
|
9
|
+
const ELECTRON_ENTRY = join(APP_ROOT, 'dist-electron', 'main', 'index.cjs');
|
|
10
|
+
const STANDALONE_ENTRY = join(APP_ROOT, 'dist-electron', 'main', 'standalone.cjs');
|
|
8
11
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
'[codex-devtools] Missing standalone bundle. Reinstall package or run a version that includes dist-electron output.',
|
|
12
|
-
);
|
|
13
|
-
process.exit(1);
|
|
12
|
+
function hasArg(flag) {
|
|
13
|
+
return process.argv.includes(flag);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
function runStandalone() {
|
|
17
|
+
if (!existsSync(STANDALONE_ENTRY)) {
|
|
18
|
+
console.error('[codex-devtools] Missing standalone bundle. Reinstall package and try again.');
|
|
19
|
+
process.exit(1);
|
|
20
|
+
}
|
|
17
21
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
const standaloneModule = require(STANDALONE_ENTRY);
|
|
23
|
+
if (typeof standaloneModule.startStandaloneCli !== 'function') {
|
|
24
|
+
console.error('[codex-devtools] Invalid standalone entrypoint: startStandaloneCli export not found.');
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
standaloneModule.startStandaloneCli();
|
|
21
29
|
}
|
|
22
30
|
|
|
23
|
-
|
|
31
|
+
function runDesktop() {
|
|
32
|
+
if (!existsSync(ELECTRON_ENTRY)) {
|
|
33
|
+
console.error('[codex-devtools] Missing Electron bundle. Reinstall package and try again.');
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
let electronBinary;
|
|
38
|
+
try {
|
|
39
|
+
electronBinary = require('electron');
|
|
40
|
+
} catch (error) {
|
|
41
|
+
console.error(
|
|
42
|
+
'[codex-devtools] Electron runtime is not available. Reinstall package and ensure install scripts are enabled.',
|
|
43
|
+
);
|
|
44
|
+
if (error && error.message) {
|
|
45
|
+
console.error(`[codex-devtools] ${error.message}`);
|
|
46
|
+
}
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const forwardedArgs = process.argv.slice(2).filter((arg) => arg !== '--desktop');
|
|
51
|
+
const child = spawn(electronBinary, [APP_ROOT, ...forwardedArgs], {
|
|
52
|
+
stdio: 'inherit',
|
|
53
|
+
env: process.env,
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
child.on('error', (error) => {
|
|
57
|
+
console.error('[codex-devtools] Failed to launch Electron.', error);
|
|
58
|
+
process.exit(1);
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
child.on('exit', (code, signal) => {
|
|
62
|
+
if (signal) {
|
|
63
|
+
process.kill(process.pid, signal);
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
process.exit(code ?? 0);
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (hasArg('--help') || hasArg('-h')) {
|
|
72
|
+
console.log('codex-devtools');
|
|
73
|
+
console.log('');
|
|
74
|
+
console.log('Usage:');
|
|
75
|
+
console.log(' codex-devtools Launch Electron desktop app (default)');
|
|
76
|
+
console.log(' codex-devtools --web Run standalone HTTP mode');
|
|
77
|
+
console.log(' codex-devtools --desktop Force desktop mode');
|
|
78
|
+
process.exit(0);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (hasArg('--web') || hasArg('--standalone')) {
|
|
82
|
+
runStandalone();
|
|
83
|
+
} else {
|
|
84
|
+
runDesktop();
|
|
85
|
+
}
|
|
@@ -164,9 +164,21 @@ const removeIpcHandlers = (targetIpcMain) => {
|
|
|
164
164
|
logger$1.info("All handlers removed");
|
|
165
165
|
};
|
|
166
166
|
const logger = CodexServiceContext.createLogger("Main");
|
|
167
|
+
const APP_DISPLAY_NAME = "codex-devtools";
|
|
167
168
|
let mainWindow = null;
|
|
168
169
|
let serviceContext = null;
|
|
169
170
|
let removeFileChangeListener = null;
|
|
171
|
+
function resolveAppIconPath() {
|
|
172
|
+
const candidates = [
|
|
173
|
+
path.join(process.cwd(), "resources/logo.png"),
|
|
174
|
+
path.join(process.cwd(), "resources/icon.png"),
|
|
175
|
+
path.join(__dirname, "../../resources/logo.png"),
|
|
176
|
+
path.join(__dirname, "../../resources/icon.png"),
|
|
177
|
+
path.join(process.resourcesPath, "resources/logo.png"),
|
|
178
|
+
path.join(process.resourcesPath, "resources/icon.png")
|
|
179
|
+
];
|
|
180
|
+
return candidates.find((candidate) => fs.existsSync(candidate));
|
|
181
|
+
}
|
|
170
182
|
function getRendererIndexPath() {
|
|
171
183
|
const candidates = [
|
|
172
184
|
path.join(__dirname, "../../out/renderer/index.html"),
|
|
@@ -175,9 +187,12 @@ function getRendererIndexPath() {
|
|
|
175
187
|
return candidates.find((candidate) => fs.existsSync(candidate)) ?? candidates[0];
|
|
176
188
|
}
|
|
177
189
|
const createWindow = () => {
|
|
190
|
+
const iconPath = resolveAppIconPath();
|
|
178
191
|
const window = new electron.BrowserWindow({
|
|
192
|
+
title: APP_DISPLAY_NAME,
|
|
179
193
|
width: 1200,
|
|
180
194
|
height: 800,
|
|
195
|
+
...iconPath ? { icon: iconPath } : {},
|
|
181
196
|
webPreferences: {
|
|
182
197
|
preload: path.join(__dirname, "../preload/index.cjs"),
|
|
183
198
|
contextIsolation: true,
|
|
@@ -224,7 +239,12 @@ function disposeServices() {
|
|
|
224
239
|
serviceContext = null;
|
|
225
240
|
}
|
|
226
241
|
}
|
|
242
|
+
electron.app.setName(APP_DISPLAY_NAME);
|
|
227
243
|
void electron.app.whenReady().then(() => {
|
|
244
|
+
const iconPath = resolveAppIconPath();
|
|
245
|
+
if (iconPath && process.platform === "darwin" && electron.app.dock) {
|
|
246
|
+
electron.app.dock.setIcon(iconPath);
|
|
247
|
+
}
|
|
228
248
|
initializeServices();
|
|
229
249
|
mainWindow = createWindow();
|
|
230
250
|
electron.app.on("activate", () => {
|
|
@@ -187,7 +187,8 @@ const logger = CodexServiceContext.createLogger("Standalone");
|
|
|
187
187
|
const __filename$1 = node_url.fileURLToPath(require("url").pathToFileURL(__filename).href);
|
|
188
188
|
const __dirname$1 = path.dirname(__filename$1);
|
|
189
189
|
const createStandaloneServer = async (options = {}) => {
|
|
190
|
-
const
|
|
190
|
+
const enableHttpLogs = process.env.CODEX_DEVTOOLS_HTTP_LOGS === "1";
|
|
191
|
+
const app = Fastify({ logger: enableHttpLogs });
|
|
191
192
|
const serviceContext = new CodexServiceContext.CodexServiceContext({
|
|
192
193
|
sessionsPath: options.sessionsPath ?? process.env.CODEX_SESSIONS_PATH,
|
|
193
194
|
configPath: options.configPath
|
|
@@ -555,6 +555,9 @@ video {
|
|
|
555
555
|
max-width: 1536px;
|
|
556
556
|
}
|
|
557
557
|
}
|
|
558
|
+
.visible {
|
|
559
|
+
visibility: visible;
|
|
560
|
+
}
|
|
558
561
|
.static {
|
|
559
562
|
position: static;
|
|
560
563
|
}
|
|
@@ -573,14 +576,6 @@ video {
|
|
|
573
576
|
.transform {
|
|
574
577
|
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
|
|
575
578
|
}
|
|
576
|
-
.bg-slate-950 {
|
|
577
|
-
--tw-bg-opacity: 1;
|
|
578
|
-
background-color: rgb(2 6 23 / var(--tw-bg-opacity, 1));
|
|
579
|
-
}
|
|
580
|
-
.text-slate-100 {
|
|
581
|
-
--tw-text-opacity: 1;
|
|
582
|
-
color: rgb(241 245 249 / var(--tw-text-opacity, 1));
|
|
583
|
-
}
|
|
584
579
|
.filter {
|
|
585
580
|
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
|
|
586
581
|
}
|
|
@@ -1230,6 +1225,11 @@ select {
|
|
|
1230
1225
|
padding: 10px 12px;
|
|
1231
1226
|
}
|
|
1232
1227
|
|
|
1228
|
+
:root.light .chat-user-bubble {
|
|
1229
|
+
border-color: rgba(37, 99, 235, 0.24);
|
|
1230
|
+
background: rgba(37, 99, 235, 0.1);
|
|
1231
|
+
}
|
|
1232
|
+
|
|
1233
1233
|
.chat-attachments {
|
|
1234
1234
|
display: grid;
|
|
1235
1235
|
gap: 8px;
|
|
@@ -7734,7 +7734,7 @@ const createAppStore = (client2 = api) => create()((...args) => ({
|
|
|
7734
7734
|
}));
|
|
7735
7735
|
const useAppStore = createAppStore();
|
|
7736
7736
|
const REFRESH_DEBOUNCE_MS = 120;
|
|
7737
|
-
const FALLBACK_POLL_INTERVAL_MS =
|
|
7737
|
+
const FALLBACK_POLL_INTERVAL_MS = 15e3;
|
|
7738
7738
|
function initializeEventListeners(store = useAppStore, client2 = api) {
|
|
7739
7739
|
let refreshTimer = null;
|
|
7740
7740
|
let pollTimer = null;
|
|
@@ -7761,6 +7761,9 @@ function initializeEventListeners(store = useAppStore, client2 = api) {
|
|
|
7761
7761
|
}, REFRESH_DEBOUNCE_MS);
|
|
7762
7762
|
});
|
|
7763
7763
|
const runFallbackRefresh = () => {
|
|
7764
|
+
if (typeof document !== "undefined" && document.visibilityState !== "visible") {
|
|
7765
|
+
return;
|
|
7766
|
+
}
|
|
7764
7767
|
if (polling) {
|
|
7765
7768
|
return;
|
|
7766
7769
|
}
|
|
@@ -11564,6 +11567,7 @@ const DateGroupedSessions = () => {
|
|
|
11564
11567
|
const {
|
|
11565
11568
|
sessions,
|
|
11566
11569
|
sessionsLoading,
|
|
11570
|
+
activeProjectCwd,
|
|
11567
11571
|
activeSessionId,
|
|
11568
11572
|
sessionPreviews,
|
|
11569
11573
|
sessionUpdateBadges,
|
|
@@ -11572,6 +11576,7 @@ const DateGroupedSessions = () => {
|
|
|
11572
11576
|
} = useAppStore((state) => ({
|
|
11573
11577
|
sessions: state.sessions,
|
|
11574
11578
|
sessionsLoading: state.sessionsLoading,
|
|
11579
|
+
activeProjectCwd: state.activeProjectCwd,
|
|
11575
11580
|
activeSessionId: state.activeSessionId,
|
|
11576
11581
|
sessionPreviews: state.sessionPreviews,
|
|
11577
11582
|
sessionUpdateBadges: state.sessionUpdateBadges,
|
|
@@ -11594,7 +11599,7 @@ const DateGroupedSessions = () => {
|
|
|
11594
11599
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sidebar-loading", children: "Loading sessions..." });
|
|
11595
11600
|
}
|
|
11596
11601
|
if (groups.length === 0) {
|
|
11597
|
-
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sidebar-empty", children: "No sessions found for this project." });
|
|
11602
|
+
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "sidebar-empty", children: activeProjectCwd ? "No sessions found for this project." : "Select a project to load sessions." });
|
|
11598
11603
|
}
|
|
11599
11604
|
return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "session-groups", children: groups.map((group) => /* @__PURE__ */ jsxRuntimeExports.jsxs("section", { className: "session-group", children: [
|
|
11600
11605
|
/* @__PURE__ */ jsxRuntimeExports.jsx("h2", { className: "session-group-title", children: group.label }),
|
|
@@ -11679,6 +11684,11 @@ const Sidebar = () => {
|
|
|
11679
11684
|
}
|
|
11680
11685
|
)
|
|
11681
11686
|
] }),
|
|
11687
|
+
!projectsLoading && projects.length === 0 ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "sidebar-empty", children: [
|
|
11688
|
+
"No projects discovered. Set ",
|
|
11689
|
+
/* @__PURE__ */ jsxRuntimeExports.jsx("code", { children: "CODEX_SESSIONS_PATH" }),
|
|
11690
|
+
" and restart."
|
|
11691
|
+
] }) : null,
|
|
11682
11692
|
/* @__PURE__ */ jsxRuntimeExports.jsx(DateGroupedSessions, {})
|
|
11683
11693
|
] });
|
|
11684
11694
|
};
|
package/out/renderer/index.html
CHANGED
|
@@ -7,10 +7,10 @@
|
|
|
7
7
|
<link rel="icon" type="image/png" sizes="32x32" href="./assets/32x32-DQgygEFU.png" />
|
|
8
8
|
<link rel="icon" type="image/png" sizes="16x16" href="./assets/16x16-B2_QkmoB.png" />
|
|
9
9
|
<title>codex-devtools</title>
|
|
10
|
-
<script type="module" crossorigin src="./assets/index-
|
|
11
|
-
<link rel="stylesheet" crossorigin href="./assets/index-
|
|
10
|
+
<script type="module" crossorigin src="./assets/index-C1DUQHyp.js"></script>
|
|
11
|
+
<link rel="stylesheet" crossorigin href="./assets/index-BTmVA30y.css">
|
|
12
12
|
</head>
|
|
13
|
-
<body
|
|
13
|
+
<body>
|
|
14
14
|
<div id="root">
|
|
15
15
|
<div style="padding: 16px; font: 500 14px/1.4 system-ui, -apple-system, Segoe UI, sans-serif;">
|
|
16
16
|
Loading codex-devtools...
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codex-devtools",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.5",
|
|
5
5
|
"description": "Desktop app for inspecting Codex session data",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": {
|
|
@@ -27,7 +27,8 @@
|
|
|
27
27
|
"README.md"
|
|
28
28
|
],
|
|
29
29
|
"scripts": {
|
|
30
|
-
"dev": "
|
|
30
|
+
"dev": "node scripts/dev.mjs",
|
|
31
|
+
"dev:raw": "electron-vite dev",
|
|
31
32
|
"build": "electron-vite build",
|
|
32
33
|
"dist": "electron-builder --mac --win --linux --publish never",
|
|
33
34
|
"dist:mac": "electron-builder --mac --publish never",
|
|
@@ -46,6 +47,7 @@
|
|
|
46
47
|
"@fastify/static": "^9.0.0",
|
|
47
48
|
"@tanstack/react-virtual": "^3.10.8",
|
|
48
49
|
"date-fns": "^3.6.0",
|
|
50
|
+
"electron": "~40.3.0",
|
|
49
51
|
"fastify": "^5.7.4",
|
|
50
52
|
"lucide-react": "^0.562.0",
|
|
51
53
|
"react": "^18.3.1",
|
|
@@ -59,7 +61,6 @@
|
|
|
59
61
|
"@types/react-dom": "^18.3.0",
|
|
60
62
|
"@vitejs/plugin-react": "^4.3.1",
|
|
61
63
|
"autoprefixer": "^10.4.17",
|
|
62
|
-
"electron": "~40.3.0",
|
|
63
64
|
"electron-builder": "^25.1.8",
|
|
64
65
|
"electron-vite": "^2.3.0",
|
|
65
66
|
"eslint": "^9.39.2",
|