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.
Files changed (81) hide show
  1. onetool/cli.py +63 -4
  2. onetool_mcp-1.0.0rc2.dist-info/METADATA +266 -0
  3. onetool_mcp-1.0.0rc2.dist-info/RECORD +129 -0
  4. {onetool_mcp-1.0.0b1.dist-info → onetool_mcp-1.0.0rc2.dist-info}/licenses/LICENSE.txt +1 -1
  5. {onetool_mcp-1.0.0b1.dist-info → onetool_mcp-1.0.0rc2.dist-info}/licenses/NOTICE.txt +54 -64
  6. ot/__main__.py +6 -6
  7. ot/config/__init__.py +48 -46
  8. ot/config/global_templates/__init__.py +2 -2
  9. ot/config/{defaults → global_templates}/diagram-templates/api-flow.mmd +33 -33
  10. ot/config/{defaults → global_templates}/diagram-templates/c4-context.puml +30 -30
  11. ot/config/{defaults → global_templates}/diagram-templates/class-diagram.mmd +87 -87
  12. ot/config/{defaults → global_templates}/diagram-templates/feature-mindmap.mmd +70 -70
  13. ot/config/{defaults → global_templates}/diagram-templates/microservices.d2 +81 -81
  14. ot/config/{defaults → global_templates}/diagram-templates/project-gantt.mmd +37 -37
  15. ot/config/{defaults → global_templates}/diagram-templates/state-machine.mmd +42 -42
  16. ot/config/global_templates/diagram.yaml +167 -0
  17. ot/config/global_templates/onetool.yaml +3 -1
  18. ot/config/{defaults → global_templates}/prompts.yaml +102 -97
  19. ot/config/global_templates/security.yaml +31 -0
  20. ot/config/global_templates/servers.yaml +93 -12
  21. ot/config/global_templates/snippets.yaml +5 -26
  22. ot/config/{defaults → global_templates}/tool_templates/__init__.py +7 -7
  23. ot/config/loader.py +221 -105
  24. ot/config/mcp.py +5 -1
  25. ot/config/secrets.py +192 -190
  26. ot/decorators.py +116 -116
  27. ot/executor/__init__.py +35 -35
  28. ot/executor/base.py +16 -16
  29. ot/executor/fence_processor.py +83 -83
  30. ot/executor/linter.py +142 -142
  31. ot/executor/pep723.py +288 -288
  32. ot/executor/runner.py +20 -6
  33. ot/executor/simple.py +163 -163
  34. ot/executor/validator.py +603 -164
  35. ot/http_client.py +145 -145
  36. ot/logging/__init__.py +37 -37
  37. ot/logging/entry.py +213 -213
  38. ot/logging/format.py +191 -188
  39. ot/logging/span.py +349 -349
  40. ot/meta.py +236 -14
  41. ot/paths.py +32 -49
  42. ot/prompts.py +218 -218
  43. ot/proxy/manager.py +14 -2
  44. ot/registry/__init__.py +189 -189
  45. ot/registry/parser.py +269 -269
  46. ot/server.py +330 -315
  47. ot/shortcuts/__init__.py +15 -15
  48. ot/shortcuts/aliases.py +87 -87
  49. ot/shortcuts/snippets.py +258 -258
  50. ot/stats/__init__.py +35 -35
  51. ot/stats/html.py +2 -2
  52. ot/stats/reader.py +354 -354
  53. ot/stats/timing.py +57 -57
  54. ot/support.py +63 -63
  55. ot/tools.py +1 -1
  56. ot/utils/batch.py +161 -161
  57. ot/utils/cache.py +120 -120
  58. ot/utils/exceptions.py +23 -23
  59. ot/utils/factory.py +178 -179
  60. ot/utils/format.py +65 -65
  61. ot/utils/http.py +202 -202
  62. ot/utils/platform.py +45 -45
  63. ot/utils/truncate.py +69 -69
  64. ot_tools/__init__.py +4 -4
  65. ot_tools/_convert/__init__.py +12 -12
  66. ot_tools/_convert/pdf.py +254 -254
  67. ot_tools/diagram.yaml +167 -167
  68. ot_tools/scaffold.py +2 -2
  69. ot_tools/transform.py +124 -19
  70. ot_tools/web_fetch.py +94 -43
  71. onetool_mcp-1.0.0b1.dist-info/METADATA +0 -163
  72. onetool_mcp-1.0.0b1.dist-info/RECORD +0 -132
  73. ot/config/defaults/bench.yaml +0 -4
  74. ot/config/defaults/onetool.yaml +0 -25
  75. ot/config/defaults/servers.yaml +0 -7
  76. ot/config/defaults/snippets.yaml +0 -4
  77. ot_tools/firecrawl.py +0 -732
  78. {onetool_mcp-1.0.0b1.dist-info → onetool_mcp-1.0.0rc2.dist-info}/WHEEL +0 -0
  79. {onetool_mcp-1.0.0b1.dist-info → onetool_mcp-1.0.0rc2.dist-info}/entry_points.txt +0 -0
  80. /ot/config/{defaults → global_templates}/tool_templates/extension.py +0 -0
  81. /ot/config/{defaults → global_templates}/tool_templates/isolated.py +0 -0
ot/logging/entry.py CHANGED
@@ -1,213 +1,213 @@
1
- """LogEntry class for structured logging.
2
-
3
- A simple struct for building log entries with automatic timing.
4
- Supports fluent API, dict-style access, and lazy duration calculation.
5
-
6
- Example:
7
- # Inline - all fields in constructor
8
- logger.debug(LogEntry(event="command.received", command=command))
9
-
10
- # Fluent - chain adds
11
- logger.debug(LogEntry(event="tool.lookup")
12
- .add("function", func_name)
13
- .add("found", True))
14
-
15
- # Multiple logs show increasing duration (no caching)
16
- entry = LogEntry(event="multi_step")
17
- do_step_1()
18
- logger.debug(entry) # duration: 0.1s
19
- do_step_2()
20
- logger.info(entry) # duration: 0.3s
21
- """
22
-
23
- from __future__ import annotations
24
-
25
- import json
26
- import time
27
- from typing import Any
28
-
29
-
30
- class LogEntry:
31
- """Structured log entry with automatic timing.
32
-
33
- Timing starts automatically on creation. Duration is calculated
34
- lazily in __str__ without caching, so multiple logs show increasing
35
- duration.
36
- """
37
-
38
- def __init__(self, **initial_fields: Any) -> None:
39
- """Initialize a log entry with optional initial fields.
40
-
41
- Args:
42
- **initial_fields: Initial fields for the log entry
43
- """
44
- self._start_time = time.perf_counter()
45
- self._fields: dict[str, Any] = dict(initial_fields)
46
- self._status: str | None = None
47
- self._status_code: int | None = None
48
- self._error_type: str | None = None
49
- self._error_message: str | None = None
50
-
51
- def add(self, key: str | None = None, value: Any = None, **kwargs: Any) -> LogEntry:
52
- """Add one or more fields to the entry.
53
-
54
- Can be called with a single key-value pair or with keyword arguments.
55
-
56
- Args:
57
- key: Field name (optional if using kwargs)
58
- value: Field value (required if key is provided)
59
- **kwargs: Bulk field additions
60
-
61
- Returns:
62
- Self for method chaining
63
-
64
- Example:
65
- entry.add("function", func_name)
66
- entry.add(function=func_name, found=True)
67
- """
68
- if key is not None:
69
- self._fields[key] = value
70
- self._fields.update(kwargs)
71
- return self
72
-
73
- def success(self, status_code: int | None = None) -> LogEntry:
74
- """Mark the entry as successful.
75
-
76
- Args:
77
- status_code: Optional HTTP status code
78
-
79
- Returns:
80
- Self for method chaining
81
- """
82
- self._status = "SUCCESS"
83
- self._status_code = status_code
84
- return self
85
-
86
- def failure(
87
- self,
88
- error: Exception | None = None,
89
- error_type: str | None = None,
90
- error_message: str | None = None,
91
- ) -> LogEntry:
92
- """Mark the entry as failed.
93
-
94
- Args:
95
- error: Exception that caused the failure
96
- error_type: Type name of the error
97
- error_message: Error message
98
-
99
- Returns:
100
- Self for method chaining
101
- """
102
- self._status = "FAILED"
103
- if error is not None:
104
- self._error_type = type(error).__name__
105
- self._error_message = str(error)
106
- if error_type is not None:
107
- self._error_type = error_type
108
- if error_message is not None:
109
- self._error_message = error_message
110
- return self
111
-
112
- def __setitem__(self, key: str, value: Any) -> None:
113
- """Set a field using dict-style access.
114
-
115
- Args:
116
- key: Field name
117
- value: Field value
118
- """
119
- self._fields[key] = value
120
-
121
- def __getitem__(self, key: str) -> Any:
122
- """Get a field using dict-style access.
123
-
124
- Args:
125
- key: Field name
126
-
127
- Returns:
128
- Field value
129
-
130
- Raises:
131
- KeyError: If field doesn't exist
132
- """
133
- return self._fields[key]
134
-
135
- def __contains__(self, key: str) -> bool:
136
- """Check if a field exists.
137
-
138
- Args:
139
- key: Field name
140
-
141
- Returns:
142
- True if field exists
143
- """
144
- return key in self._fields
145
-
146
- @property
147
- def fields(self) -> dict[str, Any]:
148
- """Return a copy of the fields for testing access.
149
-
150
- Returns:
151
- Copy of internal fields dictionary
152
- """
153
- return dict(self._fields)
154
-
155
- @property
156
- def duration(self) -> float:
157
- """Return current duration since entry creation.
158
-
159
- Returns:
160
- Duration in seconds (not cached, calculated fresh each call)
161
- """
162
- return round(time.perf_counter() - self._start_time, 3)
163
-
164
- def to_dict(self) -> dict[str, Any]:
165
- """Return all fields with duration for output.
166
-
167
- Returns:
168
- Dict with all fields, duration, and status info
169
- """
170
- output = dict(self._fields)
171
- output["duration"] = self.duration
172
-
173
- if self._status is not None:
174
- output["status"] = self._status
175
- if self._status_code is not None:
176
- output["statusCode"] = self._status_code
177
- if self._error_type is not None:
178
- output["errorType"] = self._error_type
179
- if self._error_message is not None:
180
- output["errorMessage"] = self._error_message
181
-
182
- return output
183
-
184
- def __str__(self) -> str:
185
- """Serialize to JSON with duration.
186
-
187
- Duration is calculated lazily (not cached) so multiple
188
- calls show increasing duration.
189
-
190
- Returns:
191
- JSON string with fields and duration
192
- """
193
- output = dict(self._fields)
194
- output["duration"] = round(time.perf_counter() - self._start_time, 3)
195
-
196
- if self._status is not None:
197
- output["status"] = self._status
198
- if self._status_code is not None:
199
- output["statusCode"] = self._status_code
200
- if self._error_type is not None:
201
- output["errorType"] = self._error_type
202
- if self._error_message is not None:
203
- output["errorMessage"] = self._error_message
204
-
205
- return json.dumps(output, separators=(",", ":"), default=str)
206
-
207
- def __repr__(self) -> str:
208
- """Return a debug representation.
209
-
210
- Returns:
211
- String showing LogEntry fields
212
- """
213
- return f"LogEntry({self._fields!r})"
1
+ """LogEntry class for structured logging.
2
+
3
+ A simple struct for building log entries with automatic timing.
4
+ Supports fluent API, dict-style access, and lazy duration calculation.
5
+
6
+ Example:
7
+ # Inline - all fields in constructor
8
+ logger.debug(LogEntry(event="command.received", command=command))
9
+
10
+ # Fluent - chain adds
11
+ logger.debug(LogEntry(event="tool.lookup")
12
+ .add("function", func_name)
13
+ .add("found", True))
14
+
15
+ # Multiple logs show increasing duration (no caching)
16
+ entry = LogEntry(event="multi_step")
17
+ do_step_1()
18
+ logger.debug(entry) # duration: 0.1s
19
+ do_step_2()
20
+ logger.info(entry) # duration: 0.3s
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ import json
26
+ import time
27
+ from typing import Any
28
+
29
+
30
+ class LogEntry:
31
+ """Structured log entry with automatic timing.
32
+
33
+ Timing starts automatically on creation. Duration is calculated
34
+ lazily in __str__ without caching, so multiple logs show increasing
35
+ duration.
36
+ """
37
+
38
+ def __init__(self, **initial_fields: Any) -> None:
39
+ """Initialize a log entry with optional initial fields.
40
+
41
+ Args:
42
+ **initial_fields: Initial fields for the log entry
43
+ """
44
+ self._start_time = time.perf_counter()
45
+ self._fields: dict[str, Any] = dict(initial_fields)
46
+ self._status: str | None = None
47
+ self._status_code: int | None = None
48
+ self._error_type: str | None = None
49
+ self._error_message: str | None = None
50
+
51
+ def add(self, key: str | None = None, value: Any = None, **kwargs: Any) -> LogEntry:
52
+ """Add one or more fields to the entry.
53
+
54
+ Can be called with a single key-value pair or with keyword arguments.
55
+
56
+ Args:
57
+ key: Field name (optional if using kwargs)
58
+ value: Field value (required if key is provided)
59
+ **kwargs: Bulk field additions
60
+
61
+ Returns:
62
+ Self for method chaining
63
+
64
+ Example:
65
+ entry.add("function", func_name)
66
+ entry.add(function=func_name, found=True)
67
+ """
68
+ if key is not None:
69
+ self._fields[key] = value
70
+ self._fields.update(kwargs)
71
+ return self
72
+
73
+ def success(self, status_code: int | None = None) -> LogEntry:
74
+ """Mark the entry as successful.
75
+
76
+ Args:
77
+ status_code: Optional HTTP status code
78
+
79
+ Returns:
80
+ Self for method chaining
81
+ """
82
+ self._status = "SUCCESS"
83
+ self._status_code = status_code
84
+ return self
85
+
86
+ def failure(
87
+ self,
88
+ error: Exception | None = None,
89
+ error_type: str | None = None,
90
+ error_message: str | None = None,
91
+ ) -> LogEntry:
92
+ """Mark the entry as failed.
93
+
94
+ Args:
95
+ error: Exception that caused the failure
96
+ error_type: Type name of the error
97
+ error_message: Error message
98
+
99
+ Returns:
100
+ Self for method chaining
101
+ """
102
+ self._status = "FAILED"
103
+ if error is not None:
104
+ self._error_type = type(error).__name__
105
+ self._error_message = str(error)
106
+ if error_type is not None:
107
+ self._error_type = error_type
108
+ if error_message is not None:
109
+ self._error_message = error_message
110
+ return self
111
+
112
+ def __setitem__(self, key: str, value: Any) -> None:
113
+ """Set a field using dict-style access.
114
+
115
+ Args:
116
+ key: Field name
117
+ value: Field value
118
+ """
119
+ self._fields[key] = value
120
+
121
+ def __getitem__(self, key: str) -> Any:
122
+ """Get a field using dict-style access.
123
+
124
+ Args:
125
+ key: Field name
126
+
127
+ Returns:
128
+ Field value
129
+
130
+ Raises:
131
+ KeyError: If field doesn't exist
132
+ """
133
+ return self._fields[key]
134
+
135
+ def __contains__(self, key: str) -> bool:
136
+ """Check if a field exists.
137
+
138
+ Args:
139
+ key: Field name
140
+
141
+ Returns:
142
+ True if field exists
143
+ """
144
+ return key in self._fields
145
+
146
+ @property
147
+ def fields(self) -> dict[str, Any]:
148
+ """Return a copy of the fields for testing access.
149
+
150
+ Returns:
151
+ Copy of internal fields dictionary
152
+ """
153
+ return dict(self._fields)
154
+
155
+ @property
156
+ def duration(self) -> float:
157
+ """Return current duration since entry creation.
158
+
159
+ Returns:
160
+ Duration in seconds (not cached, calculated fresh each call)
161
+ """
162
+ return round(time.perf_counter() - self._start_time, 3)
163
+
164
+ def to_dict(self) -> dict[str, Any]:
165
+ """Return all fields with duration for output.
166
+
167
+ Returns:
168
+ Dict with all fields, duration, and status info
169
+ """
170
+ output = dict(self._fields)
171
+ output["duration"] = self.duration
172
+
173
+ if self._status is not None:
174
+ output["status"] = self._status
175
+ if self._status_code is not None:
176
+ output["statusCode"] = self._status_code
177
+ if self._error_type is not None:
178
+ output["errorType"] = self._error_type
179
+ if self._error_message is not None:
180
+ output["errorMessage"] = self._error_message
181
+
182
+ return output
183
+
184
+ def __str__(self) -> str:
185
+ """Serialize to JSON with duration.
186
+
187
+ Duration is calculated lazily (not cached) so multiple
188
+ calls show increasing duration.
189
+
190
+ Returns:
191
+ JSON string with fields and duration
192
+ """
193
+ output = dict(self._fields)
194
+ output["duration"] = round(time.perf_counter() - self._start_time, 3)
195
+
196
+ if self._status is not None:
197
+ output["status"] = self._status
198
+ if self._status_code is not None:
199
+ output["statusCode"] = self._status_code
200
+ if self._error_type is not None:
201
+ output["errorType"] = self._error_type
202
+ if self._error_message is not None:
203
+ output["errorMessage"] = self._error_message
204
+
205
+ return json.dumps(output, separators=(",", ":"), default=str)
206
+
207
+ def __repr__(self) -> str:
208
+ """Return a debug representation.
209
+
210
+ Returns:
211
+ String showing LogEntry fields
212
+ """
213
+ return f"LogEntry({self._fields!r})"