anolisa-tokenless 0.7.12 → 0.7.14
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.
- package/README.md +13 -8
- package/adapters/tokenless/claude-code/.claude-plugin/plugin.json +1 -1
- package/adapters/tokenless/codex/.codex-plugin/plugin.json +5 -4
- package/adapters/tokenless/codex/README.md +22 -32
- package/adapters/tokenless/codex/hooks/hooks.json +3 -3
- package/adapters/tokenless/codex/scripts/response-diagnostics +170 -0
- package/adapters/tokenless/common/cosh-extension.json +1 -1
- package/adapters/tokenless/common/hooks/compress_response_hook.py +123 -264
- package/adapters/tokenless/common/hooks/compress_schema_hook.py +35 -31
- package/adapters/tokenless/common/hooks/compress_toon_hook.py +3 -0
- package/adapters/tokenless/common/hooks/hook_utils.py +70 -3
- package/adapters/tokenless/dsh/package.json +1 -1
- package/adapters/tokenless/hermes/__init__.py +2 -0
- package/adapters/tokenless/hermes/plugin.yaml +1 -1
- package/adapters/tokenless/manifest.json +2 -3
- package/adapters/tokenless/openclaw/openclaw.plugin.json +1 -1
- package/adapters/tokenless/openclaw/package.json +1 -1
- package/adapters/tokenless/qoder/.qoder-plugin/plugin.json +1 -1
- package/adapters/tokenless/qwencode/qwen-extension.json +1 -1
- package/package.json +5 -5
- package/adapters/tokenless/codex/scripts/compress-response +0 -445
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@ Agent adapters are available for:
|
|
|
18
18
|
- **Hermes Agent plugin** — response compression, TOON encoding, command rewriting (block + suggest), and registered but hard-disabled Tool Ready via Hermes's native plugin system.
|
|
19
19
|
- **Qoder CLI plugin** — registered but hard-disabled Tool Ready, command rewriting, and response compression via Qoder's native hook system.
|
|
20
20
|
- **Claude Code plugin** — RTK command rewriting, response/TOON compression, and registered but hard-disabled Tool Ready via Claude Code's official plugin marketplace.
|
|
21
|
-
- **Codex plugin** —
|
|
21
|
+
- **Codex plugin** — RTK command rewriting, environment-failure diagnostics, and registered but hard-disabled Tool Ready via Codex's native hook system.
|
|
22
22
|
- **OpenCode plugin** — schema/response/TOON compression, registered but hard-disabled Tool Ready, and command rewriting via OpenCode's local plugin API.
|
|
23
23
|
- **DeepSeek Harness plugin** — native response compression and environment-error attribution through DSH's `tools/post-execute` seam.
|
|
24
24
|
|
|
@@ -40,7 +40,7 @@ cover schema compression, RTK rewriting, response compression, TOON, retrieval,
|
|
|
40
40
|
| Hermes Agent plugin | — | Tool Ready ⛔ hard-disabled, Command rewriting ✅, Response compression ✅, TOON ✅, Schema compression ⏳ |
|
|
41
41
|
| Qoder CLI plugin | — | Tool Ready ⛔ hard-disabled, Command rewriting ✅, Response compression ✅ |
|
|
42
42
|
| Claude Code plugin | — | Tool Ready ⛔ hard-disabled, Command rewriting ✅, Response compression ✅, TOON ✅ |
|
|
43
|
-
| Codex plugin | — | Tool Ready ⛔ hard-disabled, Command rewriting ✅, Response compression
|
|
43
|
+
| Codex plugin | — | Tool Ready ⛔ hard-disabled, Command rewriting ✅, Environment diagnostics ✅, Response compression — protocol-blocked |
|
|
44
44
|
| OpenCode plugin | — | Tool Ready ⛔ hard-disabled, Command rewriting ✅, Schema compression ✅, Response compression ✅, TOON ✅ |
|
|
45
45
|
| DeepSeek Harness plugin | — | Response compression ✅, Environment-error attribution ✅ |
|
|
46
46
|
| AgentScope framework integration | — | Schema ✅, RTK ✅, Response ✅, TOON ✅, Retrieval ✅ |
|
|
@@ -316,16 +316,18 @@ tokenless retrieve c30ccf5ed1125e0ed871ba8e
|
|
|
316
316
|
|
|
317
317
|
# Or paste the whole truncation line — the hash is extracted automatically.
|
|
318
318
|
# (Use the FULL 24-hex hash from your output; the value below is shorthand.)
|
|
319
|
-
tokenless retrieve "<... 160 items truncated, retrieve
|
|
319
|
+
tokenless retrieve "<... 160 items truncated, run: tokenless retrieve '<<tokenless:c30ccf5ed1125e0ed871ba8e>>'>"
|
|
320
320
|
```
|
|
321
321
|
|
|
322
322
|
### compress-toon / decompress-toon
|
|
323
323
|
|
|
324
|
-
Encode JSON to TOON format (or decode back to JSON)
|
|
324
|
+
Encode JSON to TOON format (or decode back to JSON). Payloads shorter than
|
|
325
|
+
500 characters pass through unchanged by default (the same minimum the
|
|
326
|
+
adapter hooks apply); use `--min-toon-chars 0` to encode them anyway:
|
|
325
327
|
|
|
326
328
|
```bash
|
|
327
|
-
# Encode JSON to TOON
|
|
328
|
-
echo '{"name":"Alice","age":30}' | tokenless compress-toon
|
|
329
|
+
# Encode JSON to TOON (short payload, gate disabled for this call)
|
|
330
|
+
echo '{"name":"Alice","age":30}' | tokenless compress-toon --min-toon-chars 0
|
|
329
331
|
# name: Alice
|
|
330
332
|
# age: 30
|
|
331
333
|
|
|
@@ -571,9 +573,12 @@ The plugin registers hooks at four Codex events, covering four strategies:
|
|
|
571
573
|
| Session check | `SessionStart` | Verifies tokenless CLI is installed and functional (non-blocking) | ✅ Active |
|
|
572
574
|
| Tool Ready | `PreToolUse` | Registered silent pass-through; no check, repair, context, or block | ⛔ Hard-disabled |
|
|
573
575
|
| Command rewriting | `PreToolUse` | Rewrites shell commands via RTK for token savings | ✅ Active |
|
|
574
|
-
|
|
|
576
|
+
| Environment diagnostics | `PostToolUse` | Adds actionable context only for classified environment failures | ✅ Active |
|
|
575
577
|
|
|
576
|
-
> **Codex
|
|
578
|
+
> **Codex protocol constraint**: `PostToolUse` cannot replace or suppress the
|
|
579
|
+
> original tool output. Tokenless therefore does not append compressed content,
|
|
580
|
+
> which would make the model-visible payload larger. First-pass savings for
|
|
581
|
+
> supported shell commands come from RTK rewriting the command before execution.
|
|
577
582
|
|
|
578
583
|
### Install
|
|
579
584
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tokenless",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.14",
|
|
4
4
|
"description": "Token-Less context compression for Claude Code — RTK command rewriting, response/TOON compression, and Tool Ready environment pre-check",
|
|
5
5
|
"author": { "name": "ANOLISA" },
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tokenless",
|
|
3
|
-
"version": "0.7.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.7.14",
|
|
4
|
+
"description": "Shell command output reduction and environment error diagnostics for Codex. Rewrites supported commands through RTK before execution and classifies environment failures with actionable fix hints.",
|
|
5
5
|
"keywords": [
|
|
6
|
-
"
|
|
6
|
+
"rtk",
|
|
7
|
+
"shell",
|
|
7
8
|
"token",
|
|
8
9
|
"context",
|
|
9
10
|
"optimization",
|
|
@@ -13,7 +14,7 @@
|
|
|
13
14
|
"hooks": "./hooks/hooks.json",
|
|
14
15
|
"interface": {
|
|
15
16
|
"displayName": "Tokenless",
|
|
16
|
-
"shortDescription": "
|
|
17
|
+
"shortDescription": "Reduce shell output with RTK and diagnose environment errors",
|
|
17
18
|
"category": "developer-tools",
|
|
18
19
|
"capabilities": ["hook"]
|
|
19
20
|
}
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
# Tokenless Plugin for Codex
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
[Codex](https://github.com/openai/codex).
|
|
5
|
-
|
|
6
|
-
|
|
3
|
+
Command-output reduction and environment error detection plugin for
|
|
4
|
+
[Codex](https://github.com/openai/codex). It rewrites supported shell commands
|
|
5
|
+
through RTK before execution and classifies environment errors with actionable
|
|
6
|
+
fix hints.
|
|
7
7
|
|
|
8
8
|
## Features
|
|
9
9
|
|
|
10
10
|
| Feature | Description |
|
|
11
11
|
|---------|-------------|
|
|
12
|
-
| **
|
|
13
|
-
| **TOON Encoding** | Further compresses valid JSON responses (15-40% additional savings vs. compressed JSON) |
|
|
12
|
+
| **Command Rewriting** | Rewrites supported shell commands through RTK so verbose output is reduced at its source |
|
|
14
13
|
| **Environment Error Detection** | Classifies tool failures as dependency/permission/file/network/package issues; injects fix hints to prevent retry loops |
|
|
15
|
-
| **Statistics Tracking** |
|
|
14
|
+
| **Statistics Tracking** | Attributes RTK rewrites to the Codex session for auditing and optimization |
|
|
16
15
|
|
|
17
16
|
## How It Works
|
|
18
17
|
|
|
@@ -28,17 +27,14 @@ The plugin registers four hooks with Codex:
|
|
|
28
27
|
- Rewrites commands via `rtk rewrite` for token optimization
|
|
29
28
|
- Only applies to Bash/Shell/terminal/programmatic tools
|
|
30
29
|
4. **`PostToolUse`** — runs after every tool execution:
|
|
31
|
-
- Skips content-reading
|
|
30
|
+
- Skips content-reading and task-management tools
|
|
32
31
|
- Classifies environment errors and injects fix hints
|
|
33
|
-
- Compresses large JSON responses via `tokenless compress-response`
|
|
34
|
-
- Applies TOON encoding for additional savings
|
|
35
|
-
- Injects a compressed summary as `additionalContext`
|
|
36
32
|
|
|
37
|
-
> **Codex
|
|
38
|
-
>
|
|
39
|
-
>
|
|
40
|
-
>
|
|
41
|
-
>
|
|
33
|
+
> **Codex protocol constraint**: `PostToolUse` rejects output suppression and
|
|
34
|
+
> replacement. Injecting compressed content through `additionalContext` would
|
|
35
|
+
> leave the original in place and increase the prompt. The plugin therefore
|
|
36
|
+
> reserves `additionalContext` for actionable environment diagnostics. Actual
|
|
37
|
+
> first-pass savings come from RTK rewriting supported commands before they run.
|
|
42
38
|
|
|
43
39
|
## Installation
|
|
44
40
|
|
|
@@ -77,15 +73,12 @@ Or install from the marketplace (once published).
|
|
|
77
73
|
|
|
78
74
|
## Hook Output Format
|
|
79
75
|
|
|
80
|
-
|
|
76
|
+
For a classified environment failure, the plugin injects `additionalContext`
|
|
77
|
+
in the following format:
|
|
81
78
|
|
|
82
79
|
```
|
|
83
|
-
[tokenless:compressed] Bash: 45,230 → 2,100 chars (95% reduction)
|
|
84
80
|
[tokenless:env:ENV_DEPENDENCY_MISSING] Missing dependency detected. ...
|
|
85
81
|
Do NOT retry the same command — fix the environment first.
|
|
86
|
-
--- compressed content ---
|
|
87
|
-
{... compressed JSON or TOON content ...}
|
|
88
|
-
--- end compressed content ---
|
|
89
82
|
```
|
|
90
83
|
|
|
91
84
|
## Configuration
|
|
@@ -114,21 +107,18 @@ tokenless stats list --limit 20
|
|
|
114
107
|
tokenless stats show <id>
|
|
115
108
|
```
|
|
116
109
|
|
|
117
|
-
##
|
|
110
|
+
## Savings Path
|
|
118
111
|
|
|
119
112
|
```
|
|
120
|
-
|
|
113
|
+
Shell command
|
|
121
114
|
│
|
|
122
|
-
├─
|
|
123
|
-
│
|
|
124
|
-
│ ├─ Truncate: strings > 512 chars, arrays > 16 items
|
|
125
|
-
│ ├─ Drop: null values, empty strings, empty arrays, empty objects
|
|
126
|
-
│ └─ Limit: max depth 8 levels
|
|
115
|
+
├─ PreToolUse: rtk rewrite
|
|
116
|
+
│ └─ Replaces the command with an output-reducing equivalent
|
|
127
117
|
│
|
|
128
|
-
├─
|
|
129
|
-
│ └─
|
|
118
|
+
├─ Tool execution
|
|
119
|
+
│ └─ Codex receives the already-reduced output
|
|
130
120
|
│
|
|
131
|
-
└─
|
|
121
|
+
└─ PostToolUse: environment diagnostics only
|
|
132
122
|
```
|
|
133
123
|
|
|
134
124
|
## Architecture
|
|
@@ -139,7 +129,7 @@ codex-plugin-tokenless/
|
|
|
139
129
|
├── hooks/
|
|
140
130
|
│ └── hooks.json # Hook definitions (SessionStart, PreToolUse, PostToolUse)
|
|
141
131
|
├── scripts/
|
|
142
|
-
│ ├──
|
|
132
|
+
│ ├── response-diagnostics # PostToolUse: environment error detection
|
|
143
133
|
│ ├── rewrite-hook # PreToolUse: RTK command rewriting
|
|
144
134
|
│ ├── tool-ready # PreToolUse: registered hard-disabled pass-through
|
|
145
135
|
│ ├── check-tokenless # SessionStart: version/availability check
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
"hooks": [
|
|
30
30
|
{
|
|
31
31
|
"type": "command",
|
|
32
|
-
"command": "${PLUGIN_ROOT}/scripts/
|
|
33
|
-
"timeout":
|
|
34
|
-
"statusMessage": "
|
|
32
|
+
"command": "${PLUGIN_ROOT}/scripts/response-diagnostics",
|
|
33
|
+
"timeout": 10,
|
|
34
|
+
"statusMessage": "Checking tool response..."
|
|
35
35
|
}
|
|
36
36
|
]
|
|
37
37
|
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Codex PostToolUse environment diagnostics for the Tokenless plugin.
|
|
3
|
+
|
|
4
|
+
Codex does not let PostToolUse hooks replace or suppress the original tool
|
|
5
|
+
response. Adding compressed content through ``additionalContext`` therefore
|
|
6
|
+
increases the model-visible payload instead of reducing it. This hook only
|
|
7
|
+
adds actionable context for classified environment failures; successful and
|
|
8
|
+
unclassified responses pass through unchanged.
|
|
9
|
+
|
|
10
|
+
Protocol:
|
|
11
|
+
stdin <- Codex PostToolUse JSON (tool_name, tool_response, ...)
|
|
12
|
+
stdout -> {"hookSpecificOutput": {"hookEventName": "PostToolUse",
|
|
13
|
+
"additionalContext": "..."}}
|
|
14
|
+
|
|
15
|
+
Fail-open: every error path exits successfully with empty stdout so a
|
|
16
|
+
diagnostic failure never blocks the agent session.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
from __future__ import annotations
|
|
20
|
+
|
|
21
|
+
import json
|
|
22
|
+
import os
|
|
23
|
+
import sys
|
|
24
|
+
|
|
25
|
+
# Resolve shared hook utilities (common/hooks/) with FHS fallback paths.
|
|
26
|
+
# Primary: relative path (works for source-tree and FHS/RPM install).
|
|
27
|
+
# Fallbacks: system and user FHS paths (works when Codex caches only the
|
|
28
|
+
# plugin subdirectory and the relative path resolves outside the cache).
|
|
29
|
+
#
|
|
30
|
+
# Trust model (aligned with bash is_trusted_file / Rust is_trusted_path):
|
|
31
|
+
# - System FHS paths (/usr/share, /usr/local/share) are unconditional.
|
|
32
|
+
# - Other paths must be owned by the current user or root, and their parent
|
|
33
|
+
# directory must not be world-writable.
|
|
34
|
+
_HERE = os.path.dirname(os.path.abspath(__file__))
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _is_trusted_dir(path: str) -> bool:
|
|
38
|
+
"""Check whether a directory is trusted for Python module imports."""
|
|
39
|
+
for prefix in (
|
|
40
|
+
"/usr/share/",
|
|
41
|
+
"/usr/local/share/",
|
|
42
|
+
"/usr/libexec/",
|
|
43
|
+
"/usr/lib/anolisa/",
|
|
44
|
+
):
|
|
45
|
+
if path.startswith(prefix):
|
|
46
|
+
return True
|
|
47
|
+
|
|
48
|
+
try:
|
|
49
|
+
stat = os.stat(path)
|
|
50
|
+
parent_stat = os.stat(os.path.dirname(path))
|
|
51
|
+
except OSError:
|
|
52
|
+
return False
|
|
53
|
+
if stat.st_uid not in (os.getuid(), 0):
|
|
54
|
+
return False
|
|
55
|
+
if parent_stat.st_uid not in (os.getuid(), 0):
|
|
56
|
+
return False
|
|
57
|
+
return not parent_stat.st_mode & 0o002
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
try:
|
|
61
|
+
import pwd as _pwd
|
|
62
|
+
|
|
63
|
+
_REAL_HOME = _pwd.getpwuid(os.getuid()).pw_dir
|
|
64
|
+
except (ImportError, KeyError):
|
|
65
|
+
_REAL_HOME = ""
|
|
66
|
+
if not os.path.isabs(_REAL_HOME):
|
|
67
|
+
_REAL_HOME = ""
|
|
68
|
+
|
|
69
|
+
_HOOK_UTILS_CANDIDATES = [
|
|
70
|
+
os.path.join(_HERE, "..", "..", "common", "hooks"),
|
|
71
|
+
"/usr/share/anolisa/adapters/tokenless/common/hooks",
|
|
72
|
+
"/usr/local/share/anolisa/adapters/tokenless/common/hooks",
|
|
73
|
+
(
|
|
74
|
+
os.path.join(
|
|
75
|
+
_REAL_HOME,
|
|
76
|
+
".local",
|
|
77
|
+
"share",
|
|
78
|
+
"anolisa",
|
|
79
|
+
"adapters",
|
|
80
|
+
"tokenless",
|
|
81
|
+
"common",
|
|
82
|
+
"hooks",
|
|
83
|
+
)
|
|
84
|
+
if _REAL_HOME
|
|
85
|
+
else ""
|
|
86
|
+
),
|
|
87
|
+
]
|
|
88
|
+
_HOOK_UTILS_RESOLVED = ""
|
|
89
|
+
for _candidate in _HOOK_UTILS_CANDIDATES:
|
|
90
|
+
resolved = os.path.realpath(_candidate) if _candidate else ""
|
|
91
|
+
if resolved and _is_trusted_dir(resolved) and os.path.isdir(resolved):
|
|
92
|
+
_HOOK_UTILS_RESOLVED = resolved
|
|
93
|
+
sys.path.insert(0, resolved)
|
|
94
|
+
break
|
|
95
|
+
|
|
96
|
+
if _HOOK_UTILS_RESOLVED:
|
|
97
|
+
from hook_utils import ( # noqa: E402
|
|
98
|
+
SKIP_TOOLS as _SKIP_TOOLS_SHARED,
|
|
99
|
+
classify_env_error as _classify_env_error,
|
|
100
|
+
skip_silent as _skip,
|
|
101
|
+
)
|
|
102
|
+
else:
|
|
103
|
+
|
|
104
|
+
def _skip() -> None: # type: ignore[assignment,misc]
|
|
105
|
+
sys.exit(0)
|
|
106
|
+
|
|
107
|
+
def _classify_env_error( # type: ignore[assignment,misc]
|
|
108
|
+
tool_response: object,
|
|
109
|
+
) -> tuple[str | None, str | None]:
|
|
110
|
+
return None, None
|
|
111
|
+
|
|
112
|
+
_SKIP_TOOLS_SHARED: set[str] = { # type: ignore[assignment,misc]
|
|
113
|
+
"Read",
|
|
114
|
+
"read",
|
|
115
|
+
"read_file",
|
|
116
|
+
"read_many_files",
|
|
117
|
+
"Glob",
|
|
118
|
+
"glob",
|
|
119
|
+
"list_directory",
|
|
120
|
+
"Grep",
|
|
121
|
+
"grep",
|
|
122
|
+
"grep_search",
|
|
123
|
+
"search_files",
|
|
124
|
+
"Lsp",
|
|
125
|
+
"lsp",
|
|
126
|
+
"NotebookRead",
|
|
127
|
+
"notebook_read",
|
|
128
|
+
"notebookread",
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
SKIP_TOOLS: set[str] = _SKIP_TOOLS_SHARED | {
|
|
133
|
+
"TodoWrite",
|
|
134
|
+
"Task",
|
|
135
|
+
"TaskStatus",
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def main() -> None:
|
|
140
|
+
try:
|
|
141
|
+
raw = sys.stdin.read()
|
|
142
|
+
if not raw.strip():
|
|
143
|
+
_skip()
|
|
144
|
+
input_data = json.loads(raw)
|
|
145
|
+
except (json.JSONDecodeError, EOFError, ValueError):
|
|
146
|
+
_skip()
|
|
147
|
+
|
|
148
|
+
tool_name = input_data.get("tool_name", "")
|
|
149
|
+
tool_response = input_data.get("tool_response")
|
|
150
|
+
if tool_name in SKIP_TOOLS or tool_response is None:
|
|
151
|
+
_skip()
|
|
152
|
+
|
|
153
|
+
env_category, env_hint = _classify_env_error(tool_response)
|
|
154
|
+
if not env_category or not env_hint:
|
|
155
|
+
_skip()
|
|
156
|
+
|
|
157
|
+
response = {
|
|
158
|
+
"hookSpecificOutput": {
|
|
159
|
+
"hookEventName": "PostToolUse",
|
|
160
|
+
"additionalContext": (
|
|
161
|
+
f"[tokenless:env:{env_category}] {env_hint} "
|
|
162
|
+
"Do NOT retry the same command — fix the environment first."
|
|
163
|
+
),
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
print(json.dumps(response, ensure_ascii=False))
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
if __name__ == "__main__":
|
|
170
|
+
main()
|