agentkit-sdk-python 0.8.2__py3-none-any.whl → 0.8.4__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.
@@ -22,6 +22,7 @@ from contextlib import asynccontextmanager
22
22
  from typing import TYPE_CHECKING, Any
23
23
 
24
24
  import uvicorn
25
+ from a2a.types import AgentCard
25
26
  from fastapi import FastAPI, HTTPException, Request
26
27
  from fastapi.responses import StreamingResponse
27
28
  from google.adk.a2a.utils.agent_to_a2a import to_a2a
@@ -246,6 +247,12 @@ class AgentkitAgentServerApp(BaseAgentkitApp):
246
247
  app: App | None = None,
247
248
  allow_origins: list[str] | None = None,
248
249
  allow_origin_regex: str | list[str] | None = None,
250
+ a2a_host: str = "localhost",
251
+ a2a_port: int = 8000,
252
+ a2a_protocol: str = "http",
253
+ agent_card: AgentCard | str | None = None,
254
+ push_config_store: Any | None = None,
255
+ task_store: Any | None = None,
249
256
  enable_auth: bool = False,
250
257
  identity: IdentityRuntimeConfig | RuntimeIdentity | None = None,
251
258
  identity_health_routes: tuple[str, ...] = (),
@@ -291,7 +298,16 @@ class AgentkitAgentServerApp(BaseAgentkitApp):
291
298
  artifact_service=_artifact_service,
292
299
  credential_service=_credential_service,
293
300
  )
294
- to_a2a_kwargs: dict[str, Any] = {"agent": root_agent, "runner": runner}
301
+ to_a2a_kwargs: dict[str, Any] = {
302
+ "agent": root_agent,
303
+ "runner": runner,
304
+ "host": a2a_host,
305
+ "port": a2a_port,
306
+ "protocol": a2a_protocol,
307
+ "agent_card": agent_card,
308
+ "push_config_store": push_config_store,
309
+ "task_store": task_store,
310
+ }
295
311
  if enable_auth:
296
312
  to_a2a_kwargs["agent_executor_factory"] = (
297
313
  build_a2a_inbound_auth_executor_factory(
agentkit/auth/_openapi.py CHANGED
@@ -12,18 +12,22 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- """Minimal signed Volcengine OpenAPI client for the auth ADMIN commands.
15
+ """Minimal signed OpenAPI client for the auth ADMIN commands.
16
16
 
17
17
  Stdlib-only SigV4 (reusing :mod:`agentkit.auth._sigv4`) so the admin path that
18
18
  provisions the UserPool client / IAM OIDC provider / STS role carries no
19
19
  third-party dependency. Used only by ``agentkit auth admin`` — the end-user login
20
20
  path never touches it. A mandatory ``GetCallerIdentity`` guard runs before any write.
21
+
22
+ Credentials and the OpenAPI gateway host are resolved through the SDK's unified,
23
+ Cloud-Provider-aware chain (:class:`agentkit.platform.configuration.VolcConfiguration`),
24
+ so ``CLOUD_PROVIDER=byteplus`` uses ``BYTEPLUS_ACCESS_KEY`` / ``BYTEPLUS_SECRET_KEY``
25
+ and ``open.byteplusapi.com`` instead of the Volcengine equivalents.
21
26
  """
22
27
 
23
28
  from __future__ import annotations
24
29
 
25
30
  import json
26
- import os
27
31
  import urllib.error
28
32
  import urllib.parse
29
33
  import urllib.request
@@ -31,8 +35,9 @@ import urllib.request
31
35
  from agentkit.auth._sigv4 import sign_headers
32
36
  from agentkit.auth.errors import AuthError
33
37
  from agentkit.auth.ssl_trust import harden_default_ssl_context
38
+ from agentkit.platform.configuration import VolcConfiguration
39
+ from agentkit.platform.provider import CloudProvider
34
40
 
35
- _HOST = "open.volcengineapi.com"
36
41
  # Services whose OpenAPI reads parameters from the query string, not a JSON body.
37
42
  _QUERY_PARAM_SERVICES = {"iam"}
38
43
 
@@ -85,21 +90,51 @@ class OpenApiClient:
85
90
  access_key: str | None = None,
86
91
  secret_key: str | None = None,
87
92
  session_token: str | None = None,
88
- region: str = "cn-beijing",
93
+ region: str | None = None,
89
94
  expect_account: str | None = None,
90
95
  harden_ssl: bool = True,
91
96
  ) -> None:
92
97
  if harden_ssl:
93
98
  harden_default_ssl_context()
94
- self.ak = access_key or os.getenv("VOLCENGINE_ACCESS_KEY") or os.getenv("VOLC_ACCESSKEY")
95
- self.sk = secret_key or os.getenv("VOLCENGINE_SECRET_KEY") or os.getenv("VOLC_SECRETKEY")
96
- self.token = session_token or os.getenv("VOLCENGINE_SESSION_TOKEN")
97
- if not (self.ak and self.sk):
99
+ # Credentials/region come from the SDK's unified provider-aware chain
100
+ # (CLOUD_PROVIDER=volcengine|byteplus), so the admin path accepts the same
101
+ # sources as the runtime clients: BYTEPLUS_* on BytePlus, VOLCENGINE_* /
102
+ # VOLC_* on Volcengine, plus ~/.agentkit/config.yaml.
103
+ cfg = VolcConfiguration(
104
+ region=region,
105
+ access_key=access_key,
106
+ secret_key=secret_key,
107
+ session_token=session_token,
108
+ )
109
+ self.provider = cfg.provider
110
+ if self.provider == CloudProvider.BYTEPLUS:
111
+ provider_label = "BytePlus"
112
+ self.cred_env_hint = "BYTEPLUS_ACCESS_KEY / BYTEPLUS_SECRET_KEY"
113
+ else:
114
+ provider_label = "Volcengine"
115
+ self.cred_env_hint = "VOLCENGINE_ACCESS_KEY / VOLCENGINE_SECRET_KEY"
116
+ try:
117
+ creds = cfg.get_service_credentials("iam")
118
+ except ValueError as exc:
119
+ raise AuthError(
120
+ f"admin provisioning needs {provider_label} credentials.",
121
+ hint=f"export {self.cred_env_hint} for the account that owns the UserPool.",
122
+ ) from exc
123
+ if creds.source == "sso-sts":
124
+ # `agentkit login` stores the END-USER sandbox STS role; provisioning
125
+ # UserPool/IAM resources needs the account's long-lived admin AK/SK.
98
126
  raise AuthError(
99
- "admin provisioning needs Volcengine credentials.",
100
- hint="export VOLCENGINE_ACCESS_KEY / VOLCENGINE_SECRET_KEY for the account that owns the UserPool.",
127
+ "admin provisioning cannot use the SSO login session (it carries the "
128
+ "end-user sandbox role, not account admin rights).",
129
+ hint=f"export {self.cred_env_hint} for the account that owns the UserPool.",
101
130
  )
102
- self.region = region
131
+ self.ak = creds.access_key
132
+ self.sk = creds.secret_key
133
+ self.token = session_token or creds.session_token
134
+ # Every admin control-plane call signs against the provider's top OpenAPI
135
+ # gateway — the same host that serves the provider's IAM service.
136
+ self._host = cfg.get_service_endpoint("iam").host
137
+ self.region = cfg.region
103
138
  ident = self.call("sts", "GetCallerIdentity", "2018-01-01", {})
104
139
  self.account_id = str(ident.get("AccountId") or "")
105
140
  if expect_account and self.account_id != expect_account:
@@ -121,11 +156,11 @@ class OpenApiClient:
121
156
  query = {"Action": action, "Version": version}
122
157
  payload = json.dumps(body).encode()
123
158
  headers = sign_headers(
124
- "POST", _HOST, query, payload,
159
+ "POST", self._host, query, payload,
125
160
  access_key=self.ak, secret_key=self.sk, service=service, region=self.region,
126
161
  session_token=self.token,
127
162
  )
128
- url = f"https://{_HOST}/?{urllib.parse.urlencode(query)}"
163
+ url = f"https://{self._host}/?{urllib.parse.urlencode(query)}"
129
164
  req = urllib.request.Request(url, data=payload, headers=headers, method="POST")
130
165
  try:
131
166
  raw = urllib.request.urlopen(req, timeout=30).read()
@@ -147,11 +182,11 @@ class OpenApiClient:
147
182
  else:
148
183
  query[k] = str(v)
149
184
  headers = sign_headers(
150
- "GET", _HOST, query, b"",
185
+ "GET", self._host, query, b"",
151
186
  access_key=self.ak, secret_key=self.sk, service=service, region=self.region,
152
187
  session_token=self.token,
153
188
  )
154
- url = f"https://{_HOST}/?{urllib.parse.urlencode(query)}"
189
+ url = f"https://{self._host}/?{urllib.parse.urlencode(query)}"
155
190
  req = urllib.request.Request(url, headers=headers, method="GET")
156
191
  try:
157
192
  raw = urllib.request.urlopen(req, timeout=30).read()
agentkit/auth/admin.py CHANGED
@@ -73,9 +73,10 @@ class CliAccessCoords:
73
73
  client_id: str
74
74
  role_trn: str
75
75
  provider_trn: str
76
+ sts_host: str | None = None # provider STS endpoint (None = Volcengine default)
76
77
 
77
78
  def discovery_doc(self) -> dict:
78
- return {
79
+ doc = {
79
80
  "issuer": self.issuer,
80
81
  "client_id": self.client_id,
81
82
  "role_trn": self.role_trn,
@@ -84,12 +85,68 @@ class CliAccessCoords:
84
85
  "transport": "sts",
85
86
  "scope": "openid profile email offline_access",
86
87
  }
88
+ if self.sts_host:
89
+ doc["sts_host"] = self.sts_host
90
+ return doc
91
+
92
+
93
+ def tos_public_host(region: str) -> str:
94
+ """Provider-aware public host of the TOS static-site endpoint for *region*.
95
+
96
+ ``tos-<region>.volces.com`` on Volcengine, ``tos-<region>.bytepluses.com`` on
97
+ BytePlus — resolved from the platform service registry, not hardcoded here.
98
+ """
99
+ from agentkit.platform.configuration import VolcConfiguration
100
+
101
+ return VolcConfiguration(region=region).get_service_endpoint("tos").host
102
+
103
+
104
+ def sts_public_host(region: str) -> str:
105
+ """Provider-aware STS endpoint for *region*, from the platform service registry.
106
+
107
+ Published in the discovery doc as ``sts_host`` so the end-user login exchanges
108
+ the id_token against the pool's own cloud (BytePlus pools must not call the
109
+ Volcengine STS).
110
+ """
111
+ from agentkit.platform.configuration import VolcConfiguration
112
+
113
+ return VolcConfiguration(region=region).get_service_endpoint("sts").host
87
114
 
88
115
 
89
116
  def _issuer(user_pool_uid: str, region: str) -> str:
117
+ # Volcengine UserPool issuer domain template — LAST-RESORT fallback only.
118
+ # The real issuer is read from the platform (GetUserPool.IssuerUrl), which is
119
+ # provider-correct by construction; this template is wrong on BytePlus.
90
120
  return f"https://userpool-{user_pool_uid}.userpool.auth.id.{region}.volces.com"
91
121
 
92
122
 
123
+ def _pool_info(api: OpenApiClient, user_pool_uid: str) -> dict:
124
+ """Best-effort GetUserPool detail; {} when the call fails."""
125
+ try:
126
+ return api.call("id", "GetUserPool", "2025-10-30", {"UserPoolUid": user_pool_uid})
127
+ except (ApiError, AuthError):
128
+ return {}
129
+
130
+
131
+ def resolve_issuer(api: OpenApiClient, user_pool_uid: str, region: str) -> str:
132
+ """The pool's real issuer URL, read from the platform.
133
+
134
+ ``GetUserPool`` returns ``IssuerUrl`` (and ``Domain`` / ``CustomDomain``), so the
135
+ issuer is whatever domain the current cloud provider actually serves — no
136
+ hardcoded domain. IAM's ``CreateOIDCProvider`` validates the issuer's OIDC
137
+ discovery endpoint, so a template-guessed domain fails on BytePlus.
138
+ Falls back to the Volcengine template only if the platform returns nothing.
139
+ """
140
+ info = _pool_info(api, user_pool_uid)
141
+ issuer = str(info.get("IssuerUrl") or "").rstrip("/")
142
+ if issuer:
143
+ return issuer
144
+ domain = str(info.get("CustomDomain") or info.get("Domain") or "").strip()
145
+ if domain:
146
+ return f"https://{domain}"
147
+ return _issuer(user_pool_uid, region)
148
+
149
+
93
150
  def identity_console_url(region: str = "cn-beijing", *, user_pool_uid: str | None = None) -> str:
94
151
  """Volcengine console URL for the Identity (UserPool) management page.
95
152
 
@@ -100,16 +157,47 @@ def identity_console_url(region: str = "cn-beijing", *, user_pool_uid: str | Non
100
157
 
101
158
 
102
159
  def create_user_pool(name: str, *, region: str = "cn-beijing", api: OpenApiClient | None = None) -> tuple[str, str]:
103
- """Create a UserPool; return ``(uid, issuer)``."""
160
+ """Create (or, on a re-run, reuse) the UserPool named ``name``; return ``(uid, issuer)``.
161
+
162
+ A same-name pool left by an earlier run is reused instead of failing with
163
+ ``Duplicated`` — sso-setup must stay idempotent to re-run.
164
+ """
104
165
  api = api or OpenApiClient(region=region)
105
- res = api.call("id", "CreateUserPool", "2025-10-30", {
106
- "Name": name, "Description": "AgentKit CLI login pool",
107
- "PasswordSignInEnabled": True, "SelfSignUpEnabled": False,
108
- })
166
+ try:
167
+ res = api.call("id", "CreateUserPool", "2025-10-30", {
168
+ "Name": name, "Description": "AgentKit CLI login pool",
169
+ "PasswordSignInEnabled": True, "SelfSignUpEnabled": False,
170
+ })
171
+ except ApiError as exc:
172
+ if not any(k in exc.code for k in ("Duplicat", "Exist", "Conflict")):
173
+ raise
174
+ existing = _find_pool_by_name(api, name)
175
+ if not existing:
176
+ raise
177
+ return existing, resolve_issuer(api, existing, region)
109
178
  uid = str(res.get("Uid") or res.get("uid") or "")
110
179
  if not uid:
111
180
  raise AuthError(f"CreateUserPool returned no uid: {json.dumps(res)[:200]}")
112
- return uid, _issuer(uid, region)
181
+ return uid, resolve_issuer(api, uid, region)
182
+
183
+
184
+ def _find_pool_by_name(api: OpenApiClient, name: str) -> str | None:
185
+ """Uid of the pool named ``name``, or None. Raises if the name is ambiguous."""
186
+ matches: list[str] = []
187
+ page = 1
188
+ while page <= 10: # 500 pools is far beyond any real account
189
+ r = api.call("id", "ListUserPools", "2025-10-30", {"PageNumber": page, "PageSize": 50})
190
+ data = r.get("Data") or []
191
+ matches += [str(p.get("Uid")) for p in data if p.get("Name") == name and p.get("Uid")]
192
+ if len(data) < 50:
193
+ break
194
+ page += 1
195
+ if len(matches) > 1:
196
+ raise AuthError(
197
+ f"{len(matches)} user pools are named {name!r}; pass the intended one "
198
+ "explicitly with --user-pool <uid>."
199
+ )
200
+ return matches[0] if matches else None
113
201
 
114
202
 
115
203
  def _ensure_cli_client(api: OpenApiClient, user_pool_uid: str, client_name: str = CLI_CLIENT_NAME) -> str:
@@ -182,18 +270,33 @@ def _ensure_role(
182
270
  ) -> None:
183
271
  trust = {"Statement": [{"Effect": "Allow", "Principal": {"Federated": [provider_trn]},
184
272
  "Action": ["sts:AssumeRoleWithOIDC"]}]}
273
+ # Probe existence BEFORE CreateRole: an account at its RolesPerAccount quota
274
+ # returns LimitExceeded before the duplicate-name check, which would wrongly
275
+ # kill re-runs (and --role-name reuse) even though the role is already there.
276
+ role_exists = True
185
277
  try:
186
- api.call("iam", "CreateRole", "2018-01-01", {
187
- "RoleName": role_name, "DisplayName": role_name,
188
- "TrustPolicyDocument": json.dumps(trust), "MaxSessionDuration": 3600,
189
- "Description": "STS role for AgentKit CLI (UserPool federated)",
190
- })
278
+ api.call("iam", "GetRole", "2018-01-01", {"RoleName": role_name})
191
279
  except ApiError as exc:
192
- if "Exist" not in exc.code and "Conflict" not in exc.code:
280
+ if not any(k in exc.code for k in ("NotExist", "NoSuchEntity", "NotFound")):
193
281
  raise
282
+ role_exists = False
283
+ if role_exists:
194
284
  api.call("iam", "UpdateRole", "2018-01-01",
195
285
  {"RoleName": role_name, "TrustPolicyDocument": json.dumps(trust),
196
286
  "MaxSessionDuration": 3600})
287
+ else:
288
+ try:
289
+ api.call("iam", "CreateRole", "2018-01-01", {
290
+ "RoleName": role_name, "DisplayName": role_name,
291
+ "TrustPolicyDocument": json.dumps(trust), "MaxSessionDuration": 3600,
292
+ "Description": "STS role for AgentKit CLI (UserPool federated)",
293
+ })
294
+ except ApiError as exc:
295
+ if "Exist" not in exc.code and "Conflict" not in exc.code:
296
+ raise
297
+ api.call("iam", "UpdateRole", "2018-01-01",
298
+ {"RoleName": role_name, "TrustPolicyDocument": json.dumps(trust),
299
+ "MaxSessionDuration": 3600})
197
300
  doc = {"Statement": [{"Effect": "Allow", "Action": list(ROLE_ACTIONS), "Resource": ["*"]}]}
198
301
  api.call_ok("iam", "CreatePolicy", "2018-01-01",
199
302
  {"PolicyName": policy_name, "PolicyDocument": json.dumps(doc),
@@ -233,7 +336,7 @@ def provision_cli_access(
233
336
  """
234
337
  api = api or OpenApiClient(region=region, expect_account=account_id)
235
338
  acct = account_id or api.account_id
236
- issuer = _issuer(user_pool_uid, region)
339
+ issuer = resolve_issuer(api, user_pool_uid, region)
237
340
  client_id = _ensure_cli_client(api, user_pool_uid, client_name)
238
341
  if not client_id:
239
342
  raise AuthError("could not create or find the public CLI client")
@@ -243,6 +346,7 @@ def provision_cli_access(
243
346
  return CliAccessCoords(
244
347
  account_id=acct, region=region, user_pool_uid=user_pool_uid, issuer=issuer,
245
348
  client_id=client_id, role_trn=f"trn:iam::{acct}:role/{role_name}", provider_trn=provider_trn,
349
+ sts_host=sts_public_host(region),
246
350
  )
247
351
 
248
352
 
@@ -277,7 +381,12 @@ def ensure_federation(
277
381
  preset = _IDP_PRESETS.get(idp)
278
382
  if not preset:
279
383
  raise AuthError(f"unknown idp {idp!r}; supported: {', '.join(_IDP_PRESETS)}")
280
- callback = f"{_issuer(user_pool_uid, region)}/login/generic_oauth/callback"
384
+ # The platform publishes the pool's exact OAuth callback; derive it from the
385
+ # resolved issuer only when the field is absent.
386
+ info = _pool_info(api, user_pool_uid)
387
+ callback = str(info.get("OauthLoginCallbackUrl") or "") or (
388
+ f"{resolve_issuer(api, user_pool_uid, region)}/login/generic_oauth/callback"
389
+ )
281
390
  lst = api.call("id", "ListIdentityProviders", "2025-10-30",
282
391
  {"UserPoolUID": user_pool_uid, "PageNumber": 1, "PageSize": 50})
283
392
  for it in (lst.get("Data") or lst.get("data") or []):
@@ -349,7 +458,7 @@ def sso_setup(
349
458
  if custom_domain:
350
459
  manual.append(
351
460
  f"把自定义域名指向该 bucket:CNAME {custom_domain} -> "
352
- f"{bucket}.tos-{region}.volces.com,并配置 https 证书(TOS/CDN)。"
461
+ f"{bucket}.{tos_public_host(region)},并配置 https 证书(TOS/CDN)。"
353
462
  )
354
463
  return SsoSetupResult(login_address=url, coords=coords, manual_steps=manual)
355
464
 
@@ -371,18 +480,28 @@ def publish_discovery(
371
480
  The returned URL is what the end user types: ``agentkit login <url>``.
372
481
  """
373
482
  try:
374
- import os as _os
375
-
376
483
  import tos # type: ignore
377
484
  except Exception as exc: # pragma: no cover - optional dep
378
485
  raise AuthError(
379
486
  "publishing needs the `tos` package (`pip install tos`), or host the "
380
487
  "discovery doc yourself.",
381
488
  ) from exc
382
- ak = access_key or _os.getenv("VOLCENGINE_ACCESS_KEY")
383
- sk = secret_key or _os.getenv("VOLCENGINE_SECRET_KEY")
384
- token = session_token or _os.getenv("VOLCENGINE_SESSION_TOKEN")
385
- endpoint = f"tos-{coords.region}.volces.com"
489
+ from agentkit.platform.configuration import VolcConfiguration
490
+
491
+ cfg = VolcConfiguration(
492
+ region=coords.region, access_key=access_key, secret_key=secret_key,
493
+ session_token=session_token,
494
+ )
495
+ try:
496
+ creds = cfg.get_service_credentials("tos")
497
+ except ValueError as exc:
498
+ raise AuthError(
499
+ "publishing the discovery doc needs cloud credentials for TOS.",
500
+ hint=str(exc).split("\n")[0],
501
+ ) from exc
502
+ ak, sk = creds.access_key, creds.secret_key
503
+ token = session_token or creds.session_token
504
+ endpoint = cfg.get_service_endpoint("tos").host
386
505
  client = tos.TosClientV2(ak, sk, endpoint, coords.region, security_token=token)
387
506
  try:
388
507
  client.create_bucket(bucket, acl=tos.ACLType.ACL_Public_Read)
@@ -453,7 +572,7 @@ def preflight(api: OpenApiClient, *, credential_hosting: bool = True) -> list[di
453
572
  checks.append({"name": name, "status": "warn", "detail": str(exc)[:80], "fix": fix})
454
573
 
455
574
  probe("caller identity (STS)", lambda: f"account {api.account_id}",
456
- "export a valid admin VOLCENGINE_ACCESS_KEY / _SECRET_KEY")
575
+ f"export a valid admin {api.cred_env_hint}")
457
576
  def _pools():
458
577
  r = api.call("id", "ListUserPools", "2025-10-30", {"PageNumber": 1, "PageSize": 1})
459
578
  return f"reachable ({r.get('TotalCount') or r.get('Total') or len(r.get('Items') or r.get('Data') or [])}+ pools)"
agentkit/auth/profile.py CHANGED
@@ -35,7 +35,7 @@ from agentkit.auth.errors import AuthError
35
35
 
36
36
  _PROFILE_FIELDS = {
37
37
  "name", "issuer", "client_id", "role_trn", "provider_trn",
38
- "region", "scope", "transport", "address",
38
+ "region", "scope", "transport", "address", "sts_host",
39
39
  }
40
40
 
41
41
 
@@ -52,6 +52,7 @@ class AuthProfile:
52
52
  scope: str = "openid profile email offline_access"
53
53
  transport: str = "sts" # "sts" (sandbox) | reserved for future transports
54
54
  address: str | None = None # the login address this profile was resolved from
55
+ sts_host: str | None = None # provider STS endpoint from the discovery doc (None = Volcengine default)
55
56
 
56
57
  def validate(self) -> "AuthProfile":
57
58
  missing = [k for k in ("name", "issuer", "client_id", "role_trn") if not getattr(self, k)]
agentkit/auth/resolve.py CHANGED
@@ -55,6 +55,7 @@ _ALIASES = {
55
55
  "region": ("region",),
56
56
  "transport": ("transport",),
57
57
  "scope": ("scope",),
58
+ "sts_host": ("sts_host", "stsHost"),
58
59
  }
59
60
 
60
61
 
@@ -175,7 +176,7 @@ def resolve_profile(address: str, *, timeout: float = _TIMEOUT, harden_ssl: bool
175
176
  return AuthProfile(
176
177
  name=name, issuer=str(issuer), client_id=str(client_id), role_trn=str(role_trn),
177
178
  provider_trn=provider_trn, region=region, scope=scope, transport=transport,
178
- address=base,
179
+ address=base, sts_host=disc.get("sts_host"),
179
180
  ).validate()
180
181
 
181
182
 
agentkit/auth/session.py CHANGED
@@ -304,6 +304,7 @@ class AuthSession:
304
304
  self.profile.role_trn,
305
305
  self.profile.provider_trn,
306
306
  duration_seconds=self._duration,
307
+ host=self.profile.sts_host,
307
308
  )
308
309
  self._sts = StsCredentials(
309
310
  access_key=assumed.access_key_id,
agentkit/auth/sso.py CHANGED
@@ -80,13 +80,14 @@ def login(
80
80
  refresh_token = token.get("refresh_token")
81
81
 
82
82
  assumed = assume_role_with_oidc(
83
- id_token, prof.role_trn, prof.provider_trn, duration_seconds=duration_seconds
83
+ id_token, prof.role_trn, prof.provider_trn, duration_seconds=duration_seconds,
84
+ host=prof.sts_host,
84
85
  )
85
86
  account = None
86
87
  try:
87
88
  ident = get_caller_identity(
88
89
  assumed.access_key_id, assumed.secret_access_key, assumed.session_token,
89
- region=prof.region,
90
+ region=prof.region, host=prof.sts_host,
90
91
  )
91
92
  account = ident.get("AccountId")
92
93
  except Exception:
@@ -154,7 +155,8 @@ def whoami(profile: str | None = None, *, harden_ssl: bool = True) -> dict:
154
155
  raise AuthError("not logged in.", hint="run `agentkit login` first.")
155
156
  creds = session.credentials()
156
157
  ident = get_caller_identity(
157
- creds.access_key, creds.secret_key, creds.session_token, region=session.profile.region
158
+ creds.access_key, creds.secret_key, creds.session_token,
159
+ region=session.profile.region, host=session.profile.sts_host,
158
160
  )
159
161
  ident["_profile"] = session.profile.name
160
162
  ident["_expires_at"] = creds.expires_at.isoformat() if creds.expires_at else None
agentkit/auth/sts.py CHANGED
@@ -73,13 +73,16 @@ def assume_role_with_oidc(
73
73
  role_session_name: str = "agentkit-cli",
74
74
  duration_seconds: int = 3600,
75
75
  timeout: float = _TIMEOUT,
76
+ host: str | None = None,
76
77
  ) -> AssumedRole:
77
78
  """Exchange an OIDC ``id_token`` for temporary STS credentials.
78
79
 
79
- Anonymous call — the token is the credential. ``host`` MUST be
80
- ``sts.volcengineapi.com``; the token is too long for the query string so it
81
- travels in the POST body.
80
+ Anonymous call — the token is the credential; it is too long for the query
81
+ string so it travels in the POST body. ``host`` is the STS endpoint from the
82
+ login profile (the discovery doc's ``sts_host``, so BytePlus pools use the
83
+ BytePlus STS); it defaults to the Volcengine endpoint for older docs.
82
84
  """
85
+ sts_host = host or STS_HOST
83
86
  params = {
84
87
  "RoleTrn": role_trn,
85
88
  "OIDCToken": id_token,
@@ -89,7 +92,7 @@ def assume_role_with_oidc(
89
92
  if provider_trn:
90
93
  params["OIDCProviderTrn"] = provider_trn
91
94
  body = urllib.parse.urlencode(params).encode("utf-8")
92
- url = f"https://{STS_HOST}/?Action=AssumeRoleWithOIDC&Version={STS_VERSION}"
95
+ url = f"https://{sts_host}/?Action=AssumeRoleWithOIDC&Version={STS_VERSION}"
93
96
  req = urllib.request.Request(
94
97
  url, data=body, headers={"Content-Type": "application/x-www-form-urlencoded"}, method="POST"
95
98
  )
@@ -103,7 +106,7 @@ def assume_role_with_oidc(
103
106
  "id_token's aud is in the provider's client-id allow-list.",
104
107
  ) from exc
105
108
  except urllib.error.URLError as exc:
106
- raise NetworkError(f"cannot reach STS endpoint ({STS_HOST}): {exc.reason}") from exc
109
+ raise NetworkError(f"cannot reach STS endpoint ({sts_host}): {exc.reason}") from exc
107
110
 
108
111
  try:
109
112
  creds = json.loads(raw)["Result"]["Credentials"]
@@ -121,15 +124,17 @@ def get_caller_identity(
121
124
  *,
122
125
  region: str = "cn-beijing",
123
126
  timeout: float = _TIMEOUT,
127
+ host: str | None = None,
124
128
  ) -> dict:
125
129
  """Return the verified identity (``AccountId`` / ``IdentityType`` / ``UserId``)."""
130
+ sts_host = host or STS_HOST
126
131
  query = {"Action": "GetCallerIdentity", "Version": STS_VERSION}
127
132
  headers = sign_headers(
128
- "POST", STS_HOST, query, b"",
133
+ "POST", sts_host, query, b"",
129
134
  access_key=access_key, secret_key=secret_key, service="sts", region=region,
130
135
  session_token=session_token,
131
136
  )
132
- url = f"https://{STS_HOST}/?" + urllib.parse.urlencode(query)
137
+ url = f"https://{sts_host}/?" + urllib.parse.urlencode(query)
133
138
  req = urllib.request.Request(url, data=b"", headers=headers, method="POST")
134
139
  try:
135
140
  raw = urllib.request.urlopen(req, timeout=timeout).read()
@@ -137,5 +142,5 @@ def get_caller_identity(
137
142
  detail = redact(exc.read().decode("utf-8", "replace"))[:200]
138
143
  raise SsoError(f"GetCallerIdentity failed: {detail}") from exc
139
144
  except urllib.error.URLError as exc:
140
- raise NetworkError(f"cannot reach STS endpoint ({STS_HOST}): {exc.reason}") from exc
145
+ raise NetworkError(f"cannot reach STS endpoint ({sts_host}): {exc.reason}") from exc
141
146
  return json.loads(raw).get("Result") or {}
@@ -146,7 +146,8 @@ class VolcConfiguration:
146
146
  1. Explicitly passed in constructor
147
147
  2. Environment variable (VOLCENGINE_REGION / VOLC_REGION)
148
148
  3. Global config file (~/.agentkit/config.yaml)
149
- 4. Default (cn-beijing)
149
+ 4. Environment variable (REGION)
150
+ 5. Default (cn-beijing)
150
151
  """
151
152
  if self._region:
152
153
  return self._region
@@ -163,6 +164,7 @@ class VolcConfiguration:
163
164
  or os.getenv("VOLC_REGION")
164
165
  or get_global_config_str("region")
165
166
  or get_global_config_str("volcengine", "region")
167
+ or os.getenv("REGION")
166
168
  )
167
169
 
168
170
  if base_region:
@@ -409,7 +411,9 @@ class VolcConfiguration:
409
411
  else:
410
412
  ak = os.getenv("VOLCENGINE_ACCESS_KEY") or os.getenv("VOLC_ACCESSKEY")
411
413
  sk = os.getenv("VOLCENGINE_SECRET_KEY") or os.getenv("VOLC_SECRETKEY")
412
- token = os.getenv("VOLCENGINE_SESSION_TOKEN") or os.getenv("VOLC_SESSIONTOKEN")
414
+ token = os.getenv("VOLCENGINE_SESSION_TOKEN") or os.getenv(
415
+ "VOLC_SESSIONTOKEN"
416
+ )
413
417
 
414
418
  if ak and sk:
415
419
  return Credentials(
@@ -16,7 +16,8 @@ from __future__ import annotations
16
16
 
17
17
  from typing import Dict
18
18
 
19
- from agentkit.client import BaseAgentkitClient
19
+ from agentkit.client.base_service_client import BaseServiceClient
20
+ from agentkit.platform.configuration import VolcConfiguration
20
21
  from agentkit.sdk.identity.types import (
21
22
  CreateInboundAuthConfigRequest,
22
23
  CreateInboundAuthConfigResponse,
@@ -27,7 +28,7 @@ from agentkit.sdk.identity.types import (
27
28
  )
28
29
 
29
30
 
30
- class AgentkitIdentityClient(BaseAgentkitClient):
31
+ class AgentkitIdentityClient(BaseServiceClient):
31
32
  """AgentKit Identity / Inbound Auth Config Service."""
32
33
 
33
34
  API_ACTIONS: Dict[str, str] = {
@@ -44,11 +45,16 @@ class AgentkitIdentityClient(BaseAgentkitClient):
44
45
  session_token: str = "",
45
46
  ) -> None:
46
47
  super().__init__(
48
+ service="agent_identity",
47
49
  access_key=access_key,
48
50
  secret_key=secret_key,
49
51
  region=region,
50
52
  session_token=session_token,
51
53
  service_name="identity",
54
+ platform_config=VolcConfiguration(
55
+ region=region or None,
56
+ provider="volcengine",
57
+ ),
52
58
  )
53
59
 
54
60
  def create_inbound_auth_config(
@@ -15,9 +15,8 @@
15
15
  # Request/response models for the InboundAuthConfig APIs.
16
16
  #
17
17
  # ``CreateInboundAuthConfig`` mirrors the published OpenAPI definition
18
- # (Version 2025-10-30). ``ListInboundAuthConfigs`` and
19
- # ``DeleteInboundAuthConfig`` follow the standard Volcengine list/delete
20
- # conventions; adjust the field names here if the published specs differ.
18
+ # (Version 2025-10-30). ``ListInboundAuthConfigs`` uses the id service's
19
+ # PageNumber/PageSize pagination contract.
21
20
 
22
21
  from __future__ import annotations
23
22
 
@@ -32,15 +31,20 @@ class IdentityBaseModel(BaseModel):
32
31
 
33
32
 
34
33
  # Data Types
35
- class ApiKeyMetadata(IdentityBaseModel):
36
- location: Optional[str] = Field(default=None, alias="Location")
34
+ class ApiKeyInfo(IdentityBaseModel):
35
+ location: str = Field(..., alias="Location")
37
36
  parameter_name: Optional[str] = Field(default=None, alias="ParameterName")
37
+ prefix: Optional[str] = Field(default=None, alias="Prefix")
38
+
39
+
40
+ # Backward-compatible name used by earlier SDK code.
41
+ ApiKeyMetadata = ApiKeyInfo
38
42
 
39
43
 
40
44
  class ApiKeyAuthConfig(IdentityBaseModel):
41
45
  api_key_name: str = Field(..., alias="ApiKeyName")
42
46
  api_key: Optional[str] = Field(default=None, alias="ApiKey")
43
- api_key_metadata: Optional[list[ApiKeyMetadata]] = Field(
47
+ api_key_metadata: Optional[list[ApiKeyInfo]] = Field(
44
48
  default=None, alias="ApiKeyMetadata"
45
49
  )
46
50
  expiry_timestamp: Optional[int] = Field(default=None, alias="ExpiryTimestamp")
@@ -54,72 +58,62 @@ class JwtAuthConfig(IdentityBaseModel):
54
58
  allowed_clients: Optional[list[str]] = Field(default=None, alias="AllowedClients")
55
59
 
56
60
 
57
- # CreateInboundAuthConfig - Request
58
- class CreateInboundAuthConfigRequest(IdentityBaseModel):
61
+ class InboundAuthConfig(IdentityBaseModel):
62
+ trn: str = Field(..., alias="Trn")
63
+ inbound_auth_config_id: str = Field(..., alias="InboundAuthConfigId")
64
+ config_name: str = Field(..., alias="ConfigName")
65
+ description: Optional[str] = Field(default=None, alias="Description")
59
66
  auth_type: str = Field(..., alias="AuthType")
60
- api_key_auth_configs: Optional[list[ApiKeyAuthConfig]] = Field(
61
- default=None, alias="ApiKeyAuthConfigs"
62
- )
63
67
  jwt_auth_config: Optional[JwtAuthConfig] = Field(
64
68
  default=None, alias="JwtAuthConfig"
65
69
  )
66
- config_name: Optional[str] = Field(default=None, alias="ConfigName")
67
- description: Optional[str] = Field(default=None, alias="Description")
70
+ api_key_auth_configs: Optional[list[ApiKeyAuthConfig]] = Field(
71
+ default=None, alias="ApiKeyAuthConfigs"
72
+ )
73
+ created_at: str = Field(..., alias="CreatedAt")
74
+ updated_at: str = Field(..., alias="UpdatedAt")
68
75
  instance_id: Optional[str] = Field(default=None, alias="InstanceId")
69
76
 
70
77
 
71
- # CreateInboundAuthConfig - Response
72
- class CreateInboundAuthConfigResponse(IdentityBaseModel):
73
- inbound_auth_config_id: Optional[str] = Field(
74
- default=None, alias="InboundAuthConfigId"
75
- )
76
- trn: Optional[str] = Field(default=None, alias="Trn")
78
+ # CreateInboundAuthConfig - Request
79
+ class CreateInboundAuthConfigRequest(IdentityBaseModel):
77
80
  config_name: Optional[str] = Field(default=None, alias="ConfigName")
78
81
  description: Optional[str] = Field(default=None, alias="Description")
79
- auth_type: Optional[str] = Field(default=None, alias="AuthType")
80
- jwt_auth_config: Optional[JwtAuthConfig] = Field(
81
- default=None, alias="JwtAuthConfig"
82
- )
82
+ auth_type: str = Field(..., alias="AuthType")
83
+ instance_id: Optional[str] = Field(default=None, alias="InstanceId")
83
84
  api_key_auth_configs: Optional[list[ApiKeyAuthConfig]] = Field(
84
85
  default=None, alias="ApiKeyAuthConfigs"
85
86
  )
86
- instance_id: Optional[str] = Field(default=None, alias="InstanceId")
87
- created_at: Optional[str] = Field(default=None, alias="CreatedAt")
88
- updated_at: Optional[str] = Field(default=None, alias="UpdatedAt")
87
+ jwt_auth_config: Optional[JwtAuthConfig] = Field(
88
+ default=None, alias="JwtAuthConfig"
89
+ )
90
+
91
+
92
+ # CreateInboundAuthConfig - Response
93
+ class CreateInboundAuthConfigResponse(InboundAuthConfig):
94
+ pass
89
95
 
90
96
 
91
97
  # ListInboundAuthConfigs - Request
92
98
  class ListInboundAuthConfigsRequest(IdentityBaseModel):
99
+ page_number: int = Field(..., alias="PageNumber")
100
+ page_size: int = Field(..., alias="PageSize")
101
+ auth_type: Optional[str] = Field(default=None, alias="AuthType")
93
102
  instance_id: Optional[str] = Field(default=None, alias="InstanceId")
94
- max_results: Optional[int] = Field(default=None, alias="MaxResults")
95
- next_token: Optional[str] = Field(default=None, alias="NextToken")
96
103
 
97
104
 
98
105
  # ListInboundAuthConfigs - Response
99
- class InboundAuthConfigForList(IdentityBaseModel):
100
- inbound_auth_config_id: Optional[str] = Field(
101
- default=None, alias="InboundAuthConfigId"
102
- )
103
- trn: Optional[str] = Field(default=None, alias="Trn")
104
- config_name: Optional[str] = Field(default=None, alias="ConfigName")
105
- description: Optional[str] = Field(default=None, alias="Description")
106
- auth_type: Optional[str] = Field(default=None, alias="AuthType")
107
- jwt_auth_config: Optional[JwtAuthConfig] = Field(
108
- default=None, alias="JwtAuthConfig"
109
- )
110
- api_key_auth_configs: Optional[list[ApiKeyAuthConfig]] = Field(
111
- default=None, alias="ApiKeyAuthConfigs"
112
- )
113
- instance_id: Optional[str] = Field(default=None, alias="InstanceId")
114
- created_at: Optional[str] = Field(default=None, alias="CreatedAt")
115
- updated_at: Optional[str] = Field(default=None, alias="UpdatedAt")
106
+ class InboundAuthConfigForList(InboundAuthConfig):
107
+ pass
116
108
 
117
109
 
118
110
  class ListInboundAuthConfigsResponse(IdentityBaseModel):
111
+ page_number: int = Field(..., alias="PageNumber")
112
+ page_size: int = Field(..., alias="PageSize")
113
+ total_count: int = Field(..., alias="TotalCount")
119
114
  inbound_auth_configs: Optional[list[InboundAuthConfigForList]] = Field(
120
115
  default=None, alias="InboundAuthConfigs"
121
116
  )
122
- next_token: Optional[str] = Field(default=None, alias="NextToken")
123
117
 
124
118
 
125
119
  # DeleteInboundAuthConfig - Request
@@ -129,6 +123,4 @@ class DeleteInboundAuthConfigRequest(IdentityBaseModel):
129
123
 
130
124
  # DeleteInboundAuthConfig - Response
131
125
  class DeleteInboundAuthConfigResponse(IdentityBaseModel):
132
- inbound_auth_config_id: Optional[str] = Field(
133
- default=None, alias="InboundAuthConfigId"
134
- )
126
+ pass
@@ -161,16 +161,24 @@ def _profile_app() -> typer.Typer:
161
161
  return app
162
162
 
163
163
 
164
+ def _default_region() -> str:
165
+ """Provider-aware default region (CLOUD_PROVIDER + env/config), for --region."""
166
+ from agentkit.platform.configuration import VolcConfiguration
167
+
168
+ return VolcConfiguration().region
169
+
170
+
164
171
  def _admin_app() -> typer.Typer:
165
172
  app = typer.Typer(
166
173
  help="Admin: provision UserPool CLI login and publish its discovery doc. "
167
- "Needs Volcengine AK/SK for the account that owns the UserPool.",
174
+ "Needs the cloud account's AK/SK (Volcengine or BytePlus, per CLOUD_PROVIDER) "
175
+ "for the account that owns the UserPool.",
168
176
  )
169
177
 
170
178
  @app.command("doctor")
171
179
  def doctor(
172
180
  account: Optional[str] = typer.Option(None, "--account", help="Expected account id (guard)."),
173
- region: str = typer.Option("cn-beijing", "--region"),
181
+ region: Optional[str] = typer.Option(None, "--region", help="Region (default: the provider's default region)."),
174
182
  data_plane: bool = typer.Option(
175
183
  True, "--data-plane/--no-data-plane",
176
184
  help="Also check credential-hosting prerequisites (APIG / VPC / VeFaaS / KMS)."),
@@ -184,6 +192,7 @@ def _admin_app() -> typer.Typer:
184
192
  from agentkit.auth.admin import preflight
185
193
  from agentkit.auth.errors import AuthError
186
194
 
195
+ region = region or _default_region()
187
196
  try:
188
197
  api = OpenApiClient(region=region, expect_account=account)
189
198
  except AuthError as exc:
@@ -217,12 +226,13 @@ def _admin_app() -> typer.Typer:
217
226
  @app.command("create-userpool")
218
227
  def create_userpool(
219
228
  name: str = typer.Option(..., "--name", help="UserPool name."),
220
- region: str = typer.Option("cn-beijing", "--region"),
229
+ region: Optional[str] = typer.Option(None, "--region", help="Region (default: the provider's default region)."),
221
230
  ) -> None:
222
231
  """Create a UserPool (the IdP). Federate it to Feishu/ByteDance-SSO in the console."""
223
232
  from agentkit.auth.admin import create_user_pool
224
233
  from agentkit.auth.errors import AuthError
225
234
 
235
+ region = region or _default_region()
226
236
  try:
227
237
  uid, issuer = create_user_pool(name, region=region)
228
238
  except AuthError as exc:
@@ -234,12 +244,13 @@ def _admin_app() -> typer.Typer:
234
244
  def provision(
235
245
  user_pool: str = typer.Option(..., "--user-pool", help="UserPool uid."),
236
246
  account: Optional[str] = typer.Option(None, "--account", help="Account id (default: caller)."),
237
- region: str = typer.Option("cn-beijing", "--region"),
247
+ region: Optional[str] = typer.Option(None, "--region", help="Region (default: the provider's default region)."),
238
248
  ) -> None:
239
249
  """Ensure the public CLI client + IAM OIDC provider + STS role (idempotent)."""
240
250
  from agentkit.auth.admin import provision_cli_access
241
251
  from agentkit.auth.errors import AuthError
242
252
 
253
+ region = region or _default_region()
243
254
  try:
244
255
  coords = provision_cli_access(user_pool, region=region, account_id=account)
245
256
  except AuthError as exc:
@@ -253,7 +264,7 @@ def _admin_app() -> typer.Typer:
253
264
  user_pool: Optional[str] = typer.Option(None, "--user-pool", help="Reuse an existing UserPool uid."),
254
265
  create_pool: Optional[str] = typer.Option(None, "--create-pool", help="Create a new UserPool with this name."),
255
266
  account: Optional[str] = typer.Option(None, "--account", help="Account id (default: caller)."),
256
- region: str = typer.Option("cn-beijing", "--region"),
267
+ region: Optional[str] = typer.Option(None, "--region", help="Region (default: the provider's default region)."),
257
268
  idp: Optional[str] = typer.Option(None, "--idp", help="Federate an upstream IdP: bytedance | feishu."),
258
269
  idp_client_id: Optional[str] = typer.Option(None, "--idp-client-id"),
259
270
  idp_secret: Optional[str] = typer.Option(None, "--idp-secret"),
@@ -270,9 +281,10 @@ def _admin_app() -> typer.Typer:
270
281
  override. ``--yes`` (or passing flags) runs it non-interactively.
271
282
  """
272
283
  from agentkit.auth._openapi import OpenApiClient
273
- from agentkit.auth.admin import CLI_CLIENT_NAME, OIDC_PROVIDER_NAME, ROLE_NAME, sso_setup
284
+ from agentkit.auth.admin import CLI_CLIENT_NAME, OIDC_PROVIDER_NAME, ROLE_NAME, sso_setup, tos_public_host
274
285
  from agentkit.auth.errors import AuthError
275
286
 
287
+ region = region or _default_region()
276
288
  try:
277
289
  api = OpenApiClient(region=region, expect_account=account)
278
290
  except AuthError as exc:
@@ -317,7 +329,7 @@ def _admin_app() -> typer.Typer:
317
329
 
318
330
  # 5. 列出将要做的改动,确认后执行
319
331
  if interactive:
320
- host = dom or f"{bk}.tos-{region}.volces.com"
332
+ host = dom or f"{bk}.{tos_public_host(region)}"
321
333
  typer.secho(" 将要执行以下配置:", fg=typer.colors.CYAN, bold=True, err=True)
322
334
  typer.secho(f" • UserPool {'复用 ' + user_pool if user_pool else '新建 (agentkit-cli-pool)'}", err=True)
323
335
  typer.secho(f" • 上游联邦 {idp + ' 联邦登录' if idp else '不配置(用 UserPool 本地/已有登录)'}", err=True)
@@ -385,12 +397,13 @@ def _admin_app() -> typer.Typer:
385
397
  user_pool: str = typer.Option(..., "--user-pool", help="UserPool uid."),
386
398
  bucket: str = typer.Option(..., "--bucket", help="TOS bucket to host the discovery doc."),
387
399
  account: Optional[str] = typer.Option(None, "--account"),
388
- region: str = typer.Option("cn-beijing", "--region"),
400
+ region: Optional[str] = typer.Option(None, "--region", help="Region (default: the provider's default region)."),
389
401
  ) -> None:
390
402
  """Provision (if needed) and publish /.well-known/agentkit-cli; print the login address."""
391
403
  from agentkit.auth.admin import provision_cli_access, publish_discovery
392
404
  from agentkit.auth.errors import AuthError
393
405
 
406
+ region = region or _default_region()
394
407
  try:
395
408
  coords = provision_cli_access(user_pool, region=region, account_id=account)
396
409
  url = publish_discovery(coords, bucket=bucket)
@@ -46,27 +46,12 @@ def delete_credential_command(
46
46
  ),
47
47
  ):
48
48
  """Delete a credential (inbound auth config) by name."""
49
- from agentkit.toolkit.cli.utils import PaginationHelper
49
+ from agentkit.toolkit.cli.cli_list import fetch_all_inbound_auth_configs
50
50
  from agentkit.sdk.identity.client import AgentkitIdentityClient
51
51
  from agentkit.sdk.identity import types as it
52
52
 
53
53
  client = AgentkitIdentityClient(region=(region or "").strip())
54
-
55
- def build_request(next_token_val):
56
- return it.ListInboundAuthConfigsRequest(
57
- max_results=50,
58
- next_token=next_token_val,
59
- )
60
-
61
- configs, _, _ = PaginationHelper.fetch_all_pages(
62
- request_func=client.list_inbound_auth_configs,
63
- request_builder=build_request,
64
- max_results=50,
65
- next_token=None,
66
- fetch_all=True,
67
- max_batches=None,
68
- sleep_ms=0,
69
- )
54
+ configs = fetch_all_inbound_auth_configs(client, page_size=50)
70
55
 
71
56
  matches = [c for c in configs if c.config_name == name]
72
57
  if not matches:
@@ -51,6 +51,33 @@ def _is_harness_runtime(runtime: rt.AgentKitRuntimesForListRuntimes) -> bool:
51
51
  _HARNESS_APP = "harness"
52
52
 
53
53
 
54
+ def fetch_all_inbound_auth_configs(client, *, page_size: int):
55
+ """Fetch inbound auth configs using the id service's page-number protocol."""
56
+ from agentkit.sdk.identity import types as it
57
+
58
+ configs = []
59
+ page_number = 1
60
+ while True:
61
+ response = client.list_inbound_auth_configs(
62
+ it.ListInboundAuthConfigsRequest(
63
+ page_number=page_number,
64
+ page_size=page_size,
65
+ )
66
+ )
67
+ items = response.inbound_auth_configs or []
68
+ configs.extend(items)
69
+
70
+ total_count = response.total_count
71
+ if page_number * page_size >= total_count:
72
+ break
73
+ if not items or len(items) < page_size:
74
+ break
75
+
76
+ page_number += 1
77
+
78
+ return configs
79
+
80
+
54
81
  def _user_id_from_token(token: str) -> Optional[str]:
55
82
  """Return the OIDC ``sub`` claim from a JWT bearer token, else ``None``.
56
83
 
@@ -240,9 +267,7 @@ def list_sessions_command(
240
267
  output: str = typer.Option(
241
268
  "table", "--output", help="Output format: table|json|yaml"
242
269
  ),
243
- quiet: bool = typer.Option(
244
- False, "--quiet", "-q", help="Print only session ids"
245
- ),
270
+ quiet: bool = typer.Option(False, "--quiet", "-q", help="Print only session ids"),
246
271
  no_color: bool = typer.Option(
247
272
  False, "--no-color", "-nc", help="Disable colored output for tables/panels"
248
273
  ),
@@ -304,7 +329,9 @@ def list_sessions_command(
304
329
  if output.lower() == "yaml":
305
330
  import yaml
306
331
 
307
- local_console.print(yaml.safe_dump(sessions, sort_keys=False, allow_unicode=True))
332
+ local_console.print(
333
+ yaml.safe_dump(sessions, sort_keys=False, allow_unicode=True)
334
+ )
308
335
  return
309
336
 
310
337
  table = Table(
@@ -343,7 +370,7 @@ def list_credentials_command(
343
370
  "table", "--output", help="Output format: table|json|yaml"
344
371
  ),
345
372
  quiet: bool = typer.Option(
346
- False, "--quiet", "-q", help="Print only credential names"
373
+ False, "--quiet", "-q", help="Print only InstanceId values"
347
374
  ),
348
375
  no_color: bool = typer.Option(
349
376
  False, "--no-color", "-nc", help="Disable colored output for tables/panels"
@@ -353,34 +380,19 @@ def list_credentials_command(
353
380
  ),
354
381
  ):
355
382
  """List credentials (inbound auth configs) visible to the credentials."""
356
- from agentkit.toolkit.cli.utils import PaginationHelper, OutputFormatter
383
+ from agentkit.toolkit.cli.utils import OutputFormatter
357
384
  from agentkit.sdk.identity.client import AgentkitIdentityClient
358
- from agentkit.sdk.identity import types as it
359
385
 
360
386
  local_console = console if not no_color else Console(no_color=True)
361
387
 
362
388
  client = AgentkitIdentityClient(region=(region or "").strip())
363
389
 
364
- def build_request(next_token_val):
365
- return it.ListInboundAuthConfigsRequest(
366
- max_results=limit,
367
- next_token=next_token_val,
368
- )
369
-
370
390
  with local_console.status("[cyan]Fetching credentials...[/cyan]", spinner="dots"):
371
- configs, _, _ = PaginationHelper.fetch_all_pages(
372
- request_func=client.list_inbound_auth_configs,
373
- request_builder=build_request,
374
- max_results=limit,
375
- next_token=None,
376
- fetch_all=True,
377
- max_batches=None,
378
- sleep_ms=0,
379
- )
391
+ configs = fetch_all_inbound_auth_configs(client, page_size=limit)
380
392
 
381
393
  if quiet:
382
394
  for c in configs:
383
- local_console.print(c.config_name or "")
395
+ local_console.print(c.instance_id or "")
384
396
  return
385
397
 
386
398
  if output.lower() == "json":
@@ -391,7 +403,7 @@ def list_credentials_command(
391
403
  return
392
404
 
393
405
  columns = [
394
- ("ConfigName", "Name", "cyan"),
406
+ ("InstanceId", "InstanceId", "cyan"),
395
407
  ("AuthType", "AuthType", "white"),
396
408
  ("InboundAuthConfigId", "InboundAuthConfigId", "green"),
397
409
  ("CreatedAt", "CreatedAt", "magenta"),
@@ -57,8 +57,8 @@ PROVIDER_TYPE_ALIASES = {
57
57
  "VIKINGDB_MEMORY": "VIKINGDB_MEMORY",
58
58
  }
59
59
  CREATE_PROVIDER_TYPE_HELP = (
60
- "Provider type: MEM0 | VIKINGDB_MEMORY. Defaults to MEM0; when cloud provider "
61
- "is byteplus, defaults to VIKINGDB_MEMORY and MEM0 is not supported."
60
+ "Provider type for create. Defaults depend on the active cloud provider; "
61
+ "run 'agentkit memory provider-types' to view supported values."
62
62
  )
63
63
 
64
64
 
@@ -467,17 +467,25 @@ def add_command(
467
467
  def provider_types_command():
468
468
  """List allowed ProviderType values and common aliases."""
469
469
  try:
470
+ cloud_provider = VolcConfiguration().provider
470
471
  table = Table(title="Allowed Provider Types")
471
472
  table.add_column("Value", style="cyan")
472
473
  table.add_column("Aliases", style="magenta")
473
- table.add_row("MEM0", "mem0")
474
+
475
+ if cloud_provider != CloudProvider.BYTEPLUS:
476
+ table.add_row("MEM0", "mem0")
474
477
  table.add_row("VIKINGDB_MEMORY", "vikingdb, vikingdb_memory, vikingdb-memory")
475
478
  console.print(table)
476
- console.print(
477
- "Default for create is [bold]MEM0[/bold], or "
478
- "[bold]VIKINGDB_MEMORY[/bold] when cloud provider is byteplus. "
479
- "MEM0 is not supported on BytePlus."
480
- )
479
+ if cloud_provider == CloudProvider.BYTEPLUS:
480
+ console.print(
481
+ "Cloud provider: [bold]byteplus[/bold]. Default for create is "
482
+ "[bold]VIKINGDB_MEMORY[/bold]. MEM0 is not supported on BytePlus."
483
+ )
484
+ else:
485
+ console.print(
486
+ "Cloud provider: [bold]volcengine[/bold]. Default for create is "
487
+ "[bold]MEM0[/bold]."
488
+ )
481
489
  except Exception as e:
482
490
  console.print(f"[red]Failed to list provider types: {e}[/red]")
483
491
  raise typer.Exit(1)
agentkit/version.py CHANGED
@@ -12,4 +12,4 @@
12
12
  # See the License for the specific language governing permissions and
13
13
  # limitations under the License.
14
14
 
15
- VERSION = "0.8.2"
15
+ VERSION = "0.8.4"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: agentkit-sdk-python
3
- Version: 0.8.2
3
+ Version: 0.8.4
4
4
  Summary: Python SDK for transforming any AI agent into a production-ready application. Framework-agnostic primitives for runtime, memory, authentication, and tools with volcengine-managed infrastructure.
5
5
  Author-email: Xiangrui Cheng <innsdcc@gmail.com>, Yumeng Bao <baoyumeng.123@gmail.com>, Yaozheng Fang <fangyozheng@gmail.com>, Guodong Li <cu.eric.lee@gmail.com>
6
6
  License: Apache License
@@ -1,6 +1,6 @@
1
1
  agentkit/__init__.py,sha256=l27ZMDslc3VhmmnPZJyrqVvTDoZ0LqhCtM5hw0caHcU,1021
2
2
  agentkit/errors.py,sha256=UWlXv0ZsXd_oLTMlxuf4u9-XkTdRYeVZueE--Z3JsHU,1214
3
- agentkit/version.py,sha256=g4CsgqE9kLMs6p4wSITaFW9ouorJTtg305eCrh59Tp0,653
3
+ agentkit/version.py,sha256=fKAnVe0_BYK2q2PZxJGyG7eEu4cEnejRK9V0vQ6lftQ,653
4
4
  agentkit/apps/__init__.py,sha256=_Na1A4NSaMbVfPbsFKj2U-yI5mytD7W5skMaAOGbauY,2328
5
5
  agentkit/apps/base_app.py,sha256=3hZZExL1wyTGWveJEZZoqXN086MzmkVS_WU1vyulIWg,754
6
6
  agentkit/apps/utils.py,sha256=IzimIDmT6FS6PV9MLimPh46mq5zT-EjVmnYPxBdyEq0,1934
@@ -8,7 +8,7 @@ agentkit/apps/a2a_app/__init__.py,sha256=pkSabKw7_ai4NOo56pXKL40EcaxIDh6HYxPXOY7
8
8
  agentkit/apps/a2a_app/a2a_app.py,sha256=mFuPFuqRlGdQ2VIjQq2_gtQKWwnkwSjSmIMRnammWJU,7605
9
9
  agentkit/apps/a2a_app/telemetry.py,sha256=vR8tf7EHLor62cxs5PBx4mrfHeOaV1a7Xryqlu8nGCU,4290
10
10
  agentkit/apps/agent_server_app/__init__.py,sha256=pkSabKw7_ai4NOo56pXKL40EcaxIDh6HYxPXOY7qWbo,634
11
- agentkit/apps/agent_server_app/agent_server_app.py,sha256=d955uLspgQg3B6sKtI2NKer1encsYFFb7mG2eleOLYo,26465
11
+ agentkit/apps/agent_server_app/agent_server_app.py,sha256=vdaNu0T3uRAVrw21KA2KWl5_0TyjoYxTCDh6vP0CGXM,26997
12
12
  agentkit/apps/agent_server_app/credential_service.py,sha256=jBSIY6-1yc01rRRVYN8wuahTIs9AEY4zH5JGSAWIzUU,3468
13
13
  agentkit/apps/agent_server_app/inbound_auth.py,sha256=FPCfFdg13Z9E-kasyZ-in3COdXHG_exKHAFThwXFnS8,1394
14
14
  agentkit/apps/agent_server_app/inbound_auth_adapter.py,sha256=n0ji_wKVmBOabepqTqWR1_0mrcYjH2xZlQJx-tGgNcs,6087
@@ -27,22 +27,22 @@ agentkit/apps/simple_app/simple_app.py,sha256=NgWONHpLckkqzw8iTP2kk2MJiB9L6Y22FD
27
27
  agentkit/apps/simple_app/simple_app_handlers.py,sha256=Rby8HGCDlWo5kXmliU2YEyqbaNI2u69JIZ5YqetJJco,15561
28
28
  agentkit/apps/simple_app/telemetry.py,sha256=F3sYCWmJb-tgLUoM-2EjYX6fnLT9N5kkVNbfHkPVqHg,5052
29
29
  agentkit/auth/__init__.py,sha256=eIW6ziL3rtBYEupfmqq8MshZ40wL3muYjCQRikFG_j0,3643
30
- agentkit/auth/_openapi.py,sha256=ofFX7Ch-1xQeOvwUYRU4YwGKUqDgIfI8lsnk8Vbi12s,8230
30
+ agentkit/auth/_openapi.py,sha256=bToFSAqSCO_nvfvK0FegkJJtP50eZQhe5ZAtHBGla3E,10088
31
31
  agentkit/auth/_redact.py,sha256=Ef3yLlWj6jw0G6gZKy3cY64X6sm0jhzor8qx8b0Dp4A,911
32
32
  agentkit/auth/_sigv4.py,sha256=yAbFD57g3cBvCkGTVJap0BCakQeukyR_FlzMDYZdTkw,3375
33
- agentkit/auth/admin.py,sha256=JDyKIptLKMQOAp8DjUvrCRnJ2jER6cZUrXoUJcojMDU,23554
33
+ agentkit/auth/admin.py,sha256=ZbyN21O4wVzkcGUzwliPneTEKZorLgCDVcxNXfijfE8,28721
34
34
  agentkit/auth/credential_hosting.py,sha256=lFFYseYHkqCUsv1djtK3EFR1XvESmw6l1Zgu1CcwIa8,24280
35
35
  agentkit/auth/errors.py,sha256=eNNdzXP35QAlYy-jM5I9CQZCSS9rW0cp5_1F0I75JcU,1448
36
36
  agentkit/auth/model_login.py,sha256=_30pbZgs22o4UtGF03dMgFRN9yE4OSyLqXJm9JhEe7E,13775
37
37
  agentkit/auth/oauth.py,sha256=vbFRJpmlQXxcKRjHk2LIDLs1I3hsVrWTvLRnDA8XNN4,8812
38
- agentkit/auth/profile.py,sha256=gJpPj1ivpjRdH3MnjB2ICN4fYVaQlkt9DreJqkOze0Y,5656
38
+ agentkit/auth/profile.py,sha256=DN8NGgPyd4X_HyEwXZjTfhv782NiBMij7H0TmdsfrT4,5776
39
39
  agentkit/auth/providers.py,sha256=zcOjEryJvuUctnRl3_Uae6HdZ8hGc0NVX4Lp3Y_2W68,3041
40
- agentkit/auth/resolve.py,sha256=UAKFBRtGyLcR-nkisk49_bpGVG635SKM2kqVV37ofe4,7276
41
- agentkit/auth/session.py,sha256=iQ6Memsm7yTSPllJil6JjT-rHQeJnIzOch1s-WxPkGQ,13391
40
+ agentkit/auth/resolve.py,sha256=vWeCBdwbQGDn_vsZ9oIhX5EXKFFomw7KONZACvI_zlQ,7348
41
+ agentkit/auth/session.py,sha256=_VzpAAf-chx1ZFcDrcl6cH_4YzH718owV8FkZFlOGys,13431
42
42
  agentkit/auth/ssl_trust.py,sha256=QBE8pr-u9QV_FzqmRHkwOdynu1Kexm5_zGeMZbkH5_I,4069
43
- agentkit/auth/sso.py,sha256=pjNZGza_-UnfZcMNXuAHGdBT7xJzAOeBV7FpipCUQog,6051
43
+ agentkit/auth/sso.py,sha256=v_7l0a1Z2JRDAATXRrAJc8ixlCBnulCfMkZE7h3ebJg,6140
44
44
  agentkit/auth/store.py,sha256=Wxkotn9jvPyNcVRJ_T3oRHV5qGuiyhe92JOhc6WiX7k,4239
45
- agentkit/auth/sts.py,sha256=mHcC4XJg9kwcX-Qt3_Ez88QnAOHkV7b_XRIIs3XznSM,5277
45
+ agentkit/auth/sts.py,sha256=VE18SsI6GTJBJmtIrxqs-ECeOstC79qe99UizO3EExE,5535
46
46
  agentkit/client/__init__.py,sha256=WHKgNGkpYsJp0xD20drYcxAMDclwDqrfURqxEVv0V1Y,1053
47
47
  agentkit/client/base_agentkit_client.py,sha256=NV1m2FtboUcMdVUJL2ep75nAwDQ42roiWgl3YKaUSn8,2955
48
48
  agentkit/client/base_iam_client.py,sha256=F3ggcZjt14CAcgDYpncF2XGr1zTGnhaOzqEJl4NGHwU,2432
@@ -69,7 +69,7 @@ agentkit/identity/runtime.py,sha256=9K_CLqOfOfhw1DYSupChW47fc5k3_sK6tUTB-ky6Vo4,
69
69
  agentkit/identity/transport.py,sha256=Rdesbrai204tduAgvWTFrp0gXyCF0Sw_fqMbJUQSXyQ,238
70
70
  agentkit/identity/types.py,sha256=kCwNddu74pf8WWHHTkO2NUmU-VkSn91uTWMx9vkUSBc,588
71
71
  agentkit/platform/__init__.py,sha256=XD1YoXWJPpLGrP410Tb_psPFKR3LUo3-47UlqayUumo,3464
72
- agentkit/platform/configuration.py,sha256=lclvtiUUO1D6iwapmPygYGhNJCMfkqt4fHPBCIEqUhE,23378
72
+ agentkit/platform/configuration.py,sha256=6pmCzhyiq3d2Q7VolrBxKyUJd5ZIJV713dSh0MvTF1U,23488
73
73
  agentkit/platform/console_urls.py,sha256=JcnjwyuxN5c4RuXcPevsxy6aInurVFtchqbibJBqjSk,1125
74
74
  agentkit/platform/constants.py,sha256=52XqqOEBcvGQFgEb2rALyaDhdx1MOT9YSyS1s8VSYV0,3975
75
75
  agentkit/platform/context.py,sha256=eb6ub4nUhoV1hXawjSVdY7gfc5XcgHJjFIhrzOuQ2G0,1662
@@ -79,8 +79,8 @@ agentkit/sdk/account/client.py,sha256=hOxqpiI0H7qlsBZR3aUNKi8G7eJOr46GtAS-J9on_U
79
79
  agentkit/sdk/account/types.py,sha256=RQdVaeQxd_ntlyG2HZIx4q24m1aDvttxncXtrSamILE,1540
80
80
  agentkit/sdk/identity/__init__.py,sha256=pkSabKw7_ai4NOo56pXKL40EcaxIDh6HYxPXOY7qWbo,634
81
81
  agentkit/sdk/identity/auth.py,sha256=zRX5ViIiEJZedBx4dctb7zEGYsOme70UmOPZFkBXvKk,2808
82
- agentkit/sdk/identity/client.py,sha256=fYP_QaRpPorve7Pl1pgYh_uYJOWEBKgf6yRnYo1P1Aw,2657
83
- agentkit/sdk/identity/types.py,sha256=rdQOoKMzTPHrWoiEEMNxzsNYIMo82T5nrBFZhLN55hY,5455
82
+ agentkit/sdk/identity/client.py,sha256=LY0qds5y2p0b3_y1c7xa_0EnGCOub7c-D7VMMCEv-ew,2915
83
+ agentkit/sdk/identity/types.py,sha256=L3C5SF62H7ZQqcTPzo4QJbcYzFauARfcgdPNv1KkHac,4621
84
84
  agentkit/sdk/knowledge/__init__.py,sha256=o0jcuhemoY-DmfpnCu4TsTHBpmZpfUxIFjnEEltlS0I,1600
85
85
  agentkit/sdk/knowledge/client.py,sha256=pEvsq5lcGMtteDTbXvh-bX7P79UdXPU3x49GLxCY-XI,3832
86
86
  agentkit/sdk/knowledge/types.py,sha256=01ViOou0YxdGqPrGCdlI7LTZKGFrPf3OPnvsrIJb-Ts,10545
@@ -116,19 +116,19 @@ agentkit/toolkit/cli/__init__.py,sha256=pkSabKw7_ai4NOo56pXKL40EcaxIDh6HYxPXOY7q
116
116
  agentkit/toolkit/cli/__main__.py,sha256=arwJ1gHkaaoQAXb0ezo_FeyxiMqVy0FXujB2WOX_ohU,775
117
117
  agentkit/toolkit/cli/cli.py,sha256=cwtaKwo8XeJZ-cWyDJSNe8oS-LnBXEn2R-JWHH9moys,4893
118
118
  agentkit/toolkit/cli/cli_add.py,sha256=aLyvN9Vcjis_KLhy92uuPi7e8ltFdHjwFOb-nME7CV0,39730
119
- agentkit/toolkit/cli/cli_auth.py,sha256=eislIHxafJovjDSQai8zfO4zcd502-U5oJYelnPFKgQ,26445
119
+ agentkit/toolkit/cli/cli_auth.py,sha256=qfvzLwOV3bGnClX_-EP2CC1uDyEy8fezWoTaCe7Ourw,27271
120
120
  agentkit/toolkit/cli/cli_build.py,sha256=gtRBPJfm6Z4y37ISC_CiGwEkMhD4fD7IQi1H6Lzc2Yo,2984
121
121
  agentkit/toolkit/cli/cli_config.py,sha256=09TUTlV9-QmBfNpDox2HBCpbgsO7hS9rZRoAAUdE9eI,29311
122
- agentkit/toolkit/cli/cli_delete.py,sha256=Q6utRf5ak1fHF_Bm73weWgiiQA3Oz3iWzl5ij5_cTGA,6584
122
+ agentkit/toolkit/cli/cli_delete.py,sha256=duoX7N1_uklleNMEcxz8t575FluzxLnGeokYUKyx58E,6228
123
123
  agentkit/toolkit/cli/cli_deploy.py,sha256=B912gRSpgLFBCLF8w8lD1J_jP5-PvpT_Zjblx-0yees,7066
124
124
  agentkit/toolkit/cli/cli_destroy.py,sha256=QpH7cctsaIFd2io6hhEeKnCjxK7DbE7AnFsecWL5BxY,1797
125
125
  agentkit/toolkit/cli/cli_init.py,sha256=feuypfgggXj6_0ZP4TEQ3rIZOuYRVUxXwvpdq9nsOY0,17911
126
126
  agentkit/toolkit/cli/cli_invoke.py,sha256=sLaCXXoOeTPzECZFtNCV8EIlIQPQZsaih2s5rocz2h8,46082
127
127
  agentkit/toolkit/cli/cli_knowledge.py,sha256=J3pcJs01tWJAMp79nFnX5pU6AEZK7XVCZtyPRLKkfUI,25142
128
128
  agentkit/toolkit/cli/cli_launch.py,sha256=vkhjTBcxteVGwxtkDXKQxDjqTsFyDPx0SZcKL-zkPMg,3774
129
- agentkit/toolkit/cli/cli_list.py,sha256=KBqSRMaiO6Frej_ZvTV4_ODWgMVdHzJtsl63K43Y3hY,14256
129
+ agentkit/toolkit/cli/cli_list.py,sha256=4_SENlUS1P1WRP75fga05JVRkIG4IKGftrFpoVAn108,14555
130
130
  agentkit/toolkit/cli/cli_logs.py,sha256=hfyz89MpS7KCGd3ExUiDJoyveEwt_tOCKab_8P_I3Ck,9355
131
- agentkit/toolkit/cli/cli_memory.py,sha256=kyxGUP2RsCa725r1aRkyWtwqqAM9YySViQ_j_2L2ZTE,37798
131
+ agentkit/toolkit/cli/cli_memory.py,sha256=mN1DwUeIjLD_xSRw6xFQoY8EVz0K8mMZf3PGydZkndE,38113
132
132
  agentkit/toolkit/cli/cli_model_gateway.py,sha256=_kMcDo-Y55G2LZZx4rL4Ksp6DQkou8A42_MKbsG-LgI,41233
133
133
  agentkit/toolkit/cli/cli_runtime.py,sha256=nzk3oVICVACXqZrg0KjgjpjN-K3ezQKAu0dwdjnsMPg,31961
134
134
  agentkit/toolkit/cli/cli_skill.py,sha256=nEZXc9CVGop4e0WC-V2AAHqy7to4nw6KnKOtzS2likQ,16170
@@ -285,9 +285,9 @@ agentkit_identity/py.typed,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
285
285
  agentkit_identity/runtime.py,sha256=hQHLvbAK760teFPTGZ0RG9Ed5DQAXAqIdaAm9ojzS34,14423
286
286
  agentkit_identity/transport.py,sha256=kwGHSEQ5Qcn1kIu6N6DVid7MdDUMj5uaIRIUA_tJ3cM,7693
287
287
  agentkit_identity/types.py,sha256=lT8KQz1pG0rgdy5Gh6WnM0mq9VqCsWSE41Z8Fw3DHZo,7358
288
- agentkit_sdk_python-0.8.2.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
289
- agentkit_sdk_python-0.8.2.dist-info/METADATA,sha256=ugfvvvLHRLoSYCYia3xEE394p17bvkHjjXPaQCGX5s0,21580
290
- agentkit_sdk_python-0.8.2.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
291
- agentkit_sdk_python-0.8.2.dist-info/entry_points.txt,sha256=fhzZUsvsLXeB4mPaa0SBQiTBqFT404uDAKPaePAOUAE,58
292
- agentkit_sdk_python-0.8.2.dist-info/top_level.txt,sha256=Kw8DVx7vzg-oUh7xC_hBZw7OwKW3Y_fo_8rkWOL1d5o,27
293
- agentkit_sdk_python-0.8.2.dist-info/RECORD,,
288
+ agentkit_sdk_python-0.8.4.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
289
+ agentkit_sdk_python-0.8.4.dist-info/METADATA,sha256=CmkfzVUQCoQ62WFvXFle1Il9-B77xpfEU-NOgAwtPUQ,21580
290
+ agentkit_sdk_python-0.8.4.dist-info/WHEEL,sha256=YVMoNqKzERt-wjUZwJ33xBGAwnFl-4cqbYkTtWa4itE,91
291
+ agentkit_sdk_python-0.8.4.dist-info/entry_points.txt,sha256=fhzZUsvsLXeB4mPaa0SBQiTBqFT404uDAKPaePAOUAE,58
292
+ agentkit_sdk_python-0.8.4.dist-info/top_level.txt,sha256=Kw8DVx7vzg-oUh7xC_hBZw7OwKW3Y_fo_8rkWOL1d5o,27
293
+ agentkit_sdk_python-0.8.4.dist-info/RECORD,,