minimalcode 1.5.2__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.
- minimalcode/__init__.py +3 -0
- minimalcode/__main__.py +3 -0
- minimalcode/agent.py +1084 -0
- minimalcode/cli.py +1520 -0
- minimalcode/clipboard.py +212 -0
- minimalcode/config.py +1065 -0
- minimalcode/defaults.json +491 -0
- minimalcode/errors.py +31 -0
- minimalcode/highlight/__init__.py +47 -0
- minimalcode/highlight/code.py +261 -0
- minimalcode/highlight/color.py +58 -0
- minimalcode/highlight/markdown.py +710 -0
- minimalcode/highlight/palette.py +73 -0
- minimalcode/highlight/sanitize.py +175 -0
- minimalcode/highlight/thinking.py +71 -0
- minimalcode/httpclient.py +278 -0
- minimalcode/importer.py +253 -0
- minimalcode/prompt.py +195 -0
- minimalcode/provider/__init__.py +28 -0
- minimalcode/provider/anthropic.py +805 -0
- minimalcode/provider/anthropic_env.py +161 -0
- minimalcode/provider/chat.py +394 -0
- minimalcode/provider/client.py +243 -0
- minimalcode/provider/common.py +176 -0
- minimalcode/provider/deepseek_web.py +1158 -0
- minimalcode/provider/factory.py +63 -0
- minimalcode/provider/responses.py +692 -0
- minimalcode/provider/sha3_wasm_bg.wasm +0 -0
- minimalcode/provider/transport.py +241 -0
- minimalcode/provider/types.py +54 -0
- minimalcode/sandbox/__init__.py +64 -0
- minimalcode/sandbox/audit.py +120 -0
- minimalcode/sandbox/backends.py +343 -0
- minimalcode/sandbox/execution.py +435 -0
- minimalcode/sandbox/network.py +793 -0
- minimalcode/sandbox/policy.py +253 -0
- minimalcode/sandbox/runner.py +347 -0
- minimalcode/sandbox/sensitive.py +286 -0
- minimalcode/session.py +465 -0
- minimalcode/shell.py +333 -0
- minimalcode/subagent.py +120 -0
- minimalcode/tools/__init__.py +46 -0
- minimalcode/tools/files.py +1139 -0
- minimalcode/tools/process.py +164 -0
- minimalcode/tools/remote.py +74 -0
- minimalcode/tools/runtime.py +219 -0
- minimalcode/tools/schemas.py +418 -0
- minimalcode/tools/search.py +521 -0
- minimalcode/tools/search_tools.py +583 -0
- minimalcode/tools/validation.py +99 -0
- minimalcode/vision.py +231 -0
- minimalcode/web.py +238 -0
- minimalcode-1.5.2.dist-info/METADATA +646 -0
- minimalcode-1.5.2.dist-info/RECORD +58 -0
- minimalcode-1.5.2.dist-info/WHEEL +5 -0
- minimalcode-1.5.2.dist-info/entry_points.txt +2 -0
- minimalcode-1.5.2.dist-info/licenses/LICENSE +201 -0
- minimalcode-1.5.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
"""Tool schema declarations exposed to the model.
|
|
2
|
+
|
|
3
|
+
Schemas live apart from execution code so protocol payloads can be reviewed and
|
|
4
|
+
tested without importing the filesystem, sandbox, or HTTP layers.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Any
|
|
10
|
+
|
|
11
|
+
from ..vision import ProviderVisionClient
|
|
12
|
+
from ..web import ProviderWebClient
|
|
13
|
+
|
|
14
|
+
# Every name the dispatcher accepts. `tools.allow`, `--read-only`, and the
|
|
15
|
+
# advertised schemas are all expressed against this set so that a tool cannot
|
|
16
|
+
# be offered to the model without the dispatcher accepting it, or the reverse.
|
|
17
|
+
TOOL_NAMES = frozenset(
|
|
18
|
+
{
|
|
19
|
+
"read",
|
|
20
|
+
"read_range",
|
|
21
|
+
"write",
|
|
22
|
+
"append_file",
|
|
23
|
+
"edit",
|
|
24
|
+
"shell",
|
|
25
|
+
"grep",
|
|
26
|
+
"find",
|
|
27
|
+
"subagent",
|
|
28
|
+
"read_image",
|
|
29
|
+
"web_search",
|
|
30
|
+
"web_fetch",
|
|
31
|
+
}
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
# Tools that cannot change the workspace or start a process. They are the whole
|
|
35
|
+
# of `--read-only`, and the only tools that may run concurrently: a batch of
|
|
36
|
+
# reads has no ordering dependency, while `write` followed by `shell` does.
|
|
37
|
+
READ_ONLY_TOOLS = frozenset(
|
|
38
|
+
{
|
|
39
|
+
"read",
|
|
40
|
+
"read_range",
|
|
41
|
+
"grep",
|
|
42
|
+
"find",
|
|
43
|
+
"read_image",
|
|
44
|
+
"web_search",
|
|
45
|
+
"web_fetch",
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# The always-available focused tools. Order is stable because providers and
|
|
50
|
+
# prompt caches can key off the serialized schema list.
|
|
51
|
+
TOOL_SCHEMAS: list[dict[str, Any]] = [
|
|
52
|
+
{
|
|
53
|
+
"type": "function",
|
|
54
|
+
"function": {
|
|
55
|
+
"name": "read",
|
|
56
|
+
"description": "Read a UTF-8 text file by line range. Output includes line numbers.",
|
|
57
|
+
"parameters": {
|
|
58
|
+
"type": "object",
|
|
59
|
+
"properties": {
|
|
60
|
+
"path": {"type": "string", "description": "File path"},
|
|
61
|
+
"start_line": {"type": "integer", "minimum": 1},
|
|
62
|
+
"end_line": {"type": "integer", "minimum": 1},
|
|
63
|
+
},
|
|
64
|
+
"required": ["path"],
|
|
65
|
+
"additionalProperties": False,
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
{
|
|
70
|
+
"type": "function",
|
|
71
|
+
"function": {
|
|
72
|
+
"name": "read_range",
|
|
73
|
+
"description": (
|
|
74
|
+
"Read an explicit line range with line numbers. Use it to inspect "
|
|
75
|
+
"the exact region before a line-number edit."
|
|
76
|
+
),
|
|
77
|
+
"parameters": {
|
|
78
|
+
"type": "object",
|
|
79
|
+
"properties": {
|
|
80
|
+
"path": {"type": "string", "description": "File path"},
|
|
81
|
+
"start_line": {"type": "integer", "minimum": 1},
|
|
82
|
+
"end_line": {"type": "integer", "minimum": 1},
|
|
83
|
+
},
|
|
84
|
+
"required": ["path", "start_line", "end_line"],
|
|
85
|
+
"additionalProperties": False,
|
|
86
|
+
},
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
"type": "function",
|
|
91
|
+
"function": {
|
|
92
|
+
"name": "write",
|
|
93
|
+
"description": "Create a file or overwrite it with complete UTF-8 text.",
|
|
94
|
+
"parameters": {
|
|
95
|
+
"type": "object",
|
|
96
|
+
"properties": {
|
|
97
|
+
"path": {"type": "string", "description": "File path"},
|
|
98
|
+
"content": {
|
|
99
|
+
"type": "string",
|
|
100
|
+
"description": "Complete file content",
|
|
101
|
+
},
|
|
102
|
+
},
|
|
103
|
+
"required": ["path", "content"],
|
|
104
|
+
"additionalProperties": False,
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
"type": "function",
|
|
110
|
+
"function": {
|
|
111
|
+
"name": "append_file",
|
|
112
|
+
"description": (
|
|
113
|
+
"Append UTF-8 text at EOF, creating the file when missing. Use it "
|
|
114
|
+
"instead of an edit that guesses the file tail; the existing line "
|
|
115
|
+
"ending style is preserved."
|
|
116
|
+
),
|
|
117
|
+
"parameters": {
|
|
118
|
+
"type": "object",
|
|
119
|
+
"properties": {
|
|
120
|
+
"path": {"type": "string", "description": "File path"},
|
|
121
|
+
"content": {
|
|
122
|
+
"type": "string",
|
|
123
|
+
"description": "Text to append at the end of the file",
|
|
124
|
+
},
|
|
125
|
+
},
|
|
126
|
+
"required": ["path", "content"],
|
|
127
|
+
"additionalProperties": False,
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"type": "function",
|
|
133
|
+
"function": {
|
|
134
|
+
"name": "edit",
|
|
135
|
+
"description": (
|
|
136
|
+
"Replace a line range with a patch block. Read the target lines "
|
|
137
|
+
"first, then pass start_line/end_line and new_text; use the "
|
|
138
|
+
"exact old_text fallback only when line numbers are unreliable. "
|
|
139
|
+
"end_line = start_line - 1 inserts before start_line."
|
|
140
|
+
),
|
|
141
|
+
"parameters": {
|
|
142
|
+
"type": "object",
|
|
143
|
+
"properties": {
|
|
144
|
+
"path": {"type": "string", "description": "File path"},
|
|
145
|
+
"start_line": {
|
|
146
|
+
"type": "integer",
|
|
147
|
+
"minimum": 1,
|
|
148
|
+
"description": "First line to replace (from a fresh read)",
|
|
149
|
+
},
|
|
150
|
+
"end_line": {
|
|
151
|
+
"type": "integer",
|
|
152
|
+
"minimum": 0,
|
|
153
|
+
"description": (
|
|
154
|
+
"Last line to replace; start_line - 1 inserts instead"
|
|
155
|
+
),
|
|
156
|
+
},
|
|
157
|
+
"new_text": {
|
|
158
|
+
"type": "string",
|
|
159
|
+
"description": "Replacement patch block",
|
|
160
|
+
},
|
|
161
|
+
"old_text": {
|
|
162
|
+
"type": "string",
|
|
163
|
+
"description": (
|
|
164
|
+
"Exact-text fallback; do not pass with line numbers"
|
|
165
|
+
),
|
|
166
|
+
},
|
|
167
|
+
"replace_all": {
|
|
168
|
+
"type": "boolean",
|
|
169
|
+
"description": "Exact-text fallback only: replace every match",
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
"required": ["path", "new_text"],
|
|
173
|
+
"additionalProperties": False,
|
|
174
|
+
},
|
|
175
|
+
},
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
"type": "function",
|
|
179
|
+
"function": {
|
|
180
|
+
"name": "shell",
|
|
181
|
+
"description": "Run a command in the configured shell. Use it for tests, builds, git, and commands unavailable as focused tools.",
|
|
182
|
+
"parameters": {
|
|
183
|
+
"type": "object",
|
|
184
|
+
"properties": {
|
|
185
|
+
"command": {"type": "string", "description": "Shell command"},
|
|
186
|
+
"timeout": {
|
|
187
|
+
"type": "number",
|
|
188
|
+
"minimum": 1,
|
|
189
|
+
"maximum": 3600,
|
|
190
|
+
"description": (
|
|
191
|
+
"Timeout in seconds, capped by shell.timeout_seconds"
|
|
192
|
+
),
|
|
193
|
+
},
|
|
194
|
+
"cwd": {
|
|
195
|
+
"type": "string",
|
|
196
|
+
"description": "Working directory, relative to the workspace",
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
"required": ["command"],
|
|
200
|
+
"additionalProperties": False,
|
|
201
|
+
},
|
|
202
|
+
},
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
"type": "function",
|
|
206
|
+
"function": {
|
|
207
|
+
"name": "grep",
|
|
208
|
+
"description": "Search text with ripgrep semantics. Use before reading large codebases.",
|
|
209
|
+
"parameters": {
|
|
210
|
+
"type": "object",
|
|
211
|
+
"properties": {
|
|
212
|
+
"pattern": {"type": "string", "description": "Regular expression"},
|
|
213
|
+
"path": {
|
|
214
|
+
"type": "string",
|
|
215
|
+
"description": "File or directory, default .",
|
|
216
|
+
},
|
|
217
|
+
"glob": {
|
|
218
|
+
"type": "string",
|
|
219
|
+
"description": "Optional glob such as *.py",
|
|
220
|
+
},
|
|
221
|
+
"max_results": {
|
|
222
|
+
"type": "integer",
|
|
223
|
+
"minimum": 1,
|
|
224
|
+
"maximum": 2000,
|
|
225
|
+
},
|
|
226
|
+
},
|
|
227
|
+
"required": ["pattern"],
|
|
228
|
+
"additionalProperties": False,
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
},
|
|
232
|
+
{
|
|
233
|
+
"type": "function",
|
|
234
|
+
"function": {
|
|
235
|
+
"name": "find",
|
|
236
|
+
"description": "Find files by glob pattern.",
|
|
237
|
+
"parameters": {
|
|
238
|
+
"type": "object",
|
|
239
|
+
"properties": {
|
|
240
|
+
"pattern": {
|
|
241
|
+
"type": "string",
|
|
242
|
+
"description": "Glob such as **/*.py or *.toml",
|
|
243
|
+
},
|
|
244
|
+
"path": {"type": "string", "description": "Directory, default ."},
|
|
245
|
+
"max_results": {
|
|
246
|
+
"type": "integer",
|
|
247
|
+
"minimum": 1,
|
|
248
|
+
"maximum": 5000,
|
|
249
|
+
},
|
|
250
|
+
},
|
|
251
|
+
"required": ["pattern"],
|
|
252
|
+
"additionalProperties": False,
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
},
|
|
256
|
+
]
|
|
257
|
+
|
|
258
|
+
# Optional schemas are appended only when the backing client is enabled, so the
|
|
259
|
+
# model never sees a tool that the current configuration would reject.
|
|
260
|
+
READ_IMAGE_SCHEMA: dict[str, Any] = {
|
|
261
|
+
"type": "function",
|
|
262
|
+
"function": {
|
|
263
|
+
"name": "read_image",
|
|
264
|
+
"description": (
|
|
265
|
+
"Describe an image or screenshot with the provider's vision model. "
|
|
266
|
+
"Use it to read text, UI details, or diagrams that plain text tools cannot see."
|
|
267
|
+
),
|
|
268
|
+
"parameters": {
|
|
269
|
+
"type": "object",
|
|
270
|
+
"properties": {
|
|
271
|
+
"path": {
|
|
272
|
+
"type": "string",
|
|
273
|
+
"description": "Image path in the workspace",
|
|
274
|
+
},
|
|
275
|
+
"prompt": {
|
|
276
|
+
"type": ["string", "null"],
|
|
277
|
+
"description": (
|
|
278
|
+
"Question about the image; defaults to a full description "
|
|
279
|
+
"with verbatim visible text"
|
|
280
|
+
),
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
"required": ["path"],
|
|
284
|
+
"additionalProperties": False,
|
|
285
|
+
},
|
|
286
|
+
},
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
SUBAGENT_SCHEMA: dict[str, Any] = {
|
|
291
|
+
"type": "function",
|
|
292
|
+
"function": {
|
|
293
|
+
"name": "subagent",
|
|
294
|
+
"description": (
|
|
295
|
+
"Delegate a self-contained task to a fresh MinimalCode agent in a child "
|
|
296
|
+
"shell and return its final answer. Use it for code review, broad "
|
|
297
|
+
"analysis, or independent verification whose output would flood this "
|
|
298
|
+
"context. Adjacent subagent calls in one turn run concurrently, so "
|
|
299
|
+
"dispatch independent tasks as separate calls. The subagent is "
|
|
300
|
+
"workspace-aware and uses the same provider."
|
|
301
|
+
),
|
|
302
|
+
"parameters": {
|
|
303
|
+
"type": "object",
|
|
304
|
+
"properties": {
|
|
305
|
+
"task": {
|
|
306
|
+
"type": "string",
|
|
307
|
+
"description": "Complete instruction for the subagent",
|
|
308
|
+
},
|
|
309
|
+
"cwd": {
|
|
310
|
+
"type": "string",
|
|
311
|
+
"description": "Working directory, relative to the workspace",
|
|
312
|
+
},
|
|
313
|
+
"timeout": {
|
|
314
|
+
"type": "number",
|
|
315
|
+
"minimum": 1,
|
|
316
|
+
"maximum": 3600,
|
|
317
|
+
"description": "Timeout in seconds, capped by subagent.timeout_seconds",
|
|
318
|
+
},
|
|
319
|
+
"max_turns": {
|
|
320
|
+
"type": "integer",
|
|
321
|
+
"minimum": 1,
|
|
322
|
+
"maximum": 10000,
|
|
323
|
+
"description": "Model/tool rounds allowed in the child, capped by config",
|
|
324
|
+
},
|
|
325
|
+
},
|
|
326
|
+
"required": ["task"],
|
|
327
|
+
"additionalProperties": False,
|
|
328
|
+
},
|
|
329
|
+
},
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
|
|
333
|
+
def _web_schemas(web_client: ProviderWebClient) -> list[dict[str, Any]]:
|
|
334
|
+
"""Build provider-backed web schemas with the configured result bounds."""
|
|
335
|
+
return [
|
|
336
|
+
{
|
|
337
|
+
"type": "function",
|
|
338
|
+
"function": {
|
|
339
|
+
"name": "web_search",
|
|
340
|
+
"description": "Search the web through the configured provider.",
|
|
341
|
+
"parameters": {
|
|
342
|
+
"type": "object",
|
|
343
|
+
"properties": {
|
|
344
|
+
"query": {
|
|
345
|
+
"type": "string",
|
|
346
|
+
"description": "Search query, 1-128 characters",
|
|
347
|
+
},
|
|
348
|
+
"count": {
|
|
349
|
+
"type": "integer",
|
|
350
|
+
"minimum": 1,
|
|
351
|
+
"maximum": web_client.max_count,
|
|
352
|
+
"description": (
|
|
353
|
+
f"Number of results, default {web_client.default_count}"
|
|
354
|
+
),
|
|
355
|
+
},
|
|
356
|
+
"need_content": {
|
|
357
|
+
"type": "boolean",
|
|
358
|
+
"description": "Include page content when available",
|
|
359
|
+
},
|
|
360
|
+
"ori_question": {
|
|
361
|
+
"type": ["string", "null"],
|
|
362
|
+
"description": "Original user question",
|
|
363
|
+
},
|
|
364
|
+
"localization": {
|
|
365
|
+
"type": ["string", "null"],
|
|
366
|
+
"description": "Optional localization IP",
|
|
367
|
+
},
|
|
368
|
+
},
|
|
369
|
+
"required": ["query"],
|
|
370
|
+
"additionalProperties": False,
|
|
371
|
+
},
|
|
372
|
+
},
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
"type": "function",
|
|
376
|
+
"function": {
|
|
377
|
+
"name": "web_fetch",
|
|
378
|
+
"description": "Fetch an HTTP or HTTPS page through the provider.",
|
|
379
|
+
"parameters": {
|
|
380
|
+
"type": "object",
|
|
381
|
+
"properties": {
|
|
382
|
+
"url": {
|
|
383
|
+
"type": "string",
|
|
384
|
+
"description": "Absolute HTTP or HTTPS URL",
|
|
385
|
+
}
|
|
386
|
+
},
|
|
387
|
+
"required": ["url"],
|
|
388
|
+
"additionalProperties": False,
|
|
389
|
+
},
|
|
390
|
+
},
|
|
391
|
+
},
|
|
392
|
+
]
|
|
393
|
+
|
|
394
|
+
|
|
395
|
+
def available_tool_schemas(
|
|
396
|
+
web_client: ProviderWebClient | None = None,
|
|
397
|
+
vision_client: ProviderVisionClient | None = None,
|
|
398
|
+
subagent: bool = False,
|
|
399
|
+
*,
|
|
400
|
+
allowed: frozenset[str] | None = None,
|
|
401
|
+
) -> list[dict[str, Any]]:
|
|
402
|
+
"""Return the schemas enabled by the active clients and depth limit.
|
|
403
|
+
|
|
404
|
+
Keeping this decision in one place ensures the advertised tool set and the
|
|
405
|
+
dispatcher's accepted names stay in sync. ``allowed`` carries the
|
|
406
|
+
``tools.allow`` / ``--read-only`` restriction so a disabled tool is never
|
|
407
|
+
advertised: a schema the model can see but not call only wastes a turn.
|
|
408
|
+
"""
|
|
409
|
+
schemas = list(TOOL_SCHEMAS)
|
|
410
|
+
if subagent:
|
|
411
|
+
schemas.append(SUBAGENT_SCHEMA)
|
|
412
|
+
if vision_client is not None and vision_client.enabled:
|
|
413
|
+
schemas.append(READ_IMAGE_SCHEMA)
|
|
414
|
+
if web_client is not None and web_client.enabled:
|
|
415
|
+
schemas.extend(_web_schemas(web_client))
|
|
416
|
+
if allowed is None:
|
|
417
|
+
return schemas
|
|
418
|
+
return [schema for schema in schemas if schema["function"]["name"] in allowed]
|