codex-lens 0.1.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/src/global.css ADDED
@@ -0,0 +1,521 @@
1
+ :root {
2
+ --bg-primary: #1e1e1e;
3
+ --bg-secondary: #252526;
4
+ --bg-tertiary: #2d2d30;
5
+ --text-primary: #cccccc;
6
+ --text-secondary: #858585;
7
+ --border-color: #3c3c3c;
8
+ --accent-color: #007acc;
9
+ --accent-hover: #1e8ad2;
10
+ --diff-add-bg: #2d4a2d;
11
+ --diff-add-text: #89d185;
12
+ --diff-remove-bg: #5a2d2d;
13
+ --diff-remove-text: #f48771;
14
+ --font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
15
+ --font-mono: 'SF Mono', 'Fira Code', 'Consolas', monospace;
16
+ }
17
+
18
+ * {
19
+ margin: 0;
20
+ padding: 0;
21
+ box-sizing: border-box;
22
+ }
23
+
24
+ html, body, #root {
25
+ height: 100%;
26
+ width: 100%;
27
+ overflow: hidden;
28
+ }
29
+
30
+ body {
31
+ font-family: var(--font-family);
32
+ background-color: var(--bg-primary);
33
+ color: var(--text-primary);
34
+ font-size: 14px;
35
+ line-height: 1.5;
36
+ }
37
+
38
+ .app-container {
39
+ display: flex;
40
+ height: 100vh;
41
+ width: 100vw;
42
+ }
43
+
44
+ .panel {
45
+ display: flex;
46
+ flex-direction: column;
47
+ overflow: hidden;
48
+ border-right: 1px solid var(--border-color);
49
+ }
50
+
51
+ .panel:last-child {
52
+ border-right: none;
53
+ }
54
+
55
+ .panel-header {
56
+ padding: 8px 12px;
57
+ background: var(--bg-tertiary);
58
+ border-bottom: 1px solid var(--border-color);
59
+ font-weight: 600;
60
+ font-size: 12px;
61
+ text-transform: uppercase;
62
+ color: var(--text-secondary);
63
+ }
64
+
65
+ .panel-content {
66
+ flex: 1;
67
+ overflow: auto;
68
+ }
69
+
70
+ .file-tree {
71
+ padding: 8px;
72
+ }
73
+
74
+ .file-item {
75
+ padding: 4px 8px;
76
+ cursor: pointer;
77
+ border-radius: 3px;
78
+ display: flex;
79
+ align-items: center;
80
+ gap: 6px;
81
+ }
82
+
83
+ .file-item:hover {
84
+ background: var(--bg-tertiary);
85
+ }
86
+
87
+ .file-item.active {
88
+ background: var(--accent-color);
89
+ }
90
+
91
+ .file-icon {
92
+ width: 16px;
93
+ height: 16px;
94
+ }
95
+
96
+ .diff-line {
97
+ font-family: var(--font-mono);
98
+ font-size: 13px;
99
+ padding: 2px 12px;
100
+ white-space: pre;
101
+ }
102
+
103
+ .diff-line.added {
104
+ background: var(--diff-add-bg);
105
+ color: var(--diff-add-text);
106
+ }
107
+
108
+ .diff-line.removed {
109
+ background: var(--diff-remove-bg);
110
+ color: var(--diff-remove-text);
111
+ }
112
+
113
+ .diff-line::before {
114
+ display: inline-block;
115
+ width: 16px;
116
+ margin-right: 8px;
117
+ text-align: center;
118
+ font-weight: bold;
119
+ }
120
+
121
+ .diff-line.added::before {
122
+ content: '+';
123
+ }
124
+
125
+ .diff-line.removed::before {
126
+ content: '-';
127
+ }
128
+
129
+ .chat-message {
130
+ padding: 8px 12px;
131
+ margin: 4px 8px;
132
+ border-radius: 8px;
133
+ max-width: 85%;
134
+ }
135
+
136
+ .chat-message.user {
137
+ background: var(--accent-color);
138
+ color: white;
139
+ margin-left: auto;
140
+ }
141
+
142
+ .chat-message.codex {
143
+ background: var(--bg-tertiary);
144
+ color: var(--text-primary);
145
+ }
146
+
147
+ .chat-input-container {
148
+ padding: 12px;
149
+ border-top: 1px solid var(--border-color);
150
+ background: var(--bg-secondary);
151
+ }
152
+
153
+ .chat-input {
154
+ width: 100%;
155
+ padding: 8px 12px;
156
+ background: var(--bg-primary);
157
+ border: 1px solid var(--border-color);
158
+ border-radius: 4px;
159
+ color: var(--text-primary);
160
+ font-family: var(--font-family);
161
+ resize: none;
162
+ }
163
+
164
+ .chat-input:focus {
165
+ outline: none;
166
+ border-color: var(--accent-color);
167
+ }
168
+
169
+ ::-webkit-scrollbar {
170
+ width: 10px;
171
+ height: 10px;
172
+ }
173
+
174
+ ::-webkit-scrollbar-track {
175
+ background: var(--bg-secondary);
176
+ }
177
+
178
+ ::-webkit-scrollbar-thumb {
179
+ background: var(--border-color);
180
+ border-radius: 5px;
181
+ }
182
+
183
+ ::-webkit-scrollbar-thumb:hover {
184
+ background: var(--text-secondary);
185
+ }
186
+
187
+ .ws-status {
188
+ display: inline-block;
189
+ width: 8px;
190
+ height: 8px;
191
+ border-radius: 50%;
192
+ margin-left: 8px;
193
+ }
194
+
195
+ .ws-status.connected {
196
+ background: #0dbc79;
197
+ }
198
+
199
+ .ws-status.disconnected {
200
+ background: #cd3131;
201
+ }
202
+
203
+ .version-info {
204
+ display: flex;
205
+ align-items: center;
206
+ gap: 8px;
207
+ margin-left: auto;
208
+ }
209
+
210
+ .version-number {
211
+ font-size: 11px;
212
+ color: var(--text-secondary);
213
+ font-weight: normal;
214
+ }
215
+
216
+ .update-badge {
217
+ font-size: 10px;
218
+ padding: 2px 6px;
219
+ background: #d9534f;
220
+ color: white;
221
+ border-radius: 3px;
222
+ cursor: pointer;
223
+ }
224
+
225
+ .update-badge:hover {
226
+ background: #c9302c;
227
+ }
228
+
229
+ .terminal-wrapper {
230
+ flex: 1;
231
+ overflow: hidden;
232
+ min-height: 0;
233
+ }
234
+
235
+ .left-panel {
236
+ width: 250px;
237
+ flex-shrink: 0;
238
+ }
239
+
240
+ .middle-panel {
241
+ flex: 1;
242
+ min-width: 300px;
243
+ }
244
+
245
+ .right-panel {
246
+ width: 40%;
247
+ min-width: 300px;
248
+ max-width: 60%;
249
+ }
250
+
251
+ .section {
252
+ margin-bottom: 16px;
253
+ }
254
+
255
+ .section-title {
256
+ padding: 8px 12px 4px;
257
+ font-size: 11px;
258
+ font-weight: 600;
259
+ color: var(--text-secondary);
260
+ text-transform: uppercase;
261
+ }
262
+
263
+ .empty-state {
264
+ padding: 20px;
265
+ text-align: center;
266
+ color: var(--text-secondary);
267
+ font-size: 13px;
268
+ }
269
+
270
+ .code-panel {
271
+ font-family: var(--font-mono);
272
+ }
273
+
274
+ .code-content {
275
+ padding: 12px;
276
+ white-space: pre-wrap;
277
+ word-break: break-all;
278
+ }
279
+
280
+ .diff-container {
281
+ font-family: var(--font-mono);
282
+ font-size: 13px;
283
+ }
284
+
285
+ .tab-bar {
286
+ display: flex;
287
+ background: var(--bg-secondary);
288
+ border-bottom: 1px solid var(--border-color);
289
+ overflow-x: auto;
290
+ min-height: 36px;
291
+ }
292
+
293
+ .tab {
294
+ display: flex;
295
+ align-items: center;
296
+ gap: 8px;
297
+ padding: 8px 12px;
298
+ background: var(--bg-secondary);
299
+ border-right: 1px solid var(--border-color);
300
+ cursor: pointer;
301
+ min-width: 100px;
302
+ max-width: 200px;
303
+ font-size: 13px;
304
+ color: var(--text-secondary);
305
+ }
306
+
307
+ .tab:hover {
308
+ background: var(--bg-tertiary);
309
+ }
310
+
311
+ .tab.active {
312
+ background: var(--bg-primary);
313
+ color: var(--text-primary);
314
+ border-bottom: 2px solid var(--accent-color);
315
+ }
316
+
317
+ .tab-name {
318
+ flex: 1;
319
+ overflow: hidden;
320
+ text-overflow: ellipsis;
321
+ white-space: nowrap;
322
+ }
323
+
324
+ .tab-close {
325
+ background: none;
326
+ border: none;
327
+ color: var(--text-secondary);
328
+ font-size: 16px;
329
+ cursor: pointer;
330
+ padding: 0 4px;
331
+ border-radius: 3px;
332
+ line-height: 1;
333
+ }
334
+
335
+ .tab-close:hover {
336
+ background: rgba(255, 255, 255, 0.1);
337
+ color: var(--text-primary);
338
+ }
339
+
340
+ .context-menu {
341
+ position: fixed;
342
+ background: var(--bg-tertiary);
343
+ border: 1px solid var(--border-color);
344
+ border-radius: 4px;
345
+ padding: 4px 0;
346
+ min-width: 150px;
347
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
348
+ z-index: 1000;
349
+ }
350
+
351
+ .context-menu-item {
352
+ padding: 8px 16px;
353
+ cursor: pointer;
354
+ font-size: 13px;
355
+ color: var(--text-primary);
356
+ }
357
+
358
+ .context-menu-item:hover {
359
+ background: var(--accent-color);
360
+ }
361
+
362
+ .task-bar {
363
+ display: flex;
364
+ align-items: center;
365
+ justify-content: space-between;
366
+ padding: 8px 12px;
367
+ background: var(--bg-secondary);
368
+ border-bottom: 1px solid var(--border-color);
369
+ min-height: 44px;
370
+ }
371
+
372
+ .task-status {
373
+ display: flex;
374
+ align-items: center;
375
+ gap: 8px;
376
+ font-size: 13px;
377
+ font-weight: 500;
378
+ }
379
+
380
+ .task-status.idle {
381
+ color: var(--text-secondary);
382
+ }
383
+
384
+ .task-status.running {
385
+ color: var(--accent-color);
386
+ }
387
+
388
+ .task-status::before {
389
+ content: '';
390
+ display: inline-block;
391
+ width: 8px;
392
+ height: 8px;
393
+ border-radius: 50%;
394
+ }
395
+
396
+ .task-status.idle::before {
397
+ background: var(--text-secondary);
398
+ }
399
+
400
+ .task-status.running::before {
401
+ background: var(--accent-color);
402
+ animation: pulse 1.5s infinite;
403
+ }
404
+
405
+ @keyframes pulse {
406
+ 0%, 100% { opacity: 1; }
407
+ 50% { opacity: 0.5; }
408
+ }
409
+
410
+ .task-buttons {
411
+ display: flex;
412
+ gap: 8px;
413
+ }
414
+
415
+ .task-btn {
416
+ padding: 6px 12px;
417
+ border: none;
418
+ border-radius: 4px;
419
+ font-size: 12px;
420
+ font-weight: 500;
421
+ cursor: pointer;
422
+ transition: background 0.2s;
423
+ }
424
+
425
+ .task-btn-start {
426
+ background: var(--accent-color);
427
+ color: white;
428
+ }
429
+
430
+ .task-btn-start:hover {
431
+ background: var(--accent-hover);
432
+ }
433
+
434
+ .task-btn-rollback {
435
+ background: #d9534f;
436
+ color: white;
437
+ }
438
+
439
+ .task-btn-rollback:hover {
440
+ background: #c9302c;
441
+ }
442
+
443
+ .task-btn-complete {
444
+ background: #5cb85c;
445
+ color: white;
446
+ }
447
+
448
+ .task-btn-complete:hover {
449
+ background: #4cae4c;
450
+ }
451
+
452
+ .modal-overlay {
453
+ position: fixed;
454
+ top: 0;
455
+ left: 0;
456
+ right: 0;
457
+ bottom: 0;
458
+ background: rgba(0, 0, 0, 0.6);
459
+ display: flex;
460
+ align-items: center;
461
+ justify-content: center;
462
+ z-index: 2000;
463
+ }
464
+
465
+ .modal-content {
466
+ background: var(--bg-secondary);
467
+ border: 1px solid var(--border-color);
468
+ border-radius: 8px;
469
+ padding: 20px;
470
+ min-width: 320px;
471
+ max-width: 400px;
472
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
473
+ }
474
+
475
+ .modal-title {
476
+ font-size: 16px;
477
+ font-weight: 600;
478
+ margin-bottom: 12px;
479
+ color: var(--text-primary);
480
+ }
481
+
482
+ .modal-body {
483
+ font-size: 14px;
484
+ color: var(--text-secondary);
485
+ margin-bottom: 20px;
486
+ line-height: 1.6;
487
+ }
488
+
489
+ .modal-buttons {
490
+ display: flex;
491
+ justify-content: flex-end;
492
+ gap: 12px;
493
+ }
494
+
495
+ .modal-btn {
496
+ padding: 8px 16px;
497
+ border: none;
498
+ border-radius: 4px;
499
+ font-size: 13px;
500
+ font-weight: 500;
501
+ cursor: pointer;
502
+ transition: background 0.2s;
503
+ }
504
+
505
+ .modal-btn-cancel {
506
+ background: var(--bg-tertiary);
507
+ color: var(--text-primary);
508
+ }
509
+
510
+ .modal-btn-cancel:hover {
511
+ background: var(--border-color);
512
+ }
513
+
514
+ .modal-btn-danger {
515
+ background: #d9534f;
516
+ color: white;
517
+ }
518
+
519
+ .modal-btn-danger:hover {
520
+ background: #c9302c;
521
+ }
package/src/index.html ADDED
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html lang="zh-CN">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Codex Viewer</title>
7
+ </head>
8
+ <body>
9
+ <div id="root"></div>
10
+ <script type="module" src="/main.jsx"></script>
11
+ </body>
12
+ </html>
@@ -0,0 +1,126 @@
1
+ import { diffLines, diffWords, diffChars } from 'diff';
2
+
3
+ export function generateLineDiff(oldContent, newContent) {
4
+ if (!oldContent && !newContent) {
5
+ return [];
6
+ }
7
+
8
+ const oldLines = (oldContent || '').split('\n');
9
+ const newLines = (newContent || '').split('\n');
10
+
11
+ const changes = diffLines(oldLines.join('\n'), newLines.join('\n'));
12
+ const result = [];
13
+
14
+ let oldLineNum = 1;
15
+ let newLineNum = 1;
16
+
17
+ for (const change of changes) {
18
+ const lines = change.value.split('\n').filter(l => l !== '' || change.value === '\n');
19
+
20
+ for (const line of lines) {
21
+ if (change.added) {
22
+ result.push({
23
+ type: 'added',
24
+ content: line,
25
+ oldLineNumber: null,
26
+ newLineNumber: newLineNum++
27
+ });
28
+ } else if (change.removed) {
29
+ result.push({
30
+ type: 'removed',
31
+ content: line,
32
+ oldLineNumber: oldLineNum++,
33
+ newLineNumber: null
34
+ });
35
+ } else {
36
+ result.push({
37
+ type: 'unchanged',
38
+ content: line,
39
+ oldLineNumber: oldLineNum++,
40
+ newLineNumber: newLineNum++
41
+ });
42
+ }
43
+ }
44
+ }
45
+
46
+ return result;
47
+ }
48
+
49
+ export function generateWordDiff(oldContent, newContent) {
50
+ if (!oldContent && !newContent) {
51
+ return [];
52
+ }
53
+
54
+ const changes = diffWords(oldContent || '', newContent || '');
55
+ const result = [];
56
+
57
+ for (const change of changes) {
58
+ result.push({
59
+ type: change.added ? 'added' : change.removed ? 'removed' : 'unchanged',
60
+ content: change.value
61
+ });
62
+ }
63
+
64
+ return result;
65
+ }
66
+
67
+ export function generateCharDiff(oldContent, newContent) {
68
+ if (!oldContent && !newContent) {
69
+ return [];
70
+ }
71
+
72
+ const changes = diffChars(oldContent || '', newContent || '');
73
+ const result = [];
74
+
75
+ for (const change of changes) {
76
+ result.push({
77
+ type: change.added ? 'added' : change.removed ? 'removed' : 'unchanged',
78
+ content: change.value
79
+ });
80
+ }
81
+
82
+ return result;
83
+ }
84
+
85
+ export function formatDiffAsText(diff, options = {}) {
86
+ const { showLineNumbers = true, prefixAdded = '+ ', prefixRemoved = '- ', prefixUnchanged = ' ' } = options;
87
+
88
+ return diff.map(line => {
89
+ let prefix;
90
+ if (line.type === 'added') {
91
+ prefix = prefixAdded;
92
+ } else if (line.type === 'removed') {
93
+ prefix = prefixRemoved;
94
+ } else {
95
+ prefix = prefixUnchanged;
96
+ }
97
+
98
+ const lineNumStr = showLineNumbers
99
+ ? `${String(line.oldLineNumber || '').padStart(4)} ${String(line.newLineNumber || '').padStart(4)} | `
100
+ : '';
101
+
102
+ return `${lineNumStr}${prefix}${line.content}`;
103
+ }).join('\n');
104
+ }
105
+
106
+ export function getDiffStats(diff) {
107
+ const stats = {
108
+ added: 0,
109
+ removed: 0,
110
+ unchanged: 0
111
+ };
112
+
113
+ for (const line of diff) {
114
+ if (line.type === 'added') {
115
+ stats.added++;
116
+ } else if (line.type === 'removed') {
117
+ stats.removed++;
118
+ } else {
119
+ stats.unchanged++;
120
+ }
121
+ }
122
+
123
+ stats.total = stats.added + stats.removed + stats.unchanged;
124
+
125
+ return stats;
126
+ }