flatagents 2.4.4__tar.gz → 2.5.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 (36) hide show
  1. {flatagents-2.4.4 → flatagents-2.5.0}/.gitignore +1 -0
  2. {flatagents-2.4.4 → flatagents-2.5.0}/PKG-INFO +1 -1
  3. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/__init__.py +1 -1
  4. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/assets/flatagent.d.ts +1 -1
  5. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/assets/flatagent.slim.d.ts +1 -1
  6. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/assets/flatagents-runtime.d.ts +1 -1
  7. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/assets/flatagents-runtime.schema.json +1 -1
  8. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/assets/flatagents-runtime.slim.d.ts +1 -1
  9. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/assets/flatmachine.d.ts +1 -1
  10. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/assets/flatmachine.slim.d.ts +1 -1
  11. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/assets/profiles.d.ts +1 -1
  12. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/assets/profiles.slim.d.ts +1 -1
  13. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/flatagent.py +27 -4
  14. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/providers/openai_codex_client.py +24 -4
  15. {flatagents-2.4.4 → flatagents-2.5.0}/pyproject.toml +1 -1
  16. {flatagents-2.4.4 → flatagents-2.5.0}/MACHINES.md +0 -0
  17. {flatagents-2.4.4 → flatagents-2.5.0}/README.md +0 -0
  18. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/assets/README.md +0 -0
  19. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/assets/__init__.py +0 -0
  20. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/assets/flatagent.schema.json +0 -0
  21. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/assets/flatmachine.schema.json +0 -0
  22. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/assets/profiles.schema.json +0 -0
  23. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/baseagent.py +0 -0
  24. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/monitoring.py +0 -0
  25. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/profiles.py +0 -0
  26. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/providers/__init__.py +0 -0
  27. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/providers/anthropic.py +0 -0
  28. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/providers/cerebras.py +0 -0
  29. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/providers/openai.py +0 -0
  30. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/providers/openai_codex_auth.py +0 -0
  31. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/providers/openai_codex_login.py +0 -0
  32. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/providers/openai_codex_types.py +0 -0
  33. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/tool_loop.py +0 -0
  34. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/tools.py +0 -0
  35. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/utils.py +0 -0
  36. {flatagents-2.4.4 → flatagents-2.5.0}/flatagents/validation.py +0 -0
@@ -15,4 +15,5 @@ data
15
15
  logs
16
16
 
17
17
  .aider.tags.cache.v4/
18
+ .speed-kills/
18
19
  auth.json
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: flatagents
3
- Version: 2.4.4
3
+ Version: 2.5.0
4
4
  Summary: A lightweight framework for building LLM-powered agents.
5
5
  Project-URL: Homepage, https://github.com/memgrafter/flatagents
6
6
  Project-URL: Repository, https://github.com/memgrafter/flatagents
@@ -1,4 +1,4 @@
1
- __version__ = "2.4.4"
1
+ __version__ = "2.5.0"
2
2
 
3
3
  from .baseagent import (
4
4
  # Base agent (abstract, for multi-step agents)
@@ -151,7 +151,7 @@
151
151
  * The profile field specifies which profile name to use as base.
152
152
  */
153
153
 
154
- export const SPEC_VERSION = "2.4.4";
154
+ export const SPEC_VERSION = "2.5.0";
155
155
 
156
156
  export interface AgentWrapper {
157
157
  spec: "flatagent";
@@ -1,4 +1,4 @@
1
- export const SPEC_VERSION = "2.4.4";
1
+ export const SPEC_VERSION = "2.5.0";
2
2
  export interface AgentWrapper {
3
3
  spec: "flatagent";
4
4
  spec_version: string;
@@ -800,7 +800,7 @@ export interface BackendConfig {
800
800
  aws_region?: string;
801
801
  }
802
802
 
803
- export const SPEC_VERSION = "2.4.4";
803
+ export const SPEC_VERSION = "2.5.0";
804
804
 
805
805
  export interface SDKRuntimeWrapper {
806
806
  spec: "flatagents-runtime";
@@ -11,7 +11,7 @@
11
11
  },
12
12
  "spec_version": {
13
13
  "type": "string",
14
- "const": "2.4.4"
14
+ "const": "2.5.0"
15
15
  },
16
16
  "execution_lock": {
17
17
  "$ref": "#/definitions/ExecutionLock"
@@ -252,7 +252,7 @@ export interface BackendConfig {
252
252
  dynamodb_table?: string;
253
253
  aws_region?: string;
254
254
  }
255
- export const SPEC_VERSION = "2.4.4";
255
+ export const SPEC_VERSION = "2.5.0";
256
256
  export interface SDKRuntimeWrapper {
257
257
  spec: "flatagents-runtime";
258
258
  spec_version: typeof SPEC_VERSION;
@@ -319,7 +319,7 @@
319
319
  * config_hash - Content-addressed machine config key for cross-SDK resume (v2.1.0)
320
320
  */
321
321
 
322
- export const SPEC_VERSION = "2.4.4";
322
+ export const SPEC_VERSION = "2.5.0";
323
323
 
324
324
  export interface MachineWrapper {
325
325
  spec: "flatmachine";
@@ -1,4 +1,4 @@
1
- export const SPEC_VERSION = "2.4.4";
1
+ export const SPEC_VERSION = "2.5.0";
2
2
  export interface MachineWrapper {
3
3
  spec: "flatmachine";
4
4
  spec_version: string;
@@ -110,7 +110,7 @@
110
110
  * oauth - OAuth settings (used by codex backend)
111
111
  */
112
112
 
113
- export const SPEC_VERSION = "2.4.4";
113
+ export const SPEC_VERSION = "2.5.0";
114
114
 
115
115
  export interface ProfilesWrapper {
116
116
  spec: "flatprofiles";
@@ -1,4 +1,4 @@
1
- export const SPEC_VERSION = "2.4.4";
1
+ export const SPEC_VERSION = "2.5.0";
2
2
  export interface ProfilesWrapper {
3
3
  spec: "flatprofiles";
4
4
  spec_version: string;
@@ -741,6 +741,13 @@ class FlatAgent:
741
741
  _external_tools = None
742
742
  tools_prompt = self._render_tool_prompt(_mcp_tools)
743
743
 
744
+ # Session identity is transport metadata, not prompt input.
745
+ # Strip it from input_data so continuation calls (messages=..., no fresh
746
+ # user input) are not misclassified as having new user content.
747
+ codex_session_id = None
748
+ if self._backend == "codex" and "session_id" in input_data:
749
+ codex_session_id = input_data.pop("session_id")
750
+
744
751
  # Render prompts
745
752
  system_prompt = self._render_system_prompt(input_data, tools_prompt=tools_prompt, tools=_mcp_tools)
746
753
  user_prompt = self._render_user_prompt(input_data, tools_prompt=tools_prompt, tools=_mcp_tools)
@@ -815,10 +822,10 @@ class FlatAgent:
815
822
  if key not in _KNOWN_MODEL_FIELDS and key not in params and value is not None:
816
823
  params[key] = value
817
824
 
818
- # Forward session_id from input_data into params for the Codex backend so
819
- # prompt_cache_key is set, enabling KV-cache hits across continuation turns.
820
- if self._backend == "codex" and "session_id" in input_data and "session_id" not in params:
821
- params["session_id"] = input_data["session_id"]
825
+ # Forward machine-provided session_id into Codex params so prompt_cache_key
826
+ # is set for this request.
827
+ if self._backend == "codex" and codex_session_id and "session_id" not in params:
828
+ params["session_id"] = codex_session_id
822
829
 
823
830
  # Add tools if available
824
831
  if _external_tools:
@@ -884,6 +891,22 @@ class FlatAgent:
884
891
  finish_reason = self._extract_finish_reason(response)
885
892
  if finish_reason:
886
893
  monitor.metrics["finish_reason"] = finish_reason.value
894
+
895
+ # Debug session continuity for codex prompt caching.
896
+ if self._backend == "codex":
897
+ request_meta = getattr(response, "_request_meta", {}) or {}
898
+ request_headers = request_meta.get("headers") if isinstance(request_meta, dict) else {}
899
+ if not isinstance(request_headers, dict):
900
+ request_headers = {}
901
+ session_header = request_headers.get("session_id")
902
+ prompt_cache_key = request_meta.get("prompt_cache_key") if isinstance(request_meta, dict) else None
903
+ logger.info(
904
+ "Codex request debug: session_id=%s prompt_cache_key=%s finish_reason=%s cache_read_tokens=%s",
905
+ session_header,
906
+ prompt_cache_key,
907
+ finish_reason.value if finish_reason else None,
908
+ usage_info.cache_read_tokens if usage_info else 0,
909
+ )
887
910
 
888
911
  # Extract rate limit headers from successful response
889
912
  response_headers = extract_headers_from_response(response)
@@ -147,6 +147,7 @@ class CodexClient:
147
147
  "url": request_url,
148
148
  "headers": self._redact_request_headers(headers),
149
149
  "retries_used": retries_used,
150
+ "prompt_cache_key": session_id,
150
151
  }
151
152
  return result
152
153
  except CodexHTTPError as first_error:
@@ -184,6 +185,7 @@ class CodexClient:
184
185
  "url": request_url,
185
186
  "headers": self._redact_request_headers(retry_headers),
186
187
  "retries_used": retries_used,
188
+ "prompt_cache_key": session_id,
187
189
  }
188
190
  return result
189
191
 
@@ -365,14 +367,32 @@ class CodexClient:
365
367
  response_obj = event.get("response") if isinstance(event.get("response"), dict) else {}
366
368
  result.status = str(response_obj.get("status")) if response_obj.get("status") else None
367
369
  usage_obj = response_obj.get("usage") if isinstance(response_obj.get("usage"), dict) else {}
368
- input_tokens = int(usage_obj.get("input_tokens") or 0)
369
- output_tokens = int(usage_obj.get("output_tokens") or 0)
370
- total_tokens = int(usage_obj.get("total_tokens") or (input_tokens + output_tokens))
371
- cached_tokens = int(
370
+ current_input_tokens = int(usage_obj.get("input_tokens") or 0)
371
+ current_output_tokens = int(usage_obj.get("output_tokens") or 0)
372
+ current_total_tokens = int(
373
+ usage_obj.get("total_tokens") or (current_input_tokens + current_output_tokens)
374
+ )
375
+ current_cached_tokens = int(
372
376
  (usage_obj.get("input_tokens_details") or {}).get("cached_tokens")
373
377
  if isinstance(usage_obj.get("input_tokens_details"), dict)
374
378
  else 0
375
379
  )
380
+
381
+ # Some payloads emit both response.completed and response.done with
382
+ # different usage fidelity. Preserve best-known values instead of
383
+ # letting a later sparse event overwrite cache metrics with zeros.
384
+ previous_usage = result.usage
385
+ if previous_usage is not None:
386
+ input_tokens = max(previous_usage.input_tokens, current_input_tokens)
387
+ output_tokens = max(previous_usage.output_tokens, current_output_tokens)
388
+ total_tokens = max(previous_usage.total_tokens, current_total_tokens)
389
+ cached_tokens = max(previous_usage.cached_tokens, current_cached_tokens)
390
+ else:
391
+ input_tokens = current_input_tokens
392
+ output_tokens = current_output_tokens
393
+ total_tokens = current_total_tokens
394
+ cached_tokens = current_cached_tokens
395
+
376
396
  result.usage = CodexUsage(
377
397
  input_tokens=input_tokens,
378
398
  output_tokens=output_tokens,
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "flatagents"
7
- version = "2.4.4"
7
+ version = "2.5.0"
8
8
  description = "A lightweight framework for building LLM-powered agents."
9
9
  readme = "README.md"
10
10
  license = "Apache-2.0"
File without changes
File without changes