interloper-api 0.91.0__tar.gz → 0.92.0__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 (25) hide show
  1. {interloper_api-0.91.0 → interloper_api-0.92.0}/PKG-INFO +1 -1
  2. {interloper_api-0.91.0 → interloper_api-0.92.0}/pyproject.toml +1 -1
  3. {interloper_api-0.91.0 → interloper_api-0.92.0}/pyproject.toml.orig +1 -1
  4. {interloper_api-0.91.0 → interloper_api-0.92.0}/src/interloper_api/routes/agent.py +9 -0
  5. {interloper_api-0.91.0 → interloper_api-0.92.0}/src/interloper_api/routes/oauth.py +9 -6
  6. {interloper_api-0.91.0 → interloper_api-0.92.0}/README.md +0 -0
  7. {interloper_api-0.91.0 → interloper_api-0.92.0}/src/interloper_api/__init__.py +0 -0
  8. {interloper_api-0.91.0 → interloper_api-0.92.0}/src/interloper_api/app.py +0 -0
  9. {interloper_api-0.91.0 → interloper_api-0.92.0}/src/interloper_api/dependencies/__init__.py +0 -0
  10. {interloper_api-0.91.0 → interloper_api-0.92.0}/src/interloper_api/dependencies/auth.py +0 -0
  11. {interloper_api-0.91.0 → interloper_api-0.92.0}/src/interloper_api/dependencies/rbac.py +0 -0
  12. {interloper_api-0.91.0 → interloper_api-0.92.0}/src/interloper_api/dependencies/state.py +0 -0
  13. {interloper_api-0.91.0 → interloper_api-0.92.0}/src/interloper_api/notifications/__init__.py +0 -0
  14. {interloper_api-0.91.0 → interloper_api-0.92.0}/src/interloper_api/notifications/invitations.py +0 -0
  15. {interloper_api-0.91.0 → interloper_api-0.92.0}/src/interloper_api/routes/__init__.py +0 -0
  16. {interloper_api-0.91.0 → interloper_api-0.92.0}/src/interloper_api/routes/admin.py +0 -0
  17. {interloper_api-0.91.0 → interloper_api-0.92.0}/src/interloper_api/routes/auth.py +0 -0
  18. {interloper_api-0.91.0 → interloper_api-0.92.0}/src/interloper_api/routes/backfills.py +0 -0
  19. {interloper_api-0.91.0 → interloper_api-0.92.0}/src/interloper_api/routes/catalog.py +0 -0
  20. {interloper_api-0.91.0 → interloper_api-0.92.0}/src/interloper_api/routes/components.py +0 -0
  21. {interloper_api-0.91.0 → interloper_api-0.92.0}/src/interloper_api/routes/health.py +0 -0
  22. {interloper_api-0.91.0 → interloper_api-0.92.0}/src/interloper_api/routes/organisations.py +0 -0
  23. {interloper_api-0.91.0 → interloper_api-0.92.0}/src/interloper_api/routes/runs.py +0 -0
  24. {interloper_api-0.91.0 → interloper_api-0.92.0}/src/interloper_api/routes/tokens.py +0 -0
  25. {interloper_api-0.91.0 → interloper_api-0.92.0}/src/interloper_api/routes/websocket.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: interloper-api
3
- Version: 0.91.0
3
+ Version: 0.92.0
4
4
  Summary: Interloper FastAPI routes
5
5
  Author: Guillaume Onfroy
6
6
  Author-email: Guillaume Onfroy <guillaume@digitlcloud.com>
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "interloper-api"
3
- version = "0.91.0"
3
+ version = "0.92.0"
4
4
  description = "Interloper FastAPI routes"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -3,7 +3,7 @@
3
3
  # ###############
4
4
  [project]
5
5
  name = "interloper-api"
6
- version = "0.91.0"
6
+ version = "0.92.0"
7
7
  description = "Interloper FastAPI routes"
8
8
  readme = "README.md"
9
9
  authors = [{ name = "Guillaume Onfroy", email = "guillaume@digitlcloud.com" }]
@@ -233,6 +233,15 @@ async def chat(
233
233
  messages = result.all_messages()
234
234
  history = ModelMessagesTypeAdapter.dump_python(messages, mode="json")
235
235
  store.conversations.save(conversation.id, history, title=_first_prompt(messages))
236
+ usage = result.usage
237
+ logger.info(
238
+ "Agent turn on conversation %s: %d requests, %d input tokens, %d output tokens, %d messages stored",
239
+ conversation.id,
240
+ usage.requests,
241
+ usage.input_tokens,
242
+ usage.output_tokens,
243
+ len(messages),
244
+ )
236
245
 
237
246
  return await LoggedAdapter.dispatch_request(
238
247
  request,
@@ -106,9 +106,10 @@ async def exchange_authorization_code(
106
106
  ) -> dict[str, Any]:
107
107
  """Exchange an authorization code for tokens. Requires authentication.
108
108
 
109
- Returns only the provider's token response (e.g. ``refresh_token``); the
110
- in-house OAuth credentials are never included — connections resolve them
111
- from env at runtime.
109
+ Returns only the provider's token response (e.g. ``refresh_token``), read
110
+ through the provider's own parser so dialect envelopes never reach the
111
+ browser; the in-house OAuth credentials are never included — connections
112
+ resolve them from env at runtime.
112
113
 
113
114
  Args:
114
115
  provider: The registry key of the provider to exchange against.
@@ -117,11 +118,12 @@ async def exchange_authorization_code(
117
118
  identity itself is not used.
118
119
 
119
120
  Returns:
120
- The provider's raw token response.
121
+ The provider's token response, credentials at the top level.
121
122
 
122
123
  Raises:
123
124
  HTTPException: 400 when the provider is unknown or has no credentials
124
- configured, 500 when the exchange itself fails.
125
+ configured, 500 when the exchange itself fails — including a
126
+ rejection the provider reports inside a 200 body.
125
127
  """
126
128
  spec = PROVIDERS.get(provider)
127
129
  if spec is None:
@@ -142,8 +144,9 @@ async def exchange_authorization_code(
142
144
  async with httpx2.AsyncClient(timeout=30, follow_redirects=True) as client:
143
145
  response = await client.send(request)
144
146
  response.raise_for_status()
147
+ tokens = spec.parse_authorization_code_response(response.json())
145
148
  logger.info("Successfully exchanged auth code for provider %s", provider)
146
- return response.json()
149
+ return tokens
147
150
  except httpx2.HTTPStatusError as exception:
148
151
  detail = exception.response.text
149
152
  logger.error("Token exchange failed for %s: %s %s", provider, exception.response.status_code, detail)