tithon 0.1.0__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.
- tithon-0.1.0/.gitattributes +4 -0
- tithon-0.1.0/.gitignore +66 -0
- tithon-0.1.0/CHANGELOG.md +15 -0
- tithon-0.1.0/LICENSE +21 -0
- tithon-0.1.0/PKG-INFO +312 -0
- tithon-0.1.0/README.md +260 -0
- tithon-0.1.0/docs/SPEC.md +466 -0
- tithon-0.1.0/extension/.vscodeignore +9 -0
- tithon-0.1.0/extension/CHANGELOG.md +3 -0
- tithon-0.1.0/extension/esbuild.mjs +48 -0
- tithon-0.1.0/extension/integration/runTest.ts +68 -0
- tithon-0.1.0/extension/integration/seed.ts +70 -0
- tithon-0.1.0/extension/integration/suite/addcell.test.ts +92 -0
- tithon-0.1.0/extension/integration/suite/autoopen.test.ts +83 -0
- tithon-0.1.0/extension/integration/suite/autostart.test.ts +66 -0
- tithon-0.1.0/extension/integration/suite/dupcode.test.ts +56 -0
- tithon-0.1.0/extension/integration/suite/editedcell.test.ts +80 -0
- tithon-0.1.0/extension/integration/suite/editordefault.test.ts +55 -0
- tithon-0.1.0/extension/integration/suite/index.ts +25 -0
- tithon-0.1.0/extension/integration/suite/interrupt.test.ts +82 -0
- tithon-0.1.0/extension/integration/suite/live.test.ts +102 -0
- tithon-0.1.0/extension/integration/suite/livedisplay.test.ts +118 -0
- tithon-0.1.0/extension/integration/suite/livereconnect.test.ts +93 -0
- tithon-0.1.0/extension/integration/suite/lsp.test.ts +165 -0
- tithon-0.1.0/extension/integration/suite/multicell.test.ts +91 -0
- tithon-0.1.0/extension/integration/suite/opentext.test.ts +134 -0
- tithon-0.1.0/extension/integration/suite/opentextshot.test.ts +84 -0
- tithon-0.1.0/extension/integration/suite/reconnect.test.ts +97 -0
- tithon-0.1.0/extension/integration/suite/reconnectstates.test.ts +99 -0
- tithon-0.1.0/extension/integration/suite/reopen.test.ts +70 -0
- tithon-0.1.0/extension/integration/suite/restartdaemon.test.ts +85 -0
- tithon-0.1.0/extension/integration/suite/restartkernel.test.ts +59 -0
- tithon-0.1.0/extension/integration/suite/restore.test.ts +98 -0
- tithon-0.1.0/extension/integration/suite/richoutputs.test.ts +96 -0
- tithon-0.1.0/extension/integration/suite/runcell.test.ts +77 -0
- tithon-0.1.0/extension/integration/suite/screenshot.test.ts +61 -0
- tithon-0.1.0/extension/integration/suite/twofiles.test.ts +68 -0
- tithon-0.1.0/extension/integration/suite/widget.test.ts +74 -0
- tithon-0.1.0/extension/integration/suite/widgetlive.test.ts +72 -0
- tithon-0.1.0/extension/package-lock.json +6731 -0
- tithon-0.1.0/extension/package.json +176 -0
- tithon-0.1.0/extension/src/artifactCache.ts +66 -0
- tithon-0.1.0/extension/src/cellAttach.ts +161 -0
- tithon-0.1.0/extension/src/codeLens.ts +58 -0
- tithon-0.1.0/extension/src/css.d.ts +7 -0
- tithon-0.1.0/extension/src/daemonClient.ts +133 -0
- tithon-0.1.0/extension/src/daemonProcess.ts +207 -0
- tithon-0.1.0/extension/src/extension.ts +281 -0
- tithon-0.1.0/extension/src/liveSync.ts +330 -0
- tithon-0.1.0/extension/src/notebookSerializer.ts +68 -0
- tithon-0.1.0/extension/src/outputFold.ts +175 -0
- tithon-0.1.0/extension/src/richOutput.ts +180 -0
- tithon-0.1.0/extension/src/serializer.ts +240 -0
- tithon-0.1.0/extension/src/sessionClient.ts +473 -0
- tithon-0.1.0/extension/src/sessionController.ts +866 -0
- tithon-0.1.0/extension/src/widgetRender.ts +134 -0
- tithon-0.1.0/extension/src/widgetRendererEntry.ts +113 -0
- tithon-0.1.0/extension/test/artifactCache.test.ts +39 -0
- tithon-0.1.0/extension/test/cellAttach.test.ts +146 -0
- tithon-0.1.0/extension/test/fixtures/tqdm_widget_state.json +377 -0
- tithon-0.1.0/extension/test/liveSync.test.ts +314 -0
- tithon-0.1.0/extension/test/outputFold.test.ts +76 -0
- tithon-0.1.0/extension/test/restore.test.ts +138 -0
- tithon-0.1.0/extension/test/richDaemon.test.ts +131 -0
- tithon-0.1.0/extension/test/richOutput.test.ts +79 -0
- tithon-0.1.0/extension/test/serializer.test.ts +196 -0
- tithon-0.1.0/extension/test/setup.ts +41 -0
- tithon-0.1.0/extension/test/widget.test.ts +90 -0
- tithon-0.1.0/extension/tsconfig.integration.json +17 -0
- tithon-0.1.0/extension/tsconfig.json +18 -0
- tithon-0.1.0/extension/vitest.config.ts +14 -0
- tithon-0.1.0/pyproject.toml +70 -0
- tithon-0.1.0/scripts/Makefile +26 -0
- tithon-0.1.0/scripts/_check_v1.py +58 -0
- tithon-0.1.0/scripts/_check_v2.py +48 -0
- tithon-0.1.0/scripts/_check_v3.py +67 -0
- tithon-0.1.0/scripts/_check_v5.py +60 -0
- tithon-0.1.0/scripts/_clear_client.py +50 -0
- tithon-0.1.0/scripts/_lastseq.py +19 -0
- tithon-0.1.0/scripts/_stalled_client.py +32 -0
- tithon-0.1.0/scripts/_workdir_client.py +38 -0
- tithon-0.1.0/scripts/corpus/_gen.py +117 -0
- tithon-0.1.0/scripts/corpus/crlf_mixed.py +8 -0
- tithon-0.1.0/scripts/corpus/crlf_string_marker.py +6 -0
- tithon-0.1.0/scripts/corpus/empty_cells.py +5 -0
- tithon-0.1.0/scripts/corpus/magics_markdown.py +10 -0
- tithon-0.1.0/scripts/corpus/mixed_indent.py +7 -0
- tithon-0.1.0/scripts/corpus/module_header.py +10 -0
- tithon-0.1.0/scripts/corpus/no_final_newline.py +5 -0
- tithon-0.1.0/scripts/corpus/string_marker.py +8 -0
- tithon-0.1.0/scripts/demo_reconnect.sh +38 -0
- tithon-0.1.0/scripts/lib.sh +51 -0
- tithon-0.1.0/scripts/run_verify.sh +42 -0
- tithon-0.1.0/scripts/shot.sh +116 -0
- tithon-0.1.0/scripts/v1.sh +31 -0
- tithon-0.1.0/scripts/v10.sh +54 -0
- tithon-0.1.0/scripts/v11.sh +51 -0
- tithon-0.1.0/scripts/v12.sh +52 -0
- tithon-0.1.0/scripts/v13.sh +46 -0
- tithon-0.1.0/scripts/v14.sh +46 -0
- tithon-0.1.0/scripts/v15.sh +48 -0
- tithon-0.1.0/scripts/v16.sh +54 -0
- tithon-0.1.0/scripts/v17.sh +53 -0
- tithon-0.1.0/scripts/v18.sh +39 -0
- tithon-0.1.0/scripts/v19.sh +43 -0
- tithon-0.1.0/scripts/v2.sh +23 -0
- tithon-0.1.0/scripts/v20.sh +41 -0
- tithon-0.1.0/scripts/v21.sh +42 -0
- tithon-0.1.0/scripts/v22.sh +42 -0
- tithon-0.1.0/scripts/v23.sh +40 -0
- tithon-0.1.0/scripts/v24.sh +45 -0
- tithon-0.1.0/scripts/v25.sh +39 -0
- tithon-0.1.0/scripts/v26.sh +43 -0
- tithon-0.1.0/scripts/v27.sh +43 -0
- tithon-0.1.0/scripts/v28.sh +56 -0
- tithon-0.1.0/scripts/v29.sh +47 -0
- tithon-0.1.0/scripts/v3.sh +24 -0
- tithon-0.1.0/scripts/v30.sh +49 -0
- tithon-0.1.0/scripts/v31.sh +89 -0
- tithon-0.1.0/scripts/v32.sh +119 -0
- tithon-0.1.0/scripts/v33.sh +57 -0
- tithon-0.1.0/scripts/v34.sh +87 -0
- tithon-0.1.0/scripts/v35.sh +58 -0
- tithon-0.1.0/scripts/v36.sh +41 -0
- tithon-0.1.0/scripts/v4.sh +51 -0
- tithon-0.1.0/scripts/v5.sh +51 -0
- tithon-0.1.0/scripts/v6.sh +38 -0
- tithon-0.1.0/scripts/v7.sh +43 -0
- tithon-0.1.0/scripts/v8.sh +72 -0
- tithon-0.1.0/scripts/v9.sh +57 -0
- tithon-0.1.0/src/tithon/__init__.py +3 -0
- tithon-0.1.0/src/tithon/__main__.py +7 -0
- tithon-0.1.0/src/tithon/artifacts.py +91 -0
- tithon-0.1.0/src/tithon/cli.py +241 -0
- tithon-0.1.0/src/tithon/daemon.py +804 -0
- tithon-0.1.0/src/tithon/folding.py +165 -0
- tithon-0.1.0/src/tithon/journal.py +228 -0
- tithon-0.1.0/src/tithon/kernel.py +121 -0
- tithon-0.1.0/src/tithon/widgets.py +92 -0
- tithon-0.1.0/test/test_artifacts.py +113 -0
- tithon-0.1.0/test/test_backpressure.py +87 -0
- tithon-0.1.0/test/test_clear.py +94 -0
- tithon-0.1.0/test/test_folding.py +139 -0
- tithon-0.1.0/test/test_journal_origin.py +63 -0
- tithon-0.1.0/test/test_session_layout.py +43 -0
- tithon-0.1.0/test/test_widgets.py +111 -0
- tithon-0.1.0/uv.lock +2463 -0
tithon-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
*.egg-info/
|
|
9
|
+
.eggs/
|
|
10
|
+
*.egg
|
|
11
|
+
.pytest_cache/
|
|
12
|
+
.mypy_cache/
|
|
13
|
+
.dmypy.json
|
|
14
|
+
dmypy.json
|
|
15
|
+
.ruff_cache/
|
|
16
|
+
.coverage
|
|
17
|
+
.coverage.*
|
|
18
|
+
coverage.xml
|
|
19
|
+
htmlcov/
|
|
20
|
+
.hypothesis/
|
|
21
|
+
.tox/
|
|
22
|
+
.nox/
|
|
23
|
+
.ipynb_checkpoints/
|
|
24
|
+
.venv/
|
|
25
|
+
|
|
26
|
+
# Node / TypeScript
|
|
27
|
+
node_modules/
|
|
28
|
+
*.tsbuildinfo
|
|
29
|
+
.eslintcache
|
|
30
|
+
*.log
|
|
31
|
+
npm-debug.log*
|
|
32
|
+
yarn-debug.log*
|
|
33
|
+
coverage/
|
|
34
|
+
*.lcov
|
|
35
|
+
.nyc_output
|
|
36
|
+
*.tgz
|
|
37
|
+
.npm
|
|
38
|
+
|
|
39
|
+
# Project
|
|
40
|
+
# tithon daemon state (socket, journal, kernel connection files)
|
|
41
|
+
.tithon/
|
|
42
|
+
|
|
43
|
+
# esbuild output
|
|
44
|
+
dist/
|
|
45
|
+
out-int/
|
|
46
|
+
|
|
47
|
+
# VSCode extension test runner
|
|
48
|
+
.vscode-test/
|
|
49
|
+
|
|
50
|
+
# packaged extension
|
|
51
|
+
*.vsix
|
|
52
|
+
|
|
53
|
+
# screenshot render artifacts during script test
|
|
54
|
+
scripts/screenshots/
|
|
55
|
+
|
|
56
|
+
# daemon startup log (nohup)
|
|
57
|
+
nohup.out
|
|
58
|
+
|
|
59
|
+
# Local Agent
|
|
60
|
+
.claude/
|
|
61
|
+
|
|
62
|
+
# OS
|
|
63
|
+
.DS_Store
|
|
64
|
+
Thumbs.db
|
|
65
|
+
*.swp
|
|
66
|
+
*~
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-06-17
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Initial alpha release of Tithon.
|
|
13
|
+
- Persistent remote interactive Python sessions with loss-free journal.
|
|
14
|
+
- Real-time cell output streaming and widget state mirroring.
|
|
15
|
+
- VSCode extension to sync kernel state losslessly.
|
tithon-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) [year] [fullname]
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
tithon-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: tithon
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Tithon - The immortal Python REPL that will set you free.
|
|
5
|
+
Project-URL: Homepage, https://github.com/rnoro/tithon
|
|
6
|
+
Project-URL: Documentation, https://tithon.readthedocs.io/
|
|
7
|
+
Project-URL: Repository, https://github.com/rnoro/tithon
|
|
8
|
+
Project-URL: Bug Tracker, https://github.com/rnoro/tithon/issues
|
|
9
|
+
Project-URL: Discussions, https://github.com/rnoro/tithon/discussions
|
|
10
|
+
Project-URL: Changelog, https://github.com/rnoro/tithon/blob/main/CHANGELOG.md
|
|
11
|
+
Author-email: rnoro <rnoro5122@gmail.com>
|
|
12
|
+
License: MIT License
|
|
13
|
+
|
|
14
|
+
Copyright (c) [year] [fullname]
|
|
15
|
+
|
|
16
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
17
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
18
|
+
in the Software without restriction, including without limitation the rights
|
|
19
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
20
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
21
|
+
furnished to do so, subject to the following conditions:
|
|
22
|
+
|
|
23
|
+
The above copyright notice and this permission notice shall be included in all
|
|
24
|
+
copies or substantial portions of the Software.
|
|
25
|
+
|
|
26
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
27
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
28
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
29
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
30
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
31
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
32
|
+
SOFTWARE.
|
|
33
|
+
License-File: LICENSE
|
|
34
|
+
Keywords: interactive,jupyter,kernel,persistent,repl,vscode
|
|
35
|
+
Classifier: Development Status :: 3 - Alpha
|
|
36
|
+
Classifier: Intended Audience :: Developers
|
|
37
|
+
Classifier: Intended Audience :: Science/Research
|
|
38
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
39
|
+
Classifier: Operating System :: OS Independent
|
|
40
|
+
Classifier: Programming Language :: Python :: 3
|
|
41
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
42
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
43
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
44
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
45
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
46
|
+
Classifier: Topic :: Text Processing :: Linguistic
|
|
47
|
+
Requires-Python: >=3.11
|
|
48
|
+
Requires-Dist: ipykernel>=6
|
|
49
|
+
Requires-Dist: jupyter-client>=8
|
|
50
|
+
Requires-Dist: websockets>=12
|
|
51
|
+
Description-Content-Type: text/markdown
|
|
52
|
+
|
|
53
|
+
> ### **Attention!**
|
|
54
|
+
>
|
|
55
|
+
> Currently Tithon is alpha version. It may has lots of bugs and issues.
|
|
56
|
+
> Please report issues when you find any bugs which can help me to develop Tithon.
|
|
57
|
+
|
|
58
|
+
# Tithon
|
|
59
|
+
|
|
60
|
+
**The immortal Python REPL that will set you free.** Tithon keeps an interactive
|
|
61
|
+
Python (Jupyter) kernel running on a remote host independently of any client,
|
|
62
|
+
and losslessly restores cell output, progress, and widget state whenever a
|
|
63
|
+
client (re)connects — close your laptop mid-run, reopen over an SSH/VSCode
|
|
64
|
+
tunnel hours later, and your outputs are still there and still streaming.
|
|
65
|
+
|
|
66
|
+
> The name is from Tithonus of Greek myth, granted immortality but not eternal
|
|
67
|
+
> youth — like a remote kernel that stays alive while its outputs wither the
|
|
68
|
+
> moment the client disconnects. Tithon lifts the curse: _immortality, with
|
|
69
|
+
> eternal youth this time._
|
|
70
|
+
|
|
71
|
+
The authoritative design document is [`docs/SPEC.md`](docs/SPEC.md); it also
|
|
72
|
+
covers current implementation maturity and the verification matrix.
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
## Features
|
|
77
|
+
|
|
78
|
+
- **Kernel persistence.** The kernel is spawned detached (`setsid`) and is not a
|
|
79
|
+
child of the daemon, so it survives daemon restarts, crashes, and disconnects.
|
|
80
|
+
- **Loss-free journal.** Every iopub/shell message is preserved verbatim in a
|
|
81
|
+
SQLite (WAL) journal, plus a per-execution _folded_ snapshot (the current
|
|
82
|
+
display state) for fast reconnects.
|
|
83
|
+
- **Snapshot + delta sync.** Clients attach with a `last_seen_seq` and receive a
|
|
84
|
+
snapshot followed by a monotonic-sequence delta stream — gapless and ordered.
|
|
85
|
+
- **Live streaming with bounded cost.** Output streams to cells _as it runs_;
|
|
86
|
+
rendering is coalesced so a 50,000-iteration loop collapses to a handful of
|
|
87
|
+
UI updates instead of melting the renderer.
|
|
88
|
+
- **Outputs live in the journal, not the file.** A percent-format `.py` stays
|
|
89
|
+
pure source (byte-exact round-trip, clean diffs); outputs are reattached to
|
|
90
|
+
cells by content hash. Rich outputs (images) are stored as files, not base64.
|
|
91
|
+
- **Widget state mirror.** `ipywidgets` comm traffic is folded into a
|
|
92
|
+
`widget-state+json` snapshot — a `tqdm` bar with 50k updates reconnects as a
|
|
93
|
+
single bar, not 50k events.
|
|
94
|
+
- **Host protection.** A slow or stalled client cannot grow daemon memory
|
|
95
|
+
without bound or block other clients; the daemon caps per-subscriber buffers
|
|
96
|
+
and drops clients that fall too far behind (they reconnect and resync).
|
|
97
|
+
- **Unix-socket only.** The daemon binds a `0600` unix domain socket — no TCP.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## How it works
|
|
102
|
+
|
|
103
|
+
```
|
|
104
|
+
VSCode / CLI client Remote Host
|
|
105
|
+
┌────────────────────┐ ┌───────────────────────────────┐
|
|
106
|
+
│ subscribe(last_seq)│ ── unix sock ── │ tithon daemon │
|
|
107
|
+
│ snapshot + delta │ ◀───0600───── │ ├─ journal (SQLite WAL) │
|
|
108
|
+
│ restore / live │ │ ├─ folded snapshots │
|
|
109
|
+
└────────────────────┘ │ └─ widget mirror │
|
|
110
|
+
│ │ ZMQ (detached) │
|
|
111
|
+
│ ┌─────┴───────┐ │
|
|
112
|
+
│ │ ipykernel │ survives │
|
|
113
|
+
│ └─────────────┘ restarts │
|
|
114
|
+
└───────────────────────────────┘
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
The daemon owns the kernel and journals everything it emits. Clients never talk
|
|
118
|
+
to the kernel directly — they sync against the journal, so any number of clients
|
|
119
|
+
can connect and disconnect at any time and always converge on the same state.
|
|
120
|
+
|
|
121
|
+
---
|
|
122
|
+
|
|
123
|
+
## Requirements
|
|
124
|
+
|
|
125
|
+
- **Python 3.11+** (the daemon and CLI).
|
|
126
|
+
- [**uv**](https://github.com/astral-sh/uv) for environment management.
|
|
127
|
+
- **Node 20+ / npm** — only to build or run the VSCode extension.
|
|
128
|
+
|
|
129
|
+
---
|
|
130
|
+
|
|
131
|
+
## Installation
|
|
132
|
+
|
|
133
|
+
### Daemon + CLI
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
uv sync # create .venv (Python 3.11+), install tithon + dev deps
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
This puts a `tithon` entry point in `.venv/bin`. Run it with `uv run tithon …`,
|
|
140
|
+
or call `.venv/bin/tithon` directly. Dependencies are managed with
|
|
141
|
+
[uv](https://docs.astral.sh/uv/): runtime deps in `[project.dependencies]`, dev
|
|
142
|
+
and verification deps in `[dependency-groups]`, all pinned by `uv.lock`.
|
|
143
|
+
|
|
144
|
+
### VSCode extension
|
|
145
|
+
|
|
146
|
+
The extension is not yet on the Marketplace; build it from source and either run
|
|
147
|
+
it in a development host or package it as a `.vsix`:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
cd extension
|
|
151
|
+
npm install
|
|
152
|
+
npm run build # tsc -> dist/
|
|
153
|
+
npx vsce package # optional: -> tithon-extension-<version>.vsix
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Press **F5** in `extension/` to launch an Extension Development Host, or install
|
|
157
|
+
the `.vsix` (Extensions panel ▸ "Install from VSIX…"). For the remote workflow
|
|
158
|
+
this project is built for, see
|
|
159
|
+
[Remote workflow (VSCode tunnel)](#remote-workflow-vscode-tunnel) below; the
|
|
160
|
+
automated integration harness is described in [`docs/SPEC.md`](docs/SPEC.md).
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## Quickstart(CLI)
|
|
165
|
+
|
|
166
|
+
State (socket, log, journal, artifacts) lives under `TITHON_HOME`, default
|
|
167
|
+
`~/.tithon`.
|
|
168
|
+
|
|
169
|
+
**1. Start the daemon** (it runs in the foreground; background it):
|
|
170
|
+
|
|
171
|
+
```bash
|
|
172
|
+
tithon daemon &
|
|
173
|
+
tail -f ~/.tithon/daemon.log # optional
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
**2. Run code** — kernel state persists across calls:
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
tithon run -c 'x = 41'
|
|
180
|
+
tithon run -c 'x += 1; print(x)' # -> 42
|
|
181
|
+
tithon status
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
**3. Survive a disconnect** — the kernel outlives the daemon, and a reconnect
|
|
185
|
+
restores everything:
|
|
186
|
+
|
|
187
|
+
```bash
|
|
188
|
+
tithon run -c 'for i in range(3): print("line", i)'
|
|
189
|
+
|
|
190
|
+
pkill -9 -f 'tithon daemon' # kill the daemon; the kernel lives on
|
|
191
|
+
tithon daemon & # restart -> re-attaches the same kernel
|
|
192
|
+
|
|
193
|
+
tithon attach --since 0 --once # full snapshot: the prior output is back
|
|
194
|
+
tithon run -c 'print(x)' # -> 42, kernel state intact
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## Quickstart(Remote workflow)
|
|
200
|
+
|
|
201
|
+
This is the workflow Tithon is built for: you edit from a laptop while the kernel
|
|
202
|
+
runs on a remote GPU host and keeps running across your disconnects. With a
|
|
203
|
+
VSCode **Tunnel** (or **Remote-SSH**) connection the VSCode _Extension Host_ runs
|
|
204
|
+
**on the remote host**, so the Tithon extension reaches the daemon's host-local
|
|
205
|
+
unix socket directly — no port forwarding. Your laptop only renders the UI, so
|
|
206
|
+
closing it never stops the work.
|
|
207
|
+
|
|
208
|
+
**On the remote host** — install (see [Installation](#installation)) and:
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
# 1. Start the daemon. It binds $TITHON_HOME/daemon.sock on the host
|
|
212
|
+
# (default ~/.tithon/daemon.sock) and owns the kernel.
|
|
213
|
+
tithon daemon &
|
|
214
|
+
|
|
215
|
+
# 2. Make the extension available to the remote VSCode — package it once...
|
|
216
|
+
cd extension && npm install && npx vsce package # -> tithon-extension-<version>.vsix
|
|
217
|
+
# ...then install the .vsix into the remote VSCode (Extensions ▸ "Install from
|
|
218
|
+
# VSIX…", or `code --install-extension tithon-extension-<version>.vsix`).
|
|
219
|
+
# During development you can instead open extension/ and press F5.
|
|
220
|
+
|
|
221
|
+
# 3. Expose the host to VSCode.
|
|
222
|
+
code tunnel # or connect via Remote-SSH
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
**From your laptop:**
|
|
226
|
+
|
|
227
|
+
1. Connect to the host (VSCode ▸ _Connect to Tunnel…_ or _Remote-SSH_) and open
|
|
228
|
+
your project folder.
|
|
229
|
+
2. Open a percent-format `.py`. Run cells with the **Run Cell** CodeLens, then
|
|
230
|
+
run **Tithon: Start Live Output Sync** to stream output into the cells as it
|
|
231
|
+
is produced.
|
|
232
|
+
3. Close the laptop or drop the connection — the daemon and kernel keep running
|
|
233
|
+
on the host.
|
|
234
|
+
4. Reconnect later and run **Tithon: Restore Cell Outputs from Daemon** (or just
|
|
235
|
+
reopen the notebook): the outputs are back and resume streaming live.
|
|
236
|
+
|
|
237
|
+
> **Note.** The daemon and the extension must share `TITHON_HOME` (both default
|
|
238
|
+
> to `~/.tithon` for the same user on the host). Because the Extension Host runs
|
|
239
|
+
> on the host, it uses the host-local socket — no manual forwarding. If you
|
|
240
|
+
> instead run the extension on your laptop against a remote daemon, you must
|
|
241
|
+
> forward the unix socket yourself (e.g. SSH `RemoteForward` or `socat`); that is
|
|
242
|
+
> not the default path.
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
## CLI reference
|
|
247
|
+
|
|
248
|
+
| Command | Description |
|
|
249
|
+
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
250
|
+
| `tithon daemon` | Run the daemon (foreground). Owns the kernel and serves clients. |
|
|
251
|
+
| `tithon run -c CODE` | Submit code and stream its output. `--no-wait` prints the exec id and exits; `--timeout N` bounds the wait. |
|
|
252
|
+
| `tithon attach` | Stream events as NDJSON. `--since N` sets the resume point; `--once` exits after the backlog sync; `--until-done` exits after the next completion. |
|
|
253
|
+
| `tithon status` | Print session, queue, kernel, and widget-model status. |
|
|
254
|
+
|
|
255
|
+
`attach --since` is the reconnect knob:
|
|
256
|
+
|
|
257
|
+
- `--since 0` — full folded snapshot, then live delta.
|
|
258
|
+
- `--since N` — replay only events after seq `N`, then a `sync` marker, then live.
|
|
259
|
+
- `--since -1` — live only (ignore history).
|
|
260
|
+
|
|
261
|
+
---
|
|
262
|
+
|
|
263
|
+
## VSCode extension
|
|
264
|
+
|
|
265
|
+
The extension opens percent-format `.py` files as a notebook (`tithon-py`) and
|
|
266
|
+
talks to the daemon over its unix socket. Commands:
|
|
267
|
+
|
|
268
|
+
| Command | What it does |
|
|
269
|
+
| -------------------------------------------------------------------- | --------------------------------------------------------------------------- |
|
|
270
|
+
| `Tithon: Restore Cell Outputs from Daemon` (`tithon.restoreOutputs`) | Reconnect and restore the journal's folded outputs into the notebook cells. |
|
|
271
|
+
| `Tithon: Start Live Output Sync` (`tithon.startLive`) | Keep a session open and stream output into cells in real time. |
|
|
272
|
+
| `Run Cell` (CodeLens, `tithon.runCell`) | Submit a `# %%` cell's code to the daemon. |
|
|
273
|
+
|
|
274
|
+
Outputs are matched to cells by content hash, so they survive edits and reopens;
|
|
275
|
+
an output whose cell was edited since it ran is flagged stale.
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## Configuration
|
|
280
|
+
|
|
281
|
+
Environment variables read by the daemon and CLI:
|
|
282
|
+
|
|
283
|
+
| Variable | Default | Purpose |
|
|
284
|
+
| -------------------------- | ----------- | ------------------------------------------------------------------ |
|
|
285
|
+
| `TITHON_HOME` | `~/.tithon` | Root for the socket, log, journal, and artifacts. |
|
|
286
|
+
| `TITHON_SUB_QUEUE_MAX` | `10000` | Max queued events per client before it is dropped (backpressure). |
|
|
287
|
+
| `TITHON_SEND_TIMEOUT` | `10.0` | Seconds a client may stall a send before being dropped. |
|
|
288
|
+
| `TITHON_WRITE_BUFFER_HIGH` | `1048576` | Per-connection send-buffer high-water mark (bounds daemon memory). |
|
|
289
|
+
| `TITHON_SOCK_SNDBUF` | `1048576` | Per-connection kernel socket send buffer. |
|
|
290
|
+
| `TITHON_SUB_POLL` | `0.5` | Interval at which a blocked sender re-checks for drop. |
|
|
291
|
+
|
|
292
|
+
**Where outputs are stored.** A percent `.py` never holds outputs. They live in
|
|
293
|
+
`$TITHON_HOME/sessions/default/journal.db` (raw messages + folded snapshots),
|
|
294
|
+
with rich outputs (images) written as files under `<workdir>/.tithon/outputs/`
|
|
295
|
+
and referenced from the journal.
|
|
296
|
+
|
|
297
|
+
---
|
|
298
|
+
|
|
299
|
+
## Architecture invariants
|
|
300
|
+
|
|
301
|
+
These are load-bearing; see [`docs/SPEC.md`](docs/SPEC.md) for the full
|
|
302
|
+
rationale.
|
|
303
|
+
|
|
304
|
+
1. The kernel is spawned detached and its connection file is persisted, so the
|
|
305
|
+
daemon re-attaches to it after a restart.
|
|
306
|
+
2. All iopub/shell messages are kept verbatim in SQLite (WAL), with a folded
|
|
307
|
+
per-execution snapshot maintained alongside.
|
|
308
|
+
3. Client sync is snapshot + delta over a monotonically increasing sequence.
|
|
309
|
+
4. Rich `image/*` outputs are stored as files, not base64 in the journal.
|
|
310
|
+
5. The daemon binds a `0600` unix domain socket only — never TCP.
|
|
311
|
+
|
|
312
|
+
---
|
tithon-0.1.0/README.md
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
> ### **Attention!**
|
|
2
|
+
>
|
|
3
|
+
> Currently Tithon is alpha version. It may has lots of bugs and issues.
|
|
4
|
+
> Please report issues when you find any bugs which can help me to develop Tithon.
|
|
5
|
+
|
|
6
|
+
# Tithon
|
|
7
|
+
|
|
8
|
+
**The immortal Python REPL that will set you free.** Tithon keeps an interactive
|
|
9
|
+
Python (Jupyter) kernel running on a remote host independently of any client,
|
|
10
|
+
and losslessly restores cell output, progress, and widget state whenever a
|
|
11
|
+
client (re)connects — close your laptop mid-run, reopen over an SSH/VSCode
|
|
12
|
+
tunnel hours later, and your outputs are still there and still streaming.
|
|
13
|
+
|
|
14
|
+
> The name is from Tithonus of Greek myth, granted immortality but not eternal
|
|
15
|
+
> youth — like a remote kernel that stays alive while its outputs wither the
|
|
16
|
+
> moment the client disconnects. Tithon lifts the curse: _immortality, with
|
|
17
|
+
> eternal youth this time._
|
|
18
|
+
|
|
19
|
+
The authoritative design document is [`docs/SPEC.md`](docs/SPEC.md); it also
|
|
20
|
+
covers current implementation maturity and the verification matrix.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Features
|
|
25
|
+
|
|
26
|
+
- **Kernel persistence.** The kernel is spawned detached (`setsid`) and is not a
|
|
27
|
+
child of the daemon, so it survives daemon restarts, crashes, and disconnects.
|
|
28
|
+
- **Loss-free journal.** Every iopub/shell message is preserved verbatim in a
|
|
29
|
+
SQLite (WAL) journal, plus a per-execution _folded_ snapshot (the current
|
|
30
|
+
display state) for fast reconnects.
|
|
31
|
+
- **Snapshot + delta sync.** Clients attach with a `last_seen_seq` and receive a
|
|
32
|
+
snapshot followed by a monotonic-sequence delta stream — gapless and ordered.
|
|
33
|
+
- **Live streaming with bounded cost.** Output streams to cells _as it runs_;
|
|
34
|
+
rendering is coalesced so a 50,000-iteration loop collapses to a handful of
|
|
35
|
+
UI updates instead of melting the renderer.
|
|
36
|
+
- **Outputs live in the journal, not the file.** A percent-format `.py` stays
|
|
37
|
+
pure source (byte-exact round-trip, clean diffs); outputs are reattached to
|
|
38
|
+
cells by content hash. Rich outputs (images) are stored as files, not base64.
|
|
39
|
+
- **Widget state mirror.** `ipywidgets` comm traffic is folded into a
|
|
40
|
+
`widget-state+json` snapshot — a `tqdm` bar with 50k updates reconnects as a
|
|
41
|
+
single bar, not 50k events.
|
|
42
|
+
- **Host protection.** A slow or stalled client cannot grow daemon memory
|
|
43
|
+
without bound or block other clients; the daemon caps per-subscriber buffers
|
|
44
|
+
and drops clients that fall too far behind (they reconnect and resync).
|
|
45
|
+
- **Unix-socket only.** The daemon binds a `0600` unix domain socket — no TCP.
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## How it works
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
VSCode / CLI client Remote Host
|
|
53
|
+
┌────────────────────┐ ┌───────────────────────────────┐
|
|
54
|
+
│ subscribe(last_seq)│ ── unix sock ── │ tithon daemon │
|
|
55
|
+
│ snapshot + delta │ ◀───0600───── │ ├─ journal (SQLite WAL) │
|
|
56
|
+
│ restore / live │ │ ├─ folded snapshots │
|
|
57
|
+
└────────────────────┘ │ └─ widget mirror │
|
|
58
|
+
│ │ ZMQ (detached) │
|
|
59
|
+
│ ┌─────┴───────┐ │
|
|
60
|
+
│ │ ipykernel │ survives │
|
|
61
|
+
│ └─────────────┘ restarts │
|
|
62
|
+
└───────────────────────────────┘
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The daemon owns the kernel and journals everything it emits. Clients never talk
|
|
66
|
+
to the kernel directly — they sync against the journal, so any number of clients
|
|
67
|
+
can connect and disconnect at any time and always converge on the same state.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Requirements
|
|
72
|
+
|
|
73
|
+
- **Python 3.11+** (the daemon and CLI).
|
|
74
|
+
- [**uv**](https://github.com/astral-sh/uv) for environment management.
|
|
75
|
+
- **Node 20+ / npm** — only to build or run the VSCode extension.
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Installation
|
|
80
|
+
|
|
81
|
+
### Daemon + CLI
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
uv sync # create .venv (Python 3.11+), install tithon + dev deps
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
This puts a `tithon` entry point in `.venv/bin`. Run it with `uv run tithon …`,
|
|
88
|
+
or call `.venv/bin/tithon` directly. Dependencies are managed with
|
|
89
|
+
[uv](https://docs.astral.sh/uv/): runtime deps in `[project.dependencies]`, dev
|
|
90
|
+
and verification deps in `[dependency-groups]`, all pinned by `uv.lock`.
|
|
91
|
+
|
|
92
|
+
### VSCode extension
|
|
93
|
+
|
|
94
|
+
The extension is not yet on the Marketplace; build it from source and either run
|
|
95
|
+
it in a development host or package it as a `.vsix`:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
cd extension
|
|
99
|
+
npm install
|
|
100
|
+
npm run build # tsc -> dist/
|
|
101
|
+
npx vsce package # optional: -> tithon-extension-<version>.vsix
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Press **F5** in `extension/` to launch an Extension Development Host, or install
|
|
105
|
+
the `.vsix` (Extensions panel ▸ "Install from VSIX…"). For the remote workflow
|
|
106
|
+
this project is built for, see
|
|
107
|
+
[Remote workflow (VSCode tunnel)](#remote-workflow-vscode-tunnel) below; the
|
|
108
|
+
automated integration harness is described in [`docs/SPEC.md`](docs/SPEC.md).
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## Quickstart(CLI)
|
|
113
|
+
|
|
114
|
+
State (socket, log, journal, artifacts) lives under `TITHON_HOME`, default
|
|
115
|
+
`~/.tithon`.
|
|
116
|
+
|
|
117
|
+
**1. Start the daemon** (it runs in the foreground; background it):
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
tithon daemon &
|
|
121
|
+
tail -f ~/.tithon/daemon.log # optional
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**2. Run code** — kernel state persists across calls:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
tithon run -c 'x = 41'
|
|
128
|
+
tithon run -c 'x += 1; print(x)' # -> 42
|
|
129
|
+
tithon status
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
**3. Survive a disconnect** — the kernel outlives the daemon, and a reconnect
|
|
133
|
+
restores everything:
|
|
134
|
+
|
|
135
|
+
```bash
|
|
136
|
+
tithon run -c 'for i in range(3): print("line", i)'
|
|
137
|
+
|
|
138
|
+
pkill -9 -f 'tithon daemon' # kill the daemon; the kernel lives on
|
|
139
|
+
tithon daemon & # restart -> re-attaches the same kernel
|
|
140
|
+
|
|
141
|
+
tithon attach --since 0 --once # full snapshot: the prior output is back
|
|
142
|
+
tithon run -c 'print(x)' # -> 42, kernel state intact
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
---
|
|
146
|
+
|
|
147
|
+
## Quickstart(Remote workflow)
|
|
148
|
+
|
|
149
|
+
This is the workflow Tithon is built for: you edit from a laptop while the kernel
|
|
150
|
+
runs on a remote GPU host and keeps running across your disconnects. With a
|
|
151
|
+
VSCode **Tunnel** (or **Remote-SSH**) connection the VSCode _Extension Host_ runs
|
|
152
|
+
**on the remote host**, so the Tithon extension reaches the daemon's host-local
|
|
153
|
+
unix socket directly — no port forwarding. Your laptop only renders the UI, so
|
|
154
|
+
closing it never stops the work.
|
|
155
|
+
|
|
156
|
+
**On the remote host** — install (see [Installation](#installation)) and:
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
# 1. Start the daemon. It binds $TITHON_HOME/daemon.sock on the host
|
|
160
|
+
# (default ~/.tithon/daemon.sock) and owns the kernel.
|
|
161
|
+
tithon daemon &
|
|
162
|
+
|
|
163
|
+
# 2. Make the extension available to the remote VSCode — package it once...
|
|
164
|
+
cd extension && npm install && npx vsce package # -> tithon-extension-<version>.vsix
|
|
165
|
+
# ...then install the .vsix into the remote VSCode (Extensions ▸ "Install from
|
|
166
|
+
# VSIX…", or `code --install-extension tithon-extension-<version>.vsix`).
|
|
167
|
+
# During development you can instead open extension/ and press F5.
|
|
168
|
+
|
|
169
|
+
# 3. Expose the host to VSCode.
|
|
170
|
+
code tunnel # or connect via Remote-SSH
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**From your laptop:**
|
|
174
|
+
|
|
175
|
+
1. Connect to the host (VSCode ▸ _Connect to Tunnel…_ or _Remote-SSH_) and open
|
|
176
|
+
your project folder.
|
|
177
|
+
2. Open a percent-format `.py`. Run cells with the **Run Cell** CodeLens, then
|
|
178
|
+
run **Tithon: Start Live Output Sync** to stream output into the cells as it
|
|
179
|
+
is produced.
|
|
180
|
+
3. Close the laptop or drop the connection — the daemon and kernel keep running
|
|
181
|
+
on the host.
|
|
182
|
+
4. Reconnect later and run **Tithon: Restore Cell Outputs from Daemon** (or just
|
|
183
|
+
reopen the notebook): the outputs are back and resume streaming live.
|
|
184
|
+
|
|
185
|
+
> **Note.** The daemon and the extension must share `TITHON_HOME` (both default
|
|
186
|
+
> to `~/.tithon` for the same user on the host). Because the Extension Host runs
|
|
187
|
+
> on the host, it uses the host-local socket — no manual forwarding. If you
|
|
188
|
+
> instead run the extension on your laptop against a remote daemon, you must
|
|
189
|
+
> forward the unix socket yourself (e.g. SSH `RemoteForward` or `socat`); that is
|
|
190
|
+
> not the default path.
|
|
191
|
+
|
|
192
|
+
---
|
|
193
|
+
|
|
194
|
+
## CLI reference
|
|
195
|
+
|
|
196
|
+
| Command | Description |
|
|
197
|
+
| -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
198
|
+
| `tithon daemon` | Run the daemon (foreground). Owns the kernel and serves clients. |
|
|
199
|
+
| `tithon run -c CODE` | Submit code and stream its output. `--no-wait` prints the exec id and exits; `--timeout N` bounds the wait. |
|
|
200
|
+
| `tithon attach` | Stream events as NDJSON. `--since N` sets the resume point; `--once` exits after the backlog sync; `--until-done` exits after the next completion. |
|
|
201
|
+
| `tithon status` | Print session, queue, kernel, and widget-model status. |
|
|
202
|
+
|
|
203
|
+
`attach --since` is the reconnect knob:
|
|
204
|
+
|
|
205
|
+
- `--since 0` — full folded snapshot, then live delta.
|
|
206
|
+
- `--since N` — replay only events after seq `N`, then a `sync` marker, then live.
|
|
207
|
+
- `--since -1` — live only (ignore history).
|
|
208
|
+
|
|
209
|
+
---
|
|
210
|
+
|
|
211
|
+
## VSCode extension
|
|
212
|
+
|
|
213
|
+
The extension opens percent-format `.py` files as a notebook (`tithon-py`) and
|
|
214
|
+
talks to the daemon over its unix socket. Commands:
|
|
215
|
+
|
|
216
|
+
| Command | What it does |
|
|
217
|
+
| -------------------------------------------------------------------- | --------------------------------------------------------------------------- |
|
|
218
|
+
| `Tithon: Restore Cell Outputs from Daemon` (`tithon.restoreOutputs`) | Reconnect and restore the journal's folded outputs into the notebook cells. |
|
|
219
|
+
| `Tithon: Start Live Output Sync` (`tithon.startLive`) | Keep a session open and stream output into cells in real time. |
|
|
220
|
+
| `Run Cell` (CodeLens, `tithon.runCell`) | Submit a `# %%` cell's code to the daemon. |
|
|
221
|
+
|
|
222
|
+
Outputs are matched to cells by content hash, so they survive edits and reopens;
|
|
223
|
+
an output whose cell was edited since it ran is flagged stale.
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
## Configuration
|
|
228
|
+
|
|
229
|
+
Environment variables read by the daemon and CLI:
|
|
230
|
+
|
|
231
|
+
| Variable | Default | Purpose |
|
|
232
|
+
| -------------------------- | ----------- | ------------------------------------------------------------------ |
|
|
233
|
+
| `TITHON_HOME` | `~/.tithon` | Root for the socket, log, journal, and artifacts. |
|
|
234
|
+
| `TITHON_SUB_QUEUE_MAX` | `10000` | Max queued events per client before it is dropped (backpressure). |
|
|
235
|
+
| `TITHON_SEND_TIMEOUT` | `10.0` | Seconds a client may stall a send before being dropped. |
|
|
236
|
+
| `TITHON_WRITE_BUFFER_HIGH` | `1048576` | Per-connection send-buffer high-water mark (bounds daemon memory). |
|
|
237
|
+
| `TITHON_SOCK_SNDBUF` | `1048576` | Per-connection kernel socket send buffer. |
|
|
238
|
+
| `TITHON_SUB_POLL` | `0.5` | Interval at which a blocked sender re-checks for drop. |
|
|
239
|
+
|
|
240
|
+
**Where outputs are stored.** A percent `.py` never holds outputs. They live in
|
|
241
|
+
`$TITHON_HOME/sessions/default/journal.db` (raw messages + folded snapshots),
|
|
242
|
+
with rich outputs (images) written as files under `<workdir>/.tithon/outputs/`
|
|
243
|
+
and referenced from the journal.
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
247
|
+
## Architecture invariants
|
|
248
|
+
|
|
249
|
+
These are load-bearing; see [`docs/SPEC.md`](docs/SPEC.md) for the full
|
|
250
|
+
rationale.
|
|
251
|
+
|
|
252
|
+
1. The kernel is spawned detached and its connection file is persisted, so the
|
|
253
|
+
daemon re-attaches to it after a restart.
|
|
254
|
+
2. All iopub/shell messages are kept verbatim in SQLite (WAL), with a folded
|
|
255
|
+
per-execution snapshot maintained alongside.
|
|
256
|
+
3. Client sync is snapshot + delta over a monotonically increasing sequence.
|
|
257
|
+
4. Rich `image/*` outputs are stored as files, not base64 in the journal.
|
|
258
|
+
5. The daemon binds a `0600` unix domain socket only — never TCP.
|
|
259
|
+
|
|
260
|
+
---
|