onetool-mcp 1.0.0b1__py3-none-any.whl → 1.0.0rc2__py3-none-any.whl
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.
- onetool/cli.py +63 -4
- onetool_mcp-1.0.0rc2.dist-info/METADATA +266 -0
- onetool_mcp-1.0.0rc2.dist-info/RECORD +129 -0
- {onetool_mcp-1.0.0b1.dist-info → onetool_mcp-1.0.0rc2.dist-info}/licenses/LICENSE.txt +1 -1
- {onetool_mcp-1.0.0b1.dist-info → onetool_mcp-1.0.0rc2.dist-info}/licenses/NOTICE.txt +54 -64
- ot/__main__.py +6 -6
- ot/config/__init__.py +48 -46
- ot/config/global_templates/__init__.py +2 -2
- ot/config/{defaults → global_templates}/diagram-templates/api-flow.mmd +33 -33
- ot/config/{defaults → global_templates}/diagram-templates/c4-context.puml +30 -30
- ot/config/{defaults → global_templates}/diagram-templates/class-diagram.mmd +87 -87
- ot/config/{defaults → global_templates}/diagram-templates/feature-mindmap.mmd +70 -70
- ot/config/{defaults → global_templates}/diagram-templates/microservices.d2 +81 -81
- ot/config/{defaults → global_templates}/diagram-templates/project-gantt.mmd +37 -37
- ot/config/{defaults → global_templates}/diagram-templates/state-machine.mmd +42 -42
- ot/config/global_templates/diagram.yaml +167 -0
- ot/config/global_templates/onetool.yaml +3 -1
- ot/config/{defaults → global_templates}/prompts.yaml +102 -97
- ot/config/global_templates/security.yaml +31 -0
- ot/config/global_templates/servers.yaml +93 -12
- ot/config/global_templates/snippets.yaml +5 -26
- ot/config/{defaults → global_templates}/tool_templates/__init__.py +7 -7
- ot/config/loader.py +221 -105
- ot/config/mcp.py +5 -1
- ot/config/secrets.py +192 -190
- ot/decorators.py +116 -116
- ot/executor/__init__.py +35 -35
- ot/executor/base.py +16 -16
- ot/executor/fence_processor.py +83 -83
- ot/executor/linter.py +142 -142
- ot/executor/pep723.py +288 -288
- ot/executor/runner.py +20 -6
- ot/executor/simple.py +163 -163
- ot/executor/validator.py +603 -164
- ot/http_client.py +145 -145
- ot/logging/__init__.py +37 -37
- ot/logging/entry.py +213 -213
- ot/logging/format.py +191 -188
- ot/logging/span.py +349 -349
- ot/meta.py +236 -14
- ot/paths.py +32 -49
- ot/prompts.py +218 -218
- ot/proxy/manager.py +14 -2
- ot/registry/__init__.py +189 -189
- ot/registry/parser.py +269 -269
- ot/server.py +330 -315
- ot/shortcuts/__init__.py +15 -15
- ot/shortcuts/aliases.py +87 -87
- ot/shortcuts/snippets.py +258 -258
- ot/stats/__init__.py +35 -35
- ot/stats/html.py +2 -2
- ot/stats/reader.py +354 -354
- ot/stats/timing.py +57 -57
- ot/support.py +63 -63
- ot/tools.py +1 -1
- ot/utils/batch.py +161 -161
- ot/utils/cache.py +120 -120
- ot/utils/exceptions.py +23 -23
- ot/utils/factory.py +178 -179
- ot/utils/format.py +65 -65
- ot/utils/http.py +202 -202
- ot/utils/platform.py +45 -45
- ot/utils/truncate.py +69 -69
- ot_tools/__init__.py +4 -4
- ot_tools/_convert/__init__.py +12 -12
- ot_tools/_convert/pdf.py +254 -254
- ot_tools/diagram.yaml +167 -167
- ot_tools/scaffold.py +2 -2
- ot_tools/transform.py +124 -19
- ot_tools/web_fetch.py +94 -43
- onetool_mcp-1.0.0b1.dist-info/METADATA +0 -163
- onetool_mcp-1.0.0b1.dist-info/RECORD +0 -132
- ot/config/defaults/bench.yaml +0 -4
- ot/config/defaults/onetool.yaml +0 -25
- ot/config/defaults/servers.yaml +0 -7
- ot/config/defaults/snippets.yaml +0 -4
- ot_tools/firecrawl.py +0 -732
- {onetool_mcp-1.0.0b1.dist-info → onetool_mcp-1.0.0rc2.dist-info}/WHEEL +0 -0
- {onetool_mcp-1.0.0b1.dist-info → onetool_mcp-1.0.0rc2.dist-info}/entry_points.txt +0 -0
- /ot/config/{defaults → global_templates}/tool_templates/extension.py +0 -0
- /ot/config/{defaults → global_templates}/tool_templates/isolated.py +0 -0
ot/logging/format.py
CHANGED
|
@@ -1,188 +1,191 @@
|
|
|
1
|
-
"""Output formatting for log entries.
|
|
2
|
-
|
|
3
|
-
Provides truncation and credential sanitisation at OUTPUT time.
|
|
4
|
-
Full values are preserved in LogEntry for programmatic access.
|
|
5
|
-
|
|
6
|
-
Field-based truncation limits:
|
|
7
|
-
| Pattern | Limit |
|
|
8
|
-
|------------------------------------------------|-------|
|
|
9
|
-
| path, filepath, source, dest, directory | 200 |
|
|
10
|
-
|
|
|
11
|
-
|
|
|
12
|
-
|
|
|
13
|
-
|
|
|
14
|
-
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
from
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
34
|
-
"
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"
|
|
38
|
-
"
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
URL
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
parsed.
|
|
97
|
-
|
|
98
|
-
parsed.
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
if
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
if
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
#
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
1
|
+
"""Output formatting for log entries.
|
|
2
|
+
|
|
3
|
+
Provides truncation and credential sanitisation at OUTPUT time.
|
|
4
|
+
Full values are preserved in LogEntry for programmatic access.
|
|
5
|
+
|
|
6
|
+
Field-based truncation limits:
|
|
7
|
+
| Pattern | Limit |
|
|
8
|
+
|------------------------------------------------|-------|
|
|
9
|
+
| path, filepath, source, dest, directory | 200 |
|
|
10
|
+
| command | 200 |
|
|
11
|
+
| url | 120 |
|
|
12
|
+
| query, topic | 100 |
|
|
13
|
+
| pattern, prompt | 100 |
|
|
14
|
+
| error | 300 |
|
|
15
|
+
| default | 120 |
|
|
16
|
+
|
|
17
|
+
Credential sanitisation:
|
|
18
|
+
- URLs with credentials: postgres://user:pass@host -> postgres://***:***@host
|
|
19
|
+
- Applied to fields containing 'url' or values starting with http(s)://
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
from __future__ import annotations
|
|
23
|
+
|
|
24
|
+
import re
|
|
25
|
+
from typing import Any
|
|
26
|
+
from urllib.parse import urlparse, urlunparse
|
|
27
|
+
|
|
28
|
+
# Field name patterns mapped to truncation limits
|
|
29
|
+
FIELD_LIMITS: dict[str, int] = {
|
|
30
|
+
"path": 200,
|
|
31
|
+
"filepath": 200,
|
|
32
|
+
"source": 200,
|
|
33
|
+
"dest": 200,
|
|
34
|
+
"directory": 200,
|
|
35
|
+
"command": 200,
|
|
36
|
+
"url": 120,
|
|
37
|
+
"query": 100,
|
|
38
|
+
"topic": 100,
|
|
39
|
+
"pattern": 100,
|
|
40
|
+
"prompt": 100,
|
|
41
|
+
"error": 300,
|
|
42
|
+
}
|
|
43
|
+
DEFAULT_LIMIT = 120
|
|
44
|
+
|
|
45
|
+
# URL credential pattern: scheme://user:pass@host
|
|
46
|
+
URL_WITH_CREDS = re.compile(r"^([a-zA-Z][a-zA-Z0-9+.-]*://)([^:]+):([^@]+)@(.+)$")
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _get_field_limit(field_name: str) -> int:
|
|
50
|
+
"""Get truncation limit for a field based on name patterns.
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
field_name: Name of the field (case-insensitive matching)
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
Truncation limit in characters
|
|
57
|
+
"""
|
|
58
|
+
lower_name = field_name.lower()
|
|
59
|
+
|
|
60
|
+
# Check for pattern matches in field name
|
|
61
|
+
for pattern, limit in FIELD_LIMITS.items():
|
|
62
|
+
if pattern in lower_name:
|
|
63
|
+
return limit
|
|
64
|
+
|
|
65
|
+
return DEFAULT_LIMIT
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def sanitize_url(url: str) -> str:
|
|
69
|
+
"""Mask credentials in a URL.
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
url: URL string, potentially with embedded credentials
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
URL with username:password masked as ***:***
|
|
76
|
+
|
|
77
|
+
Example:
|
|
78
|
+
postgres://user:password@host/db -> postgres://***:***@host/db
|
|
79
|
+
"""
|
|
80
|
+
match = URL_WITH_CREDS.match(url)
|
|
81
|
+
if match:
|
|
82
|
+
scheme, _user, _password, rest = match.groups()
|
|
83
|
+
return f"{scheme}***:***@{rest}"
|
|
84
|
+
|
|
85
|
+
# Also handle parsed URLs without regex (for edge cases)
|
|
86
|
+
try:
|
|
87
|
+
parsed = urlparse(url)
|
|
88
|
+
if parsed.username or parsed.password:
|
|
89
|
+
# Reconstruct with masked credentials
|
|
90
|
+
netloc = "***:***@" if parsed.password else "***@"
|
|
91
|
+
netloc += parsed.hostname or ""
|
|
92
|
+
if parsed.port:
|
|
93
|
+
netloc += f":{parsed.port}"
|
|
94
|
+
return urlunparse(
|
|
95
|
+
(
|
|
96
|
+
parsed.scheme,
|
|
97
|
+
netloc,
|
|
98
|
+
parsed.path,
|
|
99
|
+
parsed.params,
|
|
100
|
+
parsed.query,
|
|
101
|
+
parsed.fragment,
|
|
102
|
+
)
|
|
103
|
+
)
|
|
104
|
+
except Exception:
|
|
105
|
+
pass # Return original if parsing fails
|
|
106
|
+
|
|
107
|
+
return url
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def format_value(value: Any, field_name: str = "", max_length: int | None = None) -> Any:
|
|
111
|
+
"""Format a single value for output with truncation.
|
|
112
|
+
|
|
113
|
+
Only string values are truncated. Other types pass through unchanged.
|
|
114
|
+
|
|
115
|
+
Args:
|
|
116
|
+
value: Value to format
|
|
117
|
+
field_name: Field name for determining truncation limit
|
|
118
|
+
max_length: Override truncation limit (None = use field-based limit)
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
Formatted value (truncated string or original value)
|
|
122
|
+
"""
|
|
123
|
+
if not isinstance(value, str):
|
|
124
|
+
return value
|
|
125
|
+
|
|
126
|
+
if max_length is None:
|
|
127
|
+
max_length = _get_field_limit(field_name)
|
|
128
|
+
|
|
129
|
+
if len(value) <= max_length:
|
|
130
|
+
return value
|
|
131
|
+
|
|
132
|
+
# Truncate with ellipsis
|
|
133
|
+
return value[: max_length - 3] + "..."
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
def sanitize_for_output(value: Any, field_name: str = "") -> Any:
|
|
137
|
+
"""Sanitize a value by masking credentials.
|
|
138
|
+
|
|
139
|
+
Applies to:
|
|
140
|
+
- Fields containing 'url' in name
|
|
141
|
+
- String values starting with http:// or https://
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
value: Value to sanitize
|
|
145
|
+
field_name: Field name for context
|
|
146
|
+
|
|
147
|
+
Returns:
|
|
148
|
+
Sanitized value
|
|
149
|
+
"""
|
|
150
|
+
if not isinstance(value, str):
|
|
151
|
+
return value
|
|
152
|
+
|
|
153
|
+
lower_name = field_name.lower()
|
|
154
|
+
lower_value = value.lower()
|
|
155
|
+
|
|
156
|
+
# Apply URL sanitisation if field name contains 'url' or value is a URL
|
|
157
|
+
if "url" in lower_name or lower_value.startswith(("http://", "https://")):
|
|
158
|
+
return sanitize_url(value)
|
|
159
|
+
|
|
160
|
+
return value
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def format_log_entry(
|
|
164
|
+
entry_dict: dict[str, Any],
|
|
165
|
+
verbose: bool = False,
|
|
166
|
+
) -> dict[str, Any]:
|
|
167
|
+
"""Format a log entry dict for output.
|
|
168
|
+
|
|
169
|
+
Applies truncation and credential sanitisation to all fields.
|
|
170
|
+
Full values are preserved in the original entry.
|
|
171
|
+
|
|
172
|
+
Args:
|
|
173
|
+
entry_dict: Log entry as dict (from LogEntry.to_dict())
|
|
174
|
+
verbose: If True, skip truncation (still sanitizes credentials)
|
|
175
|
+
|
|
176
|
+
Returns:
|
|
177
|
+
New dict with formatted values
|
|
178
|
+
"""
|
|
179
|
+
formatted: dict[str, Any] = {}
|
|
180
|
+
|
|
181
|
+
for key, value in entry_dict.items():
|
|
182
|
+
# Always sanitize credentials
|
|
183
|
+
sanitized = sanitize_for_output(value, key)
|
|
184
|
+
|
|
185
|
+
# Apply truncation unless verbose mode
|
|
186
|
+
if verbose:
|
|
187
|
+
formatted[key] = sanitized
|
|
188
|
+
else:
|
|
189
|
+
formatted[key] = format_value(sanitized, key)
|
|
190
|
+
|
|
191
|
+
return formatted
|