prizmkit 1.1.150 → 1.1.151
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.
- package/bundled/VERSION.json +3 -3
- package/bundled/dev-pipeline/prizmkit_runtime/runner_classification.py +3 -0
- package/bundled/dev-pipeline/scripts/parse-stream-progress.py +20 -2
- package/bundled/dev-pipeline/tests/test_python_runner_parity.py +19 -0
- package/bundled/dev-pipeline/tests/test_unified_cli.py +37 -0
- package/bundled/skills/_metadata.json +1 -1
- package/package.json +1 -1
package/bundled/VERSION.json
CHANGED
|
@@ -168,6 +168,7 @@ def _is_terminal_success(result: AISessionResult) -> bool:
|
|
|
168
168
|
and result.termination_reason not in {"timeout", "stale_session"}
|
|
169
169
|
and not result.fatal_error_code
|
|
170
170
|
and not result.progress_summary.fatal_error_code
|
|
171
|
+
and result.progress_summary.stop_reason.strip().lower() != "length"
|
|
171
172
|
and result.progress_summary.result_subtype == "success"
|
|
172
173
|
)
|
|
173
174
|
|
|
@@ -228,6 +229,8 @@ def _next_no_progress_count(previous: object | None, current: object, count: int
|
|
|
228
229
|
|
|
229
230
|
|
|
230
231
|
def _is_context_overflow(result: AISessionResult) -> bool:
|
|
232
|
+
if result.progress_summary.stop_reason.strip().lower() == "length":
|
|
233
|
+
return True
|
|
231
234
|
if (result.fatal_error_code or "").lower() == CONTEXT_OVERFLOW:
|
|
232
235
|
return True
|
|
233
236
|
text = "\n".join(
|
|
@@ -277,6 +277,7 @@ class SemanticLogNormalizer:
|
|
|
277
277
|
|
|
278
278
|
_SUCCESS_STOPS = {"stop", "end_turn", "completed", "success"}
|
|
279
279
|
_ERROR_STOPS = {"error", "aborted", "failed", "cancelled", "canceled"}
|
|
280
|
+
_CONTEXT_STOPS = {"length"}
|
|
280
281
|
|
|
281
282
|
def __init__(self):
|
|
282
283
|
self.renderer = SemanticLogRenderer()
|
|
@@ -617,7 +618,10 @@ class SemanticLogNormalizer:
|
|
|
617
618
|
will_retry = bool(event.get("willRetry"))
|
|
618
619
|
if will_retry:
|
|
619
620
|
return ""
|
|
620
|
-
|
|
621
|
+
if stop_reason in self._CONTEXT_STOPS:
|
|
622
|
+
status = CONTEXT_OVERFLOW_CODE
|
|
623
|
+
else:
|
|
624
|
+
status = "error" if stop_reason in self._ERROR_STOPS else "success"
|
|
621
625
|
details = f"status={status}"
|
|
622
626
|
if stop_reason:
|
|
623
627
|
details += f" stop_reason={stop_reason}"
|
|
@@ -768,6 +772,16 @@ class ProgressTracker:
|
|
|
768
772
|
self._current_tool_id = ""
|
|
769
773
|
self._pi_retrying_terminal_error = False
|
|
770
774
|
|
|
775
|
+
def _record_pi_length_stop(self):
|
|
776
|
+
"""Normalize Pi's token-limit stop into the existing context continuation path."""
|
|
777
|
+
self.result_subtype = "error"
|
|
778
|
+
self.stop_reason = "length"
|
|
779
|
+
self.last_result_is_error = True
|
|
780
|
+
self.api_error_code = CONTEXT_OVERFLOW_CODE
|
|
781
|
+
self.fatal_error_code = CONTEXT_OVERFLOW_CODE
|
|
782
|
+
self.terminal_result_text = "stop_reason=length"
|
|
783
|
+
self.terminal_success_at = ""
|
|
784
|
+
|
|
771
785
|
def process_event(self, event):
|
|
772
786
|
"""Process a single stream-json event and update state.
|
|
773
787
|
|
|
@@ -846,7 +860,9 @@ class ProgressTracker:
|
|
|
846
860
|
stop_reason = str(message.get("stopReason") or "")
|
|
847
861
|
if stop_reason:
|
|
848
862
|
self.stop_reason = stop_reason
|
|
849
|
-
if stop_reason
|
|
863
|
+
if stop_reason == "length":
|
|
864
|
+
self._record_pi_length_stop()
|
|
865
|
+
elif stop_reason in {"error", "aborted"}:
|
|
850
866
|
error_text = str(message.get("errorMessage") or stop_reason)
|
|
851
867
|
self.result_subtype = "error"
|
|
852
868
|
self.last_result_is_error = True
|
|
@@ -880,6 +896,8 @@ class ProgressTracker:
|
|
|
880
896
|
messages = event.get("messages") if isinstance(event.get("messages"), list) else []
|
|
881
897
|
final_message = messages[-1] if messages and isinstance(messages[-1], dict) else {}
|
|
882
898
|
final_stop_reason = str(final_message.get("stopReason") or self.stop_reason or "")
|
|
899
|
+
if final_stop_reason == "length":
|
|
900
|
+
self._record_pi_length_stop()
|
|
883
901
|
will_retry = bool(event.get("willRetry"))
|
|
884
902
|
if will_retry:
|
|
885
903
|
self._pi_retrying_terminal_error = bool(
|
|
@@ -3795,6 +3795,25 @@ def test_terminal_success_without_semantic_completion_is_skipped(tmp_path):
|
|
|
3795
3795
|
assert classification.fatal_error_code == ""
|
|
3796
3796
|
|
|
3797
3797
|
|
|
3798
|
+
def test_pi_length_stop_uses_existing_context_overflow_continuation(tmp_path):
|
|
3799
|
+
from dataclasses import replace
|
|
3800
|
+
|
|
3801
|
+
from prizmkit_runtime.runner_classification import classify_session
|
|
3802
|
+
from prizmkit_runtime.status import ProgressSummary
|
|
3803
|
+
|
|
3804
|
+
base_head = _init_git_repo_for_invalid_checkpoint_test(tmp_path)
|
|
3805
|
+
raw = replace(
|
|
3806
|
+
_terminal_success_result(tmp_path),
|
|
3807
|
+
progress_summary=ProgressSummary(result_subtype="success", stop_reason="length"),
|
|
3808
|
+
)
|
|
3809
|
+
|
|
3810
|
+
classification = classify_session(raw, project_root=tmp_path, base_head=base_head)
|
|
3811
|
+
|
|
3812
|
+
assert classification.session_status == "context_overflow"
|
|
3813
|
+
assert classification.reason == "context_overflow"
|
|
3814
|
+
assert classification.fatal_error_code == "context_overflow"
|
|
3815
|
+
|
|
3816
|
+
|
|
3798
3817
|
def test_terminal_success_text_does_not_hide_provider_failure(tmp_path):
|
|
3799
3818
|
from prizmkit_runtime.runner_classification import classify_session
|
|
3800
3819
|
from prizmkit_runtime.runner_models import PromptGenerationResult
|
|
@@ -994,6 +994,29 @@ def test_progress_parser_does_not_mark_failed_pi_agent_end_as_success():
|
|
|
994
994
|
assert "provider request failed" in data["errors"]
|
|
995
995
|
|
|
996
996
|
|
|
997
|
+
def test_progress_parser_maps_pi_length_stop_to_context_overflow():
|
|
998
|
+
module = _load_progress_parser_module()
|
|
999
|
+
tracker = module.ProgressTracker()
|
|
1000
|
+
tracker.process_event({"type": "session", "version": 3, "id": "pi-session", "cwd": "/tmp/project"})
|
|
1001
|
+
tracker.process_event({"type": "agent_start"})
|
|
1002
|
+
message = {
|
|
1003
|
+
"role": "assistant",
|
|
1004
|
+
"content": [{"type": "thinking", "thinking": "Planning the next test"}],
|
|
1005
|
+
"stopReason": "length",
|
|
1006
|
+
}
|
|
1007
|
+
tracker.process_event({"type": "message_end", "message": message})
|
|
1008
|
+
tracker.process_event({"type": "agent_end", "willRetry": False, "messages": [message]})
|
|
1009
|
+
|
|
1010
|
+
data = tracker.to_dict()
|
|
1011
|
+
|
|
1012
|
+
assert data["result_subtype"] == "error"
|
|
1013
|
+
assert data["stop_reason"] == "length"
|
|
1014
|
+
assert data["last_result_is_error"] is True
|
|
1015
|
+
assert data["api_error_code"] == "context_overflow"
|
|
1016
|
+
assert data["fatal_error_code"] == "context_overflow"
|
|
1017
|
+
assert data["terminal_success_at"] == ""
|
|
1018
|
+
|
|
1019
|
+
|
|
997
1020
|
def test_progress_parser_recovers_from_retrying_pi_attempt_before_final_success():
|
|
998
1021
|
module = _load_progress_parser_module()
|
|
999
1022
|
tracker = module.ProgressTracker()
|
|
@@ -1190,6 +1213,20 @@ def test_semantic_log_normalizer_emits_terminal_metadata_once():
|
|
|
1190
1213
|
assert "[FINAL] Done" in rendered
|
|
1191
1214
|
|
|
1192
1215
|
|
|
1216
|
+
def test_semantic_log_normalizer_labels_pi_length_as_context_overflow():
|
|
1217
|
+
module = _load_progress_parser_module()
|
|
1218
|
+
normalizer = module.SemanticLogNormalizer()
|
|
1219
|
+
rendered = normalizer.process_event({
|
|
1220
|
+
"type": "agent_end",
|
|
1221
|
+
"willRetry": False,
|
|
1222
|
+
"messages": [{"role": "assistant", "content": [], "stopReason": "length"}],
|
|
1223
|
+
})
|
|
1224
|
+
rendered += normalizer.finish()
|
|
1225
|
+
|
|
1226
|
+
assert rendered.count("[SESSION_END]") == 1
|
|
1227
|
+
assert "status=context_overflow stop_reason=length" in rendered
|
|
1228
|
+
|
|
1229
|
+
|
|
1193
1230
|
def test_semantic_log_normalizer_preserves_identical_text_from_distinct_turns():
|
|
1194
1231
|
module = _load_progress_parser_module()
|
|
1195
1232
|
normalizer = module.SemanticLogNormalizer()
|