agentx-security-sdk 0.3.2__tar.gz → 0.3.4__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 (20) hide show
  1. {agentx_security_sdk-0.3.2 → agentx_security_sdk-0.3.4}/PKG-INFO +7 -1
  2. {agentx_security_sdk-0.3.2 → agentx_security_sdk-0.3.4}/README.md +6 -0
  3. {agentx_security_sdk-0.3.2 → agentx_security_sdk-0.3.4}/agentx_sdk/cli.py +131 -1
  4. {agentx_security_sdk-0.3.2 → agentx_security_sdk-0.3.4}/agentx_security_sdk.egg-info/PKG-INFO +7 -1
  5. {agentx_security_sdk-0.3.2 → agentx_security_sdk-0.3.4}/setup.py +1 -1
  6. {agentx_security_sdk-0.3.2 → agentx_security_sdk-0.3.4}/agentx_sdk/__init__.py +0 -0
  7. {agentx_security_sdk-0.3.2 → agentx_security_sdk-0.3.4}/agentx_sdk/client.py +0 -0
  8. {agentx_security_sdk-0.3.2 → agentx_security_sdk-0.3.4}/agentx_sdk/db.py +0 -0
  9. {agentx_security_sdk-0.3.2 → agentx_security_sdk-0.3.4}/agentx_sdk/decorators.py +0 -0
  10. {agentx_security_sdk-0.3.2 → agentx_security_sdk-0.3.4}/agentx_sdk/test_agentx_sdk.py +0 -0
  11. {agentx_security_sdk-0.3.2 → agentx_security_sdk-0.3.4}/agentx_sdk/test_cli.py +0 -0
  12. {agentx_security_sdk-0.3.2 → agentx_security_sdk-0.3.4}/agentx_sdk/test_client.py +0 -0
  13. {agentx_security_sdk-0.3.2 → agentx_security_sdk-0.3.4}/agentx_sdk/test_db.py +0 -0
  14. {agentx_security_sdk-0.3.2 → agentx_security_sdk-0.3.4}/agentx_sdk/test_fail_modes.py +0 -0
  15. {agentx_security_sdk-0.3.2 → agentx_security_sdk-0.3.4}/agentx_security_sdk.egg-info/SOURCES.txt +0 -0
  16. {agentx_security_sdk-0.3.2 → agentx_security_sdk-0.3.4}/agentx_security_sdk.egg-info/dependency_links.txt +0 -0
  17. {agentx_security_sdk-0.3.2 → agentx_security_sdk-0.3.4}/agentx_security_sdk.egg-info/entry_points.txt +0 -0
  18. {agentx_security_sdk-0.3.2 → agentx_security_sdk-0.3.4}/agentx_security_sdk.egg-info/requires.txt +0 -0
  19. {agentx_security_sdk-0.3.2 → agentx_security_sdk-0.3.4}/agentx_security_sdk.egg-info/top_level.txt +0 -0
  20. {agentx_security_sdk-0.3.2 → agentx_security_sdk-0.3.4}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentx-security-sdk
3
- Version: 0.3.2
3
+ Version: 0.3.4
4
4
  Summary: The self-healing exception handler for autonomous AI agents.
5
5
  Home-page: https://github.com/vdalal/semantic-gateway
6
6
  Author: AgentX Core Team
@@ -118,6 +118,12 @@ cd backend
118
118
  uvicorn gateway:app --host "0.0.0.0" --port=8000
119
119
  ```
120
120
 
121
+ > **Both commands above build the gateway from source** (internal / source-access).
122
+ > The gateway is closed-source, so **design partners run a prebuilt private image
123
+ > instead** — `pip install agentx-security-sdk` does not ship it. Request access at
124
+ > [agentx-core.com](https://agentx-core.com); once granted, the starter kit in
125
+ > [`deploy/partner/`](deploy/partner/) pulls and runs the image (no source needed).
126
+
121
127
  The reasoning engine is now listening on http://localhost:8000. In `local`/`linked` mode it owns the policy lifecycle from a local SQLite store (seeded on first boot, editable via the Policy & Discovery tabs); in `cloud` mode it mirrors policies from your Supabase-backed Control Plane.
122
128
 
123
129
  ---
@@ -93,6 +93,12 @@ cd backend
93
93
  uvicorn gateway:app --host "0.0.0.0" --port=8000
94
94
  ```
95
95
 
96
+ > **Both commands above build the gateway from source** (internal / source-access).
97
+ > The gateway is closed-source, so **design partners run a prebuilt private image
98
+ > instead** — `pip install agentx-security-sdk` does not ship it. Request access at
99
+ > [agentx-core.com](https://agentx-core.com); once granted, the starter kit in
100
+ > [`deploy/partner/`](deploy/partner/) pulls and runs the image (no source needed).
101
+
96
102
  The reasoning engine is now listening on http://localhost:8000. In `local`/`linked` mode it owns the policy lifecycle from a local SQLite store (seeded on first boot, editable via the Policy & Discovery tabs); in `cloud` mode it mirrors policies from your Supabase-backed Control Plane.
97
103
 
98
104
  ---
@@ -206,6 +206,130 @@ def execute_vector_seed_compilation(gateway_url, api_key, output_dir=".agentx"):
206
206
  print("=" * 75)
207
207
  sys.exit(1)
208
208
 
209
+ def _contribution_consent_value(env):
210
+ """Return the explicit AGENTX_CONTRIBUTE choice (True/False) if the developer
211
+ has set it (process env first, then .env), else None (undecided)."""
212
+ raw = os.environ.get("AGENTX_CONTRIBUTE")
213
+ if raw is None:
214
+ raw = env.get("AGENTX_CONTRIBUTE")
215
+ if raw is None:
216
+ return None
217
+ return raw.strip().lower() in ("1", "true", "yes", "on")
218
+
219
+
220
+ def _persist_contribution_choice(value):
221
+ """Append AGENTX_CONTRIBUTE to ./.env so the choice sticks and the env var
222
+ stays the one canonical switch. Best-effort; never fatal."""
223
+ try:
224
+ prefix = "\n" if os.path.exists(".env") and os.path.getsize(".env") > 0 else ""
225
+ with open(".env", "a", encoding="utf-8") as f:
226
+ f.write(f"{prefix}AGENTX_CONTRIBUTE={'true' if value else 'false'}\n")
227
+ except Exception:
228
+ pass
229
+
230
+
231
+ def resolve_contribution_consent(env):
232
+ """Decide whether to contribute. The explicit AGENTX_CONTRIBUTE (process env or
233
+ .env) is canonical and ALWAYS wins — set it and we never prompt. Only when it
234
+ is UNSET *and* we're on an interactive terminal do we surface a one-time,
235
+ value-framed prompt (and persist the answer to .env) — killing the discovery
236
+ friction without removing consent. Unset + non-interactive = OFF, so CI and
237
+ scripts are never blocked or hung."""
238
+ explicit = _contribution_consent_value(env)
239
+ if explicit is not None:
240
+ return explicit
241
+ if not sys.stdin.isatty():
242
+ print("\n 🔒 Contribution is OFF (AGENTX_CONTRIBUTE unset). Set it to true to help")
243
+ print(" grow shared immunity — abstract signals only, never your data.")
244
+ return False
245
+ print("\n 🌐 Help grow shared immunity?")
246
+ print(" We'd share ONLY anonymous, abstract signals (which policy fired, on")
247
+ print(" what day) — never your queries, reasoning, payloads, or any identifier.")
248
+ try:
249
+ answer = input(" Contribute these abstract signals? [y/N]: ").strip().lower()
250
+ except (EOFError, KeyboardInterrupt):
251
+ answer = ""
252
+ choice = answer in ("y", "yes")
253
+ _persist_contribution_choice(choice)
254
+ print(f" {'✅ On' if choice else '🔒 Off'} — saved AGENTX_CONTRIBUTE="
255
+ f"{'true' if choice else 'false'} to ./.env (change it anytime).")
256
+ return choice
257
+
258
+
259
+ def execute_contribution_push(gateway_url, control_plane_url, api_key, env):
260
+ """Grow the shared-immunity corpus from this machine — privacy-preserving by
261
+ construction.
262
+
263
+ The gateway projects the local incident store down to ABSTRACT, de-identified
264
+ signal (`/v1/contribution`), so raw payloads, chain-of-thought, and identifiers
265
+ never reach this process, let alone the network. We show exactly what would
266
+ leave, always write it locally for inspection, and POST it to the shared corpus
267
+ ONLY when the developer has explicitly opted in (AGENTX_CONTRIBUTE). Default is
268
+ OFF — nothing leaves your box without consent.
269
+ """
270
+ headers = {"Authorization": f"Bearer {api_key}"}
271
+ try:
272
+ res = requests.get(f"{gateway_url}/v1/contribution", headers=headers, timeout=5.0)
273
+ except requests.exceptions.ConnectionError:
274
+ print(f"❌ Unable to reach the AgentX gateway at {gateway_url} (is it up? `docker ps`).")
275
+ print("=" * 75)
276
+ return
277
+ if res.status_code != 200:
278
+ print(f"❌ Gateway returned status {res.status_code} for the contribution projection. Skipping.")
279
+ print("=" * 75)
280
+ return
281
+
282
+ body = res.json()
283
+ contributions = body.get("contributions", [])
284
+ fields = body.get("fields", [])
285
+
286
+ # Always write a local artifact so there is a record and the dev can inspect
287
+ # exactly what the abstract contribution looks like (the open data path).
288
+ target_dir = ".agentx"
289
+ os.makedirs(target_dir, exist_ok=True)
290
+ artifact = os.path.join(target_dir, "contribution.jsonl")
291
+ with open(artifact, "w", encoding="utf-8") as f:
292
+ for c in contributions:
293
+ f.write(json.dumps(c) + "\n")
294
+
295
+ print(f"\n🧬 Abstract contribution ready: {len(contributions)} signal(s).")
296
+ print(f" Shared (and ONLY these): {', '.join(fields) or '—'}")
297
+ print(" Never shared: your queries, chain-of-thought, payloads, or any identifier.")
298
+ print(f" 💾 Written locally for your inspection: ./{artifact}")
299
+
300
+ if not contributions:
301
+ print(" (Nothing to contribute yet — run some protected agents first.)")
302
+ print("=" * 75)
303
+ return
304
+
305
+ if not resolve_contribution_consent(env):
306
+ print("\n 🔒 These signals stayed on your machine.")
307
+ print("=" * 75)
308
+ return
309
+
310
+ try:
311
+ post = requests.post(
312
+ f"{control_plane_url}/api/edge/contribute",
313
+ json={"contributions": contributions},
314
+ headers=headers,
315
+ timeout=10.0,
316
+ )
317
+ if post.status_code in (200, 201, 202):
318
+ print(f"\n ✅ Contributed {len(contributions)} abstract signal(s) to shared immunity. Thank you.")
319
+ else:
320
+ print(f"\n ⚠️ Shared corpus returned {post.status_code}. Saved locally; will retry next sync.")
321
+ except requests.exceptions.RequestException as e:
322
+ print(f"\n ⚠️ Could not reach the shared corpus ({e}). Saved locally; will retry next sync.")
323
+ print("=" * 75)
324
+
325
+
326
+ def execute_sync(gateway_url, control_plane_url, api_key, env):
327
+ """`agentx sync` = pull the latest policies, then (opt-in) push the abstract
328
+ contribution. One habit keeps you in sync with the network both ways."""
329
+ execute_policy_pull(control_plane_url, api_key)
330
+ execute_contribution_push(gateway_url, control_plane_url, api_key, env)
331
+
332
+
209
333
  def main():
210
334
  print("=" * 75)
211
335
  print("🛡️ AGENTX LOCAL OBSERVABILITY ENGINE")
@@ -248,6 +372,10 @@ def main():
248
372
 
249
373
  if command == "pull":
250
374
  execute_policy_pull(control_plane_url, api_key)
375
+ elif command == "push":
376
+ execute_contribution_push(gateway_url, control_plane_url, api_key, env)
377
+ elif command == "sync":
378
+ execute_sync(gateway_url, control_plane_url, api_key, env)
251
379
  elif command == "compile":
252
380
  # ✅ NEW SURGICAL HOOK: Routes the compile action to our new weights matrix builder
253
381
  # execute_vector_seed_compilation(gateway_url, api_key)
@@ -256,7 +384,9 @@ def main():
256
384
  execute_status_inspection(gateway_url, api_key)
257
385
  else:
258
386
  print(f"⚠️ Unknown command parameter input flag value string: '{command}'")
259
- print(" Available options: agentx status | agentx pull")
387
+ print(" Available options: agentx status | agentx pull | agentx push | agentx sync")
388
+ print(" (push = contribute abstract signals to shared immunity, opt-in via AGENTX_CONTRIBUTE;")
389
+ print(" sync = pull + push)")
260
390
  print("=" * 75)
261
391
 
262
392
  if __name__ == "__main__":
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentx-security-sdk
3
- Version: 0.3.2
3
+ Version: 0.3.4
4
4
  Summary: The self-healing exception handler for autonomous AI agents.
5
5
  Home-page: https://github.com/vdalal/semantic-gateway
6
6
  Author: AgentX Core Team
@@ -118,6 +118,12 @@ cd backend
118
118
  uvicorn gateway:app --host "0.0.0.0" --port=8000
119
119
  ```
120
120
 
121
+ > **Both commands above build the gateway from source** (internal / source-access).
122
+ > The gateway is closed-source, so **design partners run a prebuilt private image
123
+ > instead** — `pip install agentx-security-sdk` does not ship it. Request access at
124
+ > [agentx-core.com](https://agentx-core.com); once granted, the starter kit in
125
+ > [`deploy/partner/`](deploy/partner/) pulls and runs the image (no source needed).
126
+
121
127
  The reasoning engine is now listening on http://localhost:8000. In `local`/`linked` mode it owns the policy lifecycle from a local SQLite store (seeded on first boot, editable via the Policy & Discovery tabs); in `cloud` mode it mirrors policies from your Supabase-backed Control Plane.
122
128
 
123
129
  ---
@@ -9,7 +9,7 @@ if os.path.exists("README.md"):
9
9
 
10
10
  setup(
11
11
  name="agentx-security-sdk",
12
- version="0.3.2",
12
+ version="0.3.4",
13
13
  author="AgentX Core Team",
14
14
  author_email="founders@agentx-core.com",
15
15
  description="The self-healing exception handler for autonomous AI agents.",