Skip to content

Commit 9c0fd63

Browse files
committed
checkpoint
Signed-off-by: Radek Ježek <radek.jezek@ibm.com>
1 parent 947d2f0 commit 9c0fd63

File tree

116 files changed

+1723
-5484
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

116 files changed

+1723
-5484
lines changed

apps/agentstack-cli/src/agentstack_cli/__init__.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,10 @@
3838
╰────────────────────────────────────────────────────────────────────────────╯
3939
4040
╭─ Agent Management [Admin only] ────────────────────────────────────────────╮
41-
│ add Install an agent (Docker, GitHub)
41+
│ add Install an agent
4242
│ remove Uninstall an agent │
4343
│ update Update an agent │
44-
│ logs Stream agent execution logs │
45-
│ env Manage agent environment variables │
46-
│ build Build an agent remotely │
47-
│ client-side-build Build an agent container image locally │
44+
│ build Build an agent image locally │
4845
╰────────────────────────────────────────────────────────────────────────────╯
4946
5047
╭─ Platform & Configuration ─────────────────────────────────────────────────╮
@@ -100,7 +97,6 @@ def main(
10097
no_args_is_help=True,
10198
help="Manage Agent Stack platform. [Local only]",
10299
)
103-
app.add_typer(agentstack_cli.commands.build.app, name="", no_args_is_help=True, help="Build agent images.")
104100
app.add_typer(
105101
agentstack_cli.commands.server.app,
106102
name="server",
@@ -123,6 +119,8 @@ def main(
123119
# )
124120

125121

122+
app.add_typer(agentstack_cli.commands.build.app, name="", no_args_is_help=True, help="Build agent images.")
123+
126124
agent_alias = deepcopy(agentstack_cli.commands.agent.app)
127125
for cmd in agent_alias.registered_commands:
128126
cmd.rich_help_panel = "Agent commands"
@@ -153,12 +151,14 @@ async def ui():
153151
active_server = config.auth_manager.active_server
154152

155153
if active_server:
156-
if re.search(r"(localhost|127\.0\.0\.1):8333", active_server):
154+
if "agentstack-api.localtest.me" in active_server:
155+
ui_url = active_server.replace("agentstack-api.localtest.me", "agentstack.localtest.me")
156+
elif re.search(r"(localhost|127\.0\.0\.1):8333", active_server):
157157
ui_url = re.sub(r":8333", ":8334", active_server)
158158
else:
159159
ui_url = active_server
160160
else:
161-
ui_url = "http://localhost:8334"
161+
ui_url = "http://agentstack.localtest.me:8080"
162162

163163
webbrowser.open(ui_url)
164164

apps/agentstack-cli/src/agentstack_cli/api.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,10 @@ async def a2a_client(agent_card: AgentCard, context_token: ContextToken) -> Asyn
155155
@asynccontextmanager
156156
async def openai_client() -> AsyncIterator[openai.AsyncOpenAI]:
157157
async with Configuration().use_platform_client() as platform_client:
158+
headers = platform_client.headers.copy()
159+
headers.pop("Authorization", None)
158160
yield openai.AsyncOpenAI(
159161
api_key=platform_client.headers.get("Authorization", "").removeprefix("Bearer ") or "dummy",
160162
base_url=urllib.parse.urljoin(str(platform_client.base_url), urllib.parse.urljoin(API_BASE_URL, "openai")),
161-
default_headers=platform_client.headers,
163+
default_headers=headers,
162164
)

apps/agentstack-cli/src/agentstack_cli/auth_manager.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,51 @@ def save_auth_info(
155155
self._auth.servers[server] # touch
156156
self._save()
157157

158+
async def login_with_password(
159+
self,
160+
server: str,
161+
username: str,
162+
password: str,
163+
client_id: str = "agentstack-cli",
164+
) -> AuthToken:
165+
"""Authenticate using resource owner password grant (direct access)."""
166+
oauth_metadata = await self.fetch_oauth_protected_resource_metadata(server)
167+
auth_servers = oauth_metadata.get("authorization_servers", [])
168+
if not auth_servers:
169+
raise RuntimeError(f"No authorization servers found for {server}")
170+
171+
auth_server_url = auth_servers[0]
172+
oidc = await self.get_oidc_metadata(auth_server_url)
173+
token_endpoint = oidc["token_endpoint"]
174+
175+
async with httpx.AsyncClient() as client:
176+
resp = await client.post(
177+
token_endpoint,
178+
data={
179+
"grant_type": "password",
180+
"client_id": client_id,
181+
"username": username,
182+
"password": password,
183+
"scope": " ".join(oauth_metadata.get("scopes_supported", ["openid", "email", "profile"])),
184+
},
185+
)
186+
resp.raise_for_status()
187+
token_data = resp.json()
188+
189+
auth_token = AuthToken(**token_data)
190+
191+
self.save_auth_info(
192+
server=server,
193+
auth_server=auth_server_url,
194+
client_id=client_id,
195+
token=token_data,
196+
)
197+
self._auth.active_server = server
198+
self._auth.active_auth_server = auth_server_url
199+
self._save()
200+
201+
return auth_token
202+
158203
async def _exchange_refresh_token(self, auth_server: str, token: AuthToken) -> AuthToken:
159204
if not self._auth.active_server:
160205
raise ValueError("No active server configured")

0 commit comments

Comments
 (0)