AbstractAgent 0.3.16__tar.gz → 0.3.17__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.
- {abstractagent-0.3.16/src/abstractagent.egg-info → abstractagent-0.3.17}/PKG-INFO +11 -8
- {abstractagent-0.3.16 → abstractagent-0.3.17}/README.md +7 -4
- {abstractagent-0.3.16 → abstractagent-0.3.17}/pyproject.toml +4 -4
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/adapters/react_runtime.py +28 -2
- {abstractagent-0.3.16 → abstractagent-0.3.17/src/abstractagent.egg-info}/PKG-INFO +11 -8
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent.egg-info/SOURCES.txt +1 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent.egg-info/requires.txt +3 -3
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_history_monster_clamp.py +28 -15
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_packaging_profiles.py +3 -3
- abstractagent-0.3.17/tests/test_react_history_window.py +64 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/LICENSE +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/setup.cfg +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/__init__.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/adapters/__init__.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/adapters/codeact_runtime.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/adapters/emit_inventory.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/adapters/generation_params.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/adapters/loop_hooks.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/adapters/media.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/adapters/memact_runtime.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/adapters/native_loop_registry.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/adapters/progress.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/adapters/read_orchestration.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/adapters/tool_allowlist.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/adapters/tool_failure_hints.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/adapters/transcripts.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/agents/__init__.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/agents/base.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/agents/codeact.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/agents/defaults.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/agents/memact.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/agents/react.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/agents/task_reset.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/agents/unattended.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/logic/__init__.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/logic/builtins.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/logic/codeact.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/logic/memact.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/logic/react.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/logic/types.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/metrics/__init__.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/metrics/prefix_reuse.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/repl.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/sandbox/__init__.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/sandbox/interface.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/sandbox/local.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/scripts/__init__.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/scripts/lmstudio_tool_eval.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/tools/__init__.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/tools/code_execution.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/tools/self_improve.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent.egg-info/dependency_links.txt +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent.egg-info/entry_points.txt +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent.egg-info/top_level.txt +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_active_context_policy_adoption.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_adversary_hardening_2026_07_13.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_agent_plan_review_modes.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_agent_speculation_inheritance.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_agent_stream_inheritance.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_agents_integration_llm.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_base_agent_trace_accessors.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_batching_prompt_rule.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_budget_triage_tail.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_builtin_tool_specs_optional_defaults.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_c2447_visit_lane_honesty.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_claim_0029_residue_2026_07_14.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_codeact_logic.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_codeact_runtime_verifier_policy.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_delegate_session_route_composition.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_emit_inventory_drift.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_gated_remainder_wave_2026_07_14.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_generation_params_media_policies.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_improvement_wave_2026_07_13.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_llm_call_payload_requires_prompt_or_messages.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_lmstudio_tool_eval_metrics.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_loop_hooks.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_loop_hooks_0026_follow_ups.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_memact_codeact_guidance_durable_transcript.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_memact_session_memory.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_memact_workflow.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_memory_recall_tool.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_native_loop_registry.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_open_attachment_tool_available.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_operator_conclude.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_optimal_wave_batch2_2026_07_13.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_parse_prompt_cache_capture.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_prefix_reuse_metric.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_progress_detection.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_act_only_observation.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_active_attachments_disable_tools_first_iteration.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_adapter_forwards_context_attachments_media.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_delegate_agent_tool.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_election_fence_conformance.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_entity_dress_conformance.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_guidance_durable_transcript.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_logic.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_loop_aborted_generation_retry.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_loop_context_transcript_levels.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_loop_followthrough_retry.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_loop_side_effect_dedupe_comms.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_loop_truncated_output_retry.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_max_iterations_concludes.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_phase_grant_boundary.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_planish_heuristic.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_prompt_prefix_stability.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_sight_lane_media_fold.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_turn_byte_stability.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_verifier_and_plan.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_visit_composition.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_visit_merge.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_workflow_system_prompt_and_tools_override.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_workflow_toolset_refresh.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_read_orchestration_guidance.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_reasoning_first_citizen_agent.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_review_failure_containment.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_run_start_seeds_runtime_provider_model.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_session_memory.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_sibling_loop_defects_batch.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_sibling_strict_transcripts_0011.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_stuck_streak_termination.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_tool_failure_hints.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_tool_loop_prefix_extension_a3.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_tool_observe_emits_result_for_tui.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_tools_editing.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_unseeded_render_limits.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_verifier_execution_preference.py +0 -0
- {abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_verifier_schema_strict.py +0 -0
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: abstractagent
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.17
|
|
4
4
|
Summary: Agent implementations using AbstractRuntime and AbstractCore
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
7
7
|
License-File: LICENSE
|
|
8
8
|
Requires-Dist: abstractcore[tools]>=2.13.41
|
|
9
|
-
Requires-Dist: abstractruntime>=0.
|
|
9
|
+
Requires-Dist: abstractruntime>=0.7.0
|
|
10
10
|
Provides-Extra: apple
|
|
11
11
|
Requires-Dist: abstractcore[all-apple]>=2.13.41; extra == "apple"
|
|
12
|
-
Requires-Dist: abstractruntime[apple]>=0.
|
|
12
|
+
Requires-Dist: abstractruntime[apple]>=0.7.0; extra == "apple"
|
|
13
13
|
Provides-Extra: gpu
|
|
14
14
|
Requires-Dist: abstractcore[all-gpu]>=2.13.41; extra == "gpu"
|
|
15
|
-
Requires-Dist: abstractruntime[gpu]>=0.
|
|
15
|
+
Requires-Dist: abstractruntime[gpu]>=0.7.0; extra == "gpu"
|
|
16
16
|
Provides-Extra: dev
|
|
17
17
|
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
18
18
|
Provides-Extra: test
|
|
@@ -105,10 +105,13 @@ Native Python hardware profile cascades are available for deployment manifests:
|
|
|
105
105
|
AbstractCore and AbstractRuntime profiles; AbstractAgent itself remains
|
|
106
106
|
provider/runtime agnostic.
|
|
107
107
|
|
|
108
|
-
AbstractAgent 0.3.
|
|
109
|
-
`AbstractRuntime>=0.
|
|
110
|
-
|
|
111
|
-
|
|
108
|
+
AbstractAgent 0.3.17 requires `abstractcore[tools]>=2.13.41` and
|
|
109
|
+
`AbstractRuntime>=0.7.0` (the runtime release with the 50k-token history
|
|
110
|
+
window, which ReAct applies to its requests when a host sets
|
|
111
|
+
`_runtime.history_window_tokens`, as the entity visit does; 0.5.0 brought live
|
|
112
|
+
token streaming, on top of turn grounding, in-flight cancellation and
|
|
113
|
+
speculation inheritance). AbstractRuntime 0.7.0 itself requires AbstractCore
|
|
114
|
+
2.18.0 or newer.
|
|
112
115
|
|
|
113
116
|
Note: the repository may be ahead of the latest published PyPI release. To verify what you installed:
|
|
114
117
|
|
|
@@ -84,10 +84,13 @@ Native Python hardware profile cascades are available for deployment manifests:
|
|
|
84
84
|
AbstractCore and AbstractRuntime profiles; AbstractAgent itself remains
|
|
85
85
|
provider/runtime agnostic.
|
|
86
86
|
|
|
87
|
-
AbstractAgent 0.3.
|
|
88
|
-
`AbstractRuntime>=0.
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
AbstractAgent 0.3.17 requires `abstractcore[tools]>=2.13.41` and
|
|
88
|
+
`AbstractRuntime>=0.7.0` (the runtime release with the 50k-token history
|
|
89
|
+
window, which ReAct applies to its requests when a host sets
|
|
90
|
+
`_runtime.history_window_tokens`, as the entity visit does; 0.5.0 brought live
|
|
91
|
+
token streaming, on top of turn grounding, in-flight cancellation and
|
|
92
|
+
speculation inheritance). AbstractRuntime 0.7.0 itself requires AbstractCore
|
|
93
|
+
2.18.0 or newer.
|
|
91
94
|
|
|
92
95
|
Note: the repository may be ahead of the latest published PyPI release. To verify what you installed:
|
|
93
96
|
|
|
@@ -4,23 +4,23 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "abstractagent"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.17"
|
|
8
8
|
description = "Agent implementations using AbstractRuntime and AbstractCore"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.10"
|
|
11
11
|
dependencies = [
|
|
12
12
|
"abstractcore[tools]>=2.13.41",
|
|
13
|
-
"abstractruntime>=0.
|
|
13
|
+
"abstractruntime>=0.7.0",
|
|
14
14
|
]
|
|
15
15
|
|
|
16
16
|
[project.optional-dependencies]
|
|
17
17
|
apple = [
|
|
18
18
|
"abstractcore[all-apple]>=2.13.41",
|
|
19
|
-
"abstractruntime[apple]>=0.
|
|
19
|
+
"abstractruntime[apple]>=0.7.0",
|
|
20
20
|
]
|
|
21
21
|
gpu = [
|
|
22
22
|
"abstractcore[all-gpu]>=2.13.41",
|
|
23
|
-
"abstractruntime[gpu]>=0.
|
|
23
|
+
"abstractruntime[gpu]>=0.7.0",
|
|
24
24
|
]
|
|
25
25
|
dev = [
|
|
26
26
|
"pytest>=7.0",
|
|
@@ -24,6 +24,7 @@ from typing import Any, Callable, Dict, List, Optional
|
|
|
24
24
|
from abstractcore.tools import ToolCall
|
|
25
25
|
from abstractruntime import Effect, EffectType, RunState, StepPlan, WorkflowSpec
|
|
26
26
|
from abstractruntime.core.vars import ensure_limits, ensure_namespaces
|
|
27
|
+
from abstractruntime.session_history import window_transcript
|
|
27
28
|
from abstractruntime.turn_grounding import stamp_user_turn_grounding, strip_turn_grounding
|
|
28
29
|
|
|
29
30
|
from .generation_params import (
|
|
@@ -1659,6 +1660,31 @@ def create_react_workflow(
|
|
|
1659
1660
|
out.append(d)
|
|
1660
1661
|
return out
|
|
1661
1662
|
|
|
1663
|
+
def _history_window_view(messages: List[Dict[str, Any]], runtime_ns: Any) -> List[Dict[str, Any]]:
|
|
1664
|
+
"""The transcript a model request carries when the host asks for THE
|
|
1665
|
+
runtime history window (`_runtime.history_window_tokens`, set by the
|
|
1666
|
+
entity visit's BRIDGE; operator ruling 2026-09-28, ADR-0026).
|
|
1667
|
+
|
|
1668
|
+
`abstractruntime.session_history.window_transcript`: the newest whole
|
|
1669
|
+
turns up to that many tokens (a tool result stays with its turn), a
|
|
1670
|
+
labeled #TRUNCATION notice when older turns were dropped. The turn in
|
|
1671
|
+
progress starts at `_runtime.history_window_turn_start` (set by the
|
|
1672
|
+
host) and is kept whole, so an ask_user answer or operator guidance
|
|
1673
|
+
inside it never splits off the turn's own question and tool results. The durable
|
|
1674
|
+
`context.messages` is never touched — only this request's view — and
|
|
1675
|
+
the window's receipt is recorded at `_runtime.session_history`.
|
|
1676
|
+
Unset = the whole transcript (the plain task lane's full-context policy).
|
|
1677
|
+
"""
|
|
1678
|
+
if not isinstance(runtime_ns, dict) or runtime_ns.get("history_window_tokens") is None:
|
|
1679
|
+
return messages
|
|
1680
|
+
window = window_transcript(
|
|
1681
|
+
messages,
|
|
1682
|
+
max_tokens=runtime_ns["history_window_tokens"],
|
|
1683
|
+
current_turn_start=runtime_ns.get("history_window_turn_start"),
|
|
1684
|
+
)
|
|
1685
|
+
runtime_ns["session_history"] = dict(window.report)
|
|
1686
|
+
return list(window)
|
|
1687
|
+
|
|
1662
1688
|
def _sanitize_llm_messages(
|
|
1663
1689
|
messages: Any, *, limits: Optional[Dict[str, Any]] = None
|
|
1664
1690
|
) -> List[Dict[str, Any]]:
|
|
@@ -1874,7 +1900,7 @@ def create_react_workflow(
|
|
|
1874
1900
|
|
|
1875
1901
|
|
|
1876
1902
|
payload: Dict[str, Any] = {"prompt": ""}
|
|
1877
|
-
sanitized_messages = _sanitize_llm_messages(messages_view, limits=limits)
|
|
1903
|
+
sanitized_messages = _sanitize_llm_messages(_history_window_view(messages_view, runtime_ns), limits=limits)
|
|
1878
1904
|
if sanitized_messages:
|
|
1879
1905
|
payload["messages"] = sanitized_messages
|
|
1880
1906
|
else:
|
|
@@ -3765,7 +3791,7 @@ def create_react_workflow(
|
|
|
3765
3791
|
)
|
|
3766
3792
|
|
|
3767
3793
|
payload: Dict[str, Any] = {"prompt": ""}
|
|
3768
|
-
sanitized_messages = _sanitize_llm_messages(messages_view, limits=limits)
|
|
3794
|
+
sanitized_messages = _sanitize_llm_messages(_history_window_view(messages_view, runtime_ns), limits=limits)
|
|
3769
3795
|
if sanitized_messages:
|
|
3770
3796
|
payload["messages"] = sanitized_messages
|
|
3771
3797
|
else:
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: abstractagent
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.17
|
|
4
4
|
Summary: Agent implementations using AbstractRuntime and AbstractCore
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
7
7
|
License-File: LICENSE
|
|
8
8
|
Requires-Dist: abstractcore[tools]>=2.13.41
|
|
9
|
-
Requires-Dist: abstractruntime>=0.
|
|
9
|
+
Requires-Dist: abstractruntime>=0.7.0
|
|
10
10
|
Provides-Extra: apple
|
|
11
11
|
Requires-Dist: abstractcore[all-apple]>=2.13.41; extra == "apple"
|
|
12
|
-
Requires-Dist: abstractruntime[apple]>=0.
|
|
12
|
+
Requires-Dist: abstractruntime[apple]>=0.7.0; extra == "apple"
|
|
13
13
|
Provides-Extra: gpu
|
|
14
14
|
Requires-Dist: abstractcore[all-gpu]>=2.13.41; extra == "gpu"
|
|
15
|
-
Requires-Dist: abstractruntime[gpu]>=0.
|
|
15
|
+
Requires-Dist: abstractruntime[gpu]>=0.7.0; extra == "gpu"
|
|
16
16
|
Provides-Extra: dev
|
|
17
17
|
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
18
18
|
Provides-Extra: test
|
|
@@ -105,10 +105,13 @@ Native Python hardware profile cascades are available for deployment manifests:
|
|
|
105
105
|
AbstractCore and AbstractRuntime profiles; AbstractAgent itself remains
|
|
106
106
|
provider/runtime agnostic.
|
|
107
107
|
|
|
108
|
-
AbstractAgent 0.3.
|
|
109
|
-
`AbstractRuntime>=0.
|
|
110
|
-
|
|
111
|
-
|
|
108
|
+
AbstractAgent 0.3.17 requires `abstractcore[tools]>=2.13.41` and
|
|
109
|
+
`AbstractRuntime>=0.7.0` (the runtime release with the 50k-token history
|
|
110
|
+
window, which ReAct applies to its requests when a host sets
|
|
111
|
+
`_runtime.history_window_tokens`, as the entity visit does; 0.5.0 brought live
|
|
112
|
+
token streaming, on top of turn grounding, in-flight cancellation and
|
|
113
|
+
speculation inheritance). AbstractRuntime 0.7.0 itself requires AbstractCore
|
|
114
|
+
2.18.0 or newer.
|
|
112
115
|
|
|
113
116
|
Note: the repository may be ahead of the latest published PyPI release. To verify what you installed:
|
|
114
117
|
|
|
@@ -90,6 +90,7 @@ tests/test_react_delegate_agent_tool.py
|
|
|
90
90
|
tests/test_react_election_fence_conformance.py
|
|
91
91
|
tests/test_react_entity_dress_conformance.py
|
|
92
92
|
tests/test_react_guidance_durable_transcript.py
|
|
93
|
+
tests/test_react_history_window.py
|
|
93
94
|
tests/test_react_logic.py
|
|
94
95
|
tests/test_react_loop_aborted_generation_retry.py
|
|
95
96
|
tests/test_react_loop_context_transcript_levels.py
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
abstractcore[tools]>=2.13.41
|
|
2
|
-
abstractruntime>=0.
|
|
2
|
+
abstractruntime>=0.7.0
|
|
3
3
|
|
|
4
4
|
[apple]
|
|
5
5
|
abstractcore[all-apple]>=2.13.41
|
|
6
|
-
abstractruntime[apple]>=0.
|
|
6
|
+
abstractruntime[apple]>=0.7.0
|
|
7
7
|
|
|
8
8
|
[dev]
|
|
9
9
|
pytest>=7.0
|
|
10
10
|
|
|
11
11
|
[gpu]
|
|
12
12
|
abstractcore[all-gpu]>=2.13.41
|
|
13
|
-
abstractruntime[gpu]>=0.
|
|
13
|
+
abstractruntime[gpu]>=0.7.0
|
|
14
14
|
|
|
15
15
|
[test]
|
|
16
16
|
pytest>=7.0
|
|
@@ -241,18 +241,23 @@ def _poison_tools(run: Any, effect: Effect, dnn: Any = None) -> EffectOutcome:
|
|
|
241
241
|
|
|
242
242
|
def test_poisoned_visit_transcript_recovers_on_the_next_turn(tmp_path: Path) -> None:
|
|
243
243
|
"""End-to-end on the REAL merged lane (the incident's lane): turn 1
|
|
244
|
-
poisons the durable transcript with a ~495k tool message
|
|
245
|
-
|
|
246
|
-
|
|
244
|
+
poisons the durable transcript with a ~495k tool message. Within turn 1
|
|
245
|
+
the result rides the next call clamped to OVERSIZED_MESSAGE_CLAMP_CHARS
|
|
246
|
+
(the newest turn is kept whole by the window). From turn 2 on, the visit
|
|
247
|
+
BRIDGE's history window (`_runtime.history_window_tokens`, runtime 0.7,
|
|
248
|
+
ADR-0026) drops the poisoned turn whole — call, result and reply — because
|
|
249
|
+
it no longer fits beside a newer turn: the request is the labeled notice
|
|
250
|
+
and the new words. The session recovers with NO manual surgery while the
|
|
251
|
+
durable record keeps the full truth."""
|
|
247
252
|
pytest.importorskip("abstractmemory")
|
|
248
253
|
from abstractruntime.identity.entity_runtime import open_entity_runtime
|
|
249
254
|
from abstractruntime.identity.visit_workflow import (
|
|
250
255
|
HARVEST_NODE,
|
|
251
|
-
VISIT_HISTORY_TOOL_RESULT_CAP_CHARS,
|
|
252
256
|
VISITOR_WAIT_KEY,
|
|
253
257
|
ReactMiddle,
|
|
254
258
|
build_visit_workflow,
|
|
255
259
|
)
|
|
260
|
+
from abstractruntime.turn_grounding import strip_turn_grounding
|
|
256
261
|
|
|
257
262
|
home_dir = _make_home(tmp_path)
|
|
258
263
|
llm = _ScriptedLLM([
|
|
@@ -312,20 +317,28 @@ def test_poisoned_visit_transcript_recovers_on_the_next_turn(tmp_path: Path) ->
|
|
|
312
317
|
assert state.status == RunStatus.WAITING
|
|
313
318
|
assert len(llm.calls) == 3
|
|
314
319
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
assert len(
|
|
318
|
-
clamped =
|
|
319
|
-
assert len(clamped) <=
|
|
320
|
+
# Within turn 1, the call after the read carried the clamped stub.
|
|
321
|
+
in_turn_tool = [m for m in llm.calls[1]["messages"] if m.get("role") == "tool"]
|
|
322
|
+
assert len(in_turn_tool) == 1
|
|
323
|
+
clamped = in_turn_tool[0]["content"]
|
|
324
|
+
assert len(clamped) <= OVERSIZED_MESSAGE_CLAMP_CHARS + 200
|
|
320
325
|
assert clamped.startswith("[read_file]: --- shared/Screenshot_2026-08-01"), "head kept - labeled, never dropped"
|
|
321
326
|
assert "chars elided: oversized tool result" in clamped
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
assert
|
|
326
|
-
|
|
327
|
+
|
|
328
|
+
# Turn 2: the poisoned turn is out of the request, whole, and says so.
|
|
329
|
+
wire = llm.calls[2]["messages"]
|
|
330
|
+
assert [m for m in wire if m.get("role") == "tool"] == []
|
|
331
|
+
assert not any(m.get("tool_calls") for m in wire)
|
|
332
|
+
assert len(wire) == 1 and wire[0]["role"] == "user"
|
|
333
|
+
# One head envelope (the turn's own), then the labeled drop notice.
|
|
334
|
+
assert wire[0]["content"].count("<runtime_metadata>") == 1
|
|
335
|
+
assert strip_turn_grounding(wire[0]["content"]).startswith("[#TRUNCATION: 4 earlier message(s)")
|
|
336
|
+
assert "Are you still with me?" in wire[0]["content"]
|
|
337
|
+
report = ert.runtime.get_state(run_id).vars["_runtime"]["session_history"]
|
|
338
|
+
assert report["dropped_messages"] == 4 and report["replayed_messages"] == 1
|
|
339
|
+
# The whole request shrank from monster-class to one short message.
|
|
327
340
|
total = sum(len(str(m.get("content") or "")) for m in wire)
|
|
328
|
-
assert total <
|
|
341
|
+
assert total < 2_000, f"recovered payload still huge: {total}"
|
|
329
342
|
|
|
330
343
|
# And the durable record STILL holds the full truth (ADR-0026).
|
|
331
344
|
stored = ert.runtime.get_state(run_id).vars["context"]["messages"]
|
|
@@ -19,7 +19,7 @@ def test_base_dependency_floors_match_gateway_alignment() -> None:
|
|
|
19
19
|
deps = set(_project()["dependencies"])
|
|
20
20
|
|
|
21
21
|
assert "abstractcore[tools]>=2.13.41" in deps
|
|
22
|
-
assert "abstractruntime>=0.
|
|
22
|
+
assert "abstractruntime>=0.7.0" in deps
|
|
23
23
|
|
|
24
24
|
|
|
25
25
|
def test_hardware_profile_extras_are_core_runtime_cascades() -> None:
|
|
@@ -27,11 +27,11 @@ def test_hardware_profile_extras_are_core_runtime_cascades() -> None:
|
|
|
27
27
|
|
|
28
28
|
assert set(extras["apple"]) == {
|
|
29
29
|
"abstractcore[all-apple]>=2.13.41",
|
|
30
|
-
"abstractruntime[apple]>=0.
|
|
30
|
+
"abstractruntime[apple]>=0.7.0",
|
|
31
31
|
}
|
|
32
32
|
assert set(extras["gpu"]) == {
|
|
33
33
|
"abstractcore[all-gpu]>=2.13.41",
|
|
34
|
-
"abstractruntime[gpu]>=0.
|
|
34
|
+
"abstractruntime[gpu]>=0.7.0",
|
|
35
35
|
}
|
|
36
36
|
assert "all-apple" not in extras
|
|
37
37
|
assert "all-gpu" not in extras
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"""ReAct sends THE runtime history window when the host asks for it
|
|
2
|
+
(`_runtime.history_window_tokens`; runtime 0.7.0's entity visit sets 50k).
|
|
3
|
+
Unset, the whole transcript rides as before. The durable transcript is never
|
|
4
|
+
windowed."""
|
|
5
|
+
from __future__ import annotations
|
|
6
|
+
|
|
7
|
+
import json
|
|
8
|
+
from typing import Any, Dict, List, Optional
|
|
9
|
+
|
|
10
|
+
from abstractagent.adapters.react_runtime import create_react_workflow
|
|
11
|
+
from abstractagent.logic.react import ReActLogic
|
|
12
|
+
from abstractcore.tools import ToolDefinition
|
|
13
|
+
from abstractruntime.core.models import Effect, EffectType, RunState, RunStatus
|
|
14
|
+
from abstractruntime.core.runtime import EffectOutcome, Runtime
|
|
15
|
+
from abstractruntime.storage.in_memory import InMemoryLedgerStore, InMemoryRunStore
|
|
16
|
+
from abstractruntime.turn_grounding import strip_turn_grounding
|
|
17
|
+
|
|
18
|
+
OLD = [m for i in range(6) for m in ({"role": "user", "content": f"old {i} " + "w " * 2000},
|
|
19
|
+
{"role": "assistant", "content": f"reply {i}"})]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def _run(runtime_vars: Dict[str, Any]) -> tuple:
|
|
23
|
+
captured: List[Dict[str, Any]] = []
|
|
24
|
+
|
|
25
|
+
def llm(run: RunState, effect: Effect, dnn: Optional[str]) -> EffectOutcome:
|
|
26
|
+
captured.append(json.loads(json.dumps(effect.payload)))
|
|
27
|
+
return EffectOutcome.completed({"content": "done", "tool_calls": []})
|
|
28
|
+
|
|
29
|
+
rt = Runtime(run_store=InMemoryRunStore(), ledger_store=InMemoryLedgerStore(),
|
|
30
|
+
effect_handlers={EffectType.LLM_CALL: llm})
|
|
31
|
+
wf = create_react_workflow(logic=ReActLogic(tools=[ToolDefinition(name="t", description="t", parameters={})]),
|
|
32
|
+
workflow_id="react_window", provider="stub", model="stub", allowed_tools=["t"])
|
|
33
|
+
messages = [dict(m) for m in OLD] + [{"role": "user", "content": "now"}]
|
|
34
|
+
run_id = rt.start(workflow=wf, vars={"context": {"task": "now", "messages": messages}, "_runtime": dict(runtime_vars)})
|
|
35
|
+
state = rt.tick(workflow=wf, run_id=run_id, max_steps=40)
|
|
36
|
+
assert state.status == RunStatus.COMPLETED
|
|
37
|
+
return captured[0]["messages"], state
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def test_the_window_key_windows_the_request_and_records_it() -> None:
|
|
41
|
+
wire, state = _run({"history_window_tokens": 3000})
|
|
42
|
+
report = state.vars["_runtime"]["session_history"]
|
|
43
|
+
assert report["max_tokens"] == 3000 and report["dropped_messages"] > 0
|
|
44
|
+
assert len(wire) == report["replayed_messages"] < len(OLD) + 1
|
|
45
|
+
assert strip_turn_grounding(wire[0]["content"]).startswith("[#TRUNCATION: ")
|
|
46
|
+
assert strip_turn_grounding(wire[-1]["content"]) == "now"
|
|
47
|
+
stored = state.vars["context"]["messages"]
|
|
48
|
+
assert len(stored) >= len(OLD) + 1 and stored[0]["content"].startswith("old 0 ") # durable transcript whole
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def test_without_the_key_the_whole_transcript_rides() -> None:
|
|
52
|
+
wire, state = _run({})
|
|
53
|
+
assert "session_history" not in state.vars["_runtime"]
|
|
54
|
+
assert len(wire) == len(OLD) + 1 and wire[0]["content"].startswith("old 0 ")
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
def test_the_turn_in_progress_is_kept_whole_from_the_hosts_turn_start() -> None:
|
|
58
|
+
"""`_runtime.history_window_turn_start` marks where the turn in progress
|
|
59
|
+
began: from there on it is one turn, kept whole (and reported oversize),
|
|
60
|
+
however many user-role messages the loop added inside it."""
|
|
61
|
+
wire, state = _run({"history_window_tokens": 3000, "history_window_turn_start": 0})
|
|
62
|
+
report = state.vars["_runtime"]["session_history"]
|
|
63
|
+
assert report["dropped_messages"] == 0 and report["oversize_turn_kept"] is True
|
|
64
|
+
assert len(wire) == len(OLD) + 1 and wire[0]["content"].startswith("old 0 ")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/adapters/generation_params.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/adapters/native_loop_registry.py
RENAMED
|
File without changes
|
|
File without changes
|
{abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/adapters/read_orchestration.py
RENAMED
|
File without changes
|
|
File without changes
|
{abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/adapters/tool_failure_hints.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent/scripts/lmstudio_tool_eval.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstractagent-0.3.16 → abstractagent-0.3.17}/src/abstractagent.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_builtin_tool_specs_optional_defaults.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_delegate_session_route_composition.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_generation_params_media_policies.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_election_fence_conformance.py
RENAMED
|
File without changes
|
|
File without changes
|
{abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_guidance_durable_transcript.py
RENAMED
|
File without changes
|
|
File without changes
|
{abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_loop_aborted_generation_retry.py
RENAMED
|
File without changes
|
{abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_loop_context_transcript_levels.py
RENAMED
|
File without changes
|
|
File without changes
|
{abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_loop_side_effect_dedupe_comms.py
RENAMED
|
File without changes
|
{abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_react_loop_truncated_output_retry.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_run_start_seeds_runtime_provider_model.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{abstractagent-0.3.16 → abstractagent-0.3.17}/tests/test_tool_observe_emits_result_for_tui.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|