agentsecure 0.1.4__tar.gz → 0.1.6__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.
- {agentsecure-0.1.4/agentsecure.egg-info → agentsecure-0.1.6}/PKG-INFO +27 -6
- {agentsecure-0.1.4 → agentsecure-0.1.6}/README.md +26 -5
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/__init__.py +1 -1
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/cli/main.py +40 -6
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/agentsecure_md.py +1 -1
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/gateway/proxy.py +7 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6/agentsecure.egg-info}/PKG-INFO +27 -6
- {agentsecure-0.1.4 → agentsecure-0.1.6}/setup.cfg +1 -1
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_cli.py +14 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/LICENSE +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/NOTICE +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/__main__.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/api/__init__.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/api/server.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/api/services.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/cli/__init__.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/cli/common.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/cli/demo.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/cli/policy.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/cli/project.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/cli/proxy.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/cli/receipts.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/cli/secrets.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/cli/settings.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/client/__init__.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/client/wrappers.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/cloud.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/config/__init__.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/config/default_agentsecure.json +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/__init__.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/capabilities.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/command_metadata.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/config.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/config_profiles.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/container.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/key_service.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/models.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/policy_mutation.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/policy_ports.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/policy_response.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/policy_validation.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/product.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/provider_proxy.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/core/time.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/crypto/__init__.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/crypto/cipher.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/crypto/key_provider.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/daemon/__init__.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/daemon/commands.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/daemon/policies.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/daemon/sessions.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/daemon/supervisor.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/discovery/__init__.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/discovery/dotenv_scanner.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/discovery/env_scanner.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/discovery/patterns.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/discovery/scanner.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/discovery/suggestions.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/gateway/__init__.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/guard/__init__.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/guard/command.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/guard/network.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/guard/sanitizer.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/guard/wrappers.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/implementations/__init__.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/implementations/audit.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/implementations/encrypted_secret_store.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/implementations/grant_store.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/implementations/local_secret_store.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/implementations/policy.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/implementations/secret_store_factory.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/implementations/secrets.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/interfaces/__init__.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/interfaces/audit.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/interfaces/grants.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/interfaces/key_store.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/interfaces/policy.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/interfaces/secrets.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/workspace/__init__.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/workspace/apply.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/workspace/diff.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/workspace/materializer.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/workspace/rewriter.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/workspace/strategies.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure.egg-info/SOURCES.txt +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure.egg-info/dependency_links.txt +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure.egg-info/entry_points.txt +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure.egg-info/top_level.txt +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/pyproject.toml +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/setup.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_agentsecure_md.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_audit.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_cli_demo.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_cli_policy.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_cli_proxy.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_config_validation.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_diff.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_discovery.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_encrypted_secret_store.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_env_policy.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_env_policy_contract.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_gateway_credentials.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_guard.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_guard_network.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_key_service.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_policy.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_policy_mutation.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_product.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_provider_proxy.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_secret_scan.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_secrets.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_version.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_workspace.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_workspace_apply.py +0 -0
- {agentsecure-0.1.4 → agentsecure-0.1.6}/tests/test_wrappers.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentsecure
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.6
|
|
4
4
|
Summary: Local-first security runtime for AI coding agents
|
|
5
5
|
Home-page: https://github.com/ShellFrameAI/agentsecure-community
|
|
6
6
|
Author: ShellFrame AI
|
|
@@ -41,11 +41,22 @@ The community release is intentionally scoped to local CLI, local command guard,
|
|
|
41
41
|
## Install
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
|
-
python3 -m pip install agentsecure
|
|
44
|
+
python3 -m pip install --upgrade agentsecure
|
|
45
|
+
python3 -m agentsecure demo
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`python3 -m agentsecure` works even when `pip` installs the `agentsecure`
|
|
49
|
+
executable into a user script directory that is not on your `PATH`. If you want
|
|
50
|
+
the shorter `agentsecure` command, add Python's user script directory to your
|
|
51
|
+
shell path:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
export PATH="$(python3 -m site --user-base)/bin:$PATH"
|
|
45
55
|
agentsecure demo
|
|
46
56
|
```
|
|
47
57
|
|
|
48
|
-
|
|
58
|
+
You do not need a virtual environment to run AgentSecure. Use one only if you
|
|
59
|
+
want the install isolated to this project:
|
|
49
60
|
|
|
50
61
|
```bash
|
|
51
62
|
python3 -m venv .venv
|
|
@@ -55,6 +66,12 @@ python -m pip install agentsecure
|
|
|
55
66
|
agentsecure demo
|
|
56
67
|
```
|
|
57
68
|
|
|
69
|
+
Then run your agent:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
python3 -m agentsecure run claude
|
|
73
|
+
```
|
|
74
|
+
|
|
58
75
|
## What The Demo Shows
|
|
59
76
|
|
|
60
77
|
The built-in demo creates a temporary local project with fake secrets, applies a small sample policy, simulates a command reading `.env`, and prints what the agent would see:
|
|
@@ -217,11 +234,15 @@ agentsecure receipts --proxy
|
|
|
217
234
|
Run an agent or command through local command guard:
|
|
218
235
|
|
|
219
236
|
```bash
|
|
220
|
-
agentsecure run --protect-all -- codex
|
|
221
|
-
agentsecure run --protect-all -- claude
|
|
222
|
-
agentsecure run --protect-all -- python3 -c 'import subprocess; print(subprocess.check_output(["cat", ".env"]).decode())'
|
|
237
|
+
python3 -m agentsecure run --protect-all -- codex
|
|
238
|
+
python3 -m agentsecure run --protect-all -- claude
|
|
239
|
+
python3 -m agentsecure run --protect-all -- python3 -c 'import subprocess; print(subprocess.check_output(["cat", ".env"]).decode())'
|
|
223
240
|
```
|
|
224
241
|
|
|
242
|
+
Bare interactive agent launches keep the terminal attached so tools such as
|
|
243
|
+
Claude Code can open normally. Non-interactive commands are still output
|
|
244
|
+
sanitized by AgentSecure.
|
|
245
|
+
|
|
225
246
|
Use workspace copy mode when you want review-before-apply:
|
|
226
247
|
|
|
227
248
|
```bash
|
|
@@ -15,11 +15,22 @@ The community release is intentionally scoped to local CLI, local command guard,
|
|
|
15
15
|
## Install
|
|
16
16
|
|
|
17
17
|
```bash
|
|
18
|
-
python3 -m pip install agentsecure
|
|
18
|
+
python3 -m pip install --upgrade agentsecure
|
|
19
|
+
python3 -m agentsecure demo
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
`python3 -m agentsecure` works even when `pip` installs the `agentsecure`
|
|
23
|
+
executable into a user script directory that is not on your `PATH`. If you want
|
|
24
|
+
the shorter `agentsecure` command, add Python's user script directory to your
|
|
25
|
+
shell path:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
export PATH="$(python3 -m site --user-base)/bin:$PATH"
|
|
19
29
|
agentsecure demo
|
|
20
30
|
```
|
|
21
31
|
|
|
22
|
-
|
|
32
|
+
You do not need a virtual environment to run AgentSecure. Use one only if you
|
|
33
|
+
want the install isolated to this project:
|
|
23
34
|
|
|
24
35
|
```bash
|
|
25
36
|
python3 -m venv .venv
|
|
@@ -29,6 +40,12 @@ python -m pip install agentsecure
|
|
|
29
40
|
agentsecure demo
|
|
30
41
|
```
|
|
31
42
|
|
|
43
|
+
Then run your agent:
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
python3 -m agentsecure run claude
|
|
47
|
+
```
|
|
48
|
+
|
|
32
49
|
## What The Demo Shows
|
|
33
50
|
|
|
34
51
|
The built-in demo creates a temporary local project with fake secrets, applies a small sample policy, simulates a command reading `.env`, and prints what the agent would see:
|
|
@@ -191,11 +208,15 @@ agentsecure receipts --proxy
|
|
|
191
208
|
Run an agent or command through local command guard:
|
|
192
209
|
|
|
193
210
|
```bash
|
|
194
|
-
agentsecure run --protect-all -- codex
|
|
195
|
-
agentsecure run --protect-all -- claude
|
|
196
|
-
agentsecure run --protect-all -- python3 -c 'import subprocess; print(subprocess.check_output(["cat", ".env"]).decode())'
|
|
211
|
+
python3 -m agentsecure run --protect-all -- codex
|
|
212
|
+
python3 -m agentsecure run --protect-all -- claude
|
|
213
|
+
python3 -m agentsecure run --protect-all -- python3 -c 'import subprocess; print(subprocess.check_output(["cat", ".env"]).decode())'
|
|
197
214
|
```
|
|
198
215
|
|
|
216
|
+
Bare interactive agent launches keep the terminal attached so tools such as
|
|
217
|
+
Claude Code can open normally. Non-interactive commands are still output
|
|
218
|
+
sanitized by AgentSecure.
|
|
219
|
+
|
|
199
220
|
Use workspace copy mode when you want review-before-apply:
|
|
200
221
|
|
|
201
222
|
```bash
|
|
@@ -85,6 +85,19 @@ from agentsecure.workspace.diff import WorkspaceDiff
|
|
|
85
85
|
from agentsecure.workspace.materializer import WorkspaceMaterializer, make_tree_writable
|
|
86
86
|
|
|
87
87
|
|
|
88
|
+
INTERACTIVE_AGENT_COMMANDS = set(SUPPORTED_AGENTS)
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class LocalGatewayHandle:
|
|
92
|
+
def __init__(self, gateway: LocalGateway, thread: threading.Thread) -> None:
|
|
93
|
+
self.gateway = gateway
|
|
94
|
+
self.thread = thread
|
|
95
|
+
|
|
96
|
+
def shutdown(self) -> None:
|
|
97
|
+
self.gateway.shutdown()
|
|
98
|
+
self.thread.join(timeout=2)
|
|
99
|
+
|
|
100
|
+
|
|
88
101
|
def main(argv: Optional[List[str]] = None) -> int:
|
|
89
102
|
parser = build_parser()
|
|
90
103
|
args = parser.parse_args(argv)
|
|
@@ -338,7 +351,7 @@ def run_agent(args: argparse.Namespace) -> int:
|
|
|
338
351
|
|
|
339
352
|
daemon = _running_daemon()
|
|
340
353
|
daemon_session = None
|
|
341
|
-
|
|
354
|
+
gateway_handle = None
|
|
342
355
|
if daemon:
|
|
343
356
|
daemon_session = _daemon_create_session(
|
|
344
357
|
daemon,
|
|
@@ -357,9 +370,9 @@ def run_agent(args: argparse.Namespace) -> int:
|
|
|
357
370
|
else:
|
|
358
371
|
gateway_host = container.config.gateway.host
|
|
359
372
|
gateway_port = _available_gateway_port(gateway_host, container.config.gateway.port)
|
|
360
|
-
|
|
361
|
-
if isinstance(
|
|
362
|
-
return
|
|
373
|
+
gateway_handle = _start_local_gateway_thread(container, gateway_host, gateway_port)
|
|
374
|
+
if isinstance(gateway_handle, int):
|
|
375
|
+
return gateway_handle
|
|
363
376
|
|
|
364
377
|
env = os.environ.copy()
|
|
365
378
|
for env_name in container.config.env_policy.rules:
|
|
@@ -411,7 +424,13 @@ def run_agent(args: argparse.Namespace) -> int:
|
|
|
411
424
|
session_finished = False
|
|
412
425
|
try:
|
|
413
426
|
output_sanitizer = SecretOutputSanitizer.from_config_path(args.config)
|
|
414
|
-
|
|
427
|
+
preserve_tty = _should_preserve_interactive_tty(argv)
|
|
428
|
+
if preserve_tty:
|
|
429
|
+
print(
|
|
430
|
+
"AgentSecure interactive terminal mode: command output is not post-processed.",
|
|
431
|
+
flush=True,
|
|
432
|
+
)
|
|
433
|
+
process = _start_agent_process(argv, env, run_cwd, sanitize_output=not preserve_tty)
|
|
415
434
|
process_group_id = _process_group_id(process)
|
|
416
435
|
if cloud_session and cloud and cloud.status().get("enrolled"):
|
|
417
436
|
command_executor = _run_command_executor(
|
|
@@ -465,6 +484,8 @@ def run_agent(args: argparse.Namespace) -> int:
|
|
|
465
484
|
cloud_stop.set()
|
|
466
485
|
if cloud_thread:
|
|
467
486
|
cloud_thread.join(timeout=2)
|
|
487
|
+
if gateway_handle:
|
|
488
|
+
gateway_handle.shutdown()
|
|
468
489
|
if workspace_session and not args.workspace_keep:
|
|
469
490
|
materializer.make_writable(workspace_session.workspace_root)
|
|
470
491
|
shutil.rmtree(workspace_session.workspace_root, ignore_errors=True)
|
|
@@ -489,6 +510,19 @@ def _start_agent_process(argv: List[str], env, cwd: str, sanitize_output: bool =
|
|
|
489
510
|
return subprocess.Popen(argv, env=env, cwd=cwd, stdout=stdout, stderr=stderr)
|
|
490
511
|
|
|
491
512
|
|
|
513
|
+
def _should_preserve_interactive_tty(argv: List[str]) -> bool:
|
|
514
|
+
if not argv or not _stdio_is_tty():
|
|
515
|
+
return False
|
|
516
|
+
command = os.path.basename(argv[0])
|
|
517
|
+
if command not in INTERACTIVE_AGENT_COMMANDS:
|
|
518
|
+
return False
|
|
519
|
+
return len(argv) == 1
|
|
520
|
+
|
|
521
|
+
|
|
522
|
+
def _stdio_is_tty() -> bool:
|
|
523
|
+
return sys.stdin.isatty() and sys.stdout.isatty() and sys.stderr.isatty()
|
|
524
|
+
|
|
525
|
+
|
|
492
526
|
def _wait_for_agent_process(process, sanitizer: SecretOutputSanitizer) -> int:
|
|
493
527
|
if process.stdout is None and process.stderr is None:
|
|
494
528
|
return process.wait()
|
|
@@ -665,7 +699,7 @@ def _start_local_gateway_thread(container: Container, host: str, port: int):
|
|
|
665
699
|
if isinstance(gateway_status, Exception):
|
|
666
700
|
sys.stderr.write("agentsecure: gateway failed to start: %s\n" % gateway_status)
|
|
667
701
|
return 1
|
|
668
|
-
return gateway_thread
|
|
702
|
+
return LocalGatewayHandle(gateway, gateway_thread)
|
|
669
703
|
|
|
670
704
|
|
|
671
705
|
def _proxy_url(host: str, port: int, session_id: str = "") -> str:
|
|
@@ -568,6 +568,10 @@ class LocalGateway:
|
|
|
568
568
|
ready_callback()
|
|
569
569
|
server.serve_forever()
|
|
570
570
|
|
|
571
|
+
def shutdown(self) -> None:
|
|
572
|
+
if self._server is not None:
|
|
573
|
+
self._server.shutdown()
|
|
574
|
+
|
|
571
575
|
def _handler_class(self):
|
|
572
576
|
class BoundGatewayRequestHandler(GatewayRequestHandler):
|
|
573
577
|
pass
|
|
@@ -585,3 +589,6 @@ class LocalGateway:
|
|
|
585
589
|
class ReusableThreadingTCPServer(socketserver.ThreadingTCPServer):
|
|
586
590
|
allow_reuse_address = True
|
|
587
591
|
daemon_threads = True
|
|
592
|
+
|
|
593
|
+
def handle_error(self, request, client_address) -> None:
|
|
594
|
+
return
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: agentsecure
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.6
|
|
4
4
|
Summary: Local-first security runtime for AI coding agents
|
|
5
5
|
Home-page: https://github.com/ShellFrameAI/agentsecure-community
|
|
6
6
|
Author: ShellFrame AI
|
|
@@ -41,11 +41,22 @@ The community release is intentionally scoped to local CLI, local command guard,
|
|
|
41
41
|
## Install
|
|
42
42
|
|
|
43
43
|
```bash
|
|
44
|
-
python3 -m pip install agentsecure
|
|
44
|
+
python3 -m pip install --upgrade agentsecure
|
|
45
|
+
python3 -m agentsecure demo
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
`python3 -m agentsecure` works even when `pip` installs the `agentsecure`
|
|
49
|
+
executable into a user script directory that is not on your `PATH`. If you want
|
|
50
|
+
the shorter `agentsecure` command, add Python's user script directory to your
|
|
51
|
+
shell path:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
export PATH="$(python3 -m site --user-base)/bin:$PATH"
|
|
45
55
|
agentsecure demo
|
|
46
56
|
```
|
|
47
57
|
|
|
48
|
-
|
|
58
|
+
You do not need a virtual environment to run AgentSecure. Use one only if you
|
|
59
|
+
want the install isolated to this project:
|
|
49
60
|
|
|
50
61
|
```bash
|
|
51
62
|
python3 -m venv .venv
|
|
@@ -55,6 +66,12 @@ python -m pip install agentsecure
|
|
|
55
66
|
agentsecure demo
|
|
56
67
|
```
|
|
57
68
|
|
|
69
|
+
Then run your agent:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
python3 -m agentsecure run claude
|
|
73
|
+
```
|
|
74
|
+
|
|
58
75
|
## What The Demo Shows
|
|
59
76
|
|
|
60
77
|
The built-in demo creates a temporary local project with fake secrets, applies a small sample policy, simulates a command reading `.env`, and prints what the agent would see:
|
|
@@ -217,11 +234,15 @@ agentsecure receipts --proxy
|
|
|
217
234
|
Run an agent or command through local command guard:
|
|
218
235
|
|
|
219
236
|
```bash
|
|
220
|
-
agentsecure run --protect-all -- codex
|
|
221
|
-
agentsecure run --protect-all -- claude
|
|
222
|
-
agentsecure run --protect-all -- python3 -c 'import subprocess; print(subprocess.check_output(["cat", ".env"]).decode())'
|
|
237
|
+
python3 -m agentsecure run --protect-all -- codex
|
|
238
|
+
python3 -m agentsecure run --protect-all -- claude
|
|
239
|
+
python3 -m agentsecure run --protect-all -- python3 -c 'import subprocess; print(subprocess.check_output(["cat", ".env"]).decode())'
|
|
223
240
|
```
|
|
224
241
|
|
|
242
|
+
Bare interactive agent launches keep the terminal attached so tools such as
|
|
243
|
+
Claude Code can open normally. Non-interactive commands are still output
|
|
244
|
+
sanitized by AgentSecure.
|
|
245
|
+
|
|
225
246
|
Use workspace copy mode when you want review-before-apply:
|
|
226
247
|
|
|
227
248
|
```bash
|
|
@@ -2,6 +2,7 @@ import unittest
|
|
|
2
2
|
import socket
|
|
3
3
|
from io import StringIO
|
|
4
4
|
from contextlib import redirect_stdout
|
|
5
|
+
from unittest.mock import patch
|
|
5
6
|
|
|
6
7
|
from agentsecure.cli.main import (
|
|
7
8
|
_apply_proxy_environment,
|
|
@@ -11,6 +12,7 @@ from agentsecure.cli.main import (
|
|
|
11
12
|
build_parser,
|
|
12
13
|
_merge_no_proxy,
|
|
13
14
|
_proxy_url,
|
|
15
|
+
_should_preserve_interactive_tty,
|
|
14
16
|
)
|
|
15
17
|
from agentsecure.core.models import AgentSecureConfig, SecretBinding
|
|
16
18
|
|
|
@@ -117,6 +119,18 @@ class CliTest(unittest.TestCase):
|
|
|
117
119
|
finally:
|
|
118
120
|
sock.close()
|
|
119
121
|
|
|
122
|
+
def test_preserves_tty_for_bare_interactive_agent(self):
|
|
123
|
+
with patch("agentsecure.cli.main._stdio_is_tty", return_value=True):
|
|
124
|
+
self.assertTrue(_should_preserve_interactive_tty(["claude"]))
|
|
125
|
+
|
|
126
|
+
def test_does_not_preserve_tty_for_regular_commands(self):
|
|
127
|
+
with patch("agentsecure.cli.main._stdio_is_tty", return_value=True):
|
|
128
|
+
self.assertFalse(_should_preserve_interactive_tty(["cat", ".env"]))
|
|
129
|
+
|
|
130
|
+
def test_does_not_preserve_tty_when_agent_has_arguments(self):
|
|
131
|
+
with patch("agentsecure.cli.main._stdio_is_tty", return_value=True):
|
|
132
|
+
self.assertFalse(_should_preserve_interactive_tty(["claude", "--print", "hello"]))
|
|
133
|
+
|
|
120
134
|
|
|
121
135
|
if __name__ == "__main__":
|
|
122
136
|
unittest.main()
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{agentsecure-0.1.4 → agentsecure-0.1.6}/agentsecure/implementations/encrypted_secret_store.py
RENAMED
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|