mlx-code 0.0.3__tar.gz → 0.0.4__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.
- {mlx_code-0.0.3 → mlx_code-0.0.4}/PKG-INFO +7 -4
- {mlx_code-0.0.3 → mlx_code-0.0.4}/README.md +6 -3
- {mlx_code-0.0.3 → mlx_code-0.0.4}/mlx_code/main.py +4 -4
- {mlx_code-0.0.3 → mlx_code-0.0.4}/mlx_code/pie.py +30 -12
- {mlx_code-0.0.3 → mlx_code-0.0.4}/mlx_code.egg-info/PKG-INFO +7 -4
- {mlx_code-0.0.3 → mlx_code-0.0.4}/setup.py +1 -1
- {mlx_code-0.0.3 → mlx_code-0.0.4}/LICENSE +0 -0
- {mlx_code-0.0.3 → mlx_code-0.0.4}/mlx_code/__init__.py +0 -0
- {mlx_code-0.0.3 → mlx_code-0.0.4}/mlx_code/log.py +0 -0
- {mlx_code-0.0.3 → mlx_code-0.0.4}/mlx_code.egg-info/SOURCES.txt +0 -0
- {mlx_code-0.0.3 → mlx_code-0.0.4}/mlx_code.egg-info/dependency_links.txt +0 -0
- {mlx_code-0.0.3 → mlx_code-0.0.4}/mlx_code.egg-info/entry_points.txt +0 -0
- {mlx_code-0.0.3 → mlx_code-0.0.4}/mlx_code.egg-info/requires.txt +0 -0
- {mlx_code-0.0.3 → mlx_code-0.0.4}/mlx_code.egg-info/top_level.txt +0 -0
- {mlx_code-0.0.3 → mlx_code-0.0.4}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mlx-code
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.4
|
|
4
4
|
Summary: Coding Agent for Mac
|
|
5
5
|
Home-page: https://github.com/JosefAlbers/mlx-code
|
|
6
6
|
Author: J Joe
|
|
@@ -35,7 +35,7 @@ It features a multi-provider local server, a terminal-based chat REPL, and a ded
|
|
|
35
35
|
### Features
|
|
36
36
|
|
|
37
37
|
* **Local MLX Inference**: Powered by `mlx-lm` for optimized performance on Apple Silicon. Includes intelligent prompt caching.
|
|
38
|
-
* **Multi-Provider Compatibility**: Seamlessly translates and handles requests formatted for Claude
|
|
38
|
+
* **Multi-Provider Compatibility**: Seamlessly translates and handles requests formatted for **Claude**, **Gemini**, **Codex**, **DeepSeek** and standard OpenAI APIs.
|
|
39
39
|
* **Built-in REPL & Tools**: Comes with `pie`, a fully-featured chat REPL with tool execution and reasoning token support.
|
|
40
40
|
* **TUI Log Viewer**: Includes a Curses-based Terminal UI for filtering, inspecting, and tracking JSON logs in real-time.
|
|
41
41
|
* **Server Mode**: Easily spin up a local server compatible with standard LLM tooling.
|
|
@@ -70,8 +70,11 @@ mc --model mlx-community/Qwen3.5-4B-OptiQ-4bit
|
|
|
70
70
|
# Use DeepSeek V4 Flash API
|
|
71
71
|
me --deepseek
|
|
72
72
|
|
|
73
|
-
# Run the server only
|
|
74
|
-
mc --nocc
|
|
73
|
+
# Run the server only
|
|
74
|
+
mc --nocc
|
|
75
|
+
|
|
76
|
+
# General shell piping and chaining works too
|
|
77
|
+
echo "explain symgraph.py" | mc | cat - PLAN.md | mc
|
|
75
78
|
```
|
|
76
79
|
*(For a full list of mc server arguments, run mc --help)*
|
|
77
80
|
|
|
@@ -9,7 +9,7 @@ It features a multi-provider local server, a terminal-based chat REPL, and a ded
|
|
|
9
9
|
### Features
|
|
10
10
|
|
|
11
11
|
* **Local MLX Inference**: Powered by `mlx-lm` for optimized performance on Apple Silicon. Includes intelligent prompt caching.
|
|
12
|
-
* **Multi-Provider Compatibility**: Seamlessly translates and handles requests formatted for Claude
|
|
12
|
+
* **Multi-Provider Compatibility**: Seamlessly translates and handles requests formatted for **Claude**, **Gemini**, **Codex**, **DeepSeek** and standard OpenAI APIs.
|
|
13
13
|
* **Built-in REPL & Tools**: Comes with `pie`, a fully-featured chat REPL with tool execution and reasoning token support.
|
|
14
14
|
* **TUI Log Viewer**: Includes a Curses-based Terminal UI for filtering, inspecting, and tracking JSON logs in real-time.
|
|
15
15
|
* **Server Mode**: Easily spin up a local server compatible with standard LLM tooling.
|
|
@@ -44,8 +44,11 @@ mc --model mlx-community/Qwen3.5-4B-OptiQ-4bit
|
|
|
44
44
|
# Use DeepSeek V4 Flash API
|
|
45
45
|
me --deepseek
|
|
46
46
|
|
|
47
|
-
# Run the server only
|
|
48
|
-
mc --nocc
|
|
47
|
+
# Run the server only
|
|
48
|
+
mc --nocc
|
|
49
|
+
|
|
50
|
+
# General shell piping and chaining works too
|
|
51
|
+
echo "explain symgraph.py" | mc | cat - PLAN.md | mc
|
|
49
52
|
```
|
|
50
53
|
*(For a full list of mc server arguments, run mc --help)*
|
|
51
54
|
|
|
@@ -335,7 +335,7 @@ def parse_default(body: dict) -> tuple[list[Tool], list[Message]]:
|
|
|
335
335
|
for b in content:
|
|
336
336
|
btype = b.get("type")
|
|
337
337
|
if btype == "thinking":
|
|
338
|
-
thinking_parts.append(b.get("thinking") or b.get("text", ""))
|
|
338
|
+
thinking_parts.append(b.get("thinking") or b.get("reasoning_content") or b.get("text", ""))
|
|
339
339
|
elif btype == "text":
|
|
340
340
|
text_parts.append(b.get("text", ""))
|
|
341
341
|
return "\n".join(text_parts), "\n".join(thinking_parts)
|
|
@@ -355,7 +355,7 @@ def parse_default(body: dict) -> tuple[list[Tool], list[Message]]:
|
|
|
355
355
|
messages.append(Message(
|
|
356
356
|
role="assistant",
|
|
357
357
|
content=text or None,
|
|
358
|
-
thinking=thinking or m.get("thinking") or None,
|
|
358
|
+
thinking=thinking or m.get("reasoning_content") or m.get("thinking") or None,
|
|
359
359
|
tool_calls=[
|
|
360
360
|
ToolCall(tc["id"], tc["function"]["name"], _safe_json(tc["function"]["arguments"]))
|
|
361
361
|
for tc in m["tool_calls"]
|
|
@@ -367,7 +367,7 @@ def parse_default(body: dict) -> tuple[list[Tool], list[Message]]:
|
|
|
367
367
|
messages.append(Message(
|
|
368
368
|
role=role,
|
|
369
369
|
content=text or None,
|
|
370
|
-
thinking=thinking or m.get("thinking") or None,
|
|
370
|
+
thinking=thinking or m.get("reasoning_content") or m.get("thinking") or None,
|
|
371
371
|
))
|
|
372
372
|
|
|
373
373
|
return tools, messages
|
|
@@ -1111,7 +1111,7 @@ class DefaultAdapter(BaseAdapter):
|
|
|
1111
1111
|
if not text:
|
|
1112
1112
|
return b""
|
|
1113
1113
|
if state == "thinking":
|
|
1114
|
-
return self.chunk({"
|
|
1114
|
+
return self.chunk({"reasoning_content": text})
|
|
1115
1115
|
return self.chunk({"content": text})
|
|
1116
1116
|
|
|
1117
1117
|
def tool(self, tool):
|
|
@@ -516,7 +516,7 @@ class DefaultChat:
|
|
|
516
516
|
if text_parts:
|
|
517
517
|
msg["content"] = "".join(b.text for b in text_parts)
|
|
518
518
|
if thinking_parts:
|
|
519
|
-
msg["
|
|
519
|
+
msg["reasoning_content"] = "".join(b.thinking for b in thinking_parts)
|
|
520
520
|
if tool_calls:
|
|
521
521
|
msg["tool_calls"] = [
|
|
522
522
|
{"id": tc.id, "type": "function",
|
|
@@ -585,7 +585,7 @@ class DefaultChat:
|
|
|
585
585
|
msg = AssistantMessage()
|
|
586
586
|
try:
|
|
587
587
|
async with httpx.AsyncClient(timeout=120.0) as client:
|
|
588
|
-
async with client.stream("POST", f"{self.base_url}/chat/completions", json=payload, headers=headers) as resp:
|
|
588
|
+
async with client.stream("POST", f"{self.base_url}/v1/chat/completions", json=payload, headers=headers) as resp:
|
|
589
589
|
if resp.status_code >= 400:
|
|
590
590
|
body = await resp.aread()
|
|
591
591
|
raise RuntimeError(f"HTTP {resp.status_code}: {body.decode()}")
|
|
@@ -610,10 +610,10 @@ class DefaultChat:
|
|
|
610
610
|
delta = choice.get("delta", {})
|
|
611
611
|
finish_reason = choice.get("finish_reason") or finish_reason
|
|
612
612
|
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
_thinking_buf +=
|
|
616
|
-
es.push(Event("thinking_delta", {"delta":
|
|
613
|
+
reasoning = delta.get("reasoning_content") or delta.get("thinking")
|
|
614
|
+
if reasoning:
|
|
615
|
+
_thinking_buf += reasoning
|
|
616
|
+
es.push(Event("thinking_delta", {"delta": reasoning, "partial": msg}))
|
|
617
617
|
|
|
618
618
|
if delta.get("content"):
|
|
619
619
|
text = delta["content"]
|
|
@@ -1986,11 +1986,18 @@ async def _repl(
|
|
|
1986
1986
|
agent = Agent(api, system=system, tools=available_tools)
|
|
1987
1987
|
loop = asyncio.get_running_loop()
|
|
1988
1988
|
_suppress = False
|
|
1989
|
+
last_ev_type = ""
|
|
1990
|
+
last_delta = ""
|
|
1989
1991
|
async def on_event(event: AgentEvent) -> None:
|
|
1990
1992
|
# logger.debug(event) # □
|
|
1991
|
-
nonlocal _suppress, is_tty
|
|
1993
|
+
nonlocal _suppress, is_tty, last_ev_type, last_delta
|
|
1992
1994
|
if event.type == "text_delta":
|
|
1993
1995
|
delta = event.payload.get("delta", "")
|
|
1996
|
+
|
|
1997
|
+
if last_ev_type and last_ev_type[:4] != event.type[:4] and last_delta and not last_delta[-1].isspace() and delta and not delta[0].isspace():
|
|
1998
|
+
print()
|
|
1999
|
+
last_delta = delta
|
|
2000
|
+
last_ev_type = event.type
|
|
1994
2001
|
if "<tool_call>" in delta:
|
|
1995
2002
|
before, _, _ = delta.partition("<tool_call>")
|
|
1996
2003
|
print(before.strip(), end="", flush=True)
|
|
@@ -2004,10 +2011,19 @@ async def _repl(
|
|
|
2004
2011
|
elif is_tty:
|
|
2005
2012
|
if event.type == "thinking_delta":
|
|
2006
2013
|
delta = event.payload.get("delta", "")
|
|
2014
|
+
if last_ev_type and last_ev_type[:4] != event.type[:4] and last_delta and not last_delta[-1].isspace() and delta and not delta[0].isspace():
|
|
2015
|
+
print()
|
|
2016
|
+
last_delta = delta
|
|
2017
|
+
last_ev_type = event.type
|
|
2007
2018
|
if delta.strip():
|
|
2008
2019
|
print(f"\033[2m{delta}\033[0m", end="", flush=True)
|
|
2009
2020
|
elif event.type == "tool_start":
|
|
2010
|
-
|
|
2021
|
+
delta = f"\033[33m{event.payload['name']}:\033[0m {json.dumps(event.payload['args'])[:120]}\n"
|
|
2022
|
+
if last_ev_type and last_ev_type[:4] != event.type[:4] and last_delta and not last_delta[-1].isspace() and delta and not delta[0].isspace():
|
|
2023
|
+
print()
|
|
2024
|
+
last_delta = delta
|
|
2025
|
+
last_ev_type = event.type
|
|
2026
|
+
print(delta, flush=True)
|
|
2011
2027
|
elif event.type == "tool_result":
|
|
2012
2028
|
msg = event.payload["message"]
|
|
2013
2029
|
raw = "\n".join(b.text for b in msg.content if isinstance(b, TextContent))
|
|
@@ -2015,10 +2031,10 @@ async def _repl(
|
|
|
2015
2031
|
# print(f"\n\n\033[36m{raw[:200]}\033[0m\n", end="", flush=True) # □
|
|
2016
2032
|
elif event.type == "tool_end":
|
|
2017
2033
|
if event.payload.get("is_error"):
|
|
2018
|
-
print(" \033[31m(error)\033[0m",
|
|
2034
|
+
print(" \033[31m(error)\033[0m", flush=True)
|
|
2019
2035
|
elif event.type == "error":
|
|
2020
2036
|
err = event.payload.get("error")
|
|
2021
|
-
print(f"\n\033[31m[error]\033[0m {getattr(err, 'error_message', str(err))}")
|
|
2037
|
+
print(f"\n\033[31m[error]\033[0m {getattr(err, 'error_message', str(err))}\n")
|
|
2022
2038
|
|
|
2023
2039
|
agent.subscribe(on_event)
|
|
2024
2040
|
if is_tty:
|
|
@@ -2037,6 +2053,8 @@ async def _repl(
|
|
|
2037
2053
|
if not user_input:
|
|
2038
2054
|
continue
|
|
2039
2055
|
|
|
2056
|
+
last_delta = ""
|
|
2057
|
+
last_ev_type = ""
|
|
2040
2058
|
logger.info(user_input)
|
|
2041
2059
|
|
|
2042
2060
|
if user_input.startswith("/"):
|
|
@@ -2108,7 +2126,7 @@ def run_repl(
|
|
|
2108
2126
|
elif provider == "codex":
|
|
2109
2127
|
api = CodexChat(model=model, api_key=os.environ.get("OPENAI_API_KEY") if api_key is None else api_key, base_url=f'{base_url}/v1' if base_url else "https://api.openai.com/v1")
|
|
2110
2128
|
else:
|
|
2111
|
-
api = DefaultChat(model=model, api_key="mp" if api_key is None else api_key, base_url=
|
|
2129
|
+
api = DefaultChat(model=model, api_key="mp" if api_key is None else api_key, base_url=base_url if base_url else "https://api.openai.com/v1")
|
|
2112
2130
|
|
|
2113
2131
|
try:
|
|
2114
2132
|
asyncio.run(_repl(api, system=system, cwd=cwd, tools=tools))
|
|
@@ -2132,7 +2150,7 @@ def main():
|
|
|
2132
2150
|
if args.simulate:
|
|
2133
2151
|
asyncio.run(simulate())
|
|
2134
2152
|
elif args.deepseek:
|
|
2135
|
-
run_repl(base_url="https://api.deepseek.com
|
|
2153
|
+
run_repl(base_url="https://api.deepseek.com", model="deepseek-v4-flash", provider="default", api_key=os.environ.get('DEEPSEEK_API_KEY'))
|
|
2136
2154
|
else:
|
|
2137
2155
|
run_repl(
|
|
2138
2156
|
model=args.model,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: mlx-code
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.4
|
|
4
4
|
Summary: Coding Agent for Mac
|
|
5
5
|
Home-page: https://github.com/JosefAlbers/mlx-code
|
|
6
6
|
Author: J Joe
|
|
@@ -35,7 +35,7 @@ It features a multi-provider local server, a terminal-based chat REPL, and a ded
|
|
|
35
35
|
### Features
|
|
36
36
|
|
|
37
37
|
* **Local MLX Inference**: Powered by `mlx-lm` for optimized performance on Apple Silicon. Includes intelligent prompt caching.
|
|
38
|
-
* **Multi-Provider Compatibility**: Seamlessly translates and handles requests formatted for Claude
|
|
38
|
+
* **Multi-Provider Compatibility**: Seamlessly translates and handles requests formatted for **Claude**, **Gemini**, **Codex**, **DeepSeek** and standard OpenAI APIs.
|
|
39
39
|
* **Built-in REPL & Tools**: Comes with `pie`, a fully-featured chat REPL with tool execution and reasoning token support.
|
|
40
40
|
* **TUI Log Viewer**: Includes a Curses-based Terminal UI for filtering, inspecting, and tracking JSON logs in real-time.
|
|
41
41
|
* **Server Mode**: Easily spin up a local server compatible with standard LLM tooling.
|
|
@@ -70,8 +70,11 @@ mc --model mlx-community/Qwen3.5-4B-OptiQ-4bit
|
|
|
70
70
|
# Use DeepSeek V4 Flash API
|
|
71
71
|
me --deepseek
|
|
72
72
|
|
|
73
|
-
# Run the server only
|
|
74
|
-
mc --nocc
|
|
73
|
+
# Run the server only
|
|
74
|
+
mc --nocc
|
|
75
|
+
|
|
76
|
+
# General shell piping and chaining works too
|
|
77
|
+
echo "explain symgraph.py" | mc | cat - PLAN.md | mc
|
|
75
78
|
```
|
|
76
79
|
*(For a full list of mc server arguments, run mc --help)*
|
|
77
80
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|