feat: enhance chat CLI and TUI with initial opener handling and improved prompt logic
This commit is contained in:
@@ -32,6 +32,7 @@ load_dotenv(Path(__file__).with_name(".env"))
|
||||
|
||||
API_KEY = os.getenv("API_KEY")
|
||||
BASE_URL = os.getenv("BASE_URL")
|
||||
APP_ID = os.getenv("APP_ID")
|
||||
|
||||
for stream in (sys.stdout, sys.stderr):
|
||||
if hasattr(stream, "reconfigure"):
|
||||
@@ -144,16 +145,85 @@ def _resolve_option_token(token: str, options: List[Dict[str, str]]) -> Optional
|
||||
return None
|
||||
|
||||
|
||||
def _coerce_text(value: Any) -> str:
|
||||
return str(value or "").strip()
|
||||
|
||||
|
||||
def _first_nonempty_text(*values: Any) -> str:
|
||||
for value in values:
|
||||
text = _coerce_text(value)
|
||||
if text:
|
||||
return text
|
||||
return ""
|
||||
|
||||
|
||||
def _merge_prompt_parts(*values: Any) -> str:
|
||||
parts: List[str] = []
|
||||
seen = set()
|
||||
for value in values:
|
||||
text = _coerce_text(value)
|
||||
if not text or text in seen:
|
||||
continue
|
||||
seen.add(text)
|
||||
parts.append(text)
|
||||
return "\n".join(parts)
|
||||
|
||||
|
||||
def _interactive_prompt_text(payload: Dict[str, Any], default_text: str) -> str:
|
||||
params = payload.get("params") if isinstance(payload.get("params"), dict) else {}
|
||||
return str(
|
||||
payload.get("prompt")
|
||||
or payload.get("title")
|
||||
or payload.get("text")
|
||||
or payload.get("description")
|
||||
or params.get("description")
|
||||
or default_text
|
||||
).strip()
|
||||
opener = _first_nonempty_text(
|
||||
payload.get("opener"),
|
||||
params.get("opener"),
|
||||
payload.get("intro"),
|
||||
params.get("intro"),
|
||||
)
|
||||
prompt = _first_nonempty_text(
|
||||
payload.get("prompt"),
|
||||
params.get("prompt"),
|
||||
payload.get("text"),
|
||||
params.get("text"),
|
||||
)
|
||||
title = _first_nonempty_text(
|
||||
payload.get("title"),
|
||||
params.get("title"),
|
||||
payload.get("nodeName"),
|
||||
payload.get("label"),
|
||||
)
|
||||
description = _first_nonempty_text(
|
||||
payload.get("description"),
|
||||
payload.get("desc"),
|
||||
params.get("description"),
|
||||
params.get("desc"),
|
||||
)
|
||||
return _merge_prompt_parts(opener, prompt) or title or description or default_text
|
||||
|
||||
|
||||
def _extract_chat_init_opener(payload: Any) -> str:
|
||||
if not isinstance(payload, dict):
|
||||
return ""
|
||||
|
||||
data = payload.get("data") if isinstance(payload.get("data"), dict) else payload
|
||||
app = data.get("app") if isinstance(data.get("app"), dict) else {}
|
||||
chat_config = app.get("chatConfig") if isinstance(app.get("chatConfig"), dict) else {}
|
||||
|
||||
return _first_nonempty_text(
|
||||
chat_config.get("welcomeText"),
|
||||
app.get("welcomeText"),
|
||||
data.get("welcomeText"),
|
||||
data.get("opener"),
|
||||
app.get("opener"),
|
||||
data.get("intro"),
|
||||
app.get("intro"),
|
||||
)
|
||||
|
||||
|
||||
def _get_initial_app_opener(client: ChatClient, chat_id: str) -> str:
|
||||
if not APP_ID:
|
||||
return ""
|
||||
|
||||
response = client.get_chat_init(appId=APP_ID, chatId=chat_id)
|
||||
response.raise_for_status()
|
||||
return _extract_chat_init_opener(response.json())
|
||||
|
||||
|
||||
def _prompt_user_select(event: FastGPTInteractiveEvent) -> Optional[str]:
|
||||
@@ -165,7 +235,8 @@ def _prompt_user_select(event: FastGPTInteractiveEvent) -> Optional[str]:
|
||||
options = [item for index, raw in enumerate(raw_options, start=1) if (item := _normalize_option(raw, index))]
|
||||
|
||||
print()
|
||||
print(f"[INTERACTIVE] {prompt_text}")
|
||||
print("[INTERACTIVE]")
|
||||
print(prompt_text)
|
||||
for index, option in enumerate(options, start=1):
|
||||
print(f" {index}. {option['label']}")
|
||||
if option["description"]:
|
||||
@@ -212,7 +283,8 @@ def _prompt_user_input(event: FastGPTInteractiveEvent) -> Optional[str]:
|
||||
form_fields = params.get("inputForm") if isinstance(params.get("inputForm"), list) else []
|
||||
|
||||
print()
|
||||
print(f"[INTERACTIVE] {prompt_text}")
|
||||
print("[INTERACTIVE]")
|
||||
print(prompt_text)
|
||||
|
||||
if not form_fields:
|
||||
value = input("Input (/cancel to stop): ").strip()
|
||||
@@ -384,6 +456,15 @@ def main() -> None:
|
||||
print(f"Using chatId: {chat_id}\n")
|
||||
|
||||
with ChatClient(api_key=API_KEY, base_url=BASE_URL) as client:
|
||||
try:
|
||||
opener = _get_initial_app_opener(client, chat_id)
|
||||
except Exception as exc:
|
||||
print(f"[INIT] Failed to load app opener: {exc}\n")
|
||||
opener = ""
|
||||
|
||||
if opener:
|
||||
print(f"Assistant: {opener}\n")
|
||||
|
||||
while True:
|
||||
try:
|
||||
user_input = input("You: ").strip()
|
||||
|
||||
Reference in New Issue
Block a user