jupyterlab-codex-sidebar 0.1.3 → 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.
Files changed (139) hide show
  1. package/.claude/settings.local.json +9 -0
  2. package/.github/workflows/unit-tests.yml +27 -0
  3. package/AGENTS.md +42 -0
  4. package/README.md +67 -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/855.d20f6158cd81bb4c9056.js +1 -0
  10. package/jupyterlab_codex/labextension/static/{remoteEntry.b2fdc03a1c4582e79156.js → remoteEntry.c1e865f207776f7f24ff.js} +1 -1
  11. package/jupyterlab_codex/protocol.py +297 -0
  12. package/jupyterlab_codex/runner.py +137 -31
  13. package/jupyterlab_codex/sessions.py +582 -97
  14. package/lib/codexChat.d.ts +13 -0
  15. package/lib/codexChat.js +2410 -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 +8 -0
  21. package/lib/codexChatAttachmentLimit.js +61 -0
  22. package/lib/codexChatAttachmentLimit.js.map +1 -0
  23. package/lib/codexChatDocumentUtils.d.ts +68 -0
  24. package/lib/codexChatDocumentUtils.js +480 -0
  25. package/lib/codexChatDocumentUtils.js.map +1 -0
  26. package/lib/codexChatFormatting.d.ts +11 -0
  27. package/lib/codexChatFormatting.js +83 -0
  28. package/lib/codexChatFormatting.js.map +1 -0
  29. package/lib/codexChatNotice.d.ts +3 -0
  30. package/lib/codexChatNotice.js +74 -0
  31. package/lib/codexChatNotice.js.map +1 -0
  32. package/lib/codexChatPersistence.d.ts +35 -0
  33. package/lib/codexChatPersistence.js +158 -0
  34. package/lib/codexChatPersistence.js.map +1 -0
  35. package/lib/codexChatPrimitives.d.ts +41 -0
  36. package/lib/codexChatPrimitives.js +152 -0
  37. package/lib/codexChatPrimitives.js.map +1 -0
  38. package/lib/codexChatRender.d.ts +24 -0
  39. package/lib/codexChatRender.js +293 -0
  40. package/lib/codexChatRender.js.map +1 -0
  41. package/lib/codexChatSessionFactory.d.ts +15 -0
  42. package/lib/codexChatSessionFactory.js +45 -0
  43. package/lib/codexChatSessionFactory.js.map +1 -0
  44. package/lib/codexChatSessionKey.d.ts +3 -0
  45. package/lib/codexChatSessionKey.js +14 -0
  46. package/lib/codexChatSessionKey.js.map +1 -0
  47. package/lib/codexChatStorage.d.ts +4 -0
  48. package/lib/codexChatStorage.js +37 -0
  49. package/lib/codexChatStorage.js.map +1 -0
  50. package/lib/codexSessionResolver.d.ts +12 -0
  51. package/lib/codexSessionResolver.js +38 -0
  52. package/lib/codexSessionResolver.js.map +1 -0
  53. package/lib/handlers/activitySummarizer.d.ts +15 -0
  54. package/lib/handlers/activitySummarizer.js +327 -0
  55. package/lib/handlers/activitySummarizer.js.map +1 -0
  56. package/lib/handlers/codexMessageTypes.d.ts +30 -0
  57. package/lib/handlers/codexMessageTypes.js +2 -0
  58. package/lib/handlers/codexMessageTypes.js.map +1 -0
  59. package/lib/handlers/codexMessageUtils.d.ts +46 -0
  60. package/lib/handlers/codexMessageUtils.js +144 -0
  61. package/lib/handlers/codexMessageUtils.js.map +1 -0
  62. package/lib/handlers/handleCodexSocketMessage.d.ts +107 -0
  63. package/lib/handlers/handleCodexSocketMessage.js +78 -0
  64. package/lib/handlers/handleCodexSocketMessage.js.map +1 -0
  65. package/lib/handlers/sessionSyncHandler.d.ts +34 -0
  66. package/lib/handlers/sessionSyncHandler.js +181 -0
  67. package/lib/handlers/sessionSyncHandler.js.map +1 -0
  68. package/lib/hooks/useCodexSocket.d.ts +15 -0
  69. package/lib/hooks/useCodexSocket.js +84 -0
  70. package/lib/hooks/useCodexSocket.js.map +1 -0
  71. package/lib/index.js +1 -1
  72. package/lib/index.js.map +1 -1
  73. package/lib/panel.d.ts +1 -11
  74. package/lib/panel.js +1 -2768
  75. package/lib/panel.js.map +1 -1
  76. package/lib/protocol.d.ts +235 -0
  77. package/lib/protocol.js +278 -0
  78. package/lib/protocol.js.map +1 -0
  79. package/package.json +13 -3
  80. package/playwright.config.cjs +24 -0
  81. package/playwright.unit.config.cjs +19 -0
  82. package/pyproject.toml +1 -1
  83. package/release.sh +243 -0
  84. package/scripts/run_playwright_e2e.sh +96 -0
  85. package/scripts/run_playwright_freeze_repro.sh +58 -0
  86. package/scripts/run_playwright_queue_repro.sh +60 -0
  87. package/scripts/run_playwright_repro.sh +55 -0
  88. package/src/codexChat.tsx +3755 -0
  89. package/src/codexChatAttachmentDedup.ts +47 -0
  90. package/src/codexChatAttachmentLimit.ts +82 -0
  91. package/src/codexChatDocumentUtils.ts +612 -0
  92. package/src/codexChatFormatting.ts +94 -0
  93. package/src/codexChatNotice.ts +95 -0
  94. package/src/codexChatPersistence.ts +191 -0
  95. package/src/codexChatPrimitives.tsx +422 -0
  96. package/src/codexChatRender.tsx +376 -0
  97. package/src/codexChatSessionFactory.ts +79 -0
  98. package/src/codexChatSessionKey.ts +16 -0
  99. package/src/codexChatStorage.ts +36 -0
  100. package/src/codexSessionResolver.ts +56 -0
  101. package/src/handlers/activitySummarizer.ts +369 -0
  102. package/src/handlers/codexMessageTypes.ts +34 -0
  103. package/src/handlers/codexMessageUtils.ts +217 -0
  104. package/src/handlers/handleCodexSocketMessage.ts +204 -0
  105. package/src/handlers/sessionSyncHandler.ts +308 -0
  106. package/src/hooks/useCodexSocket.ts +109 -0
  107. package/src/index.ts +1 -1
  108. package/src/panel.tsx +1 -4131
  109. package/src/protocol.ts +582 -0
  110. package/style/index.css +424 -11
  111. package/tests/e2e/fixtures/notebooks/tab1.ipynb +322 -0
  112. package/tests/e2e/fixtures/notebooks/tab1.py +272 -0
  113. package/tests/e2e/fixtures/notebooks/tab2.ipynb +252 -0
  114. package/tests/e2e/fixtures/notebooks/tab2.py +231 -0
  115. package/tests/e2e/fixtures/notebooks/tab3.ipynb +403 -0
  116. package/tests/e2e/fixtures/notebooks/tab3.py +331 -0
  117. package/tests/e2e/fixtures/notebooks/tab4.py +339 -0
  118. package/tests/e2e/freeze-notebook-tabs-repro.spec.js +295 -0
  119. package/tests/e2e/mock-codex-cli-flood.py +127 -0
  120. package/tests/e2e/mock-codex-cli.py +95 -0
  121. package/tests/e2e/queue-multitab-repro.spec.js +189 -0
  122. package/tests/test_handlers.py +116 -0
  123. package/tests/test_protocol.py +169 -0
  124. package/tests/test_session_store_limits.py +50 -0
  125. package/tests/unit/codexChatAttachmentDedup.spec.ts +56 -0
  126. package/tests/unit/codexChatAttachmentLimit.spec.ts +42 -0
  127. package/tests/unit/codexChatLimit.spec.ts +18 -0
  128. package/tests/unit/codexChatNotice.spec.ts +45 -0
  129. package/tests/unit/codexChatPersistence.spec.ts +199 -0
  130. package/tests/unit/codexChatSessionFactory.spec.ts +94 -0
  131. package/tests/unit/codexChatSessionKey.spec.ts +18 -0
  132. package/tests/unit/codexMessageUtils.spec.ts +89 -0
  133. package/tests/unit/codexSessionResolver.spec.ts +92 -0
  134. package/tests/unit/handleCodexSocketMessage.spec.ts +476 -0
  135. package/tsconfig.tsbuildinfo +1 -1
  136. package/webpack.config.js +6 -0
  137. package/jupyterlab_codex/labextension/static/504.335f3447c84ba3d74517.js +0 -2
  138. package/jupyterlab_codex/labextension/static/972.d43137b7438a053eeb72.js +0 -1
  139. /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
package/AGENTS.md CHANGED
@@ -46,3 +46,45 @@
46
46
 
47
47
  - User-facing UI labels, buttons, notices, dialogs, and system messages must always be displayed in English.
48
48
  - Do not introduce Korean (or other non-English) UI strings in code changes.
49
+
50
+ ## 배포 프로세스 (이 레포지토리 전용)
51
+
52
+ 이 프로젝트(`jupyterlab-codex-sidebar`)는 Python 패키지(PyPI)와 JupyterLab 확장 패키지(NPM) 모두 배포해야 JupyterLab Discovery에 안정적으로 노출되고 서버 확장이 함께 동작합니다.
53
+
54
+ 1) 사전 점검
55
+ - `npm`, `node`, `jlpm`, `jupyter`, `twine`, `python`(또는 `python3`)이 설치돼 있어야 함
56
+ - PyPI/NPM 계정 토큰 준비
57
+ - 현재 변경사항은 커밋/브랜치 정리 후 진행
58
+
59
+ 2) 릴리스 버전 규칙
60
+ - `package.json`과 `pyproject.toml`의 버전은 항상 동일해야 함
61
+ - 동일 버전으로 재업로드 시도 불가(Python dist는 파일명 재사용 불가로 400 에러 발생)
62
+ - `x.y.z` 형식(SemVer)으로 bump
63
+
64
+ 3) 권장 릴리스 명령(전체 배포)
65
+ - `./release.sh <new_version>`
66
+ - 예) `./release.sh 0.1.4`
67
+
68
+ 4) 릴리스 스크립트 동작
69
+ - 버전 동기화 (`package.json`, `pyproject.toml`)
70
+ - `jlpm install`
71
+ - `jlpm run build`
72
+ - 이전 `dist/` 정리
73
+ - `python -m build` 실행 (`dist/*.tar.gz`, `dist/*.whl` 생성)
74
+ - `twine`로 PyPI 업로드
75
+ - `npm publish --access public` 실행
76
+
77
+ 5) 선택 업로드
78
+ - PyPI만: `./release.sh 0.1.4 --skip-npm`
79
+ - npm만: `./release.sh 0.1.4 --skip-pypi`
80
+ - 테스트 업로드: `./release.sh 0.1.4 --repository testpypi`
81
+
82
+ 6) 배포 후 확인
83
+ - PyPI: `pip index versions jupyterlab-codex-sidebar`
84
+ - npm: `npm view jupyterlab-codex-sidebar`
85
+ - 사용자 설치 확인(예): `pip install jupyterlab-codex-sidebar==<버전>`
86
+ - JupyterLab Extension Manager에서 `jupyterlab-codex-sidebar` 검색/표시 확인
87
+
88
+ 7) 기존 실수 방지 규칙
89
+ - `release.sh` 실행 전 `dist/`에 남은 이전 버전 파일을 지워도 되지만, 가장 중요하게 `release.sh`는 새 버전으로만 실행해야 함
90
+ - 400 에러(duplicate file)는 대개 버전 미갱신 또는 dist 재생성 누락 때문에 발생
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,10 @@ 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, preserves Jupytext structure/markers
63
+ - `.py` (`plain_py`): sends `selection` only when text is explicitly selected, and avoids introducing Jupytext markers unless requested
55
64
  - Conversation/session logs: `~/.jupyter/codex-sessions/`
56
65
  - Optional usage snapshot: best-effort scan of recent `~/.codex/sessions/`
57
66
 
@@ -134,6 +143,11 @@ jupyter lab
134
143
  - Include active cell output
135
144
  - Model / Reasoning Effort / Permission
136
145
 
146
+ Mode-specific context rules:
147
+ - `cellOutput` is sent only in `.ipynb` mode.
148
+ - In `.py` modes, `cellOutput` is not sent (`cellOutput` key is omitted).
149
+ - In `plain_py` mode, `selection` is sent only when text is explicitly selected; otherwise the `selection` key is omitted.
150
+
137
151
  ## Configuration
138
152
  Server-side defaults can also be set via environment variables:
139
153
  - `JUPYTERLAB_CODEX_MODEL`: default model when unset in UI/command
@@ -171,6 +185,37 @@ Selected UI values are passed as CLI args.
171
185
  - UI: `src/panel.tsx`
172
186
  - Server: `jupyterlab_codex/handlers.py`, `jupyterlab_codex/runner.py`
173
187
 
188
+ ## Playwright E2E (3-tab freeze reproduction)
189
+ - Purpose: reproduce the "send while previous run is still running across 3 notebook tabs" scenario.
190
+ - This suite uses a local mock Codex CLI (`tests/e2e/mock-codex-cli.py`) so it does not require real Codex auth.
191
+
192
+ Setup once:
193
+
194
+ ```bash
195
+ jlpm install
196
+ jlpm test:e2e:install
197
+ ```
198
+
199
+ Run with auto-launched JupyterLab:
200
+
201
+ ```bash
202
+ jlpm test:e2e:repro-local
203
+ ```
204
+
205
+ Or run against an already running JupyterLab:
206
+
207
+ ```bash
208
+ PLAYWRIGHT_BASE_URL="http://127.0.0.1:8888/lab" \
209
+ PLAYWRIGHT_CODEX_COMMAND="$(pwd)/tests/e2e/mock-codex-cli.py" \
210
+ jlpm test:e2e:queue-repro
211
+ ```
212
+
213
+ Files:
214
+ - Playwright config: `playwright.config.cjs`
215
+ - Test spec: `tests/e2e/queue-multitab-repro.spec.js`
216
+ - Mock CLI: `tests/e2e/mock-codex-cli.py`
217
+ - Notebook fixtures: `tests/e2e/fixtures/notebooks/`
218
+
174
219
  ## Architecture
175
220
  ```
176
221
  [UI (JupyterLab Sidebar)]
@@ -210,8 +255,11 @@ Selected UI values are passed as CLI args.
210
255
  2. JupyterLab 재실행
211
256
  3. 우측 사이드바에 `Codex` 패널이 보이는지 확인
212
257
 
213
- 4) Jupytext 페어링 만들기 (`.ipynb` <-> `.py`)
214
- - 확장은 Jupytext 페어링 워크플로우를 전제로 합니다.
258
+ 4) 문서 모드(`.ipynb` / `.py`)
259
+ - `.ipynb` 모드: 같은 이름의 페어 `.py` 파일이 필요합니다.
260
+ - `.py` 모드: 페어 `.ipynb`가 없어도 동작합니다.
261
+ - `jupytext_py`: Jupytext 메타데이터/헤더 또는 `# %%` 셀 마커가 있으면 감지
262
+ - `plain_py`: Jupytext 마커가 없는 일반 Python 스크립트로 감지
215
263
 
216
264
  ### A. `.ipynb` 파일에서 시작할 때
217
265
  1. 노트북(`.ipynb`) 열기
@@ -225,7 +273,9 @@ Selected UI values are passed as CLI args.
225
273
  3. `.ipynb` 포맷으로 페어링
226
274
  4. 같은 이름의 `.ipynb` 파일이 생성되었는지 확인
227
275
 
228
- 참고: Codex 사이드바 사용 시에는 같은 이름의 `.ipynb`와 `.py` 페어가 모두 있어야 합니다.
276
+ 참고:
277
+ - `.ipynb` 모드에서는 같은 이름의 페어 `.py`가 반드시 있어야 합니다.
278
+ - `.py` 모드에서는 페어링이 선택 사항입니다.
229
279
 
230
280
  JupyterLab 4 우측 사이드바에서 Codex CLI(`codex exec --json`)를 채팅 UI로 사용할 수 있게 해주는 확장입니다.
231
281
 
@@ -239,7 +289,10 @@ JupyterLab 4 우측 사이드바에서 Codex CLI(`codex exec --json`)를 채팅
239
289
  - 노트북 경로 기준으로 스레드(세션) 분리
240
290
  - 모델 / Reasoning Effort / 샌드박스 권한을 UI에서 선택
241
291
  - 활성 셀 텍스트를 프롬프트에 포함할지 선택
242
- - `.ipynb` `.py`(Jupytext paired) 워크플로우를 전제로 동작(페어링된 `.py`가 없으면 실행이 비활성화됨)
292
+ - 파일 타입별 모드 동작
293
+ - `.ipynb`: 페어 `.py`가 필요하며, active cell/context 및 active cell output을 전송
294
+ - `.py` (`jupytext_py`): active cell context를 전송하고 Jupytext 구조/마커를 보존
295
+ - `.py` (`plain_py`): 텍스트를 명시적으로 선택한 경우에만 `selection`을 전송하고, 요청 없이는 Jupytext 마커를 추가하지 않음
243
296
  - 세션 로그 저장: `~/.jupyter/codex-sessions/`
244
297
  - (가능한 경우) Codex 사용량 스냅샷 표시: `~/.codex/sessions/` 를 best-effort로 스캔
245
298
 
@@ -334,6 +387,11 @@ jupyter lab
334
387
  - Include active cell output: 활성 셀 output(텍스트 위주)을 프롬프트에 포함
335
388
  - Model / Reasoning Effort / Permission(샌드박스)
336
389
 
390
+ 모드별 컨텍스트 전송 규칙:
391
+ - `cellOutput`은 `.ipynb` 모드에서만 전송됩니다.
392
+ - `.py` 모드에서는 `cellOutput` key 자체를 보내지 않습니다.
393
+ - `plain_py` 모드에서는 텍스트를 명시적으로 선택한 경우에만 `selection` key를 보내며, 선택이 없으면 key를 보내지 않습니다.
394
+
337
395
  ## 설정(옵션)
338
396
  서버 측 기본값은 환경 변수로도 지정할 수 있습니다.
339
397
  - `JUPYTERLAB_CODEX_MODEL`: 모델을 명시하지 않았을 때 기본 모델로 사용