feat(repl): add .prompt command with live staged tab-completion

Implements plans/mcp-resources-prompts-design.md §5.1/§5.4 (T6):

- .prompt <server> <name> [key=value ...] fetches an MCP prompt and
  submits the result as chat input via Input::from_str + ask(), never
  through REPL line parsing; GetPromptResult messages are flattened
  into one user-role block with unconditional [user]/[assistant] labels
- missing required prompt arguments are collected interactively
- .list prompts renders server/name/description/args via the unified
  catalog (CatalogItem gains an arguments field), degrading per server
- staged live tab-completion: enabled+running+prompts-capable servers
  (no RPC), then live prompt names, then key= argument suggestions with
  (required) markers; 2s timeout per RPC, all errors degrade to silent
  empty suggestions, ctx read guard dropped before blocking
- the enabled-server alias expansion is factored into a shared helper
  used by both tool-scope rebuild and completion
- BREAKING: the former .prompt <text> temp-role builtin is renamed to
  .temp-role <text> (behavior preserved); .prompt now belongs to MCP
  prompts, and a user macro named prompt or temp-role is shadowed
This commit is contained in:
Dark-Alex-17 committed 2026-08-25 11:37:41 -06:00
1 parent 67819784b7
commit 61a3cfb662
7 files changed
+1008 -44

No files matched your search

+28
View File
@@ -565,6 +565,34 @@ mod tests {
assert_eq!(state_of(&policy, "a"), &MacroState::Enabled);
}
#[test]
fn prompt_macro_is_shadowed_by_builtin() {
let policy = MacroPolicy::effective_with(
globals(&["prompt"]),
None,
None,
None,
None,
&crate::repl::builtin_command_names(),
);
assert_eq!(state_of(&policy, "prompt"), &MacroState::ShadowedBuiltin);
}
#[test]
fn temp_role_macro_is_shadowed_by_builtin() {
let policy = MacroPolicy::effective_with(
globals(&["temp-role"]),
None,
None,
None,
None,
&crate::repl::builtin_command_names(),
);
assert_eq!(state_of(&policy, "temp-role"), &MacroState::ShadowedBuiltin);
}
#[test]
fn locked_wins_over_shadowed_builtin() {
let l = list(&["a"]);