tamfis-code 0.6.5__tar.gz → 0.6.8__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 (127) hide show
  1. {tamfis_code-0.6.5/tamfis_code.egg-info → tamfis_code-0.6.8}/PKG-INFO +1 -1
  2. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/USAGE_INSTALL_RELEASE.md +1 -1
  3. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/pyproject.toml +1 -1
  4. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/__init__.py +1 -1
  5. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/interactive.py +4 -4
  6. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/live_input.py +23 -4
  7. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/render.py +10 -1
  8. {tamfis_code-0.6.5 → tamfis_code-0.6.8/tamfis_code.egg-info}/PKG-INFO +1 -1
  9. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_live_input.py +4 -4
  10. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_tamfis_code_render.py +12 -0
  11. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/MANIFEST.in +0 -0
  12. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/README.md +0 -0
  13. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/setup.cfg +0 -0
  14. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/__main__.py +0 -0
  15. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/agent_definitions.py +0 -0
  16. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/agents.py +0 -0
  17. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/api_client.py +0 -0
  18. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/cli.py +0 -0
  19. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/clipboard.py +0 -0
  20. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/completion.py +0 -0
  21. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/config.py +0 -0
  22. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/custom_commands.py +0 -0
  23. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/doctor.py +0 -0
  24. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/enforcer.py +0 -0
  25. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/evidence.py +0 -0
  26. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/hooks.py +0 -0
  27. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/indexer.py +0 -0
  28. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/instructions.py +0 -0
  29. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/local_chat.py +0 -0
  30. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/local_tools.py +0 -0
  31. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/mcp.py +0 -0
  32. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/mcp_stdio_server.py +0 -0
  33. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/metrics.py +0 -0
  34. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/model_registry.py +0 -0
  35. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/openhands/__init__.py +0 -0
  36. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/openhands/agent.py +0 -0
  37. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/openhands/agent_server.py +0 -0
  38. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/openhands/automation.py +0 -0
  39. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/openhands/compat.py +0 -0
  40. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/openhands/conversation.py +0 -0
  41. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/openhands/delegation.py +0 -0
  42. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/openhands/events.py +0 -0
  43. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/openhands/leases.py +0 -0
  44. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/openhands/security.py +0 -0
  45. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/openhands/skills.py +0 -0
  46. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/openhands/tools.py +0 -0
  47. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/openhands/workspace.py +0 -0
  48. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/orchestrator/__init__.py +0 -0
  49. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/orchestrator/context.py +0 -0
  50. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/orchestrator/engine.py +0 -0
  51. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/orchestrator/planner.py +0 -0
  52. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/orchestrator/protocols.py +0 -0
  53. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/orchestrator/validator.py +0 -0
  54. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/project.py +0 -0
  55. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/provider_protocols.py +0 -0
  56. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/providers.py +0 -0
  57. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/pty.py +0 -0
  58. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/references.py +0 -0
  59. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/routing.py +0 -0
  60. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/runner.py +0 -0
  61. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/runner_local.py +0 -0
  62. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/safety.py +0 -0
  63. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/screenshot.py +0 -0
  64. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/sessions.py +0 -0
  65. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/state.py +0 -0
  66. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/swarm.py +0 -0
  67. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/tasks.py +0 -0
  68. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/tool_policy.py +0 -0
  69. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code/workspace.py +0 -0
  70. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code.egg-info/SOURCES.txt +0 -0
  71. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code.egg-info/dependency_links.txt +0 -0
  72. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code.egg-info/entry_points.txt +0 -0
  73. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code.egg-info/requires.txt +0 -0
  74. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tamfis_code.egg-info/top_level.txt +0 -0
  75. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_agent_definitions.py +0 -0
  76. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_agents.py +0 -0
  77. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_agents_delegation.py +0 -0
  78. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_build_installation.py +0 -0
  79. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_cli_commands.py +0 -0
  80. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_clipboard.py +0 -0
  81. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_completion.py +0 -0
  82. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_context_rollover.py +0 -0
  83. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_custom_commands.py +0 -0
  84. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_cwd_validation.py +0 -0
  85. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_doctor_session_diagnostics.py +0 -0
  86. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_enforcer.py +0 -0
  87. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_fake_tool_detection.py +0 -0
  88. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_find_references.py +0 -0
  89. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_hooks.py +0 -0
  90. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_indexer.py +0 -0
  91. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_instructions.py +0 -0
  92. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_integration_new.py +0 -0
  93. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_interactive_standalone.py +0 -0
  94. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_local_pty.py +0 -0
  95. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_mcp.py +0 -0
  96. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_mcp_search_bounds.py +0 -0
  97. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_mcp_standalone_degradation.py +0 -0
  98. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_mcp_stdio_server.py +0 -0
  99. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_metrics.py +0 -0
  100. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_openhands_runtime.py +0 -0
  101. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_openrouter_cost_routing.py +0 -0
  102. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_orchestrator.py +0 -0
  103. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_plan_mode_gate.py +0 -0
  104. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_plan_steps_and_attempts.py +0 -0
  105. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_provider_protocols.py +0 -0
  106. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_reasoning_effort_capability.py +0 -0
  107. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_reasoning_plan.py +0 -0
  108. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_references.py +0 -0
  109. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_render_task_diagnostics.py +0 -0
  110. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_routing.py +0 -0
  111. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_runner_helpers.py +0 -0
  112. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_runner_local.py +0 -0
  113. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_safety.py +0 -0
  114. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_safety_manifest.py +0 -0
  115. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_sessions.py +0 -0
  116. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_swarm.py +0 -0
  117. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_tamfis_code_api_client.py +0 -0
  118. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_tamfis_code_approval.py +0 -0
  119. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_tamfis_code_approval_flow.py +0 -0
  120. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_tamfis_code_config.py +0 -0
  121. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_tamfis_code_intent.py +0 -0
  122. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_tamfis_code_repl_exit.py +0 -0
  123. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_tamfis_code_tasks.py +0 -0
  124. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_tamfis_code_workspace.py +0 -0
  125. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_version_consistency.py +0 -0
  126. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/tests/test_workspace_discovery_gaps.py +0 -0
  127. {tamfis_code-0.6.5 → tamfis_code-0.6.8}/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.5
3
+ Version: 0.6.8
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
@@ -32,7 +32,7 @@ mutation ledger on the local machine.
32
32
 
33
33
  ## Interactive queue controls
34
34
 
35
- While a task is running, press `Ctrl+T` to open `queue next>`. The submitted
35
+ While a task is running, press `Ctrl+Y` to open `queue next>`. The submitted
36
36
  line is echoed with a durable queue ID, then applied at the next safe model
37
37
  round boundary. Multiple queued updates are processed in order. A second
38
38
  terminal can enqueue the same session with:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "tamfis-code"
3
- version = "0.6.5"
3
+ version = "0.6.8"
4
4
  description = "TamfisGPT Code -- portable subscription-backed terminal coding agent with local tools, PTY, plans, queues, and approvals"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -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.5"
20
+ __version__ = "0.6.8"
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
@@ -111,7 +111,7 @@ $ <command> explicit shell command
111
111
  /mode <name> switch mode: manual | accept-edits | auto | plan
112
112
  Shift+Tab cycle mode without typing a command (shown in the prompt as [mode]);
113
113
  also works while a task is already running, not just at this prompt
114
- Ctrl+T while a task is running: open the "queue next" input editor
114
+ Ctrl+Y while a task is running: open the "queue next" input editor (configurable)
115
115
  /model show the active model route
116
116
  /model list [route] list coding models (route: hf or openrouter)
117
117
  /model auto restore Hugging Face -> OpenRouter automatic routing
@@ -373,9 +373,9 @@ async def run_interactive(
373
373
  console.print(
374
374
  "[dim]Type /help for commands. Paste up to 1,000,000 characters; Alt+Enter adds a newline. "
375
375
  "Shift+Tab cycles mode (manual/accept-edits/auto/plan) -- works while a task is running too, "
376
- "not just at this prompt. Ctrl+T opens a visible `queue next>` editor while a task is running; "
376
+ "not just at this prompt. Ctrl+Y opens a visible `queue next>` editor while a task is running; "
377
377
  "your submitted text is acknowledged with a queue id and applied at the next safe round boundary. "
378
- "Ctrl+D or Ctrl+C exits.[/dim]\n"
378
+ "The queue shortcut defaults to Ctrl+Y (Ctrl+T is reserved by Termius); Ctrl+D or Ctrl+C exits.[/dim]\n"
379
379
  )
380
380
 
381
381
  CONFIG_DIR.mkdir(parents=True, exist_ok=True)
@@ -990,7 +990,7 @@ async def run_interactive(
990
990
  "/mode auto auto-approves everything, never prompts (server safeguards still apply)\n"
991
991
  "/mode plan read-only: propose without executing\n"
992
992
  "Shift+Tab cycle manual -> accept-edits -> auto -> plan without typing a command\n"
993
- " (also works mid-task, not just here); Ctrl+T mid-task queues a follow-up\n"
993
+ " (also works mid-task, not just here); Ctrl+Y mid-task queues a follow-up\n"
994
994
  "Other raw policy values also work directly (--approval-only, no short alias): safe, workspace,\n"
995
995
  "read-only, plan-only, suggest, full-auto, and 'never' -- note 'never' means DENY everything\n"
996
996
  "(the opposite of what it sounds like; it is not a synonym for 'auto').[/dim]"
@@ -9,7 +9,7 @@ just when an approval prompt happens to be showing:
9
9
  runner.py's approval-gate Shift+Tab handler (`_prompt`'s own binding)
10
10
  already read from and write to, so this is not a second, competing mode
11
11
  concept, just another writer of the same value.
12
- - Ctrl+T opens a real line editor for the next instruction and queues it
12
+ - Ctrl+Y opens a real line editor for the next instruction and queues it
13
13
  through the on-disk queue a second
14
14
  terminal's `tamfis-code queue "..."` already used
15
15
  (runner_local.py's `_claim_live_queued_instructions` polls it at the top
@@ -50,7 +50,25 @@ except ImportError: # Windows -- no termios/tty; this feature just disables its
50
50
  _TTY_AVAILABLE = False
51
51
 
52
52
  _SHIFT_TAB = b"\x1b[Z"
53
- _CTRL_T = b"\x14"
53
+ # Ctrl+T is reserved by Termius for opening a new terminal. Keep the queue
54
+ # shortcut on Ctrl+Y by default, while allowing an operator to choose a local
55
+ # key explicitly when another terminal client owns it.
56
+ _CTRL_T = b"\x14" # legacy/exported test constant; no longer the default
57
+ _CTRL_Y = b"\x19"
58
+ _QUEUE_KEY_ENV = "TAMFIS_CODE_QUEUE_KEY"
59
+
60
+
61
+ def queue_key_bytes() -> tuple[bytes, str]:
62
+ value = os.environ.get(_QUEUE_KEY_ENV, "ctrl-y").strip().lower().replace(" ", "")
63
+ if value in {"ctrl-t", "^t"}:
64
+ return _CTRL_T, "Ctrl+T"
65
+ if value in {"ctrl-y", "^y", ""}:
66
+ return _CTRL_Y, "Ctrl+Y"
67
+ # Single control letters are convenient for terminal clients without
68
+ # reliable multi-key escape support: ctrl-a through ctrl-z.
69
+ if value.startswith("ctrl-") and len(value) == 6 and "a" <= value[-1] <= "z":
70
+ return bytes([ord(value[-1]) - ord("a") + 1]), f"Ctrl+{value[-1].upper()}"
71
+ return _CTRL_Y, "Ctrl+Y"
54
72
  _ESCAPE_PREFIXES = (b"\x1b", b"\x1b[")
55
73
 
56
74
 
@@ -127,10 +145,11 @@ class LiveInputListener:
127
145
  buf = bytes(self._buf)
128
146
  # os.read() is allowed to return more than one byte. A keypress can
129
147
  # therefore arrive together with terminal noise or a paste prefix;
130
- # equality-only matching silently discarded Ctrl+T in that case and
148
+ # equality-only matching silently discarded the queue control byte in that case and
131
149
  # made the in-task editor appear broken. Consume the control byte
132
150
  # wherever it occurs, while keeping the editor single-flight.
133
- if _CTRL_T in buf:
151
+ queue_key, _ = queue_key_bytes()
152
+ if queue_key in buf:
134
153
  self._buf.clear()
135
154
  if self._interject_task is None or self._interject_task.done():
136
155
  self._interject_task = asyncio.ensure_future(self._interject())
@@ -411,9 +411,18 @@ 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
+ from .live_input import queue_key_bytes
424
+ _, queue_label = queue_key_bytes()
425
+ lines.append(f" [cyan]Input:[/cyan] {queue_label} queue next> · Ctrl+C/Ctrl+D exit")
417
426
  if tip:
418
427
  lines.append(f" [dim]{tip}[/dim]")
419
428
  for step in self._plan_steps:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tamfis-code
3
- Version: 0.6.5
3
+ Version: 0.6.8
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
@@ -8,7 +8,7 @@ from rich.console import Console
8
8
 
9
9
  from tamfis_code import state as state_module
10
10
  from tamfis_code.config import Config, next_mode_in_cycle
11
- from tamfis_code.live_input import LiveInputListener, _CTRL_T, _SHIFT_TAB
11
+ from tamfis_code.live_input import LiveInputListener, _CTRL_T, _CTRL_Y, _SHIFT_TAB
12
12
  from tamfis_code.render import StreamRenderer
13
13
 
14
14
 
@@ -144,7 +144,7 @@ class CtrlTInjectsFollowUpTests(_StatePatchMixin, unittest.IsolatedAsyncioTestCa
144
144
  cfg = _config("ask")
145
145
  listener = LiveInputListener(session_id=1, renderer=renderer, cli_config=cfg)
146
146
  with patch.object(listener, "_interject", side_effect=_noop) as mocked:
147
- listener._buf = bytearray(_CTRL_T)
147
+ listener._buf = bytearray(_CTRL_Y)
148
148
  listener._dispatch()
149
149
  self.assertEqual(bytes(listener._buf), b"")
150
150
  await asyncio.sleep(0) # let the scheduled task actually run
@@ -161,7 +161,7 @@ class CtrlTInjectsFollowUpTests(_StatePatchMixin, unittest.IsolatedAsyncioTestCa
161
161
  await gate.wait()
162
162
 
163
163
  with patch.object(listener, "_interject", side_effect=_blocked) as mocked:
164
- listener._buf = bytearray(_CTRL_T)
164
+ listener._buf = bytearray(_CTRL_Y)
165
165
  listener._dispatch()
166
166
  await asyncio.sleep(0)
167
167
  listener._buf = bytearray(_CTRL_T)
@@ -180,7 +180,7 @@ class CtrlTInjectsFollowUpTests(_StatePatchMixin, unittest.IsolatedAsyncioTestCa
180
180
  cfg = _config("ask")
181
181
  listener = LiveInputListener(session_id=1, renderer=renderer, cli_config=cfg)
182
182
  with patch.object(listener, "_interject", new_callable=AsyncMock) as mocked:
183
- listener._buf = bytearray(b"x" + _CTRL_T + b"y")
183
+ listener._buf = bytearray(b"x" + _CTRL_Y + b"y")
184
184
  listener._dispatch()
185
185
  await asyncio.sleep(0)
186
186
  mocked.assert_awaited_once()
@@ -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+Y 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