frankcode 0.1.0__tar.gz → 0.1.1__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 (28) hide show
  1. frankcode-0.1.1/.github/workflows/publish.yml +42 -0
  2. frankcode-0.1.1/.github/workflows/test.yml +33 -0
  3. frankcode-0.1.1/.gitignore +74 -0
  4. {frankcode-0.1.0/src/frankcode.egg-info → frankcode-0.1.1}/PKG-INFO +1 -1
  5. {frankcode-0.1.0 → frankcode-0.1.1}/pyproject.toml +5 -2
  6. {frankcode-0.1.0 → frankcode-0.1.1/src/frankcode.egg-info}/PKG-INFO +1 -1
  7. {frankcode-0.1.0 → frankcode-0.1.1}/src/frankcode.egg-info/SOURCES.txt +8 -1
  8. frankcode-0.1.1/tests/conftest.py +0 -0
  9. frankcode-0.1.1/tests/unit/test_environment.py +27 -0
  10. frankcode-0.1.1/tests/unit/test_setup.py +27 -0
  11. frankcode-0.1.1/tests/unit/test_watchdog.py +19 -0
  12. {frankcode-0.1.0 → frankcode-0.1.1}/LICENSE +0 -0
  13. {frankcode-0.1.0 → frankcode-0.1.1}/README.md +0 -0
  14. {frankcode-0.1.0 → frankcode-0.1.1}/setup.cfg +0 -0
  15. {frankcode-0.1.0 → frankcode-0.1.1}/src/frankcode/__init__.py +0 -0
  16. {frankcode-0.1.0 → frankcode-0.1.1}/src/frankcode/cli.py +0 -0
  17. {frankcode-0.1.0 → frankcode-0.1.1}/src/frankcode/configs/oh-my-opencode-slim.json +0 -0
  18. {frankcode-0.1.0 → frankcode-0.1.1}/src/frankcode/configs/opencode-verify.json +0 -0
  19. {frankcode-0.1.0 → frankcode-0.1.1}/src/frankcode/configs/opencode.json +0 -0
  20. {frankcode-0.1.0 → frankcode-0.1.1}/src/frankcode/configs/prompt-rules.json +0 -0
  21. {frankcode-0.1.0 → frankcode-0.1.1}/src/frankcode/environment.py +0 -0
  22. {frankcode-0.1.0 → frankcode-0.1.1}/src/frankcode/orchestrator.py +0 -0
  23. {frankcode-0.1.0 → frankcode-0.1.1}/src/frankcode/setup.py +0 -0
  24. {frankcode-0.1.0 → frankcode-0.1.1}/src/frankcode/utils.py +0 -0
  25. {frankcode-0.1.0 → frankcode-0.1.1}/src/frankcode.egg-info/dependency_links.txt +0 -0
  26. {frankcode-0.1.0 → frankcode-0.1.1}/src/frankcode.egg-info/entry_points.txt +0 -0
  27. {frankcode-0.1.0 → frankcode-0.1.1}/src/frankcode.egg-info/requires.txt +0 -0
  28. {frankcode-0.1.0 → frankcode-0.1.1}/src/frankcode.egg-info/top_level.txt +0 -0
@@ -0,0 +1,42 @@
1
+ name: Publish to PyPI and GitHub Releases
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*' # Triggers when a new tag like v0.1.0 is pushed
7
+
8
+ jobs:
9
+ build-and-publish:
10
+ name: Build and publish
11
+ runs-on: ubuntu-latest
12
+
13
+ permissions:
14
+ id-token: write # Mandatory for PyPI Trusted Publishing
15
+ contents: write # Mandatory for creating GitHub Releases
16
+
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+ with:
20
+ fetch-depth: 0 # Needed for setuptools_scm to resolve version correctly
21
+
22
+ - name: Set up Python
23
+ uses: actions/setup-python@v5
24
+ with:
25
+ python-version: "3.12"
26
+
27
+ - name: Install build tool
28
+ run: python -m pip install --upgrade pip build
29
+
30
+ - name: Build package
31
+ run: python -m build
32
+
33
+ - name: Create GitHub Release
34
+ uses: softprops/action-gh-release@v2
35
+ with:
36
+ files: dist/*
37
+ generate_release_notes: true
38
+
39
+ - name: Publish package distributions to PyPI
40
+ uses: pypa/gh-action-pypi-publish@release/v1
41
+ # Note: PyPI publish will fail if you haven't set up Trusted Publishing on PyPI yet.
42
+ # If it fails, the GitHub Release will still be created!
@@ -0,0 +1,33 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [ "master", "main" ]
6
+ pull_request:
7
+ branches: [ "master", "main" ]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ["3.10", "3.11", "3.12"]
15
+
16
+ steps:
17
+ - uses: actions/checkout@v4
18
+
19
+ - name: Set up Python ${{ matrix.python-version }}
20
+ uses: actions/setup-python@v5
21
+ with:
22
+ python-version: ${{ matrix.python-version }}
23
+ cache: 'pip'
24
+
25
+ - name: Install dependencies
26
+ run: |
27
+ python -m pip install --upgrade pip
28
+ pip install pytest pytest-asyncio
29
+ pip install -e .
30
+
31
+ - name: Run tests
32
+ run: |
33
+ pytest
@@ -0,0 +1,74 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ # Usually these files are written by a python script from a template
31
+ # before PyInstaller builds the exe, so as to inject date/other infos into it.
32
+ *.manifest
33
+ *.spec
34
+
35
+ # Installer logs
36
+ pip-log.txt
37
+ pip-delete-this-directory.txt
38
+
39
+ # Unit test / coverage reports
40
+ htmlcov/
41
+ .tox/
42
+ .nox/
43
+ .coverage
44
+ .coverage.*
45
+ .cache
46
+ nosetests.xml
47
+ coverage.xml
48
+ *.cover
49
+ *.pycover
50
+ .hypothesis/
51
+ .pytest_cache/
52
+ cover/
53
+
54
+ # Environments
55
+ .env
56
+ .venv
57
+ env/
58
+ venv/
59
+ ENV/
60
+ env.bak/
61
+ venv.bak/
62
+
63
+ # opencode specific and frankcode runtime
64
+ .frankcode/
65
+ .opencode/
66
+ logs/
67
+ quarantine/
68
+
69
+ # Editors
70
+ .vscode/
71
+ .idea/
72
+ *.swp
73
+ *.swo
74
+ .DS_Store
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: frankcode
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: Advanced multi-agent orchestrator for OpenCode
5
5
  Author: joeyism
6
6
  License: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "frankcode"
3
- version = "0.1.0"
3
+ dynamic = ["version"]
4
4
  description = "Advanced multi-agent orchestrator for OpenCode"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -32,9 +32,12 @@ Issues = "https://github.com/joeyism/frankcode/issues"
32
32
  frankcode = "frankcode.cli:app"
33
33
 
34
34
  [build-system]
35
- requires = ["setuptools>=61.0"]
35
+ requires = ["setuptools>=61.0", "setuptools_scm>=8.0"]
36
36
  build-backend = "setuptools.build_meta"
37
37
 
38
+ [tool.setuptools_scm]
39
+
40
+
38
41
  [tool.setuptools.package-data]
39
42
  frankcode = ["configs/*.json"]
40
43
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: frankcode
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: Advanced multi-agent orchestrator for OpenCode
5
5
  Author: joeyism
6
6
  License: MIT
@@ -1,6 +1,9 @@
1
+ .gitignore
1
2
  LICENSE
2
3
  README.md
3
4
  pyproject.toml
5
+ .github/workflows/publish.yml
6
+ .github/workflows/test.yml
4
7
  src/frankcode/__init__.py
5
8
  src/frankcode/cli.py
6
9
  src/frankcode/environment.py
@@ -16,4 +19,8 @@ src/frankcode.egg-info/top_level.txt
16
19
  src/frankcode/configs/oh-my-opencode-slim.json
17
20
  src/frankcode/configs/opencode-verify.json
18
21
  src/frankcode/configs/opencode.json
19
- src/frankcode/configs/prompt-rules.json
22
+ src/frankcode/configs/prompt-rules.json
23
+ tests/conftest.py
24
+ tests/unit/test_environment.py
25
+ tests/unit/test_setup.py
26
+ tests/unit/test_watchdog.py
File without changes
@@ -0,0 +1,27 @@
1
+ import pytest
2
+ import asyncio
3
+ from frankcode.environment import LocalEnvironment
4
+
5
+ @pytest.mark.asyncio
6
+ async def test_local_environment_exec_success():
7
+ env = LocalEnvironment()
8
+ result = await env.exec("echo 'hello world'")
9
+ assert result.stdout == "hello world"
10
+ assert result.exit_code == 0
11
+
12
+ @pytest.mark.asyncio
13
+ async def test_local_environment_exec_failure():
14
+ env = LocalEnvironment()
15
+ result = await env.exec("ls /non_existent_directory_for_frankcode_test")
16
+ assert result.exit_code != 0
17
+ assert "No such file or directory" in result.stderr
18
+
19
+ @pytest.mark.asyncio
20
+ async def test_local_environment_cwd(tmp_path):
21
+ env = LocalEnvironment()
22
+ # Create a file in a temp dir
23
+ test_file = tmp_path / "test.txt"
24
+ test_file.write_text("content")
25
+
26
+ result = await env.exec("ls", cwd=str(tmp_path))
27
+ assert "test.txt" in result.stdout
@@ -0,0 +1,27 @@
1
+ import pytest
2
+ import sys
3
+ from unittest.mock import AsyncMock, patch
4
+ from frankcode.setup import FrankSetup
5
+
6
+ @pytest.mark.asyncio
7
+ async def test_frank_setup_scaffolding(tmp_path):
8
+ # Mock environment to avoid real FS/network calls
9
+ env = AsyncMock()
10
+ setup = FrankSetup(env, str(tmp_path))
11
+
12
+ await setup.ensure_directories()
13
+
14
+ assert (tmp_path / ".frankcode").exists()
15
+ assert (tmp_path / ".frankcode" / "logs").exists()
16
+ assert (tmp_path / ".frankcode" / "quarantine").exists()
17
+
18
+ @pytest.mark.asyncio
19
+ async def test_frank_setup_os_detection():
20
+ env = AsyncMock()
21
+ setup = FrankSetup(env, "/tmp")
22
+
23
+ with patch("sys.platform", "linux"):
24
+ assert setup.get_os() == "linux"
25
+
26
+ with patch("sys.platform", "darwin"):
27
+ assert setup.get_os() == "macos"
@@ -0,0 +1,19 @@
1
+ import pytest
2
+ import hashlib
3
+ from frankcode.utils import check_error_loop
4
+
5
+ def test_check_error_loop_detection():
6
+ # Same error multiple times
7
+ error_text = "AssertionError: 1 != 2"
8
+ history = [hashlib.md5(error_text.encode()).hexdigest()] * 3
9
+
10
+ # Should detect loop on 3rd identical hash
11
+ assert check_error_loop(history, threshold=3) is True
12
+
13
+ def test_check_error_loop_no_loop():
14
+ history = [
15
+ hashlib.md5("Error A".encode()).hexdigest(),
16
+ hashlib.md5("Error B".encode()).hexdigest(),
17
+ hashlib.md5("Error A".encode()).hexdigest()
18
+ ]
19
+ assert check_error_loop(history, threshold=3) is False
File without changes
File without changes
File without changes