alpiecode 6.1.0__tar.gz → 6.2.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 (41) hide show
  1. {alpiecode-6.1.0 → alpiecode-6.2.0}/PKG-INFO +1 -1
  2. {alpiecode-6.1.0 → alpiecode-6.2.0}/pyproject.toml +1 -1
  3. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/alpiecode.egg-info/PKG-INFO +1 -1
  4. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/agent.py +93 -54
  5. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/cli.py +0 -3
  6. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/guardian.py +5 -2
  7. {alpiecode-6.1.0 → alpiecode-6.2.0}/README.md +0 -0
  8. {alpiecode-6.1.0 → alpiecode-6.2.0}/setup.cfg +0 -0
  9. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/alpiecode/__init__.py +0 -0
  10. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/alpiecode.egg-info/SOURCES.txt +0 -0
  11. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/alpiecode.egg-info/dependency_links.txt +0 -0
  12. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/alpiecode.egg-info/entry_points.txt +0 -0
  13. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/alpiecode.egg-info/requires.txt +0 -0
  14. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/alpiecode.egg-info/top_level.txt +0 -0
  15. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/__init__.py +0 -0
  16. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/backends/__init__.py +0 -0
  17. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/backends/base.py +0 -0
  18. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/backends/local_backend.py +0 -0
  19. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/backends/openai_backend.py +0 -0
  20. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/cache.py +0 -0
  21. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/client.py +0 -0
  22. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/compaction.py +0 -0
  23. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/config.py +0 -0
  24. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/context.py +0 -0
  25. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/discovery.py +0 -0
  26. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/doctor.py +0 -0
  27. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/executor.py +0 -0
  28. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/extension/alpiecode.vsix +0 -0
  29. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/github.py +0 -0
  30. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/ipython_ext.py +0 -0
  31. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/local_model.py +0 -0
  32. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/media.py +0 -0
  33. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/memory.py +0 -0
  34. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/orchestrator.py +0 -0
  35. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/progress.py +0 -0
  36. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/prompt.py +0 -0
  37. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/server.py +0 -0
  38. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/session.py +0 -0
  39. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/tools.py +0 -0
  40. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/updater.py +0 -0
  41. {alpiecode-6.1.0 → alpiecode-6.2.0}/src/codeagent/vscode_installer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alpiecode
3
- Version: 6.1.0
3
+ Version: 6.2.0
4
4
  Summary: AlpieCode — Autonomous AI Coding Agent CLI powered by local 169Pi GGUF VLM
5
5
  Requires-Python: >=3.9
6
6
  Requires-Dist: huggingface_hub>=0.20.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "alpiecode"
7
- version = "6.1.0"
7
+ version = "6.2.0"
8
8
  description = "AlpieCode — Autonomous AI Coding Agent CLI powered by local 169Pi GGUF VLM"
9
9
  requires-python = ">=3.9"
10
10
  dependencies = [
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: alpiecode
3
- Version: 6.1.0
3
+ Version: 6.2.0
4
4
  Summary: AlpieCode — Autonomous AI Coding Agent CLI powered by local 169Pi GGUF VLM
5
5
  Requires-Python: >=3.9
6
6
  Requires-Dist: huggingface_hub>=0.20.0
@@ -65,45 +65,88 @@ except ImportError:
65
65
  def _print_reasoning(reasoning: str):
66
66
  if not reasoning or not reasoning.strip():
67
67
  return
68
+ clean = reasoning.strip()
68
69
  if HAS_RICH:
69
- text = Text(reasoning.strip(), style="dim italic")
70
- console.print(Panel(text, title="💭 Thinking", border_style="dim blue", padding=(0, 1)))
70
+ console.print(Text(f"💭 {clean}", style="dim italic"))
71
71
  else:
72
- console.print(f"\n💭 Thinking: {reasoning.strip()}")
72
+ console.print(f"💭 {clean}")
73
+
74
+
75
+ def _format_tool_summary(name: str, args: dict) -> str:
76
+ if not isinstance(args, dict):
77
+ return ""
78
+ if name == "bash":
79
+ cmd = args.get("command", "").strip()
80
+ return f"$ {cmd[:80]}..." if len(cmd) > 80 else f"$ {cmd}"
81
+ elif name in ("write_file", "edit_file", "read_file"):
82
+ path = args.get("path", "")
83
+ extra = ""
84
+ if name == "write_file" and "content" in args:
85
+ lines = len(str(args["content"]).splitlines())
86
+ extra = f" ({lines} lines)"
87
+ return f"{path}{extra}"
88
+ elif name == "list_files":
89
+ return args.get("path", ".")
90
+ elif name in ("search", "web_search"):
91
+ return f"'{args.get('query', '')}'"
92
+ elif name == "fetch_web_page":
93
+ return args.get("url", "")
94
+ else:
95
+ parts = [f"{k}={repr(v)[:30]}" for k, v in args.items() if k != "content"]
96
+ return " ".join(parts)
73
97
 
74
98
 
75
99
  def _print_tool_call(turn: int, name: str, args: dict):
76
- display_args = {}
77
- for k, v in args.items():
78
- if isinstance(v, str) and len(v) > 200:
79
- display_args[k] = v[:200] + "..."
80
- else:
81
- display_args[k] = v
100
+ summary = _format_tool_summary(name, args)
82
101
  if HAS_RICH:
83
- args_str = json.dumps(display_args, indent=2)
84
- console.print(f"\n🔧 [bold cyan]Tool:[/bold cyan] [bold]{name}[/bold]", highlight=False)
85
- console.print(Text(f" {args_str}", style="cyan"))
102
+ console.print(f"\n⏺ [bold cyan]{name}[/bold cyan] [white]{summary}[/white]")
86
103
  else:
87
- console.print(f"\n🔧 Tool: {name}({display_args})")
104
+ console.print(f"\n {name} {summary}")
88
105
 
89
106
 
90
107
  def _print_tool_result(result: str):
91
- truncated = result[:1500] + ("..." if len(result) > 1500 else "")
108
+ clean = result.strip()
109
+ if '"exit_code"' in clean:
110
+ try:
111
+ data = json.loads(clean.split("\n", 1)[-1] if clean.startswith("⚠️") else clean)
112
+ out = data.get("stdout", "").strip()
113
+ err = data.get("stderr", "").strip()
114
+ code = data.get("exit_code", 0)
115
+ if code == 0:
116
+ clean = out if out else "success"
117
+ else:
118
+ clean = f"exit {code}: {err}" if err else f"exit {code}"
119
+ except Exception:
120
+ pass
121
+
122
+ lines = clean.splitlines()
123
+ if len(lines) > 8:
124
+ display = "\n".join(lines[:6]) + f"\n ... ({len(lines)-6} lines omitted)"
125
+ else:
126
+ display = clean[:500] + ("..." if len(clean) > 500 else "")
127
+
92
128
  if HAS_RICH:
93
- console.print(Text(f" {truncated}", style="green"))
129
+ style = "dim green" if not ("exit 1" in clean or "error:" in clean.lower()[:30]) else "dim red"
130
+ console.print(Text(f" └ {display}", style=style))
94
131
  else:
95
- console.print(f" {truncated}")
132
+ console.print(f" {display}")
96
133
 
97
134
 
98
135
  def _print_assistant_message(content: str):
136
+ if not content or not content.strip():
137
+ return
138
+ text = content.strip()
139
+ if text.upper().startswith("DONE:"):
140
+ text = text[5:].strip()
99
141
  if HAS_RICH:
100
142
  try:
101
- md = Markdown(content)
102
- console.print(Panel(md, title="🤖 Assistant", border_style="green", padding=(0, 1)))
143
+ console.print()
144
+ console.print(Markdown(text))
103
145
  except Exception:
104
- console.print(Panel(Text(content), title="🤖 Assistant", border_style="green", padding=(0, 1)))
146
+ console.print()
147
+ console.print(text)
105
148
  else:
106
- console.print(f"\n🤖 Assistant: {content}")
149
+ print(f"\n{text}")
107
150
 
108
151
 
109
152
  # ── Git helpers ───────────────────────────────────────────────────────
@@ -227,9 +270,27 @@ def run_agent(
227
270
 
228
271
  elif event.type == "start" and verbose:
229
272
  data = event.data
230
- if HAS_RICH:
231
- console.rule("[bold blue]Agent Started[/bold blue]")
232
- console.print(Text(f"📋 Task: {task.splitlines()[0]}", style="bold"))
273
+ if debug:
274
+ if HAS_RICH:
275
+ console.rule("[bold blue]Agent Started (Debug)[/bold blue]")
276
+ console.print(Text(f"📋 Task: {task.splitlines()[0]}", style="bold"))
277
+ console.print(f"📂 Workdir: {workdir}", style="dim")
278
+ mode_str = "[bold green]ONLINE[/bold green]" if not data["is_offline"] else "[bold yellow]OFFLINE[/bold yellow]"
279
+ console.print(f"🌐 Mode: {mode_str}", style="dim")
280
+ comp = data.get("complexity", "low")
281
+ comp_label = {"qa": "Q&A (instant)", "low": "Low (fast)", "medium": "Medium (balanced)", "high": "High (thorough)"}.get(comp, comp)
282
+ console.print(f"⚡ Complexity: {comp_label}", style="dim")
283
+ if last_discovery:
284
+ console.print(f"🔍 Discovery: {last_discovery.get('intent', 'create')} on {last_discovery.get('project_type', 'empty')} project", style="dim")
285
+ else:
286
+ print(f"[Start] task={task.splitlines()[0]}, mode={'offline' if data['is_offline'] else 'online'}")
287
+ else:
288
+ # Clean, professional presentation like Claude Code / Codex
289
+ if data.get("is_offline"):
290
+ if HAS_RICH:
291
+ console.print("[dim yellow]⚡ Offline mode[/dim yellow]")
292
+ else:
293
+ print("⚡ Offline mode")
233
294
  if github_repo:
234
295
  console.print(f"🐙 GitHub Repo: {github_repo}", style="cyan")
235
296
  if image_path:
@@ -238,36 +299,17 @@ def run_agent(
238
299
  console.print(f"🎬 Video: {video_path}", style="cyan")
239
300
  if url:
240
301
  console.print(f"📺 URL: {url}", style="cyan")
241
- console.print(f"📂 Workdir: {workdir}", style="dim")
242
- if not data["is_offline"]:
243
- console.print(f"🌐 Mode: [bold green]ONLINE[/bold green]", style="dim")
244
- else:
245
- console.print(f"🧠 Mode: [bold yellow]OFFLINE[/bold yellow]", style="dim")
246
- comp = data.get("complexity", "low")
247
- comp_label = {"qa": "Q&A (instant)", "low": "Low (fast)", "medium": "Medium (balanced)", "high": "High (thorough)"}.get(comp, comp)
248
- comp_color = {"qa": "cyan", "low": "green", "medium": "yellow", "high": "red"}.get(comp, "white")
249
- console.print(f"⚡ Complexity: [bold {comp_color}]{comp_label}[/bold {comp_color}]", style="dim")
250
- if last_discovery:
251
- intent_str = last_discovery.get('intent', 'create').title()
252
- proj_str = last_discovery.get('project_type', 'empty')
253
- console.print(f"🔍 Discovery: {intent_str} on {proj_str} project ({last_discovery.get('shell', 'bash')})", style="dim")
254
- if cfg.enable_thinking:
255
- console.print(f"🧠 Reasoning: [bold green]ON[/bold green]", style="dim")
256
- else:
257
- console.rule("Agent Started")
258
- console.print(f"📋 Task: {task.splitlines()[0]}")
259
- console.print(f"📂 Workdir: {workdir}")
260
302
 
261
303
  elif event.type == "adaptive_mode" and verbose and HAS_RICH:
262
304
  console.print("⚡ [dim]Adaptive mode: simple task detected, skipping deep reasoning for speed[/dim]")
263
305
 
264
306
  elif event.type == "turn_start":
265
307
  current_turn = event.data["turn"]
266
- if verbose:
308
+ if debug:
267
309
  if HAS_RICH:
268
- console.rule(f"[bold]Turn {current_turn}[/bold]", style="blue")
310
+ console.print(f"[dim]── Step {current_turn} ──[/dim]")
269
311
  else:
270
- console.rule(f"Turn {current_turn}")
312
+ print(f"── Step {current_turn} ──")
271
313
 
272
314
  elif event.type == "compaction" and verbose:
273
315
  console.print("🗜️ Compacting context (approaching token limit)...", style="yellow")
@@ -338,13 +380,10 @@ def run_agent(
338
380
  print(f"\n🛑 Safety ceiling ({event.data['ceiling']}) reached.")
339
381
 
340
382
  elif event.type == "done":
341
- summary = event.data["summary"]
383
+ summary = event.data.get("summary", "")
342
384
  _checkpoint(workdir, "checkpoint: done")
343
- if verbose and HAS_RICH:
344
- if "DONE" in summary.upper():
345
- console.rule("[bold green]✅ Task Complete[/bold green]")
346
- else:
347
- console.rule("[bold yellow]💬 Agent Replied[/bold yellow]")
385
+ if debug and HAS_RICH:
386
+ console.rule("[bold green]✅ Complete[/bold green]")
348
387
 
349
388
  elif event.type == "max_turns_reached" and verbose:
350
389
  progress = event.data.get("progress", {})
@@ -410,11 +449,11 @@ def run_chat(workdir: Path, cfg: Config, verbose: bool = True) -> None:
410
449
  break
411
450
 
412
451
  for event in orchestrator.run_task(session, user_input, cfg):
413
- if event.type == "turn_start" and verbose:
452
+ if event.type == "turn_start" and debug:
414
453
  if HAS_RICH:
415
- console.rule(f"[bold]Turn {event.data['turn']}[/bold]", style="blue")
454
+ console.print(f"[dim]── Step {event.data['turn']} ──[/dim]")
416
455
  else:
417
- console.rule(f"Turn {event.data['turn']}")
456
+ print(f"── Step {event.data['turn']} ──")
418
457
 
419
458
  elif event.type == "thinking" and verbose:
420
459
  _print_reasoning(event.data["content"])
@@ -162,7 +162,6 @@ def main():
162
162
  if args.command == "run":
163
163
  if args.max_turns:
164
164
  cfg.max_turns = args.max_turns
165
- _show_banner()
166
165
  from .agent import run_agent
167
166
  run_agent(
168
167
  args.task, Path(args.workdir), cfg,
@@ -182,7 +181,6 @@ def main():
182
181
  run_chat(Path(args.workdir), cfg, verbose=not args.quiet)
183
182
 
184
183
  elif args.command == "plan":
185
- _show_banner()
186
184
  plan_task = (
187
185
  f"PLANNING ONLY — Do NOT make any file edits. "
188
186
  f"Analyze the codebase and create a detailed implementation plan for the following task. "
@@ -206,7 +204,6 @@ def main():
206
204
  sys.exit(run_doctor())
207
205
 
208
206
  elif args.command == "explain":
209
- _show_banner()
210
207
  target = args.target
211
208
  target_path = Path(args.workdir) / target if not Path(target).is_absolute() else Path(target)
212
209
  if target_path.exists() and target_path.is_file():
@@ -48,6 +48,8 @@ SAFE_PREFIXES = [
48
48
  "python -m pytest", "python3 -m pytest", "pytest", "npm test",
49
49
  "npm run test", "make test", "cargo test", "go test",
50
50
  "python -c", "python3 -c", "node -e",
51
+ "python3 ", "python ", "node ", "bun ", "deno ", "cargo ", "go ",
52
+ "make", "cmake", "gcc", "g++", "clang", "clang++", "./",
51
53
  "tree", "sort", "uniq", "cut", "awk", "sed -n", "diff",
52
54
  "env", "printenv", "set",
53
55
  "type", "command -v",
@@ -138,8 +140,9 @@ def gate_command(command: str, auto_approve: bool = False) -> bool:
138
140
 
139
141
  if risk == RiskLevel.WARNING:
140
142
  if auto_approve:
141
- if HAS_RICH:
142
- console.print(Text(f" ⚠️ {reason}", style="yellow"))
143
+ if "Unknown command" not in reason:
144
+ if HAS_RICH:
145
+ console.print(Text(f" ⚠️ {reason}", style="yellow"))
143
146
  return True
144
147
  # In interactive mode, show warning but proceed
145
148
  if HAS_RICH:
File without changes
File without changes