tithon 0.2.2__tar.gz → 0.2.3__tar.gz

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 (279) hide show
  1. tithon-0.2.3/.git-blame-ignore-revs +9 -0
  2. tithon-0.2.3/.release-please-manifest.json +4 -0
  3. tithon-0.2.3/.vscode/extensions.json +3 -0
  4. tithon-0.2.3/.vscode/settings.json +28 -0
  5. {tithon-0.2.2 → tithon-0.2.3}/CHANGELOG.md +19 -0
  6. {tithon-0.2.2 → tithon-0.2.3}/PKG-INFO +29 -2
  7. {tithon-0.2.2 → tithon-0.2.3}/README.md +28 -1
  8. {tithon-0.2.2 → tithon-0.2.3}/docs/SPEC.md +46 -5
  9. {tithon-0.2.2 → tithon-0.2.3}/extension/CHANGELOG.md +16 -0
  10. {tithon-0.2.2 → tithon-0.2.3}/extension/README.md +19 -2
  11. tithon-0.2.3/extension/biome.json +39 -0
  12. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/runTest.ts +8 -4
  13. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/seed.ts +3 -3
  14. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/addcell.test.ts +5 -2
  15. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/autoopen.test.ts +41 -15
  16. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/autostart.test.ts +31 -12
  17. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/bug_addmd.test.ts +11 -5
  18. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/bug_editsave.test.ts +13 -5
  19. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/bug_emptycell.test.ts +47 -13
  20. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/bug_imageorder.test.ts +31 -9
  21. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/bug_input_hang.test.ts +52 -15
  22. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/bug_insert_reconnect.test.ts +52 -19
  23. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/bug_insertheader.test.ts +6 -4
  24. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/bug_kerneldeath.test.ts +14 -5
  25. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/bug_mdsave.test.ts +5 -3
  26. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/bug_rerun.test.ts +50 -18
  27. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/bug_rerun_reconnect.test.ts +56 -18
  28. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/bug_runall_error.test.ts +33 -10
  29. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/bug_runall_md.test.ts +15 -5
  30. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/bug_staleedit.test.ts +43 -14
  31. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/celltoggle.test.ts +54 -21
  32. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/clearspinner.test.ts +34 -15
  33. tithon-0.2.3/extension/integration/suite/closedsession.test.ts +161 -0
  34. tithon-0.2.3/extension/integration/suite/confirmdestructive.test.ts +175 -0
  35. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/crosscell.test.ts +40 -14
  36. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/demo.test.ts +70 -26
  37. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/disposeflush.test.ts +28 -14
  38. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/dupcode.test.ts +18 -7
  39. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/editedcell.test.ts +6 -7
  40. tithon-0.2.3/extension/integration/suite/editorpin.test.ts +465 -0
  41. tithon-0.2.3/extension/integration/suite/index.ts +44 -0
  42. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/interrupt.test.ts +48 -13
  43. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/live.test.ts +19 -10
  44. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/livedisplay.test.ts +16 -9
  45. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/livereconnect.test.ts +57 -18
  46. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/lsp.test.ts +45 -23
  47. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/lspdef.test.ts +26 -13
  48. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/lspinlay.test.ts +63 -24
  49. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/lsproundtrip.test.ts +37 -19
  50. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/multicell.test.ts +29 -13
  51. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/opentextshot.test.ts +6 -10
  52. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/orphanrestore.test.ts +18 -7
  53. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/reconnect.test.ts +48 -19
  54. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/reconnectprogress.test.ts +41 -17
  55. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/reconnectstates.test.ts +54 -19
  56. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/reopen.test.ts +24 -9
  57. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/reopenafterroundtrip.test.ts +38 -15
  58. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/restartdaemon.test.ts +45 -18
  59. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/restartkernel.test.ts +27 -10
  60. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/restore.test.ts +2 -4
  61. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/richoutputs.test.ts +73 -31
  62. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/runcell.test.ts +14 -4
  63. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/screenshot.test.ts +23 -11
  64. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/trainloop.test.ts +41 -18
  65. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/trainsync.test.ts +89 -35
  66. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/twofiles.test.ts +22 -8
  67. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/widget.test.ts +31 -11
  68. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/widgetdisposeflush.test.ts +24 -8
  69. {tithon-0.2.2 → tithon-0.2.3}/extension/integration/suite/widgetlive.test.ts +33 -10
  70. {tithon-0.2.2 → tithon-0.2.3}/extension/package-lock.json +303 -7
  71. {tithon-0.2.2 → tithon-0.2.3}/extension/package.json +71 -8
  72. {tithon-0.2.2 → tithon-0.2.3}/extension/src/cellAttach.ts +8 -7
  73. {tithon-0.2.2 → tithon-0.2.3}/extension/src/codeLens.ts +1 -1
  74. {tithon-0.2.2 → tithon-0.2.3}/extension/src/daemonClient.ts +30 -15
  75. {tithon-0.2.2 → tithon-0.2.3}/extension/src/daemonProcess.ts +39 -17
  76. tithon-0.2.3/extension/src/extension.ts +681 -0
  77. {tithon-0.2.2 → tithon-0.2.3}/extension/src/liveSync.ts +10 -12
  78. {tithon-0.2.2 → tithon-0.2.3}/extension/src/notebookSerializer.ts +6 -12
  79. tithon-0.2.3/extension/src/notify.ts +69 -0
  80. {tithon-0.2.2 → tithon-0.2.3}/extension/src/outputFold.ts +19 -3
  81. {tithon-0.2.2 → tithon-0.2.3}/extension/src/richOutput.ts +25 -15
  82. {tithon-0.2.2 → tithon-0.2.3}/extension/src/serializer.ts +7 -7
  83. {tithon-0.2.2 → tithon-0.2.3}/extension/src/sessionClient.ts +93 -37
  84. {tithon-0.2.2 → tithon-0.2.3}/extension/src/sessionController.ts +338 -153
  85. {tithon-0.2.2 → tithon-0.2.3}/extension/src/tracebackFormatter.ts +3 -2
  86. {tithon-0.2.2 → tithon-0.2.3}/extension/src/widgetRender.ts +4 -6
  87. {tithon-0.2.2 → tithon-0.2.3}/extension/src/widgetRendererEntry.ts +16 -17
  88. {tithon-0.2.2 → tithon-0.2.3}/extension/test/artifactCache.test.ts +16 -4
  89. {tithon-0.2.2 → tithon-0.2.3}/extension/test/cellAttach.test.ts +23 -5
  90. tithon-0.2.3/extension/test/closedSession.test.ts +98 -0
  91. {tithon-0.2.2 → tithon-0.2.3}/extension/test/fakeDaemon.ts +19 -7
  92. {tithon-0.2.2 → tithon-0.2.3}/extension/test/kernelGeneration.test.ts +38 -15
  93. {tithon-0.2.2 → tithon-0.2.3}/extension/test/liveDaemon.ts +3 -3
  94. {tithon-0.2.2 → tithon-0.2.3}/extension/test/liveSync.test.ts +46 -15
  95. tithon-0.2.3/extension/test/notify.test.ts +86 -0
  96. {tithon-0.2.2 → tithon-0.2.3}/extension/test/outputFold.test.ts +79 -23
  97. {tithon-0.2.2 → tithon-0.2.3}/extension/test/reconnectClient.test.ts +7 -4
  98. {tithon-0.2.2 → tithon-0.2.3}/extension/test/restore.test.ts +5 -4
  99. {tithon-0.2.2 → tithon-0.2.3}/extension/test/richDaemon.test.ts +12 -6
  100. {tithon-0.2.2 → tithon-0.2.3}/extension/test/richOutput.test.ts +50 -12
  101. {tithon-0.2.2 → tithon-0.2.3}/extension/test/serializer.test.ts +15 -24
  102. {tithon-0.2.2 → tithon-0.2.3}/extension/test/setup.ts +1 -5
  103. {tithon-0.2.2 → tithon-0.2.3}/extension/test/tracebackFormatter.test.ts +8 -4
  104. tithon-0.2.3/extension/test/vscodeMock.ts +75 -0
  105. {tithon-0.2.2 → tithon-0.2.3}/extension/test/widget.test.ts +6 -5
  106. {tithon-0.2.2 → tithon-0.2.3}/extension/test/widgetBuffers.test.ts +24 -9
  107. {tithon-0.2.2 → tithon-0.2.3}/extension/test/widgetEvents.test.ts +26 -11
  108. tithon-0.2.3/extension/vitest.config.ts +24 -0
  109. {tithon-0.2.2 → tithon-0.2.3}/pyproject.toml +27 -2
  110. {tithon-0.2.2 → tithon-0.2.3}/scripts/_check_input_bridge.py +3 -1
  111. {tithon-0.2.2 → tithon-0.2.3}/scripts/_check_interrupt_priority.py +24 -14
  112. {tithon-0.2.2 → tithon-0.2.3}/scripts/_check_kernel_death.py +17 -6
  113. {tithon-0.2.2 → tithon-0.2.3}/scripts/_check_multi.py +73 -37
  114. {tithon-0.2.2 → tithon-0.2.3}/scripts/_check_v1.py +4 -1
  115. {tithon-0.2.2 → tithon-0.2.3}/scripts/_check_v2.py +1 -0
  116. {tithon-0.2.2 → tithon-0.2.3}/scripts/_check_v3.py +2 -3
  117. {tithon-0.2.2 → tithon-0.2.3}/scripts/_check_v5.py +3 -6
  118. {tithon-0.2.2 → tithon-0.2.3}/scripts/_clear_client.py +8 -4
  119. tithon-0.2.3/scripts/_clone_client.py +75 -0
  120. {tithon-0.2.2 → tithon-0.2.3}/scripts/_lastseq.py +1 -0
  121. {tithon-0.2.2 → tithon-0.2.3}/scripts/_multi_client.py +17 -7
  122. {tithon-0.2.2 → tithon-0.2.3}/scripts/_stalled_client.py +1 -0
  123. {tithon-0.2.2 → tithon-0.2.3}/scripts/_workdir_client.py +18 -8
  124. {tithon-0.2.2 → tithon-0.2.3}/scripts/run_verify.sh +10 -10
  125. {tithon-0.2.2 → tithon-0.2.3}/scripts/v39.sh +2 -2
  126. tithon-0.2.3/scripts/v61.sh +98 -0
  127. tithon-0.2.3/scripts/v62.sh +78 -0
  128. tithon-0.2.3/scripts/v63.sh +41 -0
  129. tithon-0.2.3/scripts/v64.sh +95 -0
  130. tithon-0.2.3/scripts/v65.sh +61 -0
  131. {tithon-0.2.2 → tithon-0.2.3}/src/tithon/__main__.py +1 -0
  132. {tithon-0.2.2 → tithon-0.2.3}/src/tithon/artifacts.py +1 -0
  133. {tithon-0.2.2 → tithon-0.2.3}/src/tithon/cli.py +15 -6
  134. {tithon-0.2.2 → tithon-0.2.3}/src/tithon/daemon.py +381 -131
  135. {tithon-0.2.2 → tithon-0.2.3}/src/tithon/folding.py +36 -8
  136. {tithon-0.2.2 → tithon-0.2.3}/src/tithon/journal.py +164 -39
  137. {tithon-0.2.2 → tithon-0.2.3}/src/tithon/kernel.py +1 -0
  138. tithon-0.2.3/src/tithon/sidecar.py +258 -0
  139. {tithon-0.2.2 → tithon-0.2.3}/src/tithon/widgets.py +8 -4
  140. {tithon-0.2.2 → tithon-0.2.3}/test/test_artifacts.py +17 -6
  141. {tithon-0.2.2 → tithon-0.2.3}/test/test_backpressure.py +1 -2
  142. {tithon-0.2.2 → tithon-0.2.3}/test/test_barrier.py +11 -5
  143. {tithon-0.2.2 → tithon-0.2.3}/test/test_clear.py +4 -3
  144. tithon-0.2.3/test/test_closed_by_user.py +87 -0
  145. {tithon-0.2.2 → tithon-0.2.3}/test/test_comm_ordering.py +16 -4
  146. {tithon-0.2.2 → tithon-0.2.3}/test/test_display_registry.py +7 -10
  147. {tithon-0.2.2 → tithon-0.2.3}/test/test_folding.py +165 -79
  148. {tithon-0.2.2 → tithon-0.2.3}/test/test_gc.py +1 -0
  149. {tithon-0.2.2 → tithon-0.2.3}/test/test_inflight_recovery.py +20 -19
  150. {tithon-0.2.2 → tithon-0.2.3}/test/test_journal_origin.py +21 -5
  151. {tithon-0.2.2 → tithon-0.2.3}/test/test_kernel_group_kill.py +1 -0
  152. {tithon-0.2.2 → tithon-0.2.3}/test/test_kill_restart_race.py +1 -0
  153. {tithon-0.2.2 → tithon-0.2.3}/test/test_liveness.py +7 -7
  154. {tithon-0.2.2 → tithon-0.2.3}/test/test_lost_state.py +10 -5
  155. {tithon-0.2.2 → tithon-0.2.3}/test/test_orphan.py +5 -2
  156. {tithon-0.2.2 → tithon-0.2.3}/test/test_payload.py +1 -0
  157. {tithon-0.2.2 → tithon-0.2.3}/test/test_rebuild_mirror_streaming.py +29 -12
  158. {tithon-0.2.2 → tithon-0.2.3}/test/test_restart_drain.py +4 -4
  159. {tithon-0.2.2 → tithon-0.2.3}/test/test_runall_batch.py +5 -9
  160. {tithon-0.2.2 → tithon-0.2.3}/test/test_session_layout.py +5 -4
  161. tithon-0.2.3/test/test_sidecar.py +547 -0
  162. {tithon-0.2.2 → tithon-0.2.3}/test/test_widget_buffer_delta.py +36 -11
  163. {tithon-0.2.2 → tithon-0.2.3}/test/test_widgets.py +46 -20
  164. {tithon-0.2.2 → tithon-0.2.3}/uv.lock +28 -1
  165. tithon-0.2.2/.release-please-manifest.json +0 -4
  166. tithon-0.2.2/extension/integration/suite/index.ts +0 -25
  167. tithon-0.2.2/extension/src/extension.ts +0 -499
  168. tithon-0.2.2/extension/vitest.config.ts +0 -14
  169. {tithon-0.2.2 → tithon-0.2.3}/.claude/settings.local.json +0 -0
  170. {tithon-0.2.2 → tithon-0.2.3}/.gitattributes +0 -0
  171. {tithon-0.2.2 → tithon-0.2.3}/.github/scripts/format-release-pr-body.js +0 -0
  172. {tithon-0.2.2 → tithon-0.2.3}/.github/scripts/format-release-pr-body.test.js +0 -0
  173. {tithon-0.2.2 → tithon-0.2.3}/.github/workflows/release-please.yml +0 -0
  174. {tithon-0.2.2 → tithon-0.2.3}/.gitignore +0 -0
  175. {tithon-0.2.2 → tithon-0.2.3}/LICENSE +0 -0
  176. {tithon-0.2.2 → tithon-0.2.3}/docs/demo.gif +0 -0
  177. {tithon-0.2.2 → tithon-0.2.3}/docs/demo.mp4 +0 -0
  178. {tithon-0.2.2 → tithon-0.2.3}/docs/how-it-works.png +0 -0
  179. {tithon-0.2.2 → tithon-0.2.3}/docs/index.html +0 -0
  180. {tithon-0.2.2 → tithon-0.2.3}/docs/known_issue.md +0 -0
  181. {tithon-0.2.2 → tithon-0.2.3}/docs/vscode-jupyter-comparison.md +0 -0
  182. {tithon-0.2.2 → tithon-0.2.3}/extension/.vscodeignore +0 -0
  183. {tithon-0.2.2 → tithon-0.2.3}/extension/LICENSE +0 -0
  184. {tithon-0.2.2 → tithon-0.2.3}/extension/esbuild.mjs +0 -0
  185. {tithon-0.2.2 → tithon-0.2.3}/extension/icon.png +0 -0
  186. {tithon-0.2.2 → tithon-0.2.3}/extension/src/artifactCache.ts +0 -0
  187. {tithon-0.2.2 → tithon-0.2.3}/extension/src/css.d.ts +0 -0
  188. {tithon-0.2.2 → tithon-0.2.3}/extension/src/widgetTheme.css +0 -0
  189. {tithon-0.2.2 → tithon-0.2.3}/extension/test/fixtures/tqdm_widget_state.json +0 -0
  190. {tithon-0.2.2 → tithon-0.2.3}/extension/tsconfig.integration.json +0 -0
  191. {tithon-0.2.2 → tithon-0.2.3}/extension/tsconfig.json +0 -0
  192. {tithon-0.2.2 → tithon-0.2.3}/release-please-config.json +0 -0
  193. {tithon-0.2.2 → tithon-0.2.3}/scripts/Makefile +0 -0
  194. {tithon-0.2.2 → tithon-0.2.3}/scripts/bughunt.sh +0 -0
  195. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/_gen.py +0 -0
  196. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/bughunt/dup_run.py +0 -0
  197. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/bughunt/editsave.py +0 -0
  198. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/bughunt/editsave_crlf.py +0 -0
  199. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/bughunt/empty_cells.py +0 -0
  200. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/bughunt/header.py +0 -0
  201. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/bughunt/imageorder.py +0 -0
  202. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/bughunt/input_hang.py +0 -0
  203. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/bughunt/kerneldeath.py +0 -0
  204. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/bughunt/mdcell.py +0 -0
  205. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/bughunt/one_cell.py +0 -0
  206. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/bughunt/rerun.py +0 -0
  207. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/bughunt/runall_error.py +0 -0
  208. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/bughunt/runall_md.py +0 -0
  209. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/bughunt/two_cell.py +0 -0
  210. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/crlf_mixed.py +0 -0
  211. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/crlf_string_marker.py +0 -0
  212. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/empty_cells.py +0 -0
  213. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/magics_markdown.py +0 -0
  214. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/mixed_indent.py +0 -0
  215. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/module_header.py +0 -0
  216. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/no_final_newline.py +0 -0
  217. {tithon-0.2.2 → tithon-0.2.3}/scripts/corpus/string_marker.py +0 -0
  218. {tithon-0.2.2 → tithon-0.2.3}/scripts/demo_reconnect.sh +0 -0
  219. {tithon-0.2.2 → tithon-0.2.3}/scripts/lib.sh +0 -0
  220. {tithon-0.2.2 → tithon-0.2.3}/scripts/record_demo.sh +0 -0
  221. {tithon-0.2.2 → tithon-0.2.3}/scripts/shot.sh +0 -0
  222. {tithon-0.2.2 → tithon-0.2.3}/scripts/shotlsp.sh +0 -0
  223. {tithon-0.2.2 → tithon-0.2.3}/scripts/v1.sh +0 -0
  224. {tithon-0.2.2 → tithon-0.2.3}/scripts/v10.sh +0 -0
  225. {tithon-0.2.2 → tithon-0.2.3}/scripts/v11.sh +0 -0
  226. {tithon-0.2.2 → tithon-0.2.3}/scripts/v12.sh +0 -0
  227. {tithon-0.2.2 → tithon-0.2.3}/scripts/v13.sh +0 -0
  228. {tithon-0.2.2 → tithon-0.2.3}/scripts/v14.sh +0 -0
  229. {tithon-0.2.2 → tithon-0.2.3}/scripts/v15.sh +0 -0
  230. {tithon-0.2.2 → tithon-0.2.3}/scripts/v16.sh +0 -0
  231. {tithon-0.2.2 → tithon-0.2.3}/scripts/v17.sh +0 -0
  232. {tithon-0.2.2 → tithon-0.2.3}/scripts/v18.sh +0 -0
  233. {tithon-0.2.2 → tithon-0.2.3}/scripts/v19.sh +0 -0
  234. {tithon-0.2.2 → tithon-0.2.3}/scripts/v2.sh +0 -0
  235. {tithon-0.2.2 → tithon-0.2.3}/scripts/v20.sh +0 -0
  236. {tithon-0.2.2 → tithon-0.2.3}/scripts/v21.sh +0 -0
  237. {tithon-0.2.2 → tithon-0.2.3}/scripts/v22.sh +0 -0
  238. {tithon-0.2.2 → tithon-0.2.3}/scripts/v23.sh +0 -0
  239. {tithon-0.2.2 → tithon-0.2.3}/scripts/v24.sh +0 -0
  240. {tithon-0.2.2 → tithon-0.2.3}/scripts/v26.sh +0 -0
  241. {tithon-0.2.2 → tithon-0.2.3}/scripts/v27.sh +0 -0
  242. {tithon-0.2.2 → tithon-0.2.3}/scripts/v28.sh +0 -0
  243. {tithon-0.2.2 → tithon-0.2.3}/scripts/v29.sh +0 -0
  244. {tithon-0.2.2 → tithon-0.2.3}/scripts/v3.sh +0 -0
  245. {tithon-0.2.2 → tithon-0.2.3}/scripts/v30.sh +0 -0
  246. {tithon-0.2.2 → tithon-0.2.3}/scripts/v31.sh +0 -0
  247. {tithon-0.2.2 → tithon-0.2.3}/scripts/v32.sh +0 -0
  248. {tithon-0.2.2 → tithon-0.2.3}/scripts/v33.sh +0 -0
  249. {tithon-0.2.2 → tithon-0.2.3}/scripts/v34.sh +0 -0
  250. {tithon-0.2.2 → tithon-0.2.3}/scripts/v35.sh +0 -0
  251. {tithon-0.2.2 → tithon-0.2.3}/scripts/v37.sh +0 -0
  252. {tithon-0.2.2 → tithon-0.2.3}/scripts/v38.sh +0 -0
  253. {tithon-0.2.2 → tithon-0.2.3}/scripts/v4.sh +0 -0
  254. {tithon-0.2.2 → tithon-0.2.3}/scripts/v40.sh +0 -0
  255. {tithon-0.2.2 → tithon-0.2.3}/scripts/v41.sh +0 -0
  256. {tithon-0.2.2 → tithon-0.2.3}/scripts/v42.sh +0 -0
  257. {tithon-0.2.2 → tithon-0.2.3}/scripts/v43.sh +0 -0
  258. {tithon-0.2.2 → tithon-0.2.3}/scripts/v44.sh +0 -0
  259. {tithon-0.2.2 → tithon-0.2.3}/scripts/v45.sh +0 -0
  260. {tithon-0.2.2 → tithon-0.2.3}/scripts/v46.sh +0 -0
  261. {tithon-0.2.2 → tithon-0.2.3}/scripts/v47.sh +0 -0
  262. {tithon-0.2.2 → tithon-0.2.3}/scripts/v48.sh +0 -0
  263. {tithon-0.2.2 → tithon-0.2.3}/scripts/v49.sh +0 -0
  264. {tithon-0.2.2 → tithon-0.2.3}/scripts/v5.sh +0 -0
  265. {tithon-0.2.2 → tithon-0.2.3}/scripts/v50.sh +0 -0
  266. {tithon-0.2.2 → tithon-0.2.3}/scripts/v51.sh +0 -0
  267. {tithon-0.2.2 → tithon-0.2.3}/scripts/v52.sh +0 -0
  268. {tithon-0.2.2 → tithon-0.2.3}/scripts/v53.sh +0 -0
  269. {tithon-0.2.2 → tithon-0.2.3}/scripts/v54.sh +0 -0
  270. {tithon-0.2.2 → tithon-0.2.3}/scripts/v55.sh +0 -0
  271. {tithon-0.2.2 → tithon-0.2.3}/scripts/v56.sh +0 -0
  272. {tithon-0.2.2 → tithon-0.2.3}/scripts/v57.sh +0 -0
  273. {tithon-0.2.2 → tithon-0.2.3}/scripts/v58.sh +0 -0
  274. {tithon-0.2.2 → tithon-0.2.3}/scripts/v59.sh +0 -0
  275. {tithon-0.2.2 → tithon-0.2.3}/scripts/v6.sh +0 -0
  276. {tithon-0.2.2 → tithon-0.2.3}/scripts/v60.sh +0 -0
  277. {tithon-0.2.2 → tithon-0.2.3}/scripts/v7.sh +0 -0
  278. {tithon-0.2.2 → tithon-0.2.3}/scripts/v8.sh +0 -0
  279. {tithon-0.2.2 → tithon-0.2.3}/scripts/v9.sh +0 -0
@@ -0,0 +1,9 @@
1
+ # Commits that only reformat. `git blame` skips these so it lands on the
2
+ # commit that last changed the code, not the one that moved the whitespace.
3
+ #
4
+ # Enable locally with:
5
+ # git config blame.ignoreRevsFile .git-blame-ignore-revs
6
+ # (GitHub honours this file automatically.)
7
+
8
+ # style: format the tree with ruff and biome
9
+ f6c1838afe7dc977d6f08e8b65f548db1f1091d3
@@ -0,0 +1,4 @@
1
+ {
2
+ ".": "0.2.3",
3
+ "extension": "0.2.3"
4
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "recommendations": ["charliermarsh.ruff", "biomejs.biome"]
3
+ }
@@ -0,0 +1,28 @@
1
+ {
2
+ "[python]": {
3
+ "editor.defaultFormatter": "charliermarsh.ruff",
4
+ "editor.formatOnSave": true,
5
+ "editor.codeActionsOnSave": {
6
+ "source.organizeImports.ruff": "explicit"
7
+ }
8
+ },
9
+ "[typescript]": {
10
+ "editor.defaultFormatter": "biomejs.biome",
11
+ "editor.formatOnSave": true,
12
+ "editor.codeActionsOnSave": {
13
+ "source.organizeImports.biome": "explicit"
14
+ }
15
+ },
16
+ "[javascript]": {
17
+ "editor.defaultFormatter": "biomejs.biome",
18
+ "editor.formatOnSave": true
19
+ },
20
+ "[json]": {
21
+ "editor.defaultFormatter": "biomejs.biome",
22
+ "editor.formatOnSave": true
23
+ },
24
+ "[jsonc]": {
25
+ "editor.defaultFormatter": "biomejs.biome",
26
+ "editor.formatOnSave": true
27
+ }
28
+ }
@@ -1,5 +1,24 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.3](https://github.com/rnoro/tithon/compare/v0.2.2...v0.2.3) (2026-08-16)
4
+
5
+
6
+ ### Features
7
+
8
+ * **extension:** let "open as Notebook" stick, per file ([08ba8c1](https://github.com/rnoro/tithon/commit/08ba8c157988a027edcdd71ee5be831b703ed48b))
9
+ * share cell outputs through the project, not the journal ([1ba9d24](https://github.com/rnoro/tithon/commit/1ba9d24a7612bbc530a40da007517d4315be7651))
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * clear the lint backlog and undo two formatter regressions ([7cd4e10](https://github.com/rnoro/tithon/commit/7cd4e107269ca735d145cb9e2cf8b6b51346ff68))
15
+
16
+
17
+ ### Documentation
18
+
19
+ * fix guide for Windows in readme ([bd77e14](https://github.com/rnoro/tithon/commit/bd77e14dd4a39c871a476d1139fc5191736c475e))
20
+ * state invariants instead of naming the ledger ([35e4913](https://github.com/rnoro/tithon/commit/35e4913e696817d4bddd67ff8c7861bf54401aea))
21
+
3
22
  ## [0.2.2](https://github.com/rnoro/tithon/compare/v0.2.1...v0.2.2) (2026-08-12)
4
23
 
5
24
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: tithon
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: Tithon - The immortal Python REPL that will set you free.
5
5
  Project-URL: Homepage, https://github.com/rnoro/tithon
6
6
  Project-URL: Documentation, https://tithon.readthedocs.io/
@@ -105,7 +105,8 @@ moves it to the host.
105
105
  remote, connect over a Tunnel or Remote-SSH — the notebook then works exactly
106
106
  as it does locally.
107
107
 
108
- > Windows is not currently supported.
108
+ > On Windows, we recommend running Tithon inside WSL and connecting with VS Code using the WSL extension.
109
+ > Native Windows is not currently supported.
109
110
 
110
111
  ## Install
111
112
 
@@ -241,6 +242,32 @@ Outputs live in `$TITHON_HOME/sessions/<session>/journal.db` (raw messages plus
241
242
  folded snapshots), with rich outputs written as files under
242
243
  `<workdir>/.tithon/outputs/` and referenced from the journal.
243
244
 
245
+ ### Sharing a notebook's outputs
246
+
247
+ A percent-format `.py` holds only code, and the journal above is machine-local
248
+ (binary, unbounded, unmergeable). So alongside it the daemon keeps the _folded_
249
+ output state as text in your project:
250
+
251
+ ```
252
+ <project>/.tithon/
253
+ cells/<relpath>.json # what each cell currently shows
254
+ outputs/ # its images, sha256-deduplicated
255
+ ```
256
+
257
+ Commit that directory and whoever clones the repository opens the file with your
258
+ results already in it — what `.ipynb` gives you, without the outputs living in
259
+ the `.py`. Images are referenced rather than embedded, so a plot redrawn every
260
+ step of a training loop still commits one file, not one per frame. Leave the
261
+ directory uncommitted (or `.gitignore` it) to keep your outputs to yourself;
262
+ nothing else depends on it, and your own session restores from the journal
263
+ either way.
264
+
265
+ Terminating a kernel yourself (`tithon kill`, or **Tithon: Terminate Kernel…**)
266
+ means you are done with that session, so reopening the file no longer restores
267
+ its cells. The history is kept — **Tithon: Restore Previous Outputs** brings it
268
+ back. Every involuntary loss (daemon restart, host reboot, dropped tunnel, idle
269
+ GC) still restores automatically.
270
+
244
271
  ## License
245
272
 
246
273
  [MIT](LICENSE).
@@ -53,7 +53,8 @@ moves it to the host.
53
53
  remote, connect over a Tunnel or Remote-SSH — the notebook then works exactly
54
54
  as it does locally.
55
55
 
56
- > Windows is not currently supported.
56
+ > On Windows, we recommend running Tithon inside WSL and connecting with VS Code using the WSL extension.
57
+ > Native Windows is not currently supported.
57
58
 
58
59
  ## Install
59
60
 
@@ -189,6 +190,32 @@ Outputs live in `$TITHON_HOME/sessions/<session>/journal.db` (raw messages plus
189
190
  folded snapshots), with rich outputs written as files under
190
191
  `<workdir>/.tithon/outputs/` and referenced from the journal.
191
192
 
193
+ ### Sharing a notebook's outputs
194
+
195
+ A percent-format `.py` holds only code, and the journal above is machine-local
196
+ (binary, unbounded, unmergeable). So alongside it the daemon keeps the _folded_
197
+ output state as text in your project:
198
+
199
+ ```
200
+ <project>/.tithon/
201
+ cells/<relpath>.json # what each cell currently shows
202
+ outputs/ # its images, sha256-deduplicated
203
+ ```
204
+
205
+ Commit that directory and whoever clones the repository opens the file with your
206
+ results already in it — what `.ipynb` gives you, without the outputs living in
207
+ the `.py`. Images are referenced rather than embedded, so a plot redrawn every
208
+ step of a training loop still commits one file, not one per frame. Leave the
209
+ directory uncommitted (or `.gitignore` it) to keep your outputs to yourself;
210
+ nothing else depends on it, and your own session restores from the journal
211
+ either way.
212
+
213
+ Terminating a kernel yourself (`tithon kill`, or **Tithon: Terminate Kernel…**)
214
+ means you are done with that session, so reopening the file no longer restores
215
+ its cells. The history is kept — **Tithon: Restore Previous Outputs** brings it
216
+ back. Every involuntary loss (daemon restart, host reboot, dropped tunnel, idle
217
+ GC) still restores automatically.
218
+
192
219
  ## License
193
220
 
194
221
  [MIT](LICENSE).
@@ -261,7 +261,9 @@ image / widget / text output below it as native notebook rendering. Outputs come
261
261
  from the journal and are attached to cells, so the `.py` is never polluted.
262
262
 
263
263
  `.py` files open as **plain text by default**; Notebook is opt-in (command
264
- _Open as Notebook_), and you can flip back with _Open as Text Editor_.
264
+ _Open as Notebook_), and you can flip back with _Open as Text Editor_. For a
265
+ durable per-file choice, _Always Open With…_ offers exactly _Text Editor_ and
266
+ _Notebook_ from the Explorer context menu and both editor representations.
265
267
 
266
268
  - **Byte-exact round-trip is mandatory.** Serialization preserves the user's
267
269
  formatting, whitespace, and comments to the byte — no auto-reformat
@@ -342,20 +344,57 @@ drives the same daemon over the socket:
342
344
  ## 6. On-disk layout
343
345
 
344
346
  ```
345
- $TITHON_HOME (default ~/.tithon)/
347
+ $TITHON_HOME (default ~/.tithon)/ # machine-local; never in a repo
346
348
  daemon.sock # unix socket (0600)
347
349
  daemon.pid
348
350
  daemon.log
349
351
  sessions/<session-dir>/
350
352
  meta.json
353
+ kernel.json # carries an hmac-sha256 key
351
354
  journal.db # SQLite (WAL): executions, messages, artifacts
352
355
 
353
- <workdir>/.tithon/outputs/ # rich-output files, sha256-deduplicated
354
- exec{N}_{idx}_{sha8}.png
356
+ <workdir>/.tithon/ # the document's output state; shareable
357
+ outputs/ # rich-output files, sha256-deduplicated
358
+ exec{N}_{idx}_{sha8}.png
359
+ cells/<relpath>.json # folded snapshot per source file
355
360
  ```
356
361
 
357
362
  The `.tithon/outputs/` location is configurable (default: inside the workspace).
358
363
 
364
+ **What lives where, and why.** The journal is this machine's verbatim
365
+ write-ahead record — binary, WAL, unbounded, rewritten on every run — so it can
366
+ neither be committed nor merged, and it sits in `$TITHON_HOME` beside the kernel
367
+ connection file whose hmac key must never reach a repository.
368
+
369
+ What a *reader* of a shared notebook needs is not that record but the **fold**:
370
+ the current output state per execution. The daemon projects it onto
371
+ `.tithon/cells/<relpath>.json` (stable key order, one field per line). Cloning
372
+ the project therefore restores the outputs — the one property `.ipynb` has that
373
+ a percent-format `.py` does not — while images stay as deduplicated files rather
374
+ than one base64 blob per frame, so a live-updating plot commits **one** file.
375
+
376
+ It is published once per **user action** — when a submitted batch drains, or a
377
+ clear lands — not once per cell: rebuilding it re-serializes every execution's
378
+ fold, so per-cell writes would make a Run All quadratic in the notebook's
379
+ length. The shared file therefore lags a running batch by design; that is sound
380
+ because it is a projection of a journal that already holds everything, and a
381
+ daemon that dies mid-batch republishes when `_recover_inflight` terminalizes the
382
+ cell it was on. A publish that fails (read-only checkout, full disk) also
383
+ suppresses the artifact reclaim that would otherwise follow a clear, so the
384
+ shared file never names an image that has already been deleted.
385
+
386
+ The journal stays authoritative for the machine that ran the cells: a sidecar is
387
+ imported only into a session with no local executions of its own, and an imported
388
+ execution is terminal, message-less, and has its fold hydrated from the stored
389
+ snapshot (`ExecutionFold.hydrate`) so the startup artifact sweep counts its
390
+ images as live instead of reclaiming them.
391
+
392
+ Nothing machine-specific is written. A cell's origin carries its index and range
393
+ but no uri, and execution ids are renumbered on import — the file is tracked,
394
+ hand-editable and merge-prone, so its ids are data rather than keys, and each row
395
+ is rebound to the reading file's own uri (which the sidecar's location already
396
+ implies) so that per-file restore scoping keeps it.
397
+
359
398
  ---
360
399
 
361
400
  ## 7. Tricky points & how they are handled
@@ -479,7 +518,7 @@ make core # v1–v4 v47 v49 v50 v57 core journal / daemon lifecycle
479
518
  make serializer # v6 percent <-> notebook round-trip
480
519
  make backpressure# v9 slow-client host protection
481
520
  make widgets # v5 v29 v30 ipywidget mirror + render + live animation
482
- make restore # v7 v8 v15 v16 v22 v38 reconnect: output + cell-state restore, orphan
521
+ make restore # v7 v8 v15 v16 v22 v38 v61 v62 v63 reconnect restore, orphan, cloned repo, closed session
483
522
  make livesync # v10–v14 v33 v37 live streaming into cells
484
523
  make kernels # v17–v21 v23 v24 v26 v40 v45 per-file kernels + lifecycle + idle-GC
485
524
  make richoutputs # v27 v28 v31 v34 v35 matplotlib/tqdm images, live-plot GC, clear, storage
@@ -506,6 +545,8 @@ Capability → what it guarantees → how it is verified:
506
545
  | Bounded render cost | Coalescing caps UI updates | `liveSync.test.ts` (50k events → 1 sink call) |
507
546
  | Host protection | Slow client can't grow memory or block others | `test_backpressure.py`, `v9` |
508
547
  | Widget rendering | Widgets render in VSCode, restore, and animate live | `v29` (static + restore), `v30` (live) |
548
+ | Shared outputs | A cloned repo restores outputs + images | `v61` (real `git clone`), `test_sidecar.py` |
549
+ | Deliberate close | A killed session is not re-seeded; history kept | `v62` (daemon), `v63` (real VSCode seed gate) |
509
550
 
510
551
  `make vscode` downloads VSCode and needs system libraries (Debian/Ubuntu):
511
552
 
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.2.3](https://github.com/rnoro/tithon/compare/vscode-v0.2.2...vscode-v0.2.3) (2026-08-16)
4
+
5
+
6
+ ### Features
7
+
8
+ * **extension:** confirm destructive kernel actions; notify outcomes ([73c6d13](https://github.com/rnoro/tithon/commit/73c6d13fcece4630b675cb28d0e5d6e34a317527))
9
+ * **extension:** let "open as Notebook" stick, per file ([08ba8c1](https://github.com/rnoro/tithon/commit/08ba8c157988a027edcdd71ee5be831b703ed48b))
10
+ * **extension:** let "open as Notebook" stick, per file ([d921f52](https://github.com/rnoro/tithon/commit/d921f52e6a0a9f7033adea41b110c5ecc8c10c5f))
11
+ * share cell outputs through the project, not the journal ([1ba9d24](https://github.com/rnoro/tithon/commit/1ba9d24a7612bbc530a40da007517d4315be7651))
12
+
13
+
14
+ ### Bug Fixes
15
+
16
+ * clear the lint backlog and undo two formatter regressions ([7cd4e10](https://github.com/rnoro/tithon/commit/7cd4e107269ca735d145cb9e2cf8b6b51346ff68))
17
+ * **extension:** serialize durable editor choice ([376ae78](https://github.com/rnoro/tithon/commit/376ae786c296d71b3473dba9efdc04c637bc9854))
18
+
3
19
  ## [0.2.2](https://github.com/rnoro/tithon/compare/vscode-v0.2.1...vscode-v0.2.2) (2026-08-12)
4
20
 
5
21
 
@@ -107,6 +107,10 @@ stays pure source — outputs never touch the file, so diffs stay clean.
107
107
  time, with no manual command.
108
108
  - **ipywidgets** — `tqdm` bars and interactive widgets render through a bundled
109
109
  widget renderer and come back at their real state, not their initial value.
110
+ - **Shareable outputs** — the folded output state is kept as text in
111
+ `<project>/.tithon/` (images referenced as deduplicated files, not embedded).
112
+ Commit it and whoever clones the repository opens the file with your results
113
+ already in it; leave it uncommitted to keep them to yourself.
110
114
 
111
115
  ## Commands
112
116
 
@@ -115,15 +119,27 @@ The rest are run from the command palette or the notebook's kernel toolbar:
115
119
 
116
120
  | Command | What it does |
117
121
  | --- | --- |
118
- | `Tithon: Open as Notebook` / `Open as Text Editor` | Toggle a `.py` between notebook and plain text. |
122
+ | `Tithon: Open as Notebook` / `Open as Text Editor` | Toggle a `.py` between notebook and plain text, once. |
123
+ | `Tithon: Always Open With…` | Choose Text Editor or Notebook for this one file, permanently in this workspace. |
119
124
  | `Tithon: Restart Kernel` | Restart the session's kernel. |
120
125
  | `Tithon: Interrupt Kernel` | Interrupt the running cell. |
121
126
  | `Tithon: Select Python Interpreter` | Choose the interpreter the daemon runs the kernel as. |
122
127
  | `Tithon: Restart Daemon` | Restart the host daemon. |
123
- | `Tithon: Terminate Kernel…` | Kill the session's kernel. |
128
+ | `Tithon: Terminate Kernel…` | Kill the session's kernel. Reopening the file then leaves the cells empty — terminating means you are done with that session. |
129
+ | `Tithon: Restore Previous Outputs` | Put a terminated session's outputs back into the cells. |
124
130
 
125
131
  `Run Cell` is offered as a CodeLens above each `# %%` cell.
126
132
 
133
+ A `.py` opens as a normal text editor unless you say otherwise. Use `Tithon:
134
+ Always Open With…` from the Explorer context menu, editor title, or Notebook
135
+ toolbar to choose `Text Editor` or `Notebook`. Tithon records the choice as one
136
+ `workbench.editorAssociations` entry in the workspace's `.vscode/settings.json`,
137
+ so it survives reloads and can be committed for the team. If you want *every*
138
+ `.py` in a workspace to open as a notebook, that is VSCode's own setting rather
139
+ than a Tithon command — `Reopen With…` → `Configure default editor…` on a `.py`,
140
+ choosing `Notebook - Tithon`. It writes `"*.py": "tithon-py"`, which applies to
141
+ every Python file in scope, `setup.py` and `conftest.py` included.
142
+
127
143
  ## Settings
128
144
 
129
145
  | Setting | Default | Purpose |
@@ -131,6 +147,7 @@ The rest are run from the command palette or the notebook's kernel toolbar:
131
147
  | `tithon.autoStartDaemon` | `true` | Start the daemon on the host when it isn't already running (spawned detached, so it survives reconnects). |
132
148
  | `tithon.daemonCommand` | `tithon` | Command used to launch the daemon (run as `<command> daemon`). Set an absolute path if `tithon` isn't on `PATH`. |
133
149
  | `tithon.pythonPath` | `""` | Run the daemon as `<python> -m tithon daemon`. Leave empty to use the Python extension's selected interpreter. |
150
+ | `tithon.confirmDestructiveActions` | `true` | Ask in a modal dialog before Restart Kernel, Terminate Kernel and Restart Daemon. Set to `false` if you restart often and accept losing the namespace to a mis-click. |
134
151
  | `tithon.kernelIdleTimeout` | `0` | Reap a kernel after this many seconds idle (no attached notebook, nothing running or queued). Outputs stay restorable from the journal; only the in-memory variables are lost. `0` = never. Applied when the extension (re)starts the daemon. |
135
152
 
136
153
  ## How it works
@@ -0,0 +1,39 @@
1
+ {
2
+ "$schema": "https://biomejs.dev/schemas/2.5.8/schema.json",
3
+ "files": {
4
+ "includes": ["**", "!dist", "!out-int", "!.vscode-test", "!**/*.vsix", "!test/fixtures"]
5
+ },
6
+ "formatter": {
7
+ "enabled": true,
8
+ "indentStyle": "space",
9
+ "indentWidth": 2,
10
+ "lineWidth": 100
11
+ },
12
+ "javascript": {
13
+ "formatter": {
14
+ "quoteStyle": "double",
15
+ "semicolons": "always",
16
+ "trailingCommas": "all",
17
+ "arrowParentheses": "always"
18
+ }
19
+ },
20
+ "linter": {
21
+ "enabled": true,
22
+ "rules": {
23
+ "preset": "recommended",
24
+ "suspicious": {
25
+ "noExplicitAny": "off"
26
+ },
27
+ "style": {
28
+ "noNonNullAssertion": "off"
29
+ }
30
+ }
31
+ },
32
+ "assist": {
33
+ "actions": {
34
+ "source": {
35
+ "organizeImports": "on"
36
+ }
37
+ }
38
+ }
39
+ }
@@ -12,7 +12,8 @@
12
12
  * notebook/LSP guard suites against the insiders build as an early warning, so a
13
13
  * breaking change is caught before it reaches users on stable.
14
14
  */
15
- import * as path from "path";
15
+
16
+ import * as path from "node:path";
16
17
  import { runTests } from "@vscode/test-electron";
17
18
 
18
19
  async function main(): Promise<void> {
@@ -41,9 +42,7 @@ async function main(): Promise<void> {
41
42
  // Python language servers (ruff/ty) live, so it passes TITHON_LSP_EXT_DIR — a
42
43
  // curated extensions dir — and we drop --disable-extensions for that run.
43
44
  const lspExtDir = process.env.TITHON_LSP_EXT_DIR;
44
- const extArgs = lspExtDir
45
- ? [`--extensions-dir=${lspExtDir}`]
46
- : ["--disable-extensions"];
45
+ const extArgs = lspExtDir ? [`--extensions-dir=${lspExtDir}`] : ["--disable-extensions"];
47
46
 
48
47
  // Default "stable" matches @vscode/test-electron's own default (latest stable),
49
48
  // so the existing bundles are unchanged; the insiders bundle overrides it.
@@ -74,6 +73,11 @@ async function main(): Promise<void> {
74
73
  TITHON_FIXTURE: process.env.TITHON_FIXTURE ?? "",
75
74
  TITHON_HELPER: process.env.TITHON_HELPER ?? "",
76
75
  TITHON_SUITE: process.env.TITHON_SUITE ?? "",
76
+ // "1" leaves `tithon.confirmDestructiveActions` at its shipped default, so
77
+ // the suite that verifies the modal gate sees what a user sees. Every other
78
+ // suite drives restart/terminate unattended, so the bootstrap turns it off.
79
+ TITHON_CONFIRM_DESTRUCTIVE: process.env.TITHON_CONFIRM_DESTRUCTIVE ?? "",
80
+ TITHON_CONFIRM_TARGET: process.env.TITHON_CONFIRM_TARGET ?? "",
77
81
  },
78
82
  });
79
83
  }
@@ -4,10 +4,10 @@
4
4
  * source via the verified SessionClient so daemon cell_hash == the extension's
5
5
  * computeCellHash(cellSource), and waits until every execution is terminal.
6
6
  */
7
- import { readFileSync } from "fs";
8
- import { parse, cellSource } from "../src/serializer";
9
- import { SessionClient } from "../src/sessionClient";
7
+ import { readFileSync } from "node:fs";
10
8
  import { computeCellHash } from "../src/cellAttach";
9
+ import { cellSource, parse } from "../src/serializer";
10
+ import { SessionClient } from "../src/sessionClient";
11
11
 
12
12
  async function main(): Promise<void> {
13
13
  const file = process.argv[2];
@@ -8,7 +8,7 @@
8
8
  * Flow: run cell 0 (starts live), then insert a new cell and run it, and assert
9
9
  * the new cell shows its output WITHOUT any manual restore step.
10
10
  */
11
- import * as assert from "assert";
11
+ import * as assert from "node:assert";
12
12
  import * as vscode from "vscode";
13
13
 
14
14
  const dec = new TextDecoder();
@@ -64,7 +64,10 @@ describe("Tithon streams output for a cell added after live started (v14)", () =
64
64
  const nb = await vscode.workspace.openNotebookDocument(uri);
65
65
  await vscode.window.showNotebookDocument(nb);
66
66
  await waitFor(() => nb.cellCount >= 1, 15000, "cells");
67
- await vscode.commands.executeCommand("notebook.selectKernel", { id: "tithon", extension: ext.id });
67
+ await vscode.commands.executeCommand("notebook.selectKernel", {
68
+ id: "tithon",
69
+ extension: ext.id,
70
+ });
68
71
 
69
72
  // Run the first cell — this starts live sync (index has only cell 0).
70
73
  await runCell(uri, 0);
@@ -8,30 +8,41 @@
8
8
  * command. Auto-open must (a) restore the lines already produced and (b) keep
9
9
  * appending new lines as the loop runs.
10
10
  */
11
- import * as assert from "assert";
11
+ import * as assert from "node:assert";
12
+ import { readFileSync } from "node:fs";
12
13
  import * as vscode from "vscode";
13
- import { readFileSync } from "fs";
14
- import { parse, cellSource } from "../../src/serializer";
15
- import { SessionClient } from "../../src/sessionClient";
16
14
  import { computeCellHash } from "../../src/cellAttach";
15
+ import { cellSource, parse } from "../../src/serializer";
16
+ import { SessionClient } from "../../src/sessionClient";
17
17
 
18
18
  const dec = new TextDecoder();
19
19
  function cellText(cell: vscode.NotebookCell): string {
20
20
  let s = "";
21
- for (const o of cell.outputs) for (const it of o.items)
22
- if (it.mime.includes("stdout") || it.mime === "text/plain") s += dec.decode(it.data);
21
+ for (const o of cell.outputs)
22
+ for (const it of o.items)
23
+ if (it.mime.includes("stdout") || it.mime === "text/plain") s += dec.decode(it.data);
23
24
  return s;
24
25
  }
25
26
  function lines(t: string): number[] {
26
- return t.split("\n").map((x) => x.trim()).filter((x) => /^\d+$/.test(x)).map(Number);
27
+ return t
28
+ .split("\n")
29
+ .map((x) => x.trim())
30
+ .filter((x) => /^\d+$/.test(x))
31
+ .map(Number);
27
32
  }
28
33
  async function waitFor(pred: () => boolean, ms: number, label: string): Promise<void> {
29
34
  const deadline = Date.now() + ms;
30
- while (!pred()) { if (Date.now() > deadline) throw new Error(`timed out: ${label}`); await new Promise((r) => setTimeout(r, 50)); }
35
+ while (!pred()) {
36
+ if (Date.now() > deadline) throw new Error(`timed out: ${label}`);
37
+ await new Promise((r) => setTimeout(r, 50));
38
+ }
31
39
  }
32
40
  function ext(): vscode.Extension<unknown> {
33
41
  const e = vscode.extensions.all.find((x) =>
34
- (x.packageJSON?.contributes?.commands ?? []).some((c: { command?: string }) => c.command === "tithon.restartKernel"));
42
+ (x.packageJSON?.contributes?.commands ?? []).some(
43
+ (c: { command?: string }) => c.command === "tithon.restartKernel",
44
+ ),
45
+ );
35
46
  if (!e) throw new Error("Tithon extension not found");
36
47
  return e;
37
48
  }
@@ -43,12 +54,17 @@ describe("Tithon auto-restore + live on open, no command (v22)", () => {
43
54
 
44
55
  // Driver starts the long loop on this file's kernel (independent of the UI).
45
56
  const cells = parse(readFileSync(uri.fsPath, "utf8")).cells;
46
- const loopIdx = cells.findIndex((c) => c.kind === "code" && c.body.some((l) => l.text.includes("range(30)")));
57
+ const loopIdx = cells.findIndex(
58
+ (c) => c.kind === "code" && c.body.some((l) => l.text.includes("range(30)")),
59
+ );
47
60
  assert.ok(loopIdx >= 0, "fixture needs the range(30) loop");
48
61
  const src = cellSource(cells[loopIdx]);
49
62
  const driver = new SessionClient(undefined, uri.toString());
50
63
  await driver.execute(src, {
51
- uri: uri.toString(), range: { start: 0, end: 0 }, cell_hash: computeCellHash(src), index: loopIdx,
64
+ uri: uri.toString(),
65
+ range: { start: 0, end: 0 },
66
+ cell_hash: computeCellHash(src),
67
+ index: loopIdx,
52
68
  });
53
69
 
54
70
  // Let a few lines accumulate so there is real prior output to auto-restore.
@@ -66,15 +82,25 @@ describe("Tithon auto-restore + live on open, no command (v22)", () => {
66
82
  const nb = await vscode.workspace.openNotebookDocument(uri);
67
83
  await vscode.window.showNotebookDocument(nb);
68
84
  await waitFor(() => nb.cellCount >= 1, 15000, "cells");
69
- await vscode.commands.executeCommand("notebook.selectKernel", { id: "tithon", extension: ext().id });
85
+ await vscode.commands.executeCommand("notebook.selectKernel", {
86
+ id: "tithon",
87
+ extension: ext().id,
88
+ });
70
89
 
71
90
  // (a) prior output restored: at least the early lines show up.
72
- await waitFor(() => lines(cellText(nb.cellAt(loopIdx))).length >= 4, 20000, "auto-restored prior output");
91
+ await waitFor(
92
+ () => lines(cellText(nb.cellAt(loopIdx))).length >= 4,
93
+ 20000,
94
+ "auto-restored prior output",
95
+ );
73
96
  const restoredMax = Math.max(...lines(cellText(nb.cellAt(loopIdx))));
74
97
 
75
98
  // (b) live continues: the cell keeps growing past what was there at open.
76
- await waitFor(() => Math.max(...lines(cellText(nb.cellAt(loopIdx))), -1) > restoredMax,
77
- 25000, "live output continued after open");
99
+ await waitFor(
100
+ () => Math.max(...lines(cellText(nb.cellAt(loopIdx))), -1) > restoredMax,
101
+ 25000,
102
+ "live output continued after open",
103
+ );
78
104
 
79
105
  const final = lines(cellText(nb.cellAt(loopIdx)));
80
106
  assert.ok(final.length >= 5, `expected continuous output, got ${JSON.stringify(final)}`);
@@ -4,26 +4,33 @@
4
4
  * (tithon.autoStartDaemon) and stream output — "pip install tithon, then just
5
5
  * use it". Also asserts the kernel reports its Python version (label plumbing).
6
6
  */
7
- import * as assert from "assert";
7
+ import * as assert from "node:assert";
8
+ import * as fs from "node:fs";
9
+ import * as path from "node:path";
8
10
  import * as vscode from "vscode";
9
- import * as fs from "fs";
10
- import * as path from "path";
11
11
  import { SessionClient } from "../../src/sessionClient";
12
12
 
13
13
  const dec = new TextDecoder();
14
14
  function cellText(cell: vscode.NotebookCell): string {
15
15
  let s = "";
16
- for (const o of cell.outputs) for (const it of o.items)
17
- if (it.mime.includes("stdout") || it.mime === "text/plain") s += dec.decode(it.data);
16
+ for (const o of cell.outputs)
17
+ for (const it of o.items)
18
+ if (it.mime.includes("stdout") || it.mime === "text/plain") s += dec.decode(it.data);
18
19
  return s;
19
20
  }
20
21
  async function waitFor(pred: () => boolean, ms: number, label: string): Promise<void> {
21
22
  const deadline = Date.now() + ms;
22
- while (!pred()) { if (Date.now() > deadline) throw new Error(`timed out: ${label}`); await new Promise((r) => setTimeout(r, 50)); }
23
+ while (!pred()) {
24
+ if (Date.now() > deadline) throw new Error(`timed out: ${label}`);
25
+ await new Promise((r) => setTimeout(r, 50));
26
+ }
23
27
  }
24
28
  function ext(): vscode.Extension<unknown> {
25
29
  const e = vscode.extensions.all.find((x) =>
26
- (x.packageJSON?.contributes?.commands ?? []).some((c: { command?: string }) => c.command === "tithon.restartKernel"));
30
+ (x.packageJSON?.contributes?.commands ?? []).some(
31
+ (c: { command?: string }) => c.command === "tithon.restartKernel",
32
+ ),
33
+ );
27
34
  if (!e) throw new Error("Tithon extension not found");
28
35
  return e;
29
36
  }
@@ -39,20 +46,29 @@ describe("Tithon daemon auto-start (v23)", () => {
39
46
  // Use the interpreter path (Jupyter-style `<python> -m tithon`) — no venv
40
47
  // activation, no `tithon` on PATH. daemonCommand stays default "tithon"
41
48
  // (absent here) to prove the interpreter candidate is what starts it.
42
- await vscode.workspace.getConfiguration("tithon")
49
+ await vscode.workspace
50
+ .getConfiguration("tithon")
43
51
  .update("pythonPath", process.env.TITHON_PYTHON!, vscode.ConfigurationTarget.Global);
44
52
 
45
53
  const nb = await vscode.workspace.openNotebookDocument(uri);
46
54
  await vscode.window.showNotebookDocument(nb);
47
55
  await waitFor(() => nb.cellCount >= 1, 15000, "cells");
48
56
  // Selecting the kernel triggers ensureLive -> ensureDaemon (auto-start).
49
- await vscode.commands.executeCommand("notebook.selectKernel", { id: "tithon", extension: ext().id });
57
+ await vscode.commands.executeCommand("notebook.selectKernel", {
58
+ id: "tithon",
59
+ extension: ext().id,
60
+ });
50
61
  await vscode.commands.executeCommand("notebook.cell.execute", {
51
- ranges: [new vscode.NotebookRange(0, 1)], document: uri,
62
+ ranges: [new vscode.NotebookRange(0, 1)],
63
+ document: uri,
52
64
  });
53
65
 
54
66
  // Output only appears if the daemon was actually auto-started.
55
- await waitFor(() => cellText(nb.cellAt(0)).includes("AUTO_OK"), 40000, "auto-started daemon streamed output");
67
+ await waitFor(
68
+ () => cellText(nb.cellAt(0)).includes("AUTO_OK"),
69
+ 40000,
70
+ "auto-started daemon streamed output",
71
+ );
56
72
  assert.ok(fs.existsSync(pidFile), "daemon.pid should exist after auto-start");
57
73
 
58
74
  // Kernel reports its Python version (for the "Tithon · Python x.y" label).
@@ -60,7 +76,10 @@ describe("Tithon daemon auto-start (v23)", () => {
60
76
  await c.attach(0);
61
77
  const py = c.kernelInfo()?.python ?? "";
62
78
  c.close();
63
- assert.ok(/^\d+\.\d+/.test(py), `kernel should report a python version, got ${JSON.stringify(py)}`);
79
+ assert.ok(
80
+ /^\d+\.\d+/.test(py),
81
+ `kernel should report a python version, got ${JSON.stringify(py)}`,
82
+ );
64
83
  console.log(`[v23] daemon auto-started; kernel python = ${py}`);
65
84
  });
66
85
  });