fix(tui): establish 2-tier readiness model, modal/hint token separation, and adapter modal contracts
- Separate TUI dialog detection into blocking gate layer (_MAM_MODAL_TOKENS) and recovery layer (_MAM_HINT_TOKENS) to eliminate idle dialog starvation - Add modal_tokens contract across agent adapters (claude, cline) with dynamic scope facts resolution in send_keys_safe - Implement fail-closed resolution for ambiguous same-kind panes (R-1) and enforce WORKSPACE_ROOT export (R-2) - Preserve session on TUI readiness timeout when PID is alive for diagnostics - Add comprehensive test suite in tests/test_c1_tui_readiness.py and adapter contract assertions in test_a4
This commit is contained in:
@@ -23,6 +23,9 @@ def main():
|
||||
print(f"MAM_INPUT_PLACEHOLDER={q(adapter.input_placeholder or '')}")
|
||||
print(f"MAM_INPUT_RULE_PATTERN={q(adapter.input_rule_pattern or '')}")
|
||||
print(f"MAM_READY_TOKENS={q(adapter.ready_tokens)}")
|
||||
print(f"MAM_STRONG_READY_TOKENS={q(adapter.strong_ready_tokens)}")
|
||||
print(f"MAM_WEAK_READY_TOKENS={q(adapter.weak_ready_tokens)}")
|
||||
print(f"MAM_MODAL_TOKENS={q(adapter.modal_tokens or '')}")
|
||||
print(f"MAM_EXIT_KEY={q(adapter.exit_key)}")
|
||||
print(f"MAM_DELEGATE_AGENT_KEY={q(adapter.delegate_agent_key)}")
|
||||
|
||||
|
||||
@@ -40,6 +40,10 @@ class ClaudeAgentAdapter(BaseAgentAdapter):
|
||||
def input_rule_pattern(self) -> str:
|
||||
return '─{10,}'
|
||||
|
||||
@property
|
||||
def modal_tokens(self) -> Optional[str]:
|
||||
return 'Try the new fullscreen renderer\\?'
|
||||
|
||||
def artifact_path(self, uuid: str, ctx: DiscoveryContext) -> str:
|
||||
return f"{ctx.claude_dir}/{ctx.ws_key}/{uuid}.jsonl"
|
||||
|
||||
|
||||
@@ -16,6 +16,18 @@ class ClineAgentAdapter(BaseAgentAdapter):
|
||||
def ready_tokens(self) -> str:
|
||||
return 'Cline|history|Chat|What can I do|slash commands'
|
||||
|
||||
@property
|
||||
def strong_ready_tokens(self) -> str:
|
||||
return 'Cline|What can I do|slash commands'
|
||||
|
||||
@property
|
||||
def weak_ready_tokens(self) -> str:
|
||||
return 'history|Chat'
|
||||
|
||||
@property
|
||||
def modal_tokens(self) -> Optional[str]:
|
||||
return 'Select API Provider|Enter API Key|Select an API provider|API Provider|Cline API key'
|
||||
|
||||
@property
|
||||
def exit_key(self) -> str:
|
||||
return '/exit'
|
||||
|
||||
@@ -73,6 +73,18 @@ class BaseAgentAdapter:
|
||||
def input_rule_pattern(self) -> Optional[str]:
|
||||
return None
|
||||
|
||||
@property
|
||||
def modal_tokens(self) -> Optional[str]:
|
||||
return None
|
||||
|
||||
@property
|
||||
def strong_ready_tokens(self) -> str:
|
||||
return self.ready_tokens
|
||||
|
||||
@property
|
||||
def weak_ready_tokens(self) -> str:
|
||||
return ''
|
||||
|
||||
def derive_session_name(self, slug: str, role: str = "creator") -> str:
|
||||
r = role.lower()
|
||||
return f"{slug}-{r}-{self.name}"
|
||||
|
||||
Reference in New Issue
Block a user