factorly 0.1.10__py3-none-any.whl

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.
factorly/__init__.py ADDED
@@ -0,0 +1,3 @@
1
+ """Factorly — security and governance layer for AI agent tool access."""
2
+
3
+ __version__ = "0.1.10"
factorly/__main__.py ADDED
@@ -0,0 +1,5 @@
1
+ """Allow running as: python -m factorly"""
2
+
3
+ from factorly.cli import main
4
+
5
+ main()
factorly/cli.py ADDED
@@ -0,0 +1,125 @@
1
+ """Factorly CLI wrapper — downloads and runs the Go binary."""
2
+
3
+ import os
4
+ import platform
5
+ import stat
6
+ import subprocess
7
+ import sys
8
+ import urllib.request
9
+
10
+ from factorly import __version__
11
+
12
+ REPO = "factorly-dev/factorly-cli"
13
+
14
+ PLATFORM_MAP = {
15
+ "Darwin": "darwin",
16
+ "Linux": "linux",
17
+ "Windows": "windows",
18
+ }
19
+
20
+ ARCH_MAP = {
21
+ "x86_64": "amd64",
22
+ "AMD64": "amd64",
23
+ "aarch64": "arm64",
24
+ "arm64": "arm64",
25
+ }
26
+
27
+
28
+ def get_bin_dir():
29
+ """Return the directory where the binary is stored."""
30
+ return os.path.join(os.path.dirname(os.path.abspath(__file__)), "bin")
31
+
32
+
33
+ def get_binary_path():
34
+ """Return the full path to the factorly binary."""
35
+ ext = ".exe" if platform.system() == "Windows" else ""
36
+ return os.path.join(get_bin_dir(), f"factorly{ext}")
37
+
38
+
39
+ def get_binary_name():
40
+ """Return the platform-specific binary name for download."""
41
+ plat = PLATFORM_MAP.get(platform.system())
42
+ arch = ARCH_MAP.get(platform.machine())
43
+
44
+ if not plat:
45
+ print(f"Unsupported platform: {platform.system()}", file=sys.stderr)
46
+ sys.exit(1)
47
+ if not arch:
48
+ print(f"Unsupported architecture: {platform.machine()}", file=sys.stderr)
49
+ sys.exit(1)
50
+
51
+ ext = ".exe" if platform.system() == "Windows" else ""
52
+ return f"factorly-{plat}-{arch}{ext}"
53
+
54
+
55
+ def is_installed():
56
+ """Check if the correct version is already installed."""
57
+ binary = get_binary_path()
58
+ if not os.path.exists(binary):
59
+ return False
60
+ try:
61
+ result = subprocess.run(
62
+ [binary, "version"],
63
+ capture_output=True,
64
+ text=True,
65
+ timeout=5,
66
+ )
67
+ return __version__ in result.stdout
68
+ except Exception:
69
+ return False
70
+
71
+
72
+ def download_binary():
73
+ """Download the factorly binary from GitHub Releases."""
74
+ binary_name = get_binary_name()
75
+ url = f"https://github.com/{REPO}/releases/download/v{__version__}/{binary_name}"
76
+
77
+ print(f"Downloading factorly {__version__} for {platform.system()}/{platform.machine()}...")
78
+ print(f" {url}")
79
+
80
+ bin_dir = get_bin_dir()
81
+ os.makedirs(bin_dir, exist_ok=True)
82
+ binary_path = get_binary_path()
83
+
84
+ try:
85
+ req = urllib.request.Request(url, headers={"User-Agent": "factorly-pip-installer"})
86
+ with urllib.request.urlopen(req) as response:
87
+ data = response.read()
88
+ except urllib.error.HTTPError as e:
89
+ print(f"Download failed: HTTP {e.code}", file=sys.stderr)
90
+ print(f"", file=sys.stderr)
91
+ print(f"Install manually from:", file=sys.stderr)
92
+ print(f" https://github.com/{REPO}/releases/tag/v{__version__}", file=sys.stderr)
93
+ sys.exit(1)
94
+ except Exception as e:
95
+ print(f"Download failed: {e}", file=sys.stderr)
96
+ sys.exit(1)
97
+
98
+ with open(binary_path, "wb") as f:
99
+ f.write(data)
100
+
101
+ # Make executable
102
+ if platform.system() != "Windows":
103
+ st = os.stat(binary_path)
104
+ os.chmod(binary_path, st.st_mode | stat.S_IEXEC | stat.S_IXGRP | stat.S_IXOTH)
105
+
106
+ print(f"Installed factorly to {binary_path}")
107
+
108
+
109
+ def main():
110
+ """Entry point: ensure binary exists, then run it."""
111
+ if not is_installed():
112
+ download_binary()
113
+
114
+ binary = get_binary_path()
115
+ if not os.path.exists(binary):
116
+ print("factorly binary not found after download attempt.", file=sys.stderr)
117
+ print("Run: pip install --force-reinstall factorly", file=sys.stderr)
118
+ sys.exit(127)
119
+
120
+ result = subprocess.run([binary] + sys.argv[1:])
121
+ sys.exit(result.returncode)
122
+
123
+
124
+ if __name__ == "__main__":
125
+ main()
@@ -0,0 +1,88 @@
1
+ Metadata-Version: 2.4
2
+ Name: factorly
3
+ Version: 0.1.10
4
+ Summary: Security and governance layer for AI agent tool access
5
+ License: MIT
6
+ Project-URL: Homepage, https://github.com/factorly-dev/factorly-cli
7
+ Project-URL: Documentation, https://github.com/factorly-dev/factorly-cli/tree/main/docs
8
+ Project-URL: Repository, https://github.com/factorly-dev/factorly-cli
9
+ Classifier: Development Status :: 4 - Beta
10
+ Classifier: License :: OSI Approved :: MIT License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Topic :: Security
13
+ Classifier: Topic :: Software Development :: Libraries
14
+ Classifier: Environment :: Console
15
+ Classifier: Intended Audience :: Developers
16
+ Requires-Python: >=3.8
17
+ Description-Content-Type: text/markdown
18
+
19
+ ```
20
+ ░█▀▀░█▀█░█▀▀░▀█▀░█▀█░█▀▄░█░░█░█
21
+ ░█▀▀░█▀█░█░░░░█░░█░█░█▀▄░█░░░█░
22
+ ░▀░░░▀░▀░▀▀▀░░▀░░▀▀▀░▀░▀░▀▀▀░▀░
23
+ ```
24
+
25
+ # Factorly
26
+
27
+ Your agent calls tools. Factorly holds the keys.
28
+
29
+ A security and governance layer between AI agents and the tools they use. REST APIs, CLI commands, MCP servers — one config, one audit log, one set of rules.
30
+
31
+ ## Install
32
+
33
+ ```bash
34
+ pip install factorly
35
+ ```
36
+
37
+ Or with pipx:
38
+
39
+ ```bash
40
+ pipx install factorly
41
+ ```
42
+
43
+ ## Try It in 10 Seconds
44
+
45
+ ```bash
46
+ # Run any command with compression + logging
47
+ factorly exec -- git status
48
+
49
+ # Wrap any MCP server with zero config
50
+ factorly wrap -- npx @modelcontextprotocol/server-everything
51
+
52
+ # Install a template for a service you use
53
+ factorly tools import templates github
54
+ ```
55
+
56
+ ## Quick Start
57
+
58
+ ```bash
59
+ factorly init # set up a project
60
+ factorly vault set GITHUB_TOKEN ghp_xxx # store a secret
61
+ factorly sync # connect to Claude Code / Cursor
62
+ ```
63
+
64
+ ## What You Get
65
+
66
+ - **Credential isolation** — secrets in encrypted vault, agent never sees them
67
+ - **Governance** — deny, confirm, rate limit, loop detection per tool
68
+ - **Audit log** — every call logged with params, response, and governance outcome
69
+ - **36 templates** — pre-built configs for GitHub, Slack, Stripe, Gmail, Linear, and more
70
+ - **Zero-config proxy** — `factorly wrap` and `factorly exec` add safety instantly
71
+
72
+ ## Supported Platforms
73
+
74
+ | OS | Architecture |
75
+ |----|-------------|
76
+ | Linux | x64 |
77
+ | macOS | x64, arm64 |
78
+ | Windows | x64 |
79
+
80
+ The pip package downloads the pre-built Go binary for your platform on first run.
81
+
82
+ ## Documentation
83
+
84
+ Full docs at [github.com/factorly-dev/factorly-cli](https://github.com/factorly-dev/factorly-cli)
85
+
86
+ ## License
87
+
88
+ MIT
@@ -0,0 +1,8 @@
1
+ factorly/__init__.py,sha256=3oZYrF4YuL6z3Q_TUKZgH2apIrIH2Ve9t6txKyLMslc,99
2
+ factorly/__main__.py,sha256=YFfDhLet5Uh8OTKjQgwtztlB30cHNPs7vRO2MuMfm0A,82
3
+ factorly/cli.py,sha256=WaD50uu8_Z9nCd8Hnjecl70faoertZ8ia7YjSVDbH5c,3549
4
+ factorly-0.1.10.dist-info/METADATA,sha256=uDli3DpI0VQgOQm-xkbX7ew5Hmf-Kr5wVcxILl9a2DI,2632
5
+ factorly-0.1.10.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
6
+ factorly-0.1.10.dist-info/entry_points.txt,sha256=AGZZk7Z42_OlsIt5fihM3cJZklTBmQncPRcGVkxoBgg,47
7
+ factorly-0.1.10.dist-info/top_level.txt,sha256=60AbsBnDPvBtg_YaaprbcZpkskx8xI1UzsJhAxFmPug,9
8
+ factorly-0.1.10.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ factorly = factorly.cli:main
@@ -0,0 +1 @@
1
+ factorly