tabc 0.2.1__tar.gz → 0.2.2__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.
- {tabc-0.2.1 → tabc-0.2.2}/CHANGELOG.md +45 -0
- {tabc-0.2.1/tabc.egg-info → tabc-0.2.2}/PKG-INFO +25 -7
- {tabc-0.2.1 → tabc-0.2.2}/PYPI.md +22 -1
- {tabc-0.2.1 → tabc-0.2.2}/pyproject.toml +1 -1
- {tabc-0.2.1 → tabc-0.2.2/tabc.egg-info}/PKG-INFO +25 -7
- {tabc-0.2.1 → tabc-0.2.2}/tabus/bus.py +1 -1
- {tabc-0.2.1 → tabc-0.2.2}/tabus/cli.py +1 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabus/route_capture.py +3 -3
- {tabc-0.2.1 → tabc-0.2.2}/tabus/terminal_frontend.py +27 -7
- {tabc-0.2.1 → tabc-0.2.2}/GUIDE.md +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/LICENSE +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/MANIFEST.in +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/MCP.md +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/setup.cfg +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabc.egg-info/SOURCES.txt +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabc.egg-info/dependency_links.txt +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabc.egg-info/entry_points.txt +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabc.egg-info/requires.txt +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabc.egg-info/top_level.txt +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabus/__init__.py +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabus/admin.py +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabus/codex_queue.py +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabus/compat_bcn.py +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabus/compat_busd.py +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabus/daemon.py +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabus/doorbell.py +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabus/doorbell_poll.py +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabus/lang.py +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabus/locales/en.json +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabus/mcp_server.py +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabus/nodekey.py +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabus/paths.py +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabus/process_argv.py +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabus/send_refusal.py +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabus/sent.py +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabus/tac_identity.py +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabus/tac_migration.py +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabus/tac_refusal.py +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabus/tac_search.py +0 -0
- {tabc-0.2.1 → tabc-0.2.2}/tabus/tac_store.py +0 -0
|
@@ -1,5 +1,50 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.2 — 2026-10-17
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
|
|
7
|
+
- `register` treats `--kind` case-insensitively and stores it in lowercase.
|
|
8
|
+
`--kind OpenCode` registers `opencode`.
|
|
9
|
+
- Terminal route capture at a detached session boundary no longer requires a
|
|
10
|
+
recognized Codex or Claude CLI. The immediate session-boundary parent
|
|
11
|
+
qualifies when it belongs to the same OS user, leads the target terminal's
|
|
12
|
+
foreground process group, and reads standard input from that terminal.
|
|
13
|
+
Process state, executable path, and standard input are checked again before
|
|
14
|
+
the route is accepted. Product names and install directories are not an
|
|
15
|
+
admission list.
|
|
16
|
+
- Codex queue selection under `--kind codex --auto-enter on` and its fallback
|
|
17
|
+
rules are unchanged. Because the kind is case-folded, `--kind Codex` now
|
|
18
|
+
selects the same queue route.
|
|
19
|
+
|
|
20
|
+
### Notes
|
|
21
|
+
|
|
22
|
+
- The check verifies terminal ownership, not whether the program is an agent.
|
|
23
|
+
A foreground program that reads the terminal can qualify even if it is not
|
|
24
|
+
an agent. Automatic Enter remains a separate opt-in.
|
|
25
|
+
- No dedicated adapter for another agent product is added. The MCP adapter
|
|
26
|
+
still does not wake an agent.
|
|
27
|
+
|
|
28
|
+
### Upgrade notes (from 0.2.1)
|
|
29
|
+
|
|
30
|
+
- The ledger schema is unchanged. Nodes, signing keys, messages, delivery
|
|
31
|
+
states, TACs, routes, and Codex queue receipts are kept.
|
|
32
|
+
- Stop `tabus.doorbell`, install 0.2.2, restart `tabd`, then start one
|
|
33
|
+
`tabus.doorbell` from the same installation:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
python -m pip install --upgrade "tabc==0.2.2"
|
|
37
|
+
# Or, for desktop MCP support:
|
|
38
|
+
python -m pip install --upgrade "tabc[mcp]==0.2.2"
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
- Stored routes are not migrated. A failed capture does not replace an
|
|
42
|
+
existing route. Register again from the intended terminal, then confirm one
|
|
43
|
+
notification arrives.
|
|
44
|
+
- If a desktop client runs `tabc-mcp`, restart that MCP process from the client
|
|
45
|
+
after the upgrade so it loads the new installation.
|
|
46
|
+
- After restart, `tabc --version` and `tabd --version` report 0.2.2.
|
|
47
|
+
|
|
3
48
|
## 0.2.1 — 2026-10-15
|
|
4
49
|
|
|
5
50
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
2
|
Name: tabc
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: A shared inbox for AI agents and programs on one machine
|
|
5
5
|
License: MIT License
|
|
6
6
|
|
|
@@ -37,11 +37,8 @@ Classifier: Programming Language :: Python :: 3
|
|
|
37
37
|
Classifier: Topic :: Communications
|
|
38
38
|
Requires-Python: >=3.9
|
|
39
39
|
Description-Content-Type: text/markdown
|
|
40
|
-
License-File: LICENSE
|
|
41
|
-
Requires-Dist: cryptography>=41
|
|
42
40
|
Provides-Extra: mcp
|
|
43
|
-
|
|
44
|
-
Dynamic: license-file
|
|
41
|
+
License-File: LICENSE
|
|
45
42
|
|
|
46
43
|
# tabc
|
|
47
44
|
|
|
@@ -108,6 +105,27 @@ from the `pull --mode full` detail block, or a unique prefix of it.
|
|
|
108
105
|
Terminal notification is a separate process and does not start with the
|
|
109
106
|
install; see the repository's guide before turning it on.
|
|
110
107
|
|
|
108
|
+
## Updating from 0.2.1
|
|
109
|
+
|
|
110
|
+
The ledger schema is unchanged. Nodes, signing keys, messages, delivery states,
|
|
111
|
+
TACs, routes, and Codex queue receipts are kept. Stop `tabus.doorbell`, install,
|
|
112
|
+
restart `tabd`, then start one `tabus.doorbell` from the same installation:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
python -m pip install --upgrade "tabc==0.2.2"
|
|
116
|
+
# Or, when the local desktop MCP adapter is required:
|
|
117
|
+
python -m pip install --upgrade "tabc[mcp]==0.2.2"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
`--kind` is now case-insensitive; `--kind Codex` selects the same Codex queue
|
|
121
|
+
route as `--kind codex`. A detached command no longer needs a recognized agent
|
|
122
|
+
product: its immediate session-boundary parent qualifies when it owns the
|
|
123
|
+
terminal foreground and reads standard input from it. The check proves terminal
|
|
124
|
+
ownership, not that the program is an agent. Register again from the intended
|
|
125
|
+
terminal and confirm one notification arrives. Codex queue rules are otherwise
|
|
126
|
+
unchanged. See the
|
|
127
|
+
[changelog](https://github.com/jultabc/tabc/blob/main/CHANGELOG.md).
|
|
128
|
+
|
|
111
129
|
## Updating from 0.2.0
|
|
112
130
|
|
|
113
131
|
The ledger schema is unchanged. Nodes, signing keys, messages, delivery states,
|
|
@@ -143,7 +161,7 @@ python -m pip install --upgrade "tabc[mcp]==0.2.0"
|
|
|
143
161
|
Existing string TAC IDs are not converted during installation. Follow the
|
|
144
162
|
repository README's 0.2.0 ledger conversion procedure when converting TAC IDs
|
|
145
163
|
to UUIDs. Without conversion, restart `tabd` first, then `tabus.doorbell`.
|
|
146
|
-
Then follow "Updating from 0.2.0".
|
|
164
|
+
Then follow "Updating from 0.2.0" and "Updating from 0.2.1".
|
|
147
165
|
|
|
148
166
|
## Commands
|
|
149
167
|
|
|
@@ -63,6 +63,27 @@ from the `pull --mode full` detail block, or a unique prefix of it.
|
|
|
63
63
|
Terminal notification is a separate process and does not start with the
|
|
64
64
|
install; see the repository's guide before turning it on.
|
|
65
65
|
|
|
66
|
+
## Updating from 0.2.1
|
|
67
|
+
|
|
68
|
+
The ledger schema is unchanged. Nodes, signing keys, messages, delivery states,
|
|
69
|
+
TACs, routes, and Codex queue receipts are kept. Stop `tabus.doorbell`, install,
|
|
70
|
+
restart `tabd`, then start one `tabus.doorbell` from the same installation:
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
python -m pip install --upgrade "tabc==0.2.2"
|
|
74
|
+
# Or, when the local desktop MCP adapter is required:
|
|
75
|
+
python -m pip install --upgrade "tabc[mcp]==0.2.2"
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
`--kind` is now case-insensitive; `--kind Codex` selects the same Codex queue
|
|
79
|
+
route as `--kind codex`. A detached command no longer needs a recognized agent
|
|
80
|
+
product: its immediate session-boundary parent qualifies when it owns the
|
|
81
|
+
terminal foreground and reads standard input from it. The check proves terminal
|
|
82
|
+
ownership, not that the program is an agent. Register again from the intended
|
|
83
|
+
terminal and confirm one notification arrives. Codex queue rules are otherwise
|
|
84
|
+
unchanged. See the
|
|
85
|
+
[changelog](https://github.com/jultabc/tabc/blob/main/CHANGELOG.md).
|
|
86
|
+
|
|
66
87
|
## Updating from 0.2.0
|
|
67
88
|
|
|
68
89
|
The ledger schema is unchanged. Nodes, signing keys, messages, delivery states,
|
|
@@ -98,7 +119,7 @@ python -m pip install --upgrade "tabc[mcp]==0.2.0"
|
|
|
98
119
|
Existing string TAC IDs are not converted during installation. Follow the
|
|
99
120
|
repository README's 0.2.0 ledger conversion procedure when converting TAC IDs
|
|
100
121
|
to UUIDs. Without conversion, restart `tabd` first, then `tabus.doorbell`.
|
|
101
|
-
Then follow "Updating from 0.2.0".
|
|
122
|
+
Then follow "Updating from 0.2.0" and "Updating from 0.2.1".
|
|
102
123
|
|
|
103
124
|
## Commands
|
|
104
125
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.1
|
|
2
2
|
Name: tabc
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.2
|
|
4
4
|
Summary: A shared inbox for AI agents and programs on one machine
|
|
5
5
|
License: MIT License
|
|
6
6
|
|
|
@@ -37,11 +37,8 @@ Classifier: Programming Language :: Python :: 3
|
|
|
37
37
|
Classifier: Topic :: Communications
|
|
38
38
|
Requires-Python: >=3.9
|
|
39
39
|
Description-Content-Type: text/markdown
|
|
40
|
-
License-File: LICENSE
|
|
41
|
-
Requires-Dist: cryptography>=41
|
|
42
40
|
Provides-Extra: mcp
|
|
43
|
-
|
|
44
|
-
Dynamic: license-file
|
|
41
|
+
License-File: LICENSE
|
|
45
42
|
|
|
46
43
|
# tabc
|
|
47
44
|
|
|
@@ -108,6 +105,27 @@ from the `pull --mode full` detail block, or a unique prefix of it.
|
|
|
108
105
|
Terminal notification is a separate process and does not start with the
|
|
109
106
|
install; see the repository's guide before turning it on.
|
|
110
107
|
|
|
108
|
+
## Updating from 0.2.1
|
|
109
|
+
|
|
110
|
+
The ledger schema is unchanged. Nodes, signing keys, messages, delivery states,
|
|
111
|
+
TACs, routes, and Codex queue receipts are kept. Stop `tabus.doorbell`, install,
|
|
112
|
+
restart `tabd`, then start one `tabus.doorbell` from the same installation:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
python -m pip install --upgrade "tabc==0.2.2"
|
|
116
|
+
# Or, when the local desktop MCP adapter is required:
|
|
117
|
+
python -m pip install --upgrade "tabc[mcp]==0.2.2"
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
`--kind` is now case-insensitive; `--kind Codex` selects the same Codex queue
|
|
121
|
+
route as `--kind codex`. A detached command no longer needs a recognized agent
|
|
122
|
+
product: its immediate session-boundary parent qualifies when it owns the
|
|
123
|
+
terminal foreground and reads standard input from it. The check proves terminal
|
|
124
|
+
ownership, not that the program is an agent. Register again from the intended
|
|
125
|
+
terminal and confirm one notification arrives. Codex queue rules are otherwise
|
|
126
|
+
unchanged. See the
|
|
127
|
+
[changelog](https://github.com/jultabc/tabc/blob/main/CHANGELOG.md).
|
|
128
|
+
|
|
111
129
|
## Updating from 0.2.0
|
|
112
130
|
|
|
113
131
|
The ledger schema is unchanged. Nodes, signing keys, messages, delivery states,
|
|
@@ -143,7 +161,7 @@ python -m pip install --upgrade "tabc[mcp]==0.2.0"
|
|
|
143
161
|
Existing string TAC IDs are not converted during installation. Follow the
|
|
144
162
|
repository README's 0.2.0 ledger conversion procedure when converting TAC IDs
|
|
145
163
|
to UUIDs. Without conversion, restart `tabd` first, then `tabus.doorbell`.
|
|
146
|
-
Then follow "Updating from 0.2.0".
|
|
164
|
+
Then follow "Updating from 0.2.0" and "Updating from 0.2.1".
|
|
147
165
|
|
|
148
166
|
## Commands
|
|
149
167
|
|
|
@@ -74,7 +74,7 @@ DB_PATH = os.environ.get(
|
|
|
74
74
|
# drifted once already — 0.1.0.post1 shipped while this said 0.1.0. Bump
|
|
75
75
|
# both together; tests/test_version_agreement.py fails the build otherwise.
|
|
76
76
|
# Do not copy the number into documentation.
|
|
77
|
-
__version__ = "0.2.
|
|
77
|
+
__version__ = "0.2.2"
|
|
78
78
|
PROTOCOL_VERSION = "tabus.v1"
|
|
79
79
|
|
|
80
80
|
# TTLs. Past these, a derived status counts as old.
|
|
@@ -251,6 +251,7 @@ def fn_config(a):
|
|
|
251
251
|
|
|
252
252
|
def fn_register(a):
|
|
253
253
|
node = _require_acting_node(a.node)
|
|
254
|
+
a.kind = a.kind.casefold()
|
|
254
255
|
payload = {"node": node, "kind": a.kind}
|
|
255
256
|
take_route = bool(getattr(a, "take_route", False))
|
|
256
257
|
setting = getattr(a, "auto_enter", None)
|
|
@@ -6,8 +6,8 @@ that terminal. A detached shared runner can therefore carry one tab's route,
|
|
|
6
6
|
allocate a fresh PTY, and still register the stale tab. Route capture accepts
|
|
7
7
|
the inherited key only when its resolved TTY equals the controlling TTY of this
|
|
8
8
|
process or a same-session ancestor. A detached command may also use its immediate
|
|
9
|
-
session-boundary parent when that parent
|
|
10
|
-
and
|
|
9
|
+
session-boundary parent when that parent owns the target terminal foreground
|
|
10
|
+
process group and its standard input is that same terminal, regardless of kind.
|
|
11
11
|
"""
|
|
12
12
|
|
|
13
13
|
import os
|
|
@@ -99,7 +99,7 @@ def terminal_tty(
|
|
|
99
99
|
|
|
100
100
|
``ps`` is used instead of ``/proc`` so this works on both macOS and Linux.
|
|
101
101
|
Any lookup failure is a negative result. The cross-session fallback is
|
|
102
|
-
restricted to a checked
|
|
102
|
+
restricted to a checked foreground terminal owner, not arbitrary ancestors.
|
|
103
103
|
"""
|
|
104
104
|
inspect = process_row or _process_row
|
|
105
105
|
inspect_session = process_session or _session_id
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
"""
|
|
1
|
+
"""Verify a foreground terminal owner without a product-name allowlist.
|
|
2
2
|
|
|
3
3
|
This is local routing evidence, not an isolation boundary against a malicious
|
|
4
|
-
process running as the same OS user.
|
|
4
|
+
process running as the same OS user. Missing terminal evidence fails closed.
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
7
|
import ctypes
|
|
@@ -57,7 +57,7 @@ def executable_kind(executable, user_home):
|
|
|
57
57
|
|
|
58
58
|
|
|
59
59
|
def interactive_arguments(kind, argv):
|
|
60
|
-
"""
|
|
60
|
+
"""Legacy argument classifier; not used by generic route registration."""
|
|
61
61
|
if not argv or os.path.basename(argv[0]) != kind:
|
|
62
62
|
return False
|
|
63
63
|
flags = {
|
|
@@ -120,11 +120,27 @@ def process_info(pid):
|
|
|
120
120
|
fields[4], args)
|
|
121
121
|
|
|
122
122
|
|
|
123
|
+
def input_terminal(pid):
|
|
124
|
+
"""Resolve fd 0, not inherited environment variables or a process name."""
|
|
125
|
+
if sys.platform.startswith("linux"):
|
|
126
|
+
return os.path.realpath(os.readlink(f"/proc/{int(pid)}/fd/0"))
|
|
127
|
+
if sys.platform == "darwin":
|
|
128
|
+
result = subprocess.run(
|
|
129
|
+
["/usr/sbin/lsof", "-a", "-p", str(int(pid)), "-d", "0", "-Fn"],
|
|
130
|
+
capture_output=True, text=True, timeout=1, check=False,
|
|
131
|
+
)
|
|
132
|
+
names = [line[1:] for line in result.stdout.splitlines() if line.startswith("n")]
|
|
133
|
+
if result.returncode == 0 and len(names) == 1:
|
|
134
|
+
return names[0]
|
|
135
|
+
return None
|
|
136
|
+
|
|
137
|
+
|
|
123
138
|
def foreground_frontend_tty(pid, expected_tty, inspect=None, executable=None,
|
|
124
|
-
uid=None, user_home=None):
|
|
139
|
+
uid=None, user_home=None, stdin_terminal=None):
|
|
125
140
|
"""Only the boundary parent itself may qualify; never walk past a server."""
|
|
126
141
|
inspect = inspect or process_info
|
|
127
142
|
executable = executable or native_executable
|
|
143
|
+
stdin_terminal = stdin_terminal or input_terminal
|
|
128
144
|
uid = os.getuid() if uid is None else uid
|
|
129
145
|
try:
|
|
130
146
|
user_home = pwd.getpwuid(uid).pw_dir if user_home is None else user_home
|
|
@@ -135,11 +151,15 @@ def foreground_frontend_tty(pid, expected_tty, inspect=None, executable=None,
|
|
|
135
151
|
if owner != uid or not (pid == group == foreground) or tty != expected_tty:
|
|
136
152
|
return None
|
|
137
153
|
path = executable(pid)
|
|
138
|
-
|
|
139
|
-
|
|
154
|
+
# Generic terminal routing is independent of kind and installation path.
|
|
155
|
+
# The immediate boundary parent must own the foreground group AND read
|
|
156
|
+
# from that terminal. A pipe-backed server is not a terminal recipient.
|
|
157
|
+
input_path = "/dev/" + expected_tty.removeprefix("/dev/")
|
|
158
|
+
if not path or stdin_terminal(pid) != input_path:
|
|
140
159
|
return None
|
|
141
160
|
# Recheck mutable process state around executable and command inspection.
|
|
142
|
-
if inspect(pid) != before or executable(pid) != path
|
|
161
|
+
if (inspect(pid) != before or executable(pid) != path
|
|
162
|
+
or stdin_terminal(pid) != input_path):
|
|
143
163
|
return None
|
|
144
164
|
return tty
|
|
145
165
|
except (OSError, ValueError, TypeError, KeyError, ctypes.ArgumentError,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{tabc-0.2.1 → tabc-0.2.2}/MCP.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|