python-codex 0.1.14__py3-none-any.whl → 0.2.0__py3-none-any.whl
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.
- pycodex/agent.py +6 -11
- pycodex/cli.py +3 -0
- pycodex/context.py +12 -0
- pycodex/model.py +10 -3
- pycodex/runtime.py +10 -0
- pycodex/tools/code_mode_manager.py +1 -1
- pycodex/tools/unified_exec_manager.py +7 -92
- pycodex/utils/session_persist.py +42 -1
- pycodex/utils/truncation.py +206 -0
- {python_codex-0.1.14.dist-info → python_codex-0.2.0.dist-info}/METADATA +1 -1
- {python_codex-0.1.14.dist-info → python_codex-0.2.0.dist-info}/RECORD +17 -16
- workspace_server/__init__.py +2 -0
- workspace_server/app.py +473 -109
- workspace_server/workspace.html +144 -68
- {python_codex-0.1.14.dist-info → python_codex-0.2.0.dist-info}/WHEEL +0 -0
- {python_codex-0.1.14.dist-info → python_codex-0.2.0.dist-info}/entry_points.txt +0 -0
- {python_codex-0.1.14.dist-info → python_codex-0.2.0.dist-info}/licenses/LICENSE +0 -0
workspace_server/workspace.html
CHANGED
|
@@ -16,11 +16,12 @@
|
|
|
16
16
|
--accent-ink: #ffffff;
|
|
17
17
|
--code: #f6f8fa;
|
|
18
18
|
--chat-width: min(42vw, 760px);
|
|
19
|
+
--splitter-width: 8px;
|
|
19
20
|
}
|
|
20
21
|
* { box-sizing: border-box; }
|
|
21
22
|
body {
|
|
22
23
|
margin: 0;
|
|
23
|
-
height:
|
|
24
|
+
height: 100dvh;
|
|
24
25
|
overflow: hidden;
|
|
25
26
|
background: var(--bg);
|
|
26
27
|
color: var(--ink);
|
|
@@ -28,19 +29,40 @@
|
|
|
28
29
|
}
|
|
29
30
|
.workspace {
|
|
30
31
|
display: grid;
|
|
31
|
-
grid-template-columns: minmax(
|
|
32
|
-
height:
|
|
33
|
-
min-width:
|
|
32
|
+
grid-template-columns: minmax(0, 1fr) var(--splitter-width) var(--chat-width);
|
|
33
|
+
height: 100dvh;
|
|
34
|
+
min-width: 0;
|
|
35
|
+
}
|
|
36
|
+
.workspace.collapsed .splitter::after {
|
|
37
|
+
background: #7e9187;
|
|
38
|
+
}
|
|
39
|
+
.board-pane {
|
|
40
|
+
min-width: 0;
|
|
41
|
+
height: 100dvh;
|
|
42
|
+
display: grid;
|
|
43
|
+
grid-template-rows: auto minmax(0, 1fr);
|
|
44
|
+
background: #fff;
|
|
45
|
+
}
|
|
46
|
+
.boardbar {
|
|
47
|
+
min-width: 0;
|
|
48
|
+
border-bottom: 1px solid var(--line);
|
|
49
|
+
padding: 8px 12px;
|
|
50
|
+
color: var(--muted);
|
|
51
|
+
font-size: 12px;
|
|
52
|
+
white-space: nowrap;
|
|
53
|
+
overflow: hidden;
|
|
54
|
+
text-overflow: ellipsis;
|
|
34
55
|
}
|
|
35
56
|
.board {
|
|
36
57
|
border: 0;
|
|
58
|
+
min-width: 0;
|
|
37
59
|
width: 100%;
|
|
38
60
|
height: 100%;
|
|
39
61
|
background: #fff;
|
|
40
62
|
}
|
|
41
63
|
.splitter {
|
|
42
64
|
width: 8px;
|
|
43
|
-
height:
|
|
65
|
+
height: 100dvh;
|
|
44
66
|
border: 0;
|
|
45
67
|
border-left: 1px solid var(--line);
|
|
46
68
|
border-right: 1px solid var(--line);
|
|
@@ -54,7 +76,7 @@
|
|
|
54
76
|
display: block;
|
|
55
77
|
width: 2px;
|
|
56
78
|
height: 42px;
|
|
57
|
-
margin: calc(
|
|
79
|
+
margin: calc(50dvh - 21px) auto 0;
|
|
58
80
|
border-radius: 999px;
|
|
59
81
|
background: #b9c1ba;
|
|
60
82
|
}
|
|
@@ -64,14 +86,16 @@
|
|
|
64
86
|
user-select: none;
|
|
65
87
|
}
|
|
66
88
|
.chat {
|
|
89
|
+
position: relative;
|
|
67
90
|
min-width: 0;
|
|
68
|
-
height:
|
|
91
|
+
height: 100dvh;
|
|
69
92
|
overflow: hidden;
|
|
70
93
|
display: grid;
|
|
71
94
|
grid-template-rows: auto minmax(0, 1fr) auto;
|
|
72
95
|
background: var(--panel);
|
|
73
96
|
}
|
|
74
97
|
.topbar {
|
|
98
|
+
min-width: 0;
|
|
75
99
|
padding: 12px 14px;
|
|
76
100
|
border-bottom: 1px solid var(--line);
|
|
77
101
|
display: grid;
|
|
@@ -148,14 +172,6 @@
|
|
|
148
172
|
color: var(--ink);
|
|
149
173
|
background: #f3f6f4;
|
|
150
174
|
}
|
|
151
|
-
.title { font-weight: 650; }
|
|
152
|
-
.subtitle {
|
|
153
|
-
color: var(--muted);
|
|
154
|
-
font-size: 12px;
|
|
155
|
-
overflow: hidden;
|
|
156
|
-
text-overflow: ellipsis;
|
|
157
|
-
white-space: nowrap;
|
|
158
|
-
}
|
|
159
175
|
.log {
|
|
160
176
|
min-height: 0;
|
|
161
177
|
overflow-y: auto;
|
|
@@ -167,6 +183,7 @@
|
|
|
167
183
|
background: #fbfcfa;
|
|
168
184
|
}
|
|
169
185
|
.entry {
|
|
186
|
+
min-width: 0;
|
|
170
187
|
border: 1px solid var(--line);
|
|
171
188
|
border-radius: 6px;
|
|
172
189
|
padding: 10px 11px;
|
|
@@ -195,6 +212,11 @@
|
|
|
195
212
|
color: #4c4261;
|
|
196
213
|
font-size: 12px;
|
|
197
214
|
}
|
|
215
|
+
.entry.error {
|
|
216
|
+
border-color: #e4b6b6;
|
|
217
|
+
background: #fff7f7;
|
|
218
|
+
color: #7a2c2c;
|
|
219
|
+
}
|
|
198
220
|
.text {
|
|
199
221
|
white-space: pre-wrap;
|
|
200
222
|
overflow-wrap: anywhere;
|
|
@@ -261,13 +283,15 @@
|
|
|
261
283
|
text-decoration: underline;
|
|
262
284
|
}
|
|
263
285
|
.composer {
|
|
286
|
+
min-width: 0;
|
|
264
287
|
border-top: 1px solid var(--line);
|
|
265
|
-
padding: 12px;
|
|
288
|
+
padding: 12px 12px 28px;
|
|
266
289
|
display: grid;
|
|
267
290
|
gap: 8px;
|
|
268
291
|
background: #fff;
|
|
269
292
|
}
|
|
270
293
|
textarea {
|
|
294
|
+
min-width: 0;
|
|
271
295
|
resize: vertical;
|
|
272
296
|
min-height: 88px;
|
|
273
297
|
max-height: 35vh;
|
|
@@ -284,6 +308,10 @@
|
|
|
284
308
|
align-items: center;
|
|
285
309
|
}
|
|
286
310
|
.spinner {
|
|
311
|
+
position: absolute;
|
|
312
|
+
left: 12px;
|
|
313
|
+
right: 12px;
|
|
314
|
+
bottom: 6px;
|
|
287
315
|
min-height: 18px;
|
|
288
316
|
color: var(--muted);
|
|
289
317
|
font-size: 12px;
|
|
@@ -301,16 +329,16 @@
|
|
|
301
329
|
}
|
|
302
330
|
@media (max-width: 900px) {
|
|
303
331
|
body { overflow: auto; height: auto; }
|
|
304
|
-
.workspace {
|
|
305
|
-
.board { height: 56vh; border-right: 0; border-bottom: 1px solid var(--line); }
|
|
306
|
-
.splitter { display: none; }
|
|
307
|
-
.chat { min-height: 44vh; }
|
|
332
|
+
.workspace { min-width: 0; }
|
|
308
333
|
}
|
|
309
334
|
</style>
|
|
310
335
|
</head>
|
|
311
336
|
<body>
|
|
312
337
|
<div class="workspace">
|
|
313
|
-
<
|
|
338
|
+
<section class="board-pane" aria-label="workspace board">
|
|
339
|
+
<div class="boardbar">Board: <code>__BOARD_LABEL__</code></div>
|
|
340
|
+
<iframe id="boardFrame" class="board" src="board" title="board"></iframe>
|
|
341
|
+
</section>
|
|
314
342
|
<button id="splitter" class="splitter" type="button" aria-label="Resize chat panel"></button>
|
|
315
343
|
<section class="chat" aria-label="pycodex chat">
|
|
316
344
|
<div class="topbar">
|
|
@@ -318,18 +346,12 @@
|
|
|
318
346
|
<div id="tabs" class="tabs"></div>
|
|
319
347
|
<button id="newTab" class="tab-new" type="button" title="New session" aria-label="New session">+</button>
|
|
320
348
|
</div>
|
|
321
|
-
<div>
|
|
322
|
-
<div class="title">pycodex</div>
|
|
323
|
-
<div class="subtitle">Board: <code>__BOARD_LABEL__</code></div>
|
|
324
|
-
</div>
|
|
325
349
|
</div>
|
|
326
350
|
<div id="log" class="log"></div>
|
|
327
351
|
<form id="composer" class="composer">
|
|
328
352
|
<textarea id="prompt" placeholder="Ask pycodex or type /help..."></textarea>
|
|
329
|
-
<div class="actions">
|
|
330
|
-
<div id="spinner" class="spinner"></div>
|
|
331
|
-
</div>
|
|
332
353
|
</form>
|
|
354
|
+
<div id="spinner" class="spinner"></div>
|
|
333
355
|
</section>
|
|
334
356
|
</div>
|
|
335
357
|
<script src="https://cdn.jsdelivr.net/npm/markdown-it@14.1.0/dist/markdown-it.min.js"></script>
|
|
@@ -346,6 +368,8 @@
|
|
|
346
368
|
const newTabButton = document.getElementById("newTab");
|
|
347
369
|
let pollTimer = null;
|
|
348
370
|
let boardPollTimer = null;
|
|
371
|
+
let pollInFlight = false;
|
|
372
|
+
let boardPollInFlight = false;
|
|
349
373
|
let lastBoardSignature = "";
|
|
350
374
|
let lastRenderedSignature = "";
|
|
351
375
|
let resizeStart = null;
|
|
@@ -354,8 +378,10 @@
|
|
|
354
378
|
let spinnerText = "";
|
|
355
379
|
let activeSessionId = "";
|
|
356
380
|
let sessions = [];
|
|
381
|
+
let isComposing = false;
|
|
357
382
|
const sessionState = new Map();
|
|
358
383
|
let restoreScrollTop = null;
|
|
384
|
+
let suppressScrollSave = false;
|
|
359
385
|
const spinnerFrames = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
|
|
360
386
|
const markdownRenderer = window.markdownit
|
|
361
387
|
? window.markdownit({html: false, linkify: true, breaks: false})
|
|
@@ -412,17 +438,36 @@
|
|
|
412
438
|
if (stored > 0) setChatWidth(stored);
|
|
413
439
|
}
|
|
414
440
|
|
|
441
|
+
function centerSplit() {
|
|
442
|
+
setChatWidth(Math.max(0, (window.innerWidth - 8) / 2));
|
|
443
|
+
}
|
|
444
|
+
|
|
415
445
|
function setChatWidth(width) {
|
|
416
446
|
const viewportWidth = window.innerWidth || 0;
|
|
417
|
-
const
|
|
418
|
-
const
|
|
419
|
-
const
|
|
447
|
+
const splitterWidth = 8;
|
|
448
|
+
const gutterWidth = Math.min(24, Math.max(12, Math.round(viewportWidth * 0.06)));
|
|
449
|
+
const availableWidth = Math.max(0, viewportWidth - splitterWidth);
|
|
450
|
+
const maxChatWidth = Math.max(gutterWidth, availableWidth - gutterWidth);
|
|
451
|
+
const collapseWidth = Math.min(
|
|
452
|
+
280,
|
|
453
|
+
Math.max(120, Math.round(viewportWidth * 0.25)),
|
|
454
|
+
);
|
|
455
|
+
let nextWidth = Math.max(gutterWidth, Math.min(maxChatWidth, Math.round(width)));
|
|
456
|
+
let collapsed = false;
|
|
457
|
+
if (nextWidth < collapseWidth) {
|
|
458
|
+
nextWidth = gutterWidth;
|
|
459
|
+
collapsed = true;
|
|
460
|
+
} else if (availableWidth - nextWidth < collapseWidth) {
|
|
461
|
+
nextWidth = maxChatWidth;
|
|
462
|
+
collapsed = true;
|
|
463
|
+
}
|
|
420
464
|
workspace.style.setProperty("--chat-width", `${nextWidth}px`);
|
|
465
|
+
workspace.classList.toggle("collapsed", collapsed);
|
|
421
466
|
window.localStorage.setItem("pycodex.workspace.chatWidth", String(nextWidth));
|
|
422
467
|
}
|
|
423
468
|
|
|
424
469
|
function startResize(event) {
|
|
425
|
-
if (!workspace
|
|
470
|
+
if (!workspace) return;
|
|
426
471
|
const chatWidth = document.querySelector(".chat").getBoundingClientRect().width;
|
|
427
472
|
resizeStart = { pointerId: event.pointerId, startX: event.clientX, startWidth: chatWidth };
|
|
428
473
|
splitter.setPointerCapture(event.pointerId);
|
|
@@ -483,7 +528,7 @@
|
|
|
483
528
|
function stateForSession(sessionId) {
|
|
484
529
|
const key = String(sessionId || "");
|
|
485
530
|
if (!sessionState.has(key)) {
|
|
486
|
-
sessionState.set(key, {lastRenderedSignature: "", scrollTop:
|
|
531
|
+
sessionState.set(key, {lastRenderedSignature: "", scrollTop: null, draft: ""});
|
|
487
532
|
}
|
|
488
533
|
return sessionState.get(key);
|
|
489
534
|
}
|
|
@@ -491,7 +536,9 @@
|
|
|
491
536
|
function saveActiveSessionUiState() {
|
|
492
537
|
if (!activeSessionId) return;
|
|
493
538
|
const state = stateForSession(activeSessionId);
|
|
494
|
-
|
|
539
|
+
if (log.scrollHeight > log.clientHeight) {
|
|
540
|
+
state.scrollTop = log.scrollTop;
|
|
541
|
+
}
|
|
495
542
|
state.draft = prompt.value;
|
|
496
543
|
state.lastRenderedSignature = lastRenderedSignature;
|
|
497
544
|
}
|
|
@@ -538,11 +585,8 @@
|
|
|
538
585
|
|
|
539
586
|
function messageSignature(snapshot) {
|
|
540
587
|
const turns = (snapshot && snapshot.turns) || [];
|
|
541
|
-
return JSON.stringify(
|
|
542
|
-
|
|
543
|
-
spinner: snapshot.spinner || "",
|
|
544
|
-
title: snapshot.title || "",
|
|
545
|
-
turns: turns.map((item) => [
|
|
588
|
+
return JSON.stringify(
|
|
589
|
+
turns.map((item) => [
|
|
546
590
|
item.submission_id || "",
|
|
547
591
|
item.turn_id || "",
|
|
548
592
|
item.prompt || "",
|
|
@@ -552,17 +596,23 @@
|
|
|
552
596
|
item.error || "",
|
|
553
597
|
item.kind || "",
|
|
554
598
|
]),
|
|
555
|
-
|
|
599
|
+
);
|
|
556
600
|
}
|
|
557
601
|
|
|
558
602
|
async function pollSession() {
|
|
603
|
+
if (pollInFlight) return;
|
|
604
|
+
pollInFlight = true;
|
|
605
|
+
const requestedSessionId = activeSessionId;
|
|
559
606
|
try {
|
|
560
|
-
const path =
|
|
561
|
-
? `api/session?session_id=${encodeURIComponent(
|
|
607
|
+
const path = requestedSessionId
|
|
608
|
+
? `api/session?session_id=${encodeURIComponent(requestedSessionId)}`
|
|
562
609
|
: "api/session";
|
|
563
610
|
const response = await fetch(relativeUrl(path));
|
|
564
611
|
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
|
565
612
|
const payload = await response.json();
|
|
613
|
+
if (requestedSessionId && requestedSessionId !== activeSessionId) {
|
|
614
|
+
return;
|
|
615
|
+
}
|
|
566
616
|
if (payload.session_id && payload.session_id !== activeSessionId) {
|
|
567
617
|
activeSessionId = payload.session_id;
|
|
568
618
|
}
|
|
@@ -570,6 +620,8 @@
|
|
|
570
620
|
renderSnapshot(payload.snapshot);
|
|
571
621
|
} catch (error) {
|
|
572
622
|
setSpinner(`poll error: ${error.message}`);
|
|
623
|
+
} finally {
|
|
624
|
+
pollInFlight = false;
|
|
573
625
|
}
|
|
574
626
|
}
|
|
575
627
|
|
|
@@ -586,6 +638,8 @@
|
|
|
586
638
|
}
|
|
587
639
|
|
|
588
640
|
async function pollBoard() {
|
|
641
|
+
if (boardPollInFlight) return;
|
|
642
|
+
boardPollInFlight = true;
|
|
589
643
|
try {
|
|
590
644
|
const response = await fetch(relativeUrl("api/board"));
|
|
591
645
|
if (!response.ok) return;
|
|
@@ -602,6 +656,8 @@
|
|
|
602
656
|
}
|
|
603
657
|
} catch (_error) {
|
|
604
658
|
return;
|
|
659
|
+
} finally {
|
|
660
|
+
boardPollInFlight = false;
|
|
605
661
|
}
|
|
606
662
|
}
|
|
607
663
|
|
|
@@ -623,25 +679,30 @@
|
|
|
623
679
|
lastRenderedSignature = signature;
|
|
624
680
|
const shouldStick = isNearBottom();
|
|
625
681
|
const previousScrollTop = log.scrollTop;
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
turns.
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
682
|
+
suppressScrollSave = true;
|
|
683
|
+
try {
|
|
684
|
+
log.textContent = "";
|
|
685
|
+
const turns = Array.isArray(snapshot.turns) ? snapshot.turns : [];
|
|
686
|
+
if (turns.length) {
|
|
687
|
+
turns.forEach((turn) => renderTurn(turn, shouldStick));
|
|
688
|
+
}
|
|
689
|
+
setSpinner(snapshot.spinner || "");
|
|
690
|
+
if (restoreScrollTop !== null) {
|
|
691
|
+
log.scrollTop = Math.min(
|
|
692
|
+
restoreScrollTop,
|
|
693
|
+
Math.max(0, log.scrollHeight - log.clientHeight),
|
|
694
|
+
);
|
|
695
|
+
restoreScrollTop = null;
|
|
696
|
+
} else if (shouldStick) {
|
|
697
|
+
scrollToBottom();
|
|
698
|
+
} else {
|
|
699
|
+
log.scrollTop = Math.min(
|
|
700
|
+
previousScrollTop,
|
|
701
|
+
Math.max(0, log.scrollHeight - log.clientHeight),
|
|
702
|
+
);
|
|
703
|
+
}
|
|
704
|
+
} finally {
|
|
705
|
+
suppressScrollSave = false;
|
|
645
706
|
}
|
|
646
707
|
state.scrollTop = log.scrollTop;
|
|
647
708
|
}
|
|
@@ -665,7 +726,7 @@
|
|
|
665
726
|
);
|
|
666
727
|
}
|
|
667
728
|
if (turn.thinking) addEntry("thinking", turn.thinking || "", "thinking", shouldStick);
|
|
668
|
-
if (turn.error) addEntry("error", turn.error || "", "
|
|
729
|
+
if (turn.error) addEntry("error", turn.error || "", "error", shouldStick);
|
|
669
730
|
}
|
|
670
731
|
|
|
671
732
|
async function submitPrompt(text) {
|
|
@@ -676,7 +737,7 @@
|
|
|
676
737
|
});
|
|
677
738
|
const payload = await response.json();
|
|
678
739
|
if (!response.ok || !payload.ok) {
|
|
679
|
-
addEntry("error", payload.error || `HTTP ${response.status}`, "
|
|
740
|
+
addEntry("error", payload.error || `HTTP ${response.status}`, "error");
|
|
680
741
|
setSpinner("");
|
|
681
742
|
return;
|
|
682
743
|
}
|
|
@@ -697,9 +758,11 @@
|
|
|
697
758
|
state.lastRenderedSignature = "";
|
|
698
759
|
lastRenderedSignature = "";
|
|
699
760
|
prompt.value = state.draft || "";
|
|
761
|
+
suppressScrollSave = true;
|
|
700
762
|
log.textContent = "";
|
|
763
|
+
suppressScrollSave = false;
|
|
701
764
|
setSpinner("");
|
|
702
|
-
restoreScrollTop = state.scrollTop
|
|
765
|
+
restoreScrollTop = state.scrollTop;
|
|
703
766
|
await pollSession();
|
|
704
767
|
renderTabs();
|
|
705
768
|
}
|
|
@@ -709,17 +772,17 @@
|
|
|
709
772
|
const response = await fetch(relativeUrl("api/sessions"), {method: "POST"});
|
|
710
773
|
const payload = await response.json();
|
|
711
774
|
if (!response.ok || !payload.ok) {
|
|
712
|
-
addEntry("error", payload.error || `HTTP ${response.status}`, "
|
|
775
|
+
addEntry("error", payload.error || `HTTP ${response.status}`, "error");
|
|
713
776
|
return;
|
|
714
777
|
}
|
|
715
778
|
activeSessionId = payload.session_id || "";
|
|
716
779
|
const state = stateForSession(activeSessionId);
|
|
717
780
|
state.draft = "";
|
|
718
|
-
state.scrollTop =
|
|
781
|
+
state.scrollTop = null;
|
|
719
782
|
state.lastRenderedSignature = "";
|
|
720
783
|
lastRenderedSignature = "";
|
|
721
784
|
prompt.value = "";
|
|
722
|
-
restoreScrollTop =
|
|
785
|
+
restoreScrollTop = null;
|
|
723
786
|
updateSessions(payload.sessions || []);
|
|
724
787
|
renderSnapshot(payload.snapshot);
|
|
725
788
|
}
|
|
@@ -731,7 +794,7 @@
|
|
|
731
794
|
});
|
|
732
795
|
const payload = await response.json();
|
|
733
796
|
if (!response.ok || !payload.ok) {
|
|
734
|
-
addEntry("error", payload.error || `HTTP ${response.status}`, "
|
|
797
|
+
addEntry("error", payload.error || `HTTP ${response.status}`, "error");
|
|
735
798
|
return;
|
|
736
799
|
}
|
|
737
800
|
sessionState.delete(sessionId);
|
|
@@ -740,7 +803,9 @@
|
|
|
740
803
|
activeSessionId = sessions.length ? sessions[0].id || "" : "";
|
|
741
804
|
lastRenderedSignature = "";
|
|
742
805
|
prompt.value = "";
|
|
806
|
+
suppressScrollSave = true;
|
|
743
807
|
log.textContent = "";
|
|
808
|
+
suppressScrollSave = false;
|
|
744
809
|
await pollSession();
|
|
745
810
|
} else {
|
|
746
811
|
renderTabs();
|
|
@@ -760,12 +825,22 @@
|
|
|
760
825
|
stateForSession(activeSessionId).draft = prompt.value;
|
|
761
826
|
});
|
|
762
827
|
|
|
828
|
+
prompt.addEventListener("compositionstart", () => {
|
|
829
|
+
isComposing = true;
|
|
830
|
+
});
|
|
831
|
+
|
|
832
|
+
prompt.addEventListener("compositionend", () => {
|
|
833
|
+
isComposing = false;
|
|
834
|
+
});
|
|
835
|
+
|
|
763
836
|
log.addEventListener("scroll", () => {
|
|
837
|
+
if (suppressScrollSave) return;
|
|
764
838
|
if (!activeSessionId) return;
|
|
765
839
|
stateForSession(activeSessionId).scrollTop = log.scrollTop;
|
|
766
840
|
});
|
|
767
841
|
|
|
768
842
|
prompt.addEventListener("keydown", (event) => {
|
|
843
|
+
if (event.isComposing || isComposing || event.keyCode === 229) return;
|
|
769
844
|
if (event.key === "Enter" && !event.shiftKey) {
|
|
770
845
|
event.preventDefault();
|
|
771
846
|
form.requestSubmit();
|
|
@@ -776,6 +851,7 @@
|
|
|
776
851
|
splitter.addEventListener("pointermove", updateResize);
|
|
777
852
|
splitter.addEventListener("pointerup", endResize);
|
|
778
853
|
splitter.addEventListener("pointercancel", endResize);
|
|
854
|
+
splitter.addEventListener("dblclick", centerSplit);
|
|
779
855
|
newTabButton.addEventListener("click", createSession);
|
|
780
856
|
window.addEventListener("resize", () => {
|
|
781
857
|
const current = Number(window.localStorage.getItem("pycodex.workspace.chatWidth") || 0);
|
|
File without changes
|
|
File without changes
|
|
File without changes
|