tamfis-code 0.6.4__tar.gz → 0.6.7__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.
- {tamfis_code-0.6.4/tamfis_code.egg-info → tamfis_code-0.6.7}/PKG-INFO +1 -1
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/pyproject.toml +1 -1
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/__init__.py +1 -1
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/render.py +8 -1
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/runner_local.py +19 -1
- {tamfis_code-0.6.4 → tamfis_code-0.6.7/tamfis_code.egg-info}/PKG-INFO +1 -1
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_runner_local.py +23 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_tamfis_code_render.py +12 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/MANIFEST.in +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/README.md +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/USAGE_INSTALL_RELEASE.md +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/setup.cfg +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/__main__.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/agent_definitions.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/agents.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/api_client.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/cli.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/clipboard.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/completion.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/config.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/custom_commands.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/doctor.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/enforcer.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/evidence.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/hooks.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/indexer.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/instructions.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/interactive.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/live_input.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/local_chat.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/local_tools.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/mcp.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/mcp_stdio_server.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/metrics.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/model_registry.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/openhands/__init__.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/openhands/agent.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/openhands/agent_server.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/openhands/automation.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/openhands/compat.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/openhands/conversation.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/openhands/delegation.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/openhands/events.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/openhands/leases.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/openhands/security.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/openhands/skills.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/openhands/tools.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/openhands/workspace.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/orchestrator/__init__.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/orchestrator/context.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/orchestrator/engine.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/orchestrator/planner.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/orchestrator/protocols.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/orchestrator/validator.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/project.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/provider_protocols.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/providers.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/pty.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/references.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/routing.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/runner.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/safety.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/screenshot.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/sessions.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/state.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/swarm.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/tasks.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/tool_policy.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code/workspace.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code.egg-info/SOURCES.txt +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code.egg-info/dependency_links.txt +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code.egg-info/entry_points.txt +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code.egg-info/requires.txt +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tamfis_code.egg-info/top_level.txt +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_agent_definitions.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_agents.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_agents_delegation.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_build_installation.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_cli_commands.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_clipboard.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_completion.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_context_rollover.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_custom_commands.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_cwd_validation.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_doctor_session_diagnostics.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_enforcer.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_fake_tool_detection.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_find_references.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_hooks.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_indexer.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_instructions.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_integration_new.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_interactive_standalone.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_live_input.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_local_pty.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_mcp.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_mcp_search_bounds.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_mcp_standalone_degradation.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_mcp_stdio_server.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_metrics.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_openhands_runtime.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_openrouter_cost_routing.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_orchestrator.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_plan_mode_gate.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_plan_steps_and_attempts.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_provider_protocols.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_reasoning_effort_capability.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_reasoning_plan.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_references.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_render_task_diagnostics.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_routing.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_runner_helpers.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_safety.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_safety_manifest.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_sessions.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_swarm.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_tamfis_code_api_client.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_tamfis_code_approval.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_tamfis_code_approval_flow.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_tamfis_code_config.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_tamfis_code_intent.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_tamfis_code_repl_exit.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_tamfis_code_tasks.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_tamfis_code_workspace.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_version_consistency.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_workspace_discovery_gaps.py +0 -0
- {tamfis_code-0.6.4 → tamfis_code-0.6.7}/tests/test_workspace_scope.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tamfis-code
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.7
|
|
4
4
|
Summary: TamfisGPT Code -- portable subscription-backed terminal coding agent with local tools, PTY, plans, queues, and approvals
|
|
5
5
|
Project-URL: Homepage, https://github.com/tamfitronics/tamfis-code
|
|
6
6
|
Project-URL: Repository, https://github.com/tamfitronics/tamfis-code
|
|
@@ -17,7 +17,7 @@ See docs/REMOTE_AGENT_MASTER_SPEC.md, Phase 21, for the original --remote
|
|
|
17
17
|
architecture's spec.
|
|
18
18
|
"""
|
|
19
19
|
|
|
20
|
-
__version__ = "0.6.
|
|
20
|
+
__version__ = "0.6.7"
|
|
21
21
|
|
|
22
22
|
# Bumped whenever a CLI release requires a minimum backend Remote API
|
|
23
23
|
# contract version. Only meaningful for --remote; the standalone path has no
|
|
@@ -411,9 +411,16 @@ class StreamRenderer:
|
|
|
411
411
|
label = f"{mode_tag}[bold]{verb}…[/bold] [dim]({' · '.join(detail_parts)})[/dim]"
|
|
412
412
|
self._spinner.update(text=Text.from_markup(label))
|
|
413
413
|
tip = _current_tip(elapsed)
|
|
414
|
-
if not self._plan_steps and not tip:
|
|
414
|
+
if not self._plan_steps and not tip and self.live_input_listener is None:
|
|
415
415
|
return self._spinner
|
|
416
416
|
lines = []
|
|
417
|
+
if self.live_input_listener is not None:
|
|
418
|
+
# The ordinary REPL editor is suspended while the agent owns the
|
|
419
|
+
# terminal, but the input affordance must remain visible. Ctrl+T
|
|
420
|
+
# opens the coordinated editor without competing with Rich Live;
|
|
421
|
+
# this footer is rebuilt on every refresh and therefore never
|
|
422
|
+
# disappears behind the spinner or plan rows.
|
|
423
|
+
lines.append(" [cyan]Input:[/cyan] Ctrl+T queue next> · Ctrl+C/Ctrl+D exit")
|
|
417
424
|
if tip:
|
|
418
425
|
lines.append(f" [dim]{tip}[/dim]")
|
|
419
426
|
for step in self._plan_steps:
|
|
@@ -1183,6 +1183,14 @@ def _legacy_resume_messages(state, incoming_objective: str) -> tuple[list[dict[s
|
|
|
1183
1183
|
# the tail of the accumulated text, and triggers within a couple KB of a
|
|
1184
1184
|
# genuine loop, long before the content can grow large enough to matter.
|
|
1185
1185
|
_DEGENERATE_REPETITION_RE = re.compile(r"(.{6,200}?)\1{4,}", re.DOTALL)
|
|
1186
|
+
# A separate guard for a common context-confusion failure: the model starts
|
|
1187
|
+
# replaying a synthetic transcript ("then the user said ... then the
|
|
1188
|
+
# assistant responded ...") instead of answering the current task. The
|
|
1189
|
+
# individual paragraphs are often too long or slightly varied for the
|
|
1190
|
+
# contiguous backreference above, so count the unmistakable transcript
|
|
1191
|
+
# markers in the rolling tail.
|
|
1192
|
+
_CONVERSATION_ECHO_USER_MARKER = re.compile(r"\bthen\s+the\s+user\s+said\b", re.IGNORECASE)
|
|
1193
|
+
_CONVERSATION_ECHO_ASSISTANT_MARKER = re.compile(r"\bthen\s+the\s+assistant\s+(?:said|responded)\b", re.IGNORECASE)
|
|
1186
1194
|
_DEGENERATE_REPETITION_TAIL_WINDOW = 8_000
|
|
1187
1195
|
_STREAM_QUALITY_LAG_CHARS = 1_024
|
|
1188
1196
|
_CORRUPTED_STREAM_MIN_CHARS = 600
|
|
@@ -2277,6 +2285,12 @@ async def _stream_one_completion(
|
|
|
2277
2285
|
if _DEGENERATE_REPETITION_RE.search(tail_buffer):
|
|
2278
2286
|
quality_failure_reason = "degenerate_repetition"
|
|
2279
2287
|
break
|
|
2288
|
+
if (
|
|
2289
|
+
len(_CONVERSATION_ECHO_USER_MARKER.findall(tail_buffer)) >= 3
|
|
2290
|
+
and len(_CONVERSATION_ECHO_ASSISTANT_MARKER.findall(tail_buffer)) >= 3
|
|
2291
|
+
):
|
|
2292
|
+
quality_failure_reason = "conversation_echo"
|
|
2293
|
+
break
|
|
2280
2294
|
if _corrupted_lexical_stream_index(tail_buffer) is not None:
|
|
2281
2295
|
quality_failure_reason = "corrupted_output"
|
|
2282
2296
|
break
|
|
@@ -2308,6 +2322,8 @@ async def _stream_one_completion(
|
|
|
2308
2322
|
diagnosis = (
|
|
2309
2323
|
"Detected corrupted provider token output; discarding it and requesting a clean route."
|
|
2310
2324
|
if quality_failure_reason == "corrupted_output"
|
|
2325
|
+
else "Detected a repeated conversation transcript; discarding it and requesting a clean route."
|
|
2326
|
+
if quality_failure_reason == "conversation_echo"
|
|
2311
2327
|
else "Detected the model repeating itself in a loop; discarding that completion."
|
|
2312
2328
|
)
|
|
2313
2329
|
renderer.handle_event({
|
|
@@ -3634,7 +3650,7 @@ async def run_local_agent_turn(
|
|
|
3634
3650
|
renderer.handle_event({"event_type": "ai_task_failed", "payload": {"error": message}})
|
|
3635
3651
|
return TaskOutcome(status="failed", error=message)
|
|
3636
3652
|
|
|
3637
|
-
if finish_reason in {"degenerate_repetition", "corrupted_output"}:
|
|
3653
|
+
if finish_reason in {"degenerate_repetition", "conversation_echo", "corrupted_output"}:
|
|
3638
3654
|
failed_quality_provider = resolved_provider
|
|
3639
3655
|
quality_failed_providers.add(failed_quality_provider)
|
|
3640
3656
|
checkpoint_partial_parts.clear()
|
|
@@ -3677,6 +3693,8 @@ async def run_local_agent_turn(
|
|
|
3677
3693
|
reason_text = (
|
|
3678
3694
|
"corrupted token output"
|
|
3679
3695
|
if finish_reason == "corrupted_output"
|
|
3696
|
+
else "a repeated conversation transcript"
|
|
3697
|
+
if finish_reason == "conversation_echo"
|
|
3680
3698
|
else "a degenerate repetition loop"
|
|
3681
3699
|
)
|
|
3682
3700
|
error = (
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tamfis-code
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.7
|
|
4
4
|
Summary: TamfisGPT Code -- portable subscription-backed terminal coding agent with local tools, PTY, plans, queues, and approvals
|
|
5
5
|
Project-URL: Homepage, https://github.com/tamfitronics/tamfis-code
|
|
6
6
|
Project-URL: Repository, https://github.com/tamfitronics/tamfis-code
|
|
@@ -767,6 +767,29 @@ class RunLocalAgentTurnTests(_StatePatchMixin, unittest.TestCase):
|
|
|
767
767
|
)
|
|
768
768
|
self.assertNotIn(looping_phrase, visible)
|
|
769
769
|
|
|
770
|
+
def test_repeated_conversation_transcript_is_stopped_early(self):
|
|
771
|
+
with tempfile.TemporaryDirectory() as ws:
|
|
772
|
+
rounds = [[
|
|
773
|
+
_chunk(_delta(content=(
|
|
774
|
+
'Then the user said "audit the site". Then the assistant responded '
|
|
775
|
+
"with a long analysis. " if index % 2 else
|
|
776
|
+
'Then the user said "continue until fixed". Then the assistant responded '
|
|
777
|
+
"with another long analysis. "
|
|
778
|
+
))) for index in range(20)
|
|
779
|
+
]]
|
|
780
|
+
client = _FakeClient(rounds)
|
|
781
|
+
manager = _FakeManager(client)
|
|
782
|
+
renderer = _RecordingRenderer()
|
|
783
|
+
outcome = asyncio.run(run_local_agent_turn(
|
|
784
|
+
manager, ProviderType.NVIDIA, None,
|
|
785
|
+
[{"role": "user", "content": "summarize the site"}],
|
|
786
|
+
self._console(), renderer,
|
|
787
|
+
workspace_root=ws, session_id=1, approval_policy="auto", interactive=False,
|
|
788
|
+
))
|
|
789
|
+
self.assertEqual(outcome.status, "failed")
|
|
790
|
+
self.assertIn("repeated conversation transcript", outcome.error)
|
|
791
|
+
self.assertEqual(len(client.calls), 1)
|
|
792
|
+
|
|
770
793
|
def test_change_request_completed_with_no_mutation_gets_a_caveat(self):
|
|
771
794
|
"""Confirmed live: a weak model can narrate "I'll fix this" -- complete
|
|
772
795
|
with a fabricated "corrected" code block -- without ever calling
|
|
@@ -181,6 +181,18 @@ class StreamRendererTests(unittest.TestCase):
|
|
|
181
181
|
self.assertNotIn("Tip:", output)
|
|
182
182
|
renderer.finish()
|
|
183
183
|
|
|
184
|
+
def test_running_status_keeps_live_input_affordance_visible(self):
|
|
185
|
+
console = Console(file=StringIO(), no_color=True, width=200, force_terminal=True)
|
|
186
|
+
renderer = StreamRenderer(console)
|
|
187
|
+
try:
|
|
188
|
+
renderer.live_input_listener = object()
|
|
189
|
+
console.print(renderer._build_status())
|
|
190
|
+
output = console.file.getvalue()
|
|
191
|
+
self.assertIn("Ctrl+T queue next>", output)
|
|
192
|
+
self.assertIn("Ctrl+C/Ctrl+D exit", output)
|
|
193
|
+
finally:
|
|
194
|
+
renderer.finish()
|
|
195
|
+
|
|
184
196
|
def test_all_tips_reference_real_commands_only(self):
|
|
185
197
|
# Every tip must name a command that actually exists in cli.py's
|
|
186
198
|
# registered command set (or a real REPL slash command) -- this
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|