jupyterlab-codex-sidebar 0.1.4 → 0.1.6

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.
Files changed (153) hide show
  1. package/.claude/settings.local.json +9 -0
  2. package/.github/workflows/unit-tests.yml +27 -0
  3. package/.jupyterlab-playwright.log +0 -0
  4. package/README.md +83 -9
  5. package/docs/images/codex-sidebar-screenshot.png +0 -0
  6. package/jupyterlab_codex/handlers.py +938 -297
  7. package/jupyterlab_codex/labextension/package.json +13 -3
  8. package/jupyterlab_codex/labextension/static/525.224526d045c727069de6.js +2 -0
  9. package/jupyterlab_codex/labextension/static/737.e7de3ad9dd6ded798340.js +1 -0
  10. package/jupyterlab_codex/labextension/static/remoteEntry.6ef5e7167763a316c000.js +1 -0
  11. package/jupyterlab_codex/protocol.py +297 -0
  12. package/jupyterlab_codex/runner.py +58 -15
  13. package/jupyterlab_codex/sessions.py +582 -97
  14. package/lib/codexChat.d.ts +13 -0
  15. package/lib/codexChat.js +2506 -0
  16. package/lib/codexChat.js.map +1 -0
  17. package/lib/codexChatAttachmentDedup.d.ts +10 -0
  18. package/lib/codexChatAttachmentDedup.js +35 -0
  19. package/lib/codexChatAttachmentDedup.js.map +1 -0
  20. package/lib/codexChatAttachmentLimit.d.ts +18 -0
  21. package/lib/codexChatAttachmentLimit.js +50 -0
  22. package/lib/codexChatAttachmentLimit.js.map +1 -0
  23. package/lib/codexChatAttachmentState.d.ts +15 -0
  24. package/lib/codexChatAttachmentState.js +16 -0
  25. package/lib/codexChatAttachmentState.js.map +1 -0
  26. package/lib/codexChatDocumentUtils.d.ts +70 -0
  27. package/lib/codexChatDocumentUtils.js +506 -0
  28. package/lib/codexChatDocumentUtils.js.map +1 -0
  29. package/lib/codexChatFormatting.d.ts +11 -0
  30. package/lib/codexChatFormatting.js +83 -0
  31. package/lib/codexChatFormatting.js.map +1 -0
  32. package/lib/codexChatNotice.d.ts +3 -0
  33. package/lib/codexChatNotice.js +74 -0
  34. package/lib/codexChatNotice.js.map +1 -0
  35. package/lib/codexChatPersistence.d.ts +35 -0
  36. package/lib/codexChatPersistence.js +158 -0
  37. package/lib/codexChatPersistence.js.map +1 -0
  38. package/lib/codexChatPrimitives.d.ts +44 -0
  39. package/lib/codexChatPrimitives.js +156 -0
  40. package/lib/codexChatPrimitives.js.map +1 -0
  41. package/lib/codexChatRender.d.ts +24 -0
  42. package/lib/codexChatRender.js +293 -0
  43. package/lib/codexChatRender.js.map +1 -0
  44. package/lib/codexChatSessionFactory.d.ts +15 -0
  45. package/lib/codexChatSessionFactory.js +45 -0
  46. package/lib/codexChatSessionFactory.js.map +1 -0
  47. package/lib/codexChatSessionKey.d.ts +3 -0
  48. package/lib/codexChatSessionKey.js +14 -0
  49. package/lib/codexChatSessionKey.js.map +1 -0
  50. package/lib/codexChatStorage.d.ts +4 -0
  51. package/lib/codexChatStorage.js +37 -0
  52. package/lib/codexChatStorage.js.map +1 -0
  53. package/lib/codexSessionResolver.d.ts +12 -0
  54. package/lib/codexSessionResolver.js +38 -0
  55. package/lib/codexSessionResolver.js.map +1 -0
  56. package/lib/handlers/activitySummarizer.d.ts +15 -0
  57. package/lib/handlers/activitySummarizer.js +327 -0
  58. package/lib/handlers/activitySummarizer.js.map +1 -0
  59. package/lib/handlers/codexMessageTypes.d.ts +30 -0
  60. package/lib/handlers/codexMessageTypes.js +2 -0
  61. package/lib/handlers/codexMessageTypes.js.map +1 -0
  62. package/lib/handlers/codexMessageUtils.d.ts +46 -0
  63. package/lib/handlers/codexMessageUtils.js +144 -0
  64. package/lib/handlers/codexMessageUtils.js.map +1 -0
  65. package/lib/handlers/handleCodexSocketMessage.d.ts +107 -0
  66. package/lib/handlers/handleCodexSocketMessage.js +78 -0
  67. package/lib/handlers/handleCodexSocketMessage.js.map +1 -0
  68. package/lib/handlers/sessionSyncHandler.d.ts +34 -0
  69. package/lib/handlers/sessionSyncHandler.js +181 -0
  70. package/lib/handlers/sessionSyncHandler.js.map +1 -0
  71. package/lib/hooks/useCodexSocket.d.ts +15 -0
  72. package/lib/hooks/useCodexSocket.js +84 -0
  73. package/lib/hooks/useCodexSocket.js.map +1 -0
  74. package/lib/index.js +1 -1
  75. package/lib/index.js.map +1 -1
  76. package/lib/panel.d.ts +1 -11
  77. package/lib/panel.js +1 -2815
  78. package/lib/panel.js.map +1 -1
  79. package/lib/protocol.d.ts +235 -0
  80. package/lib/protocol.js +278 -0
  81. package/lib/protocol.js.map +1 -0
  82. package/package.json +13 -3
  83. package/playwright.config.cjs +27 -0
  84. package/playwright.unit.config.cjs +19 -0
  85. package/pyproject.toml +1 -1
  86. package/release.sh +52 -14
  87. package/scripts/run_playwright_e2e.sh +96 -0
  88. package/scripts/run_playwright_freeze_repro.sh +58 -0
  89. package/scripts/run_playwright_queue_repro.sh +60 -0
  90. package/scripts/run_playwright_repro.sh +55 -0
  91. package/src/codexChat.tsx +3914 -0
  92. package/src/codexChatAttachmentDedup.ts +47 -0
  93. package/src/codexChatAttachmentLimit.ts +81 -0
  94. package/src/codexChatAttachmentState.ts +37 -0
  95. package/src/codexChatDocumentUtils.ts +644 -0
  96. package/src/codexChatFormatting.ts +94 -0
  97. package/src/codexChatNotice.ts +95 -0
  98. package/src/codexChatPersistence.ts +191 -0
  99. package/src/codexChatPrimitives.tsx +446 -0
  100. package/src/codexChatRender.tsx +376 -0
  101. package/src/codexChatSessionFactory.ts +79 -0
  102. package/src/codexChatSessionKey.ts +16 -0
  103. package/src/codexChatStorage.ts +36 -0
  104. package/src/codexSessionResolver.ts +56 -0
  105. package/src/handlers/activitySummarizer.ts +369 -0
  106. package/src/handlers/codexMessageTypes.ts +34 -0
  107. package/src/handlers/codexMessageUtils.ts +217 -0
  108. package/src/handlers/handleCodexSocketMessage.ts +204 -0
  109. package/src/handlers/sessionSyncHandler.ts +308 -0
  110. package/src/hooks/useCodexSocket.ts +109 -0
  111. package/src/index.ts +1 -1
  112. package/src/panel.tsx +1 -4184
  113. package/src/protocol.ts +582 -0
  114. package/style/index.css +480 -11
  115. package/test-results/.last-run.json +4 -0
  116. package/test.py +0 -0
  117. package/tests/e2e/cell-output-error-tail.spec.js +156 -0
  118. package/tests/e2e/codex-ui-test-helpers.js +138 -0
  119. package/tests/e2e/fixtures/notebooks/error-output-tail.ipynb +58 -0
  120. package/tests/e2e/fixtures/notebooks/error-output-tail.py +19 -0
  121. package/tests/e2e/fixtures/notebooks/tab1.ipynb +322 -0
  122. package/tests/e2e/fixtures/notebooks/tab1.py +272 -0
  123. package/tests/e2e/fixtures/notebooks/tab2.ipynb +252 -0
  124. package/tests/e2e/fixtures/notebooks/tab2.py +231 -0
  125. package/tests/e2e/fixtures/notebooks/tab3.ipynb +403 -0
  126. package/tests/e2e/fixtures/notebooks/tab3.py +331 -0
  127. package/tests/e2e/fixtures/notebooks/tab4.py +339 -0
  128. package/tests/e2e/freeze-notebook-tabs-repro.spec.js +295 -0
  129. package/tests/e2e/mock-codex-cli-flood.py +127 -0
  130. package/tests/e2e/mock-codex-cli-prompt-echo.py +88 -0
  131. package/tests/e2e/mock-codex-cli.py +95 -0
  132. package/tests/e2e/queue-multitab-repro.spec.js +189 -0
  133. package/tests/test_handlers.py +116 -0
  134. package/tests/test_protocol.py +169 -0
  135. package/tests/test_session_store_limits.py +50 -0
  136. package/tests/unit/codexChatAttachmentDedup.spec.ts +56 -0
  137. package/tests/unit/codexChatAttachmentLimit.spec.ts +57 -0
  138. package/tests/unit/codexChatAttachmentState.spec.ts +71 -0
  139. package/tests/unit/codexChatDocumentUtils.spec.ts +63 -0
  140. package/tests/unit/codexChatLimit.spec.ts +18 -0
  141. package/tests/unit/codexChatNotice.spec.ts +45 -0
  142. package/tests/unit/codexChatPersistence.spec.ts +199 -0
  143. package/tests/unit/codexChatSessionFactory.spec.ts +94 -0
  144. package/tests/unit/codexChatSessionKey.spec.ts +18 -0
  145. package/tests/unit/codexMessageUtils.spec.ts +89 -0
  146. package/tests/unit/codexSessionResolver.spec.ts +92 -0
  147. package/tests/unit/handleCodexSocketMessage.spec.ts +476 -0
  148. package/tsconfig.tsbuildinfo +1 -1
  149. package/webpack.config.js +6 -0
  150. package/jupyterlab_codex/labextension/static/504.335f3447c84ba3d74517.js +0 -2
  151. package/jupyterlab_codex/labextension/static/972.8e856719e40acc1ef4cb.js +0 -1
  152. package/jupyterlab_codex/labextension/static/remoteEntry.a2982f776a1f0f515640.js +0 -1
  153. /package/jupyterlab_codex/labextension/static/{504.335f3447c84ba3d74517.js.LICENSE.txt → 525.224526d045c727069de6.js.LICENSE.txt} +0 -0
@@ -0,0 +1,9 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(npx tsc:*)",
5
+ "Bash(jlpm build:*)",
6
+ "Bash(jupyter server extension enable:*)"
7
+ ]
8
+ }
9
+ }
@@ -0,0 +1,27 @@
1
+ name: Unit Tests
2
+
3
+ on:
4
+ push:
5
+ pull_request:
6
+
7
+ jobs:
8
+ test:
9
+ runs-on: ubuntu-latest
10
+ timeout-minutes: 20
11
+ steps:
12
+ - uses: actions/checkout@v4
13
+
14
+ - uses: actions/setup-node@v4
15
+ with:
16
+ node-version: '20'
17
+
18
+ - name: Enable Corepack and select Yarn 4
19
+ run: |
20
+ corepack enable
21
+ corepack prepare yarn@4.6.0 --activate
22
+
23
+ - name: Install dependencies
24
+ run: corepack yarn install --immutable
25
+
26
+ - name: Run unit tests
27
+ run: corepack yarn run test:unit
Binary file
package/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # JupyterLab Codex Sidebar
2
2
 
3
+ ![JupyterLab Codex Sidebar Screenshot](docs/images/codex-sidebar-screenshot.png)
4
+
3
5
  ## English
4
6
 
5
7
  ### Quick Guide (Discovery Install, Read First)
@@ -21,8 +23,11 @@ Follow this order for the easiest setup.
21
23
  2. Start JupyterLab again.
22
24
  3. Confirm `Codex` appears in the right sidebar.
23
25
 
24
- 4) Create Jupytext pairs (`.ipynb` <-> `.py`)
25
- - This extension requires a Jupytext paired workflow.
26
+ 4) Notebook modes (`.ipynb` / `.py`)
27
+ - `.ipynb` mode: requires a same-name paired `.py` file.
28
+ - `.py` mode: works with or without a paired `.ipynb`.
29
+ - `jupytext_py`: detected when Jupytext metadata/header or `# %%` cell markers are present.
30
+ - `plain_py`: detected for regular Python scripts without Jupytext markers.
26
31
 
27
32
  ### A. Start from `.ipynb`
28
33
  1. Open the notebook.
@@ -36,7 +41,9 @@ Follow this order for the easiest setup.
36
41
  3. Select `.ipynb`.
37
42
  4. Confirm a same-name `.ipynb` file exists.
38
43
 
39
- Note: For Codex sidebar usage, the paired `.ipynb` and `.py` should both exist with the same base name.
44
+ Note:
45
+ - In `.ipynb` mode, the paired `.py` file must exist with the same base name.
46
+ - In `.py` mode, pairing is optional.
40
47
 
41
48
  A JupyterLab 4 sidebar extension that connects to Codex CLI (`codex exec --json`) and provides a chat-style assistant UI.
42
49
 
@@ -50,8 +57,18 @@ The backend runs `codex` as a local subprocess per request, streams JSONL events
50
57
  - Threaded sessions by notebook path
51
58
  - Model / Reasoning Effort / Sandbox selection in the UI
52
59
  - Optional inclusion of active cell text
53
- - Designed for a Jupytext paired workflow (`.ipynb` <-> `.py`)
54
- - execution is disabled if the paired `.py` file is missing
60
+ - Mode-aware behavior by file type
61
+ - `.ipynb`: requires paired `.py`; sends active cell context and optional active cell output
62
+ - `.py` (`jupytext_py`): sends active cell context and optional active cell output when opened as notebook; text selection when opened in text editor
63
+ - `.py` (`plain_py`): sends `selection` only when text is explicitly selected
64
+
65
+ | File type | Open mode | Selection attachment | Output attachment |
66
+ | --- | --- | --- | --- |
67
+ | `.ipynb` | Notebook editor (`Open With > Notebook`) | Active cell | Active cell output |
68
+ | `.py` (Jupytext mode) | Notebook editor | Active cell | Active cell output |
69
+ | `.py` (Jupytext mode) | Text editor | Selected text | None |
70
+ | `.py` (plain mode) | Notebook editor | Active selected text | None |
71
+ | `.py` (plain mode) | Text editor | Selected text | None |
55
72
  - Conversation/session logs: `~/.jupyter/codex-sessions/`
56
73
  - Optional usage snapshot: best-effort scan of recent `~/.codex/sessions/`
57
74
 
@@ -134,6 +151,11 @@ jupyter lab
134
151
  - Include active cell output
135
152
  - Model / Reasoning Effort / Permission
136
153
 
154
+ Mode-specific context rules:
155
+ - `cellOutput` is sent only in `.ipynb` mode.
156
+ - In `.py` modes, `cellOutput` is not sent (`cellOutput` key is omitted).
157
+ - In `plain_py` mode, `selection` is sent only when text is explicitly selected; otherwise the `selection` key is omitted.
158
+
137
159
  ## Configuration
138
160
  Server-side defaults can also be set via environment variables:
139
161
  - `JUPYTERLAB_CODEX_MODEL`: default model when unset in UI/command
@@ -171,6 +193,37 @@ Selected UI values are passed as CLI args.
171
193
  - UI: `src/panel.tsx`
172
194
  - Server: `jupyterlab_codex/handlers.py`, `jupyterlab_codex/runner.py`
173
195
 
196
+ ## Playwright E2E (3-tab freeze reproduction)
197
+ - Purpose: reproduce the "send while previous run is still running across 3 notebook tabs" scenario.
198
+ - This suite uses a local mock Codex CLI (`tests/e2e/mock-codex-cli.py`) so it does not require real Codex auth.
199
+
200
+ Setup once:
201
+
202
+ ```bash
203
+ jlpm install
204
+ jlpm test:e2e:install
205
+ ```
206
+
207
+ Run with auto-launched JupyterLab:
208
+
209
+ ```bash
210
+ jlpm test:e2e:repro-local
211
+ ```
212
+
213
+ Or run against an already running JupyterLab:
214
+
215
+ ```bash
216
+ PLAYWRIGHT_BASE_URL="http://127.0.0.1:8888/lab" \
217
+ PLAYWRIGHT_CODEX_COMMAND="$(pwd)/tests/e2e/mock-codex-cli.py" \
218
+ jlpm test:e2e:queue-repro
219
+ ```
220
+
221
+ Files:
222
+ - Playwright config: `playwright.config.cjs`
223
+ - Test spec: `tests/e2e/queue-multitab-repro.spec.js`
224
+ - Mock CLI: `tests/e2e/mock-codex-cli.py`
225
+ - Notebook fixtures: `tests/e2e/fixtures/notebooks/`
226
+
174
227
  ## Architecture
175
228
  ```
176
229
  [UI (JupyterLab Sidebar)]
@@ -210,8 +263,11 @@ Selected UI values are passed as CLI args.
210
263
  2. JupyterLab 재실행
211
264
  3. 우측 사이드바에 `Codex` 패널이 보이는지 확인
212
265
 
213
- 4) Jupytext 페어링 만들기 (`.ipynb` <-> `.py`)
214
- - 확장은 Jupytext 페어링 워크플로우를 전제로 합니다.
266
+ 4) 문서 모드(`.ipynb` / `.py`)
267
+ - `.ipynb` 모드: 같은 이름의 페어 `.py` 파일이 필요합니다.
268
+ - `.py` 모드: 페어 `.ipynb`가 없어도 동작합니다.
269
+ - `jupytext_py`: Jupytext 메타데이터/헤더 또는 `# %%` 셀 마커가 있으면 감지
270
+ - `plain_py`: Jupytext 마커가 없는 일반 Python 스크립트로 감지
215
271
 
216
272
  ### A. `.ipynb` 파일에서 시작할 때
217
273
  1. 노트북(`.ipynb`) 열기
@@ -225,7 +281,9 @@ Selected UI values are passed as CLI args.
225
281
  3. `.ipynb` 포맷으로 페어링
226
282
  4. 같은 이름의 `.ipynb` 파일이 생성되었는지 확인
227
283
 
228
- 참고: Codex 사이드바 사용 시에는 같은 이름의 `.ipynb`와 `.py` 페어가 모두 있어야 합니다.
284
+ 참고:
285
+ - `.ipynb` 모드에서는 같은 이름의 페어 `.py`가 반드시 있어야 합니다.
286
+ - `.py` 모드에서는 페어링이 선택 사항입니다.
229
287
 
230
288
  JupyterLab 4 우측 사이드바에서 Codex CLI(`codex exec --json`)를 채팅 UI로 사용할 수 있게 해주는 확장입니다.
231
289
 
@@ -239,7 +297,18 @@ JupyterLab 4 우측 사이드바에서 Codex CLI(`codex exec --json`)를 채팅
239
297
  - 노트북 경로 기준으로 스레드(세션) 분리
240
298
  - 모델 / Reasoning Effort / 샌드박스 권한을 UI에서 선택
241
299
  - 활성 셀 텍스트를 프롬프트에 포함할지 선택
242
- - `.ipynb` `.py`(Jupytext paired) 워크플로우를 전제로 동작(페어링된 `.py`가 없으면 실행이 비활성화됨)
300
+ - 파일 타입별 모드 동작
301
+ - `.ipynb`: 페어 `.py`가 필요하며, active cell/context 및 active cell output을 전송
302
+ - `.py` (`jupytext_py`): 노트북 모드로 열면 active cell과 active cell output을 전송하고, 텍스트 에디터로 열면 선택 텍스트를 전송
303
+ - `.py` (`plain_py`): 텍스트를 명시적으로 선택한 경우에만 `selection`을 전송하고, 요청 없이는 Jupytext 마커를 추가하지 않음
304
+
305
+ | 파일 타입 | 열기 모드 | 첨부 동작(입력) | 첨부 동작(출력) |
306
+ | --- | --- | --- | --- |
307
+ | `.ipynb` | Notebook 에디터(`Open With > Notebook`) | 현재 활성 셀 | 현재 셀 output |
308
+ | `.py` (Jupytext 모드) | Notebook 에디터 | 현재 활성 셀 | 현재 셀 output |
309
+ | `.py` (Jupytext 모드) | 텍스트 에디터 | 선택 텍스트 | 없음 |
310
+ | `.py` (plain 모드) | Notebook 에디터 | 선택 텍스트(있을 때) | 없음 |
311
+ | `.py` (plain 모드) | 텍스트 에디터 | 선택 텍스트(있을 때) | 없음 |
243
312
  - 세션 로그 저장: `~/.jupyter/codex-sessions/`
244
313
  - (가능한 경우) Codex 사용량 스냅샷 표시: `~/.codex/sessions/` 를 best-effort로 스캔
245
314
 
@@ -334,6 +403,11 @@ jupyter lab
334
403
  - Include active cell output: 활성 셀 output(텍스트 위주)을 프롬프트에 포함
335
404
  - Model / Reasoning Effort / Permission(샌드박스)
336
405
 
406
+ 모드별 컨텍스트 전송 규칙:
407
+ - `cellOutput`은 `.ipynb` 모드에서만 전송됩니다.
408
+ - `.py` 모드에서는 `cellOutput` key 자체를 보내지 않습니다.
409
+ - `plain_py` 모드에서는 텍스트를 명시적으로 선택한 경우에만 `selection` key를 보내며, 선택이 없으면 key를 보내지 않습니다.
410
+
337
411
  ## 설정(옵션)
338
412
  서버 측 기본값은 환경 변수로도 지정할 수 있습니다.
339
413
  - `JUPYTERLAB_CODEX_MODEL`: 모델을 명시하지 않았을 때 기본 모델로 사용