mycode-sdk 0.12.0__tar.gz → 0.13.0__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.
Files changed (25) hide show
  1. {mycode_sdk-0.12.0 → mycode_sdk-0.13.0}/PKG-INFO +40 -24
  2. {mycode_sdk-0.12.0 → mycode_sdk-0.13.0}/README.md +38 -22
  3. {mycode_sdk-0.12.0 → mycode_sdk-0.13.0}/pyproject.toml +1 -1
  4. {mycode_sdk-0.12.0 → mycode_sdk-0.13.0}/src/mycode/__init__.py +2 -11
  5. {mycode_sdk-0.12.0 → mycode_sdk-0.13.0}/src/mycode/agent.py +245 -81
  6. {mycode_sdk-0.12.0 → mycode_sdk-0.13.0}/src/mycode/compact.py +10 -1
  7. {mycode_sdk-0.12.0 → mycode_sdk-0.13.0}/src/mycode/hooks.py +2 -0
  8. {mycode_sdk-0.12.0 → mycode_sdk-0.13.0}/src/mycode/messages.py +4 -5
  9. {mycode_sdk-0.12.0 → mycode_sdk-0.13.0}/src/mycode/models.py +57 -63
  10. mycode_sdk-0.13.0/src/mycode/models_catalog.json +11297 -0
  11. {mycode_sdk-0.12.0 → mycode_sdk-0.13.0}/src/mycode/providers/anthropic_like.py +13 -1
  12. {mycode_sdk-0.12.0 → mycode_sdk-0.13.0}/src/mycode/providers/base.py +14 -8
  13. {mycode_sdk-0.12.0 → mycode_sdk-0.13.0}/src/mycode/providers/gemini.py +27 -1
  14. {mycode_sdk-0.12.0 → mycode_sdk-0.13.0}/src/mycode/providers/openai_chat.py +23 -7
  15. {mycode_sdk-0.12.0 → mycode_sdk-0.13.0}/src/mycode/providers/openai_responses.py +35 -5
  16. mycode_sdk-0.13.0/src/mycode/tools.py +370 -0
  17. mycode_sdk-0.12.0/src/mycode/models_catalog.json +0 -8170
  18. mycode_sdk-0.12.0/src/mycode/tools.py +0 -1101
  19. {mycode_sdk-0.12.0 → mycode_sdk-0.13.0}/.gitignore +0 -0
  20. {mycode_sdk-0.12.0 → mycode_sdk-0.13.0}/LICENSE +0 -0
  21. {mycode_sdk-0.12.0 → mycode_sdk-0.13.0}/src/mycode/attachments.py +0 -0
  22. {mycode_sdk-0.12.0 → mycode_sdk-0.13.0}/src/mycode/providers/__init__.py +0 -0
  23. {mycode_sdk-0.12.0 → mycode_sdk-0.13.0}/src/mycode/py.typed +0 -0
  24. {mycode_sdk-0.12.0 → mycode_sdk-0.13.0}/src/mycode/session.py +0 -0
  25. {mycode_sdk-0.12.0 → mycode_sdk-0.13.0}/src/mycode/utils.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: mycode-sdk
3
- Version: 0.12.0
3
+ Version: 0.13.0
4
4
  Summary: Lightweight Python SDK for building AI agents.
5
5
  Project-URL: Homepage, https://github.com/legibet/mycode
6
6
  Project-URL: Repository, https://github.com/legibet/mycode
@@ -42,15 +42,27 @@ pip install mycode-sdk
42
42
 
43
43
  ```python
44
44
  import asyncio
45
+ from pathlib import Path
46
+
47
+ from mycode import Agent, tool
45
48
 
46
- from mycode import Agent, bash_tool, read_tool
49
+
50
+ @tool
51
+ def read_file(path: str) -> str:
52
+ """Read a UTF-8 text file.
53
+
54
+ Args:
55
+ path: File path, relative to the working directory.
56
+ """
57
+
58
+ return Path(path).read_text(encoding="utf-8")
47
59
 
48
60
 
49
61
  async def main() -> None:
50
62
  agent = Agent(
51
63
  model="claude-sonnet-4-6",
52
64
  api_key="YOUR_API_KEY",
53
- tools=[read_tool, bash_tool],
65
+ tools=[read_file],
54
66
  )
55
67
 
56
68
  async for event in agent.achat("Read pyproject.toml and tell me the project name."):
@@ -142,15 +154,7 @@ agent = Agent(
142
154
 
143
155
  Construct another `Agent` with the same `(session_dir, session_id)` to load the conversation history.
144
156
 
145
- ## Built-in tools
146
-
147
- ```python
148
- from mycode import read_tool, write_tool, edit_tool, bash_tool
149
- ```
150
-
151
- Four tools for reading, writing, editing files, and running shell commands. Opt in by passing them to `tools=[...]`.
152
-
153
- ## Custom tools
157
+ ## Tools
154
158
 
155
159
  Decorate a typed function with `@tool`:
156
160
 
@@ -176,36 +180,48 @@ agent = Agent(
176
180
  )
177
181
  ```
178
182
 
179
- To call a built-in tool from inside your own tool, type the first parameter as `ToolContext`:
183
+ To call another registered tool from inside a tool, type the first parameter as `ToolContext` and dispatch by name:
180
184
 
181
185
  ```python
182
186
  from mycode import ToolContext, tool
183
187
 
184
188
 
185
189
  @tool
186
- def summarize_file(ctx: ToolContext, path: str) -> str:
187
- """Return the first line of a text file."""
190
+ def greet_team(ctx: ToolContext, names: list[str]) -> str:
191
+ """Greet several people at once."""
188
192
 
189
- result = ctx.read(path)
190
- return result.output.splitlines()[0] if result.output else ""
193
+ return "\n".join(ctx.call("greet", {"name": name}).output for name in names)
191
194
  ```
192
195
 
193
- Async tools use `await ctx.aread()`, `await ctx.awrite()`, `await ctx.aedit()`, and `await ctx.abash()`. Use `await ctx.acall(name, args)` to call another registered tool by name.
196
+ Async tools use `await ctx.acall(name, args)` instead.
194
197
 
195
198
  ## Tool hooks
196
199
 
197
200
  Inspect or replace tool calls before they run. Return `None` from `before_tool` to let the tool execute, or a `ToolExecutionResult` to skip it:
198
201
 
199
202
  ```python
200
- from mycode import Agent, Hooks, ToolExecutionResult, bash_tool
203
+ import os
204
+
205
+ from mycode import Agent, Hooks, ToolExecutionResult, tool
201
206
 
202
207
  hooks = Hooks()
203
208
 
204
209
 
210
+ @tool
211
+ def delete_file(path: str) -> str:
212
+ """Delete a file.
213
+
214
+ Args:
215
+ path: Path of the file to delete.
216
+ """
217
+
218
+ os.remove(path)
219
+ return f"deleted {path}"
220
+
221
+
205
222
  @hooks.before_tool
206
- async def block_rm(ctx):
207
- cmd = str(ctx.tool_input.get("command") or "")
208
- if ctx.tool_name == "bash" and "rm -rf" in cmd:
223
+ async def protect_dotfiles(ctx):
224
+ if ctx.tool_name == "delete_file" and str(ctx.tool_input.get("path") or "").startswith("."):
209
225
  return ToolExecutionResult(output="error: blocked", is_error=True)
210
226
  return None
211
227
 
@@ -213,7 +229,7 @@ async def block_rm(ctx):
213
229
  agent = Agent(
214
230
  model="claude-sonnet-4-6",
215
231
  api_key="...",
216
- tools=[bash_tool],
232
+ tools=[delete_file],
217
233
  hooks=hooks,
218
234
  )
219
235
  ```
@@ -14,15 +14,27 @@ pip install mycode-sdk
14
14
 
15
15
  ```python
16
16
  import asyncio
17
+ from pathlib import Path
18
+
19
+ from mycode import Agent, tool
17
20
 
18
- from mycode import Agent, bash_tool, read_tool
21
+
22
+ @tool
23
+ def read_file(path: str) -> str:
24
+ """Read a UTF-8 text file.
25
+
26
+ Args:
27
+ path: File path, relative to the working directory.
28
+ """
29
+
30
+ return Path(path).read_text(encoding="utf-8")
19
31
 
20
32
 
21
33
  async def main() -> None:
22
34
  agent = Agent(
23
35
  model="claude-sonnet-4-6",
24
36
  api_key="YOUR_API_KEY",
25
- tools=[read_tool, bash_tool],
37
+ tools=[read_file],
26
38
  )
27
39
 
28
40
  async for event in agent.achat("Read pyproject.toml and tell me the project name."):
@@ -114,15 +126,7 @@ agent = Agent(
114
126
 
115
127
  Construct another `Agent` with the same `(session_dir, session_id)` to load the conversation history.
116
128
 
117
- ## Built-in tools
118
-
119
- ```python
120
- from mycode import read_tool, write_tool, edit_tool, bash_tool
121
- ```
122
-
123
- Four tools for reading, writing, editing files, and running shell commands. Opt in by passing them to `tools=[...]`.
124
-
125
- ## Custom tools
129
+ ## Tools
126
130
 
127
131
  Decorate a typed function with `@tool`:
128
132
 
@@ -148,36 +152,48 @@ agent = Agent(
148
152
  )
149
153
  ```
150
154
 
151
- To call a built-in tool from inside your own tool, type the first parameter as `ToolContext`:
155
+ To call another registered tool from inside a tool, type the first parameter as `ToolContext` and dispatch by name:
152
156
 
153
157
  ```python
154
158
  from mycode import ToolContext, tool
155
159
 
156
160
 
157
161
  @tool
158
- def summarize_file(ctx: ToolContext, path: str) -> str:
159
- """Return the first line of a text file."""
162
+ def greet_team(ctx: ToolContext, names: list[str]) -> str:
163
+ """Greet several people at once."""
160
164
 
161
- result = ctx.read(path)
162
- return result.output.splitlines()[0] if result.output else ""
165
+ return "\n".join(ctx.call("greet", {"name": name}).output for name in names)
163
166
  ```
164
167
 
165
- Async tools use `await ctx.aread()`, `await ctx.awrite()`, `await ctx.aedit()`, and `await ctx.abash()`. Use `await ctx.acall(name, args)` to call another registered tool by name.
168
+ Async tools use `await ctx.acall(name, args)` instead.
166
169
 
167
170
  ## Tool hooks
168
171
 
169
172
  Inspect or replace tool calls before they run. Return `None` from `before_tool` to let the tool execute, or a `ToolExecutionResult` to skip it:
170
173
 
171
174
  ```python
172
- from mycode import Agent, Hooks, ToolExecutionResult, bash_tool
175
+ import os
176
+
177
+ from mycode import Agent, Hooks, ToolExecutionResult, tool
173
178
 
174
179
  hooks = Hooks()
175
180
 
176
181
 
182
+ @tool
183
+ def delete_file(path: str) -> str:
184
+ """Delete a file.
185
+
186
+ Args:
187
+ path: Path of the file to delete.
188
+ """
189
+
190
+ os.remove(path)
191
+ return f"deleted {path}"
192
+
193
+
177
194
  @hooks.before_tool
178
- async def block_rm(ctx):
179
- cmd = str(ctx.tool_input.get("command") or "")
180
- if ctx.tool_name == "bash" and "rm -rf" in cmd:
195
+ async def protect_dotfiles(ctx):
196
+ if ctx.tool_name == "delete_file" and str(ctx.tool_input.get("path") or "").startswith("."):
181
197
  return ToolExecutionResult(output="error: blocked", is_error=True)
182
198
  return None
183
199
 
@@ -185,7 +201,7 @@ async def block_rm(ctx):
185
201
  agent = Agent(
186
202
  model="claude-sonnet-4-6",
187
203
  api_key="...",
188
- tools=[bash_tool],
204
+ tools=[delete_file],
189
205
  hooks=hooks,
190
206
  )
191
207
  ```
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "mycode-sdk"
7
- version = "0.12.0"
7
+ version = "0.13.0"
8
8
  description = "Lightweight Python SDK for building AI agents."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -21,7 +21,7 @@ from mycode.messages import (
21
21
  tool_use_block,
22
22
  user_text_message,
23
23
  )
24
- from mycode.models import ModelMetadata, estimate_cost, resolve_model_metadata
24
+ from mycode.models import Cost, ModelMetadata, estimate_cost, resolve_model_metadata
25
25
  from mycode.providers.base import ProviderError, StreamStartTimeoutError
26
26
  from mycode.session import SessionStore
27
27
  from mycode.tools import (
@@ -29,12 +29,7 @@ from mycode.tools import (
29
29
  ToolExecutionResult,
30
30
  ToolExecutor,
31
31
  ToolSpec,
32
- bash_tool,
33
- cancel_all_tools,
34
- edit_tool,
35
- read_tool,
36
32
  tool,
37
- write_tool,
38
33
  )
39
34
 
40
35
  __version__ = metadata.version("mycode-sdk")
@@ -44,6 +39,7 @@ __all__ = [
44
39
  "Attachment",
45
40
  "ContentBlock",
46
41
  "ConversationMessage",
42
+ "Cost",
47
43
  "Event",
48
44
  "AfterToolHook",
49
45
  "BeforeToolHook",
@@ -63,16 +59,12 @@ __all__ = [
63
59
  "ToolSpec",
64
60
  "__version__",
65
61
  "assistant_message",
66
- "bash_tool",
67
62
  "build_message",
68
63
  "build_usage",
69
- "cancel_all_tools",
70
64
  "document_block",
71
- "edit_tool",
72
65
  "estimate_cost",
73
66
  "flatten_message_text",
74
67
  "image_block",
75
- "read_tool",
76
68
  "resolve_model_metadata",
77
69
  "text_block",
78
70
  "thinking_block",
@@ -80,5 +72,4 @@ __all__ = [
80
72
  "tool_result_block",
81
73
  "tool_use_block",
82
74
  "user_text_message",
83
- "write_tool",
84
75
  ]