@oh-my-pi/pi-coding-agent 8.2.1 → 8.2.2

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [8.2.2] - 2026-01-24
6
+
7
+ ### Removed
8
+ - Removed git utility functions (_git, git_status, git_diff, git_log, git_show, git_file_at, git_branch, git_has_changes) from IPython prelude
5
9
  ## [8.2.0] - 2026-01-24
6
10
 
7
11
  ### Added
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oh-my-pi/pi-coding-agent",
3
- "version": "8.2.1",
3
+ "version": "8.2.2",
4
4
  "description": "Coding agent CLI with read, bash, edit, write tools and session management",
5
5
  "type": "module",
6
6
  "ompConfig": {
@@ -75,11 +75,11 @@
75
75
  "test": "bun test"
76
76
  },
77
77
  "dependencies": {
78
- "@oh-my-pi/omp-stats": "8.2.1",
79
- "@oh-my-pi/pi-agent-core": "8.2.1",
80
- "@oh-my-pi/pi-ai": "8.2.1",
81
- "@oh-my-pi/pi-tui": "8.2.1",
82
- "@oh-my-pi/pi-utils": "8.2.1",
78
+ "@oh-my-pi/omp-stats": "8.2.2",
79
+ "@oh-my-pi/pi-agent-core": "8.2.2",
80
+ "@oh-my-pi/pi-ai": "8.2.2",
81
+ "@oh-my-pi/pi-tui": "8.2.2",
82
+ "@oh-my-pi/pi-utils": "8.2.2",
83
83
  "@openai/agents": "^0.4.3",
84
84
  "@sinclair/typebox": "^0.34.46",
85
85
  "ajv": "^8.17.1",
@@ -724,188 +724,6 @@ if "__omp_prelude_loaded__" not in globals():
724
724
  _emit_status("insert_at", path=str(p), line=line_num, lines_inserted=len(new_lines), position=pos)
725
725
  return p
726
726
 
727
- def _git(*args: str, cwd: str | Path | None = None) -> tuple[int, str, str]:
728
- """Run git command, return (returncode, stdout, stderr)."""
729
- result = subprocess.run(
730
- ["git", *args],
731
- cwd=str(cwd) if cwd else None,
732
- capture_output=True,
733
- text=True,
734
- )
735
- return result.returncode, result.stdout, result.stderr
736
-
737
- @_category("Git")
738
- def git_status(*, cwd: str | Path | None = None) -> dict:
739
- """Get structured git status: {branch, staged, modified, untracked, ahead, behind}."""
740
- code, out, err = _git("status", "--porcelain=v2", "--branch", cwd=cwd)
741
- if code != 0:
742
- _emit_status("git_status", error=err.strip())
743
- return {}
744
-
745
- result: dict = {"branch": None, "staged": [], "modified": [], "untracked": [], "ahead": 0, "behind": 0}
746
- for line in out.splitlines():
747
- if line.startswith("# branch.head "):
748
- result["branch"] = line.split(" ", 2)[2]
749
- elif line.startswith("# branch.ab "):
750
- parts = line.split()
751
- for p in parts[2:]:
752
- if p.startswith("+"):
753
- result["ahead"] = int(p[1:])
754
- elif p.startswith("-"):
755
- result["behind"] = int(p[1:])
756
- elif line.startswith("1 ") or line.startswith("2 "):
757
- parts = line.split(" ", 8)
758
- xy = parts[1]
759
- path = parts[-1]
760
- if xy[0] != ".":
761
- result["staged"].append(path)
762
- if xy[1] != ".":
763
- result["modified"].append(path)
764
- elif line.startswith("? "):
765
- result["untracked"].append(line[2:])
766
-
767
- clean = not any([result["staged"], result["modified"], result["untracked"]])
768
- _emit_status("git_status", branch=result["branch"], staged=len(result["staged"]), modified=len(result["modified"]), untracked=len(result["untracked"]), clean=clean, files=result["staged"][:5] + result["modified"][:5])
769
- return result
770
-
771
- @_category("Git")
772
- def git_diff(
773
- *paths: str,
774
- staged: bool = False,
775
- ref: str | None = None,
776
- stat: bool = False,
777
- cwd: str | Path | None = None,
778
- ) -> str:
779
- """Show git diff. staged=True for --cached, ref for commit comparison."""
780
- args = ["diff"]
781
- if stat:
782
- args.append("--stat")
783
- if staged:
784
- args.append("--cached")
785
- if ref:
786
- args.append(ref)
787
- if paths:
788
- args.append("--")
789
- args.extend(paths)
790
- code, out, err = _git(*args, cwd=cwd)
791
- if code != 0:
792
- _emit_status("git_diff", error=err.strip())
793
- return ""
794
- lines_count = len(out.splitlines()) if out else 0
795
- _emit_status("git_diff", staged=staged, ref=ref, lines=lines_count, preview=out[:500])
796
- return out
797
-
798
- @_category("Git")
799
- def git_log(
800
- n: int = 10,
801
- *,
802
- oneline: bool = True,
803
- ref_range: str | None = None,
804
- paths: list[str] | None = None,
805
- cwd: str | Path | None = None,
806
- ) -> list[dict]:
807
- """Get git log as list of {sha, subject, author, date}."""
808
- fmt = "%H%x00%s%x00%an%x00%aI" if not oneline else "%h%x00%s%x00%an%x00%aI"
809
- args = ["log", f"-{n}", f"--format={fmt}"]
810
- if ref_range:
811
- args.append(ref_range)
812
- if paths:
813
- args.append("--")
814
- args.extend(paths)
815
- code, out, err = _git(*args, cwd=cwd)
816
- if code != 0:
817
- _emit_status("git_log", error=err.strip())
818
- return []
819
-
820
- commits = []
821
- for line in out.strip().splitlines():
822
- parts = line.split("\x00")
823
- if len(parts) >= 4:
824
- commits.append({"sha": parts[0], "subject": parts[1], "author": parts[2], "date": parts[3]})
825
-
826
- _emit_status("git_log", commits=len(commits), entries=[{"sha": c["sha"][:8], "subject": c["subject"][:50]} for c in commits[:5]])
827
- return commits
828
-
829
- @_category("Git")
830
- def git_show(ref: str = "HEAD", *, stat: bool = True, cwd: str | Path | None = None) -> dict:
831
- """Show commit details as {sha, subject, author, date, body, files}."""
832
- args = ["show", ref, "--format=%H%x00%s%x00%an%x00%aI%x00%b", "--no-patch"]
833
- code, out, err = _git(*args, cwd=cwd)
834
- if code != 0:
835
- _emit_status("git_show", ref=ref, error=err.strip())
836
- return {}
837
-
838
- parts = out.strip().split("\x00")
839
- result = {
840
- "sha": parts[0] if len(parts) > 0 else "",
841
- "subject": parts[1] if len(parts) > 1 else "",
842
- "author": parts[2] if len(parts) > 2 else "",
843
- "date": parts[3] if len(parts) > 3 else "",
844
- "body": parts[4].strip() if len(parts) > 4 else "",
845
- "files": [],
846
- }
847
-
848
- if stat:
849
- _, stat_out, _ = _git("show", ref, "--stat", "--format=", cwd=cwd)
850
- result["files"] = [l.strip() for l in stat_out.strip().splitlines() if l.strip()]
851
-
852
- _emit_status("git_show", ref=ref, sha=result["sha"][:12], subject=result["subject"][:60], files=len(result["files"]))
853
- return result
854
-
855
- @_category("Git")
856
- def git_file_at(ref: str, path: str, *, lines: tuple[int, int] | None = None, cwd: str | Path | None = None) -> str:
857
- """Get file content at ref. Optional lines=(start, end) for range (1-indexed)."""
858
- code, out, err = _git("show", f"{ref}:{path}", cwd=cwd)
859
- if code != 0:
860
- _emit_status("git_file_at", ref=ref, path=path, error=err.strip())
861
- return ""
862
-
863
- if lines:
864
- all_lines = out.splitlines()
865
- start, end = lines
866
- start = max(1, start)
867
- end = min(len(all_lines), end)
868
- selected = all_lines[start - 1 : end]
869
- out = "\n".join(selected)
870
- _emit_status("git_file_at", ref=ref, path=path, start=start, end=end, lines=len(selected))
871
- return out
872
-
873
- _emit_status("git_file_at", ref=ref, path=path, chars=len(out))
874
- return out
875
-
876
- @_category("Git")
877
- def git_branch(*, cwd: str | Path | None = None) -> dict:
878
- """Get branches: {current, local, remote}."""
879
- code, out, _ = _git("branch", "-a", "--format=%(refname:short)%00%(HEAD)", cwd=cwd)
880
- if code != 0:
881
- _emit_status("git_branch", error="failed to list branches")
882
- return {"current": None, "local": [], "remote": []}
883
-
884
- result: dict = {"current": None, "local": [], "remote": []}
885
- for line in out.strip().splitlines():
886
- parts = line.split("\x00")
887
- name = parts[0]
888
- is_current = len(parts) > 1 and parts[1] == "*"
889
- if is_current:
890
- result["current"] = name
891
- if name.startswith("remotes/") or "/" in name and not name.startswith("feature/"):
892
- result["remote"].append(name)
893
- else:
894
- result["local"].append(name)
895
- if is_current:
896
- result["current"] = name
897
-
898
- _emit_status("git_branch", current=result["current"], local=len(result["local"]), remote=len(result["remote"]), branches=result["local"][:10])
899
- return result
900
-
901
- @_category("Git")
902
- def git_has_changes(*, cwd: str | Path | None = None) -> bool:
903
- """Check if there are uncommitted changes (staged or unstaged)."""
904
- code, out, _ = _git("status", "--porcelain", cwd=cwd)
905
- has_changes = bool(out.strip())
906
- _emit_status("git_has_changes", has_changes=has_changes)
907
- return has_changes
908
-
909
727
  @_category("Agent")
910
728
  def output(
911
729
  *ids: str,