sessiontools 0.0.1__tar.gz → 0.0.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.
- {sessiontools-0.0.1 → sessiontools-0.0.3}/PKG-INFO +2 -2
- {sessiontools-0.0.1 → sessiontools-0.0.3}/pyproject.toml +7 -2
- {sessiontools-0.0.1 → sessiontools-0.0.3}/src/sessiontools/__init__.py +7 -0
- {sessiontools-0.0.1 → sessiontools-0.0.3}/src/sessiontools/claude_code.py +36 -0
- {sessiontools-0.0.1 → sessiontools-0.0.3}/src/sessiontools/cli.py +0 -0
- {sessiontools-0.0.1 → sessiontools-0.0.3}/src/sessiontools/py.typed +0 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: sessiontools
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.3
|
|
4
4
|
Summary: The harness layer: sessions, status and idle, one driver per harness - a library first
|
|
5
5
|
Author: Cora 7
|
|
6
6
|
Author-email: Cora 7 <ai-cora@failmode.com>
|
|
7
|
-
Requires-Python: >=3.
|
|
7
|
+
Requires-Python: >=3.11
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "sessiontools"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.3"
|
|
4
4
|
description = "The harness layer: sessions, status and idle, one driver per harness - a library first"
|
|
5
5
|
authors = [
|
|
6
6
|
{ name = "Cora 7", email = "ai-cora@failmode.com" }
|
|
7
7
|
]
|
|
8
|
-
|
|
8
|
+
# >=3.11, not the recipe's >=3.13: sessionmail (the first consumer) declares
|
|
9
|
+
# >=3.11, and uv resolves for EVERY version a project allows, so a stricter
|
|
10
|
+
# floor here made sessionmail's `uv sync` unsatisfiable (Pip, 13:02 Thu
|
|
11
|
+
# 2026-09-17). Measured: the suite passes on 3.11, 3.12 and 3.13; nothing in
|
|
12
|
+
# the tree needs 3.13.
|
|
13
|
+
requires-python = ">=3.11"
|
|
9
14
|
# ZERO runtime dependencies, on purpose: sessionmail (click + mcp) will
|
|
10
15
|
# depend on this, and a stranger installing sessionmail must be happy to
|
|
11
16
|
# pull it. A library first.
|
|
@@ -6,6 +6,7 @@ cutover (Mike, voice 12:18 Thu 2026-09-17), and the one that arrives then
|
|
|
6
6
|
is `session`, whose verbs the fleet's callers are already written to.
|
|
7
7
|
|
|
8
8
|
from sessiontools import sessions, find, idle_seconds
|
|
9
|
+
from sessiontools import session_id, current, SESSION_ID_VARS
|
|
9
10
|
|
|
10
11
|
Every function speaks OUR words - busy, not busy, unknown - never a
|
|
11
12
|
harness's. The first driver is `claude_code`; the day a harness changes a
|
|
@@ -17,10 +18,13 @@ from __future__ import annotations
|
|
|
17
18
|
from importlib.metadata import PackageNotFoundError, version
|
|
18
19
|
|
|
19
20
|
from sessiontools.claude_code import (
|
|
21
|
+
SESSION_ID_VARS,
|
|
20
22
|
SIDECAR_DIR_ENV,
|
|
21
23
|
Session,
|
|
24
|
+
current,
|
|
22
25
|
find,
|
|
23
26
|
idle_seconds,
|
|
27
|
+
session_id,
|
|
24
28
|
sessions,
|
|
25
29
|
sidecar_dir,
|
|
26
30
|
)
|
|
@@ -31,11 +35,14 @@ except PackageNotFoundError: # a checkout that is not installed
|
|
|
31
35
|
__version__ = "0+unknown"
|
|
32
36
|
|
|
33
37
|
__all__ = [
|
|
38
|
+
"SESSION_ID_VARS",
|
|
34
39
|
"SIDECAR_DIR_ENV",
|
|
35
40
|
"Session",
|
|
36
41
|
"__version__",
|
|
42
|
+
"current",
|
|
37
43
|
"find",
|
|
38
44
|
"idle_seconds",
|
|
45
|
+
"session_id",
|
|
39
46
|
"sessions",
|
|
40
47
|
"sidecar_dir",
|
|
41
48
|
]
|
|
@@ -109,6 +109,42 @@ def find(session_id: str, env: dict[str, str] | None = None) -> Session | None:
|
|
|
109
109
|
return None
|
|
110
110
|
|
|
111
111
|
|
|
112
|
+
#: Where Claude Code puts THIS session's id, first non-blank wins, in this
|
|
113
|
+
#: order (Mike, voice 20:36-20:41 Wed 2026-09-23). The chain was written
|
|
114
|
+
#: three times and never shared; this is the one copy. Public, so a caller
|
|
115
|
+
#: that needs the names (to scrub a child's environment, say) reads them
|
|
116
|
+
#: here instead of spelling them again.
|
|
117
|
+
SESSION_ID_VARS = ("CLAUDE_CODE_SESSION_ID", "CLAUDE_SESSION_ID")
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
def session_id(env: dict[str, str] | None = None) -> str | None:
|
|
121
|
+
"""This session's id, from the environment ONLY; None when there is none.
|
|
122
|
+
|
|
123
|
+
Never the disk: the pager needs the id before Claude Code has written
|
|
124
|
+
its sidecar. The first NON-BLANK variable in SESSION_ID_VARS wins, and
|
|
125
|
+
its value is stripped - the rule sessionmail's `_seat.session_id`
|
|
126
|
+
already keeps (sessionmail 0c010ed, src/sessionmail/_seat.py:59
|
|
127
|
+
SESSION_VARS, :930 session_id), except that no id is None here, not
|
|
128
|
+
that module's `-` marks-line placeholder.
|
|
129
|
+
"""
|
|
130
|
+
env = os.environ if env is None else env
|
|
131
|
+
for var in SESSION_ID_VARS:
|
|
132
|
+
value = (env.get(var) or "").strip()
|
|
133
|
+
if value:
|
|
134
|
+
return value
|
|
135
|
+
return None
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def current(env: dict[str, str] | None = None) -> Session | None:
|
|
139
|
+
"""This session, read from its sidecar: `find(session_id(env))`.
|
|
140
|
+
|
|
141
|
+
None when the environment names no session, or when no sidecar names
|
|
142
|
+
the one it does. Read-only, like everything in this driver.
|
|
143
|
+
"""
|
|
144
|
+
sid = session_id(env)
|
|
145
|
+
return None if sid is None else find(sid, env)
|
|
146
|
+
|
|
147
|
+
|
|
112
148
|
def idle_seconds(session_id: str, now: float | None = None,
|
|
113
149
|
env: dict[str, str] | None = None) -> float | None:
|
|
114
150
|
"""The one number the pager wants: 0 while busy, else seconds since
|
|
File without changes
|
|
File without changes
|