agentauthlayer 0.1.2__tar.gz → 0.1.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 (117) hide show
  1. agentauthlayer-0.1.4/MANIFEST.in +2 -0
  2. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/PKG-INFO +71 -8
  3. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/README.md +60 -7
  4. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agent_auth/cli.py +91 -4
  5. agentauthlayer-0.1.4/agent_auth/runtime.py +25 -0
  6. agentauthlayer-0.1.4/agent_auth/server_runtime.py +123 -0
  7. agentauthlayer-0.1.4/agent_auth/web_dist/assets/index-BBJ7rinV.css +1 -0
  8. agentauthlayer-0.1.4/agent_auth/web_dist/assets/index-DXUoW2DG.js +429 -0
  9. agentauthlayer-0.1.4/agent_auth/web_dist/favicon.ico +0 -0
  10. agentauthlayer-0.1.4/agent_auth/web_dist/grid.svg +8 -0
  11. agentauthlayer-0.1.4/agent_auth/web_dist/index.html +18 -0
  12. agentauthlayer-0.1.4/agent_auth/web_dist/placeholder.svg +40 -0
  13. agentauthlayer-0.1.4/agent_auth/web_dist/robots.txt +14 -0
  14. agentauthlayer-0.1.4/agent_auth_definitive_guide.pdf +0 -0
  15. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agentauthlayer.egg-info/PKG-INFO +71 -8
  16. agentauthlayer-0.1.4/agentauthlayer.egg-info/SOURCES.txt +113 -0
  17. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agentauthlayer.egg-info/entry_points.txt +1 -0
  18. agentauthlayer-0.1.4/agentauthlayer.egg-info/requires.txt +12 -0
  19. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agentauthlayer.egg-info/top_level.txt +1 -0
  20. agentauthlayer-0.1.4/auth_app/__init__.py +0 -0
  21. agentauthlayer-0.1.4/auth_app/api/__init__.py +0 -0
  22. agentauthlayer-0.1.4/auth_app/api/routes/__init__.py +0 -0
  23. agentauthlayer-0.1.4/auth_app/api/routes/agents.py +94 -0
  24. agentauthlayer-0.1.4/auth_app/api/routes/audit.py +19 -0
  25. agentauthlayer-0.1.4/auth_app/api/routes/auth.py +81 -0
  26. agentauthlayer-0.1.4/auth_app/api/routes/bootstrap.py +117 -0
  27. agentauthlayer-0.1.4/auth_app/api/routes/health.py +10 -0
  28. agentauthlayer-0.1.4/auth_app/api/routes/policy.py +218 -0
  29. agentauthlayer-0.1.4/auth_app/api/routes/projects.py +84 -0
  30. agentauthlayer-0.1.4/auth_app/api/routes/tokens.py +50 -0
  31. agentauthlayer-0.1.4/auth_app/api/routes/users.py +182 -0
  32. agentauthlayer-0.1.4/auth_app/core/__init__.py +0 -0
  33. agentauthlayer-0.1.4/auth_app/core/config.py +49 -0
  34. agentauthlayer-0.1.4/auth_app/core/db.py +28 -0
  35. agentauthlayer-0.1.4/auth_app/core/errors.py +21 -0
  36. agentauthlayer-0.1.4/auth_app/core/logging.py +11 -0
  37. agentauthlayer-0.1.4/auth_app/dependencies/__init__.py +0 -0
  38. agentauthlayer-0.1.4/auth_app/dependencies/auth.py +140 -0
  39. agentauthlayer-0.1.4/auth_app/dependencies/security.py +40 -0
  40. agentauthlayer-0.1.4/auth_app/dependencies/user.py +38 -0
  41. agentauthlayer-0.1.4/auth_app/domain/__init__.py +0 -0
  42. agentauthlayer-0.1.4/auth_app/domain/enums.py +12 -0
  43. agentauthlayer-0.1.4/auth_app/domain/models.py +75 -0
  44. agentauthlayer-0.1.4/auth_app/main.py +76 -0
  45. agentauthlayer-0.1.4/auth_app/middleware/__init__.py +0 -0
  46. agentauthlayer-0.1.4/auth_app/middleware/correlation.py +27 -0
  47. agentauthlayer-0.1.4/auth_app/repositories/__init__.py +0 -0
  48. agentauthlayer-0.1.4/auth_app/repositories/agent_repo.py +28 -0
  49. agentauthlayer-0.1.4/auth_app/repositories/audit_repo.py +16 -0
  50. agentauthlayer-0.1.4/auth_app/repositories/constraint_repo.py +15 -0
  51. agentauthlayer-0.1.4/auth_app/repositories/contracts.py +157 -0
  52. agentauthlayer-0.1.4/auth_app/repositories/delegation_repo.py +22 -0
  53. agentauthlayer-0.1.4/auth_app/repositories/project_repo.py +37 -0
  54. agentauthlayer-0.1.4/auth_app/repositories/role_repo.py +19 -0
  55. agentauthlayer-0.1.4/auth_app/repositories/sqlite_agent_repo.py +113 -0
  56. agentauthlayer-0.1.4/auth_app/repositories/sqlite_audit_repo.py +75 -0
  57. agentauthlayer-0.1.4/auth_app/repositories/sqlite_constraint_repo.py +46 -0
  58. agentauthlayer-0.1.4/auth_app/repositories/sqlite_delegation_repo.py +84 -0
  59. agentauthlayer-0.1.4/auth_app/repositories/sqlite_permission_repo.py +40 -0
  60. agentauthlayer-0.1.4/auth_app/repositories/sqlite_project_repo.py +104 -0
  61. agentauthlayer-0.1.4/auth_app/repositories/sqlite_role_repo.py +67 -0
  62. agentauthlayer-0.1.4/auth_app/repositories/sqlite_token_repo.py +92 -0
  63. agentauthlayer-0.1.4/auth_app/repositories/sqlite_user_repo.py +217 -0
  64. agentauthlayer-0.1.4/auth_app/repositories/token_repo.py +24 -0
  65. agentauthlayer-0.1.4/auth_app/repositories/user_repo.py +79 -0
  66. agentauthlayer-0.1.4/auth_app/schemas/__init__.py +0 -0
  67. agentauthlayer-0.1.4/auth_app/schemas/agent.py +26 -0
  68. agentauthlayer-0.1.4/auth_app/schemas/audit.py +12 -0
  69. agentauthlayer-0.1.4/auth_app/schemas/auth.py +18 -0
  70. agentauthlayer-0.1.4/auth_app/schemas/bootstrap.py +20 -0
  71. agentauthlayer-0.1.4/auth_app/schemas/device_agents.py +12 -0
  72. agentauthlayer-0.1.4/auth_app/schemas/policy.py +80 -0
  73. agentauthlayer-0.1.4/auth_app/schemas/project.py +29 -0
  74. agentauthlayer-0.1.4/auth_app/schemas/token.py +35 -0
  75. agentauthlayer-0.1.4/auth_app/schemas/user.py +100 -0
  76. agentauthlayer-0.1.4/auth_app/services/__init__.py +0 -0
  77. agentauthlayer-0.1.4/auth_app/services/agent_service.py +48 -0
  78. agentauthlayer-0.1.4/auth_app/services/audit_service.py +48 -0
  79. agentauthlayer-0.1.4/auth_app/services/device_agent_service.py +45 -0
  80. agentauthlayer-0.1.4/auth_app/services/policy_service.py +77 -0
  81. agentauthlayer-0.1.4/auth_app/services/project_service.py +38 -0
  82. agentauthlayer-0.1.4/auth_app/services/token_service.py +89 -0
  83. agentauthlayer-0.1.4/auth_app/services/user_service.py +47 -0
  84. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/pyproject.toml +17 -3
  85. agentauthlayer-0.1.2/agentauthlayer.egg-info/SOURCES.txt +0 -38
  86. agentauthlayer-0.1.2/agentauthlayer.egg-info/requires.txt +0 -2
  87. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agent_auth/__init__.py +0 -0
  88. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agent_auth/__main__.py +0 -0
  89. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agent_auth/agents.py +0 -0
  90. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agent_auth/audit.py +0 -0
  91. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agent_auth/auth.py +0 -0
  92. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agent_auth/client.py +0 -0
  93. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agent_auth/context.py +0 -0
  94. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agent_auth/core.py +0 -0
  95. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agent_auth/credentials.py +0 -0
  96. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agent_auth/delegation.py +0 -0
  97. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agent_auth/exceptions.py +0 -0
  98. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agent_auth/models.py +0 -0
  99. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agent_auth/policy.py +0 -0
  100. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agent_auth/policy_service.py +0 -0
  101. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agent_auth/principals.py +0 -0
  102. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agent_auth/registry.py +0 -0
  103. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agent_auth/session.py +0 -0
  104. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agent_auth/storage.py +0 -0
  105. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agent_auth/tokens.py +0 -0
  106. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agent_auth/users.py +0 -0
  107. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/agentauthlayer.egg-info/dependency_links.txt +0 -0
  108. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/setup.cfg +0 -0
  109. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/tests/test_agent_auth_library.py +0 -0
  110. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/tests/test_auth_flow.py +0 -0
  111. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/tests/test_core_first_boundary.py +0 -0
  112. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/tests/test_health.py +0 -0
  113. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/tests/test_iam_policy.py +0 -0
  114. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/tests/test_project_flow.py +0 -0
  115. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/tests/test_sqlite_repos.py +0 -0
  116. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/tests/test_storage.py +0 -0
  117. {agentauthlayer-0.1.2 → agentauthlayer-0.1.4}/tests/test_tool_registry.py +0 -0
@@ -0,0 +1,2 @@
1
+ recursive-include agent_auth/web_dist *
2
+ include agent_auth_definitive_guide.pdf
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentauthlayer
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: Library-first authentication and authorization SDK for AI agents
5
5
  Author: Vaibhav Ahluwalia
6
6
  License: MIT
@@ -17,19 +17,33 @@ Requires-Python: >=3.10
17
17
  Description-Content-Type: text/markdown
18
18
  Requires-Dist: requests>=2.31.0
19
19
  Requires-Dist: python-jose>=3.3.0
20
+ Requires-Dist: fastapi
21
+ Requires-Dist: uvicorn
22
+ Requires-Dist: pydantic
23
+ Requires-Dist: pydantic-settings
24
+ Requires-Dist: passlib[bcrypt]
25
+ Requires-Dist: bcrypt==4.0.1
26
+ Requires-Dist: python-multipart
27
+ Requires-Dist: httpx
28
+ Requires-Dist: sqlalchemy
29
+ Requires-Dist: email-validator
20
30
 
21
31
  # agentauthlayer
22
32
 
23
- Python SDK for integrating agent runtimes with the Agent Auth control plane.
33
+ Unified SDK and local control plane package for Agent Auth.
24
34
 
25
35
  `agentauthlayer` helps you:
36
+ - start a local Agent Auth backend and UI with one command
26
37
  - authenticate once and reuse local credentials
27
38
  - register agents from code
28
39
  - sync tool and capability definitions
29
40
  - evaluate permissions against the control plane
30
41
  - apply permission checks inside runtime functions
31
42
 
32
- This package is the reusable SDK layer. It is intended for developers integrating Python agents, tools, and workflows with an Agent Auth deployment.
43
+ This package now ships as a unified developer install containing:
44
+ - the reusable Python SDK layer
45
+ - the local control plane backend runtime
46
+ - the packaged admin UI assets
33
47
 
34
48
  ## Install
35
49
 
@@ -39,7 +53,38 @@ pip install agentauthlayer
39
53
 
40
54
  ## Quickstart
41
55
 
42
- ### 1. Log in once
56
+ ### 1. Start the local control plane
57
+
58
+ For a local developer setup, start Agent Auth with one command:
59
+
60
+ ```bash
61
+ agentauth up
62
+ ```
63
+
64
+ This starts the packaged local control plane on `http://127.0.0.1:8002` by default.
65
+
66
+ If you want a different port:
67
+
68
+ ```bash
69
+ agentauth up --port 8014
70
+ ```
71
+
72
+ ### 2. First-time developer setup
73
+
74
+ For a fresh deployment:
75
+
76
+ 1. Open the UI in your browser.
77
+ 2. Create the first super admin password.
78
+ 3. Create your first project.
79
+ 4. Then log in from the CLI.
80
+
81
+ Open the UI with:
82
+
83
+ ```bash
84
+ agentauth ui --base-url http://127.0.0.1:8002
85
+ ```
86
+
87
+ Then log in once:
43
88
 
44
89
  ```bash
45
90
  agentauth login --base-url http://127.0.0.1:8002
@@ -55,7 +100,9 @@ agentauth logout
55
100
  agentauth ui
56
101
  ```
57
102
 
58
- ### 2. Define tools and agents in code
103
+ If the deployment has not been initialized yet, `agentauth login` will tell you to finish setup in the UI first.
104
+
105
+ ### 3. Define tools and agents in code
59
106
 
60
107
  ```python
61
108
  from agent_auth import register_tool, register_agent, require_permission
@@ -75,7 +122,7 @@ register_agent(
75
122
  )
76
123
  ```
77
124
 
78
- ### 3. Sync everything with one command
125
+ ### 4. Sync everything with one command
79
126
 
80
127
  ```bash
81
128
  agentauth sync --module your_module_name
@@ -111,6 +158,15 @@ export AGENT_AUTH_URL=http://127.0.0.1:8002
111
158
  export AGENT_AUTH_TOKEN=YOUR_ADMIN_OR_SERVICE_TOKEN
112
159
  ```
113
160
 
161
+ `AGENT_AUTH_TOKEN` is typically a bearer token, often represented as a long JWT string.
162
+
163
+ Recommended usage:
164
+ - use `agentauth login` for local human developer workflows
165
+ - use `AGENT_AUTH_TOKEN` for CI, automation, or service-driven execution
166
+
167
+ If an env token expires, requests will fail until you replace it or log in again.
168
+ Avoid committing tokens into source control or long-lived shared `.env` files.
169
+
114
170
  Resolution order used by `AuthAPIClient()`:
115
171
  1. explicit constructor arguments
116
172
  2. environment variables
@@ -160,12 +216,13 @@ agentauth delete-agent research-bot-01
160
216
 
161
217
  This package provides:
162
218
  - the Python SDK (`agent_auth`)
219
+ - local control plane startup via `agentauth up`
220
+ - packaged backend runtime (`auth_app`)
221
+ - packaged admin UI assets
163
222
  - CLI helpers for login, sync, and agent cleanup
164
223
  - registry-based tool and agent sync
165
224
  - permission evaluation helpers
166
225
 
167
- It does not package the full control plane server or admin dashboard.
168
-
169
226
  ## Suitable use cases
170
227
 
171
228
  - Python agent runtimes
@@ -181,6 +238,12 @@ It does not package the full control plane server or admin dashboard.
181
238
 
182
239
  ## Notes
183
240
 
241
+ The package naming model is:
242
+
243
+ - install name: `agentauthlayer`
244
+ - CLI: `agentauth`
245
+ - Python import namespace: `agent_auth`
246
+
184
247
  The import path remains:
185
248
 
186
249
  ```python
@@ -1,15 +1,19 @@
1
1
  # agentauthlayer
2
2
 
3
- Python SDK for integrating agent runtimes with the Agent Auth control plane.
3
+ Unified SDK and local control plane package for Agent Auth.
4
4
 
5
5
  `agentauthlayer` helps you:
6
+ - start a local Agent Auth backend and UI with one command
6
7
  - authenticate once and reuse local credentials
7
8
  - register agents from code
8
9
  - sync tool and capability definitions
9
10
  - evaluate permissions against the control plane
10
11
  - apply permission checks inside runtime functions
11
12
 
12
- This package is the reusable SDK layer. It is intended for developers integrating Python agents, tools, and workflows with an Agent Auth deployment.
13
+ This package now ships as a unified developer install containing:
14
+ - the reusable Python SDK layer
15
+ - the local control plane backend runtime
16
+ - the packaged admin UI assets
13
17
 
14
18
  ## Install
15
19
 
@@ -19,7 +23,38 @@ pip install agentauthlayer
19
23
 
20
24
  ## Quickstart
21
25
 
22
- ### 1. Log in once
26
+ ### 1. Start the local control plane
27
+
28
+ For a local developer setup, start Agent Auth with one command:
29
+
30
+ ```bash
31
+ agentauth up
32
+ ```
33
+
34
+ This starts the packaged local control plane on `http://127.0.0.1:8002` by default.
35
+
36
+ If you want a different port:
37
+
38
+ ```bash
39
+ agentauth up --port 8014
40
+ ```
41
+
42
+ ### 2. First-time developer setup
43
+
44
+ For a fresh deployment:
45
+
46
+ 1. Open the UI in your browser.
47
+ 2. Create the first super admin password.
48
+ 3. Create your first project.
49
+ 4. Then log in from the CLI.
50
+
51
+ Open the UI with:
52
+
53
+ ```bash
54
+ agentauth ui --base-url http://127.0.0.1:8002
55
+ ```
56
+
57
+ Then log in once:
23
58
 
24
59
  ```bash
25
60
  agentauth login --base-url http://127.0.0.1:8002
@@ -35,7 +70,9 @@ agentauth logout
35
70
  agentauth ui
36
71
  ```
37
72
 
38
- ### 2. Define tools and agents in code
73
+ If the deployment has not been initialized yet, `agentauth login` will tell you to finish setup in the UI first.
74
+
75
+ ### 3. Define tools and agents in code
39
76
 
40
77
  ```python
41
78
  from agent_auth import register_tool, register_agent, require_permission
@@ -55,7 +92,7 @@ register_agent(
55
92
  )
56
93
  ```
57
94
 
58
- ### 3. Sync everything with one command
95
+ ### 4. Sync everything with one command
59
96
 
60
97
  ```bash
61
98
  agentauth sync --module your_module_name
@@ -91,6 +128,15 @@ export AGENT_AUTH_URL=http://127.0.0.1:8002
91
128
  export AGENT_AUTH_TOKEN=YOUR_ADMIN_OR_SERVICE_TOKEN
92
129
  ```
93
130
 
131
+ `AGENT_AUTH_TOKEN` is typically a bearer token, often represented as a long JWT string.
132
+
133
+ Recommended usage:
134
+ - use `agentauth login` for local human developer workflows
135
+ - use `AGENT_AUTH_TOKEN` for CI, automation, or service-driven execution
136
+
137
+ If an env token expires, requests will fail until you replace it or log in again.
138
+ Avoid committing tokens into source control or long-lived shared `.env` files.
139
+
94
140
  Resolution order used by `AuthAPIClient()`:
95
141
  1. explicit constructor arguments
96
142
  2. environment variables
@@ -140,12 +186,13 @@ agentauth delete-agent research-bot-01
140
186
 
141
187
  This package provides:
142
188
  - the Python SDK (`agent_auth`)
189
+ - local control plane startup via `agentauth up`
190
+ - packaged backend runtime (`auth_app`)
191
+ - packaged admin UI assets
143
192
  - CLI helpers for login, sync, and agent cleanup
144
193
  - registry-based tool and agent sync
145
194
  - permission evaluation helpers
146
195
 
147
- It does not package the full control plane server or admin dashboard.
148
-
149
196
  ## Suitable use cases
150
197
 
151
198
  - Python agent runtimes
@@ -161,6 +208,12 @@ It does not package the full control plane server or admin dashboard.
161
208
 
162
209
  ## Notes
163
210
 
211
+ The package naming model is:
212
+
213
+ - install name: `agentauthlayer`
214
+ - CLI: `agentauth`
215
+ - Python import namespace: `agent_auth`
216
+
164
217
  The import path remains:
165
218
 
166
219
  ```python
@@ -12,12 +12,51 @@ import requests
12
12
  from agent_auth.client import AuthAPIClient
13
13
  from agent_auth.credentials import clear_credentials, load_credentials, save_credentials
14
14
  from agent_auth.registry import clear_registries, list_registered_agents, list_registered_tools
15
+ from agent_auth.server_runtime import DEFAULT_BASE_URL, start_local_server, wait_for_health
16
+
17
+
18
+ def _response_detail(response: requests.Response) -> str:
19
+ try:
20
+ payload = response.json()
21
+ if isinstance(payload, dict) and payload.get('detail'):
22
+ return str(payload['detail'])
23
+ except Exception:
24
+ pass
25
+ return response.text.strip() or f'Request failed with status {response.status_code}'
26
+
27
+
28
+ def _bootstrap_status(base_url: str) -> bool | None:
29
+ try:
30
+ response = requests.get(f"{base_url}/bootstrap/status", timeout=10)
31
+ except requests.RequestException:
32
+ return None
33
+ if not response.ok:
34
+ return None
35
+ try:
36
+ payload = response.json()
37
+ return bool(payload.get('is_setup'))
38
+ except Exception:
39
+ return None
15
40
 
16
41
 
17
42
  def login_command(args) -> int:
43
+ base_url = (args.base_url or 'http://127.0.0.1:8002').rstrip('/')
44
+ setup_status = _bootstrap_status(base_url)
45
+
46
+ if setup_status is False:
47
+ print(
48
+ '\nThis Agent Auth deployment has not been initialized yet.\n'
49
+ 'First-time developer setup:\n'
50
+ f' 1. Open the UI: {base_url}\n'
51
+ ' 2. Create the first super admin password\n'
52
+ ' 3. Create your first project\n'
53
+ ' 4. Run agentauth login again\n',
54
+ file=sys.stderr,
55
+ )
56
+ return 1
57
+
18
58
  email = args.email or input('Email: ').strip()
19
59
  password = args.password or getpass.getpass('Password: ')
20
- base_url = (args.base_url or 'http://127.0.0.1:8002').rstrip('/')
21
60
 
22
61
  response = requests.post(
23
62
  f"{base_url}/users/login",
@@ -25,7 +64,15 @@ def login_command(args) -> int:
25
64
  timeout=30,
26
65
  )
27
66
  if not response.ok:
28
- print(response.text, file=sys.stderr)
67
+ detail = _response_detail(response)
68
+ if response.status_code == 401 and setup_status is not True:
69
+ print(
70
+ f"{detail}\n\n"
71
+ 'If this is your first time using this deployment, initialize it first in the UI, then try logging in again.',
72
+ file=sys.stderr,
73
+ )
74
+ else:
75
+ print(detail, file=sys.stderr)
29
76
  return 1
30
77
 
31
78
  payload = response.json()
@@ -97,18 +144,58 @@ def delete_agent_command(args) -> int:
97
144
 
98
145
  def ui_command(args) -> int:
99
146
  creds = load_credentials() or {}
100
- base_url = (args.base_url or creds.get('base_url') or 'http://127.0.0.1:8002').rstrip('/')
147
+ base_url = (args.base_url or creds.get('base_url') or DEFAULT_BASE_URL).rstrip('/')
101
148
  webbrowser.open(base_url)
102
149
  print(f'Opened UI: {base_url}')
103
150
  return 0
104
151
 
105
152
 
153
+ def up_command(args) -> int:
154
+ host = args.host
155
+ port = args.port
156
+ process, base_url = start_local_server(host=host, port=port)
157
+
158
+ if process is None:
159
+ print(f'Agent Auth server is already running at {base_url}')
160
+ else:
161
+ print(f'Starting Agent Auth local control plane at {base_url}...')
162
+
163
+ healthy = wait_for_health(base_url, timeout_seconds=args.wait)
164
+ if not healthy:
165
+ print(
166
+ f'Agent Auth did not become ready at {base_url} within {args.wait} seconds. '
167
+ 'Check ~/.agentauth/server.log for details.',
168
+ file=sys.stderr,
169
+ )
170
+ return 1
171
+
172
+ print(f'Agent Auth is running at {base_url}')
173
+ print('Next steps:')
174
+ print(f' 1. Open the UI: {base_url}')
175
+ print(' 2. If first time, create the super admin and first project')
176
+ print(f' 3. Log in: agentauth login --base-url {base_url}')
177
+ print(' 4. Sync your module: agentauth sync --module your_module_name')
178
+
179
+ if args.open_browser:
180
+ webbrowser.open(base_url)
181
+ print('Opened browser.')
182
+
183
+ return 0
184
+
185
+
106
186
  def main():
107
187
  parser = argparse.ArgumentParser(prog='agentauth', description='Agent Auth SDK CLI')
108
188
  subparsers = parser.add_subparsers(dest='command')
109
189
 
190
+ up_parser = subparsers.add_parser('up', help='Start the local Agent Auth control plane')
191
+ up_parser.add_argument('--host', default='127.0.0.1')
192
+ up_parser.add_argument('--port', type=int, default=8002)
193
+ up_parser.add_argument('--wait', type=int, default=20)
194
+ up_parser.add_argument('--open-browser', action='store_true')
195
+ up_parser.set_defaults(func=up_command)
196
+
110
197
  login_parser = subparsers.add_parser('login', help='Log in and store local credentials')
111
- login_parser.add_argument('--base-url', default='http://127.0.0.1:8002')
198
+ login_parser.add_argument('--base-url', default=DEFAULT_BASE_URL)
112
199
  login_parser.add_argument('--email')
113
200
  login_parser.add_argument('--password')
114
201
  login_parser.set_defaults(func=login_command)
@@ -0,0 +1,25 @@
1
+ from __future__ import annotations
2
+
3
+ from pathlib import Path
4
+
5
+
6
+ def project_root() -> Path:
7
+ return Path(__file__).resolve().parent.parent
8
+
9
+
10
+ def packaged_frontend_dist_dir() -> Path:
11
+ return Path(__file__).resolve().parent / "web_dist"
12
+
13
+
14
+ def frontend_dist_dir() -> Path:
15
+ packaged = packaged_frontend_dist_dir()
16
+ if packaged.is_dir() and (packaged / "index.html").is_file():
17
+ return packaged
18
+ return project_root() / "frontend" / "dist"
19
+
20
+
21
+ def project_pdf_path() -> Path:
22
+ packaged = project_root() / "agent_auth_definitive_guide.pdf"
23
+ if packaged.is_file():
24
+ return packaged
25
+ return Path(__file__).resolve().parent.parent / "agent_auth_definitive_guide.pdf"
@@ -0,0 +1,123 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import secrets
5
+ import subprocess
6
+ import sys
7
+ import time
8
+ from pathlib import Path
9
+
10
+ import requests
11
+
12
+ from agent_auth.runtime import project_root
13
+
14
+
15
+ DEFAULT_HOST = "127.0.0.1"
16
+ DEFAULT_PORT = 8002
17
+ DEFAULT_BASE_URL = f"http://{DEFAULT_HOST}:{DEFAULT_PORT}"
18
+
19
+
20
+ def local_data_dir() -> Path:
21
+ return Path.home() / ".agentauth"
22
+
23
+
24
+ def _server_key(host: str, port: int) -> str:
25
+ safe_host = host.replace(":", "_").replace("/", "_")
26
+ return f"{safe_host}_{port}"
27
+
28
+
29
+ def local_db_path(host: str = DEFAULT_HOST, port: int = DEFAULT_PORT) -> Path:
30
+ return local_data_dir() / f"auth_{_server_key(host, port)}.db"
31
+
32
+
33
+ def local_log_path(host: str = DEFAULT_HOST, port: int = DEFAULT_PORT) -> Path:
34
+ return local_data_dir() / f"server_{_server_key(host, port)}.log"
35
+
36
+
37
+ def local_pid_path(host: str = DEFAULT_HOST, port: int = DEFAULT_PORT) -> Path:
38
+ return local_data_dir() / f"server_{_server_key(host, port)}.pid"
39
+
40
+
41
+ def ensure_local_env(host: str = DEFAULT_HOST, port: int = DEFAULT_PORT) -> dict[str, str]:
42
+ data_dir = local_data_dir()
43
+ data_dir.mkdir(parents=True, exist_ok=True)
44
+
45
+ env = os.environ.copy()
46
+ env.setdefault("STORAGE_BACKEND", "sqlite")
47
+ env.setdefault("DATABASE_URL", f"sqlite:///{local_db_path(host, port)}")
48
+ env.setdefault("JWT_SECRET_KEY", f"agentauth_local_{secrets.token_urlsafe(24)}")
49
+ env.setdefault("CORS_ORIGINS", "*")
50
+ return env
51
+
52
+
53
+ def is_running(pid: int) -> bool:
54
+ try:
55
+ os.kill(pid, 0)
56
+ except OSError:
57
+ return False
58
+ return True
59
+
60
+
61
+ def read_pid(host: str = DEFAULT_HOST, port: int = DEFAULT_PORT) -> int | None:
62
+ pid_path = local_pid_path(host, port)
63
+ if not pid_path.exists():
64
+ return None
65
+ try:
66
+ return int(pid_path.read_text().strip())
67
+ except Exception:
68
+ return None
69
+
70
+
71
+ def write_pid(pid: int, host: str = DEFAULT_HOST, port: int = DEFAULT_PORT) -> None:
72
+ local_pid_path(host, port).write_text(str(pid))
73
+
74
+
75
+ def server_url(host: str = DEFAULT_HOST, port: int = DEFAULT_PORT) -> str:
76
+ return f"http://{host}:{port}"
77
+
78
+
79
+ def wait_for_health(base_url: str, timeout_seconds: int = 20) -> bool:
80
+ deadline = time.time() + timeout_seconds
81
+ while time.time() < deadline:
82
+ try:
83
+ response = requests.get(f"{base_url}/health", timeout=2)
84
+ if response.ok:
85
+ return True
86
+ except requests.RequestException:
87
+ pass
88
+ time.sleep(0.5)
89
+ return False
90
+
91
+
92
+ def start_local_server(host: str = DEFAULT_HOST, port: int = DEFAULT_PORT) -> tuple[subprocess.Popen[bytes] | None, str]:
93
+ existing_pid = read_pid(host, port)
94
+ base_url = server_url(host, port)
95
+ if existing_pid and is_running(existing_pid) and wait_for_health(base_url, timeout_seconds=2):
96
+ return None, base_url
97
+
98
+ env = ensure_local_env(host, port)
99
+ log_path = local_log_path(host, port)
100
+ log_path.parent.mkdir(parents=True, exist_ok=True)
101
+
102
+ cmd = [
103
+ sys.executable,
104
+ "-m",
105
+ "uvicorn",
106
+ "auth_app.main:app",
107
+ "--host",
108
+ host,
109
+ "--port",
110
+ str(port),
111
+ ]
112
+
113
+ with log_path.open("ab") as log_file:
114
+ process = subprocess.Popen(
115
+ cmd,
116
+ cwd=str(project_root()),
117
+ env=env,
118
+ stdout=log_file,
119
+ stderr=subprocess.STDOUT,
120
+ )
121
+
122
+ write_pid(process.pid, host, port)
123
+ return process, base_url