feat: web prompt editor + agent personalities #58
@@ -8,8 +8,8 @@ _mcpctl() {
|
|||||||
local commands="status login logout config get describe delete logs create edit apply chat patch backup approve console cache test migrate rotate"
|
local commands="status login logout config get describe delete logs create edit apply chat patch backup approve console cache test migrate rotate"
|
||||||
local project_commands="get describe delete logs create edit attach-server detach-server"
|
local project_commands="get describe delete logs create edit attach-server detach-server"
|
||||||
local global_opts="-v --version --daemon-url --direct -p --project -h --help"
|
local global_opts="-v --version --daemon-url --direct -p --project -h --help"
|
||||||
local resources="servers instances secrets secretbackends llms agents templates projects users groups rbac prompts promptrequests serverattachments proxymodels all"
|
local resources="servers instances secrets secretbackends llms agents personalities templates projects users groups rbac prompts promptrequests serverattachments proxymodels all"
|
||||||
local resource_aliases="servers instances secrets secretbackends llms agents templates projects users groups rbac prompts promptrequests serverattachments proxymodels all server srv instance inst secret sec secretbackend sb llm agent template tpl project proj user group rbac-definition rbac-binding prompt promptrequest pr serverattachment sa proxymodel pm"
|
local resource_aliases="servers instances secrets secretbackends llms agents personalities templates projects users groups rbac prompts promptrequests serverattachments proxymodels all server srv instance inst secret sec secretbackend sb llm agent personality template tpl project proj user group rbac-definition rbac-binding prompt promptrequest pr serverattachment sa proxymodel pm"
|
||||||
|
|
||||||
# Check if --project/-p was given
|
# Check if --project/-p was given
|
||||||
local has_project=false
|
local has_project=false
|
||||||
@@ -156,11 +156,11 @@ _mcpctl() {
|
|||||||
return ;;
|
return ;;
|
||||||
delete)
|
delete)
|
||||||
if [[ -z "$resource_type" ]]; then
|
if [[ -z "$resource_type" ]]; then
|
||||||
COMPREPLY=($(compgen -W "$resources -p --project -h --help" -- "$cur"))
|
COMPREPLY=($(compgen -W "$resources -p --project --agent -h --help" -- "$cur"))
|
||||||
else
|
else
|
||||||
local names
|
local names
|
||||||
names=$(_mcpctl_resource_names "$resource_type")
|
names=$(_mcpctl_resource_names "$resource_type")
|
||||||
COMPREPLY=($(compgen -W "$names -p --project -h --help" -- "$cur"))
|
COMPREPLY=($(compgen -W "$names -p --project --agent -h --help" -- "$cur"))
|
||||||
fi
|
fi
|
||||||
return ;;
|
return ;;
|
||||||
logs)
|
logs)
|
||||||
@@ -175,7 +175,7 @@ _mcpctl() {
|
|||||||
create)
|
create)
|
||||||
local create_sub=$(_mcpctl_get_subcmd $subcmd_pos)
|
local create_sub=$(_mcpctl_get_subcmd $subcmd_pos)
|
||||||
if [[ -z "$create_sub" ]]; then
|
if [[ -z "$create_sub" ]]; then
|
||||||
COMPREPLY=($(compgen -W "server secret llm agent secretbackend project user group rbac mcptoken prompt serverattachment promptrequest help" -- "$cur"))
|
COMPREPLY=($(compgen -W "server secret llm agent secretbackend project user group rbac mcptoken prompt personality serverattachment promptrequest help" -- "$cur"))
|
||||||
else
|
else
|
||||||
case "$create_sub" in
|
case "$create_sub" in
|
||||||
server)
|
server)
|
||||||
@@ -209,7 +209,10 @@ _mcpctl() {
|
|||||||
COMPREPLY=($(compgen -W "-p --project --rbac --bind --ttl --description --force -h --help" -- "$cur"))
|
COMPREPLY=($(compgen -W "-p --project --rbac --bind --ttl --description --force -h --help" -- "$cur"))
|
||||||
;;
|
;;
|
||||||
prompt)
|
prompt)
|
||||||
COMPREPLY=($(compgen -W "-p --project --content --content-file --priority --link -h --help" -- "$cur"))
|
COMPREPLY=($(compgen -W "-p --project --agent --content --content-file --priority --link -h --help" -- "$cur"))
|
||||||
|
;;
|
||||||
|
personality)
|
||||||
|
COMPREPLY=($(compgen -W "--agent --description --priority -h --help" -- "$cur"))
|
||||||
;;
|
;;
|
||||||
serverattachment)
|
serverattachment)
|
||||||
COMPREPLY=($(compgen -W "-p --project -h --help" -- "$cur"))
|
COMPREPLY=($(compgen -W "-p --project -h --help" -- "$cur"))
|
||||||
@@ -225,7 +228,7 @@ _mcpctl() {
|
|||||||
return ;;
|
return ;;
|
||||||
edit)
|
edit)
|
||||||
if [[ -z "$resource_type" ]]; then
|
if [[ -z "$resource_type" ]]; then
|
||||||
COMPREPLY=($(compgen -W "servers secrets projects groups rbac prompts promptrequests -h --help" -- "$cur"))
|
COMPREPLY=($(compgen -W "servers secrets projects groups rbac prompts promptrequests personalities -h --help" -- "$cur"))
|
||||||
else
|
else
|
||||||
local names
|
local names
|
||||||
names=$(_mcpctl_resource_names "$resource_type")
|
names=$(_mcpctl_resource_names "$resource_type")
|
||||||
@@ -239,9 +242,9 @@ _mcpctl() {
|
|||||||
if [[ $((cword - subcmd_pos)) -eq 1 ]]; then
|
if [[ $((cword - subcmd_pos)) -eq 1 ]]; then
|
||||||
local names
|
local names
|
||||||
names=$(_mcpctl_resource_names "agents")
|
names=$(_mcpctl_resource_names "agents")
|
||||||
COMPREPLY=($(compgen -W "$names -m --message --thread --system --system-file --system-append --temperature --top-p --top-k --max-tokens --seed --stop --allow-tool --extra --no-stream -h --help" -- "$cur"))
|
COMPREPLY=($(compgen -W "$names -m --message --thread --system --system-file --system-append --personality --temperature --top-p --top-k --max-tokens --seed --stop --allow-tool --extra --no-stream -h --help" -- "$cur"))
|
||||||
else
|
else
|
||||||
COMPREPLY=($(compgen -W "-m --message --thread --system --system-file --system-append --temperature --top-p --top-k --max-tokens --seed --stop --allow-tool --extra --no-stream -h --help" -- "$cur"))
|
COMPREPLY=($(compgen -W "-m --message --thread --system --system-file --system-append --personality --temperature --top-p --top-k --max-tokens --seed --stop --allow-tool --extra --no-stream -h --help" -- "$cur"))
|
||||||
fi
|
fi
|
||||||
return ;;
|
return ;;
|
||||||
patch)
|
patch)
|
||||||
|
|||||||
@@ -31,10 +31,10 @@ function __mcpctl_has_project
|
|||||||
end
|
end
|
||||||
|
|
||||||
# Resource type detection
|
# Resource type detection
|
||||||
set -l resources servers instances secrets secretbackends llms agents templates projects users groups rbac prompts promptrequests serverattachments proxymodels all
|
set -l resources servers instances secrets secretbackends llms agents personalities templates projects users groups rbac prompts promptrequests serverattachments proxymodels all
|
||||||
|
|
||||||
function __mcpctl_needs_resource_type
|
function __mcpctl_needs_resource_type
|
||||||
set -l resource_aliases servers instances secrets secretbackends llms agents templates projects users groups rbac prompts promptrequests serverattachments proxymodels all server srv instance inst secret sec secretbackend sb llm agent template tpl project proj user group rbac-definition rbac-binding prompt promptrequest pr serverattachment sa proxymodel pm
|
set -l resource_aliases servers instances secrets secretbackends llms agents personalities templates projects users groups rbac prompts promptrequests serverattachments proxymodels all server srv instance inst secret sec secretbackend sb llm agent personality template tpl project proj user group rbac-definition rbac-binding prompt promptrequest pr serverattachment sa proxymodel pm
|
||||||
set -l tokens (commandline -opc)
|
set -l tokens (commandline -opc)
|
||||||
set -l found_cmd false
|
set -l found_cmd false
|
||||||
for tok in $tokens
|
for tok in $tokens
|
||||||
@@ -62,6 +62,7 @@ function __mcpctl_resolve_resource
|
|||||||
case secretbackend sb secretbackends; echo secretbackends
|
case secretbackend sb secretbackends; echo secretbackends
|
||||||
case llm llms; echo llms
|
case llm llms; echo llms
|
||||||
case agent agents; echo agents
|
case agent agents; echo agents
|
||||||
|
case personality personalities; echo personalities
|
||||||
case template tpl templates; echo templates
|
case template tpl templates; echo templates
|
||||||
case project proj projects; echo projects
|
case project proj projects; echo projects
|
||||||
case user users; echo users
|
case user users; echo users
|
||||||
@@ -77,7 +78,7 @@ function __mcpctl_resolve_resource
|
|||||||
end
|
end
|
||||||
|
|
||||||
function __mcpctl_get_resource_type
|
function __mcpctl_get_resource_type
|
||||||
set -l resource_aliases servers instances secrets secretbackends llms agents templates projects users groups rbac prompts promptrequests serverattachments proxymodels all server srv instance inst secret sec secretbackend sb llm agent template tpl project proj user group rbac-definition rbac-binding prompt promptrequest pr serverattachment sa proxymodel pm
|
set -l resource_aliases servers instances secrets secretbackends llms agents personalities templates projects users groups rbac prompts promptrequests serverattachments proxymodels all server srv instance inst secret sec secretbackend sb llm agent personality template tpl project proj user group rbac-definition rbac-binding prompt promptrequest pr serverattachment sa proxymodel pm
|
||||||
set -l tokens (commandline -opc)
|
set -l tokens (commandline -opc)
|
||||||
set -l found_cmd false
|
set -l found_cmd false
|
||||||
for tok in $tokens
|
for tok in $tokens
|
||||||
@@ -224,7 +225,7 @@ complete -c mcpctl -n "not __mcpctl_has_project; and not __fish_seen_subcommand_
|
|||||||
complete -c mcpctl -n "not __mcpctl_has_project; and not __fish_seen_subcommand_from $commands" -a config -d 'Manage mcpctl configuration'
|
complete -c mcpctl -n "not __mcpctl_has_project; and not __fish_seen_subcommand_from $commands" -a config -d 'Manage mcpctl configuration'
|
||||||
complete -c mcpctl -n "not __mcpctl_has_project; and not __fish_seen_subcommand_from $commands" -a get -d 'List resources (servers, projects, instances, all)'
|
complete -c mcpctl -n "not __mcpctl_has_project; and not __fish_seen_subcommand_from $commands" -a get -d 'List resources (servers, projects, instances, all)'
|
||||||
complete -c mcpctl -n "not __mcpctl_has_project; and not __fish_seen_subcommand_from $commands" -a describe -d 'Show detailed information about a resource'
|
complete -c mcpctl -n "not __mcpctl_has_project; and not __fish_seen_subcommand_from $commands" -a describe -d 'Show detailed information about a resource'
|
||||||
complete -c mcpctl -n "not __mcpctl_has_project; and not __fish_seen_subcommand_from $commands" -a delete -d 'Delete a resource (server, instance, secret, project, user, group, rbac)'
|
complete -c mcpctl -n "not __mcpctl_has_project; and not __fish_seen_subcommand_from $commands" -a delete -d 'Delete a resource (server, instance, secret, project, user, group, rbac, personality)'
|
||||||
complete -c mcpctl -n "not __mcpctl_has_project; and not __fish_seen_subcommand_from $commands" -a logs -d 'Get logs from an MCP server instance'
|
complete -c mcpctl -n "not __mcpctl_has_project; and not __fish_seen_subcommand_from $commands" -a logs -d 'Get logs from an MCP server instance'
|
||||||
complete -c mcpctl -n "not __mcpctl_has_project; and not __fish_seen_subcommand_from $commands" -a create -d 'Create a resource (server, secret, secretbackend, llm, agent, project, user, group, rbac, serverattachment, prompt)'
|
complete -c mcpctl -n "not __mcpctl_has_project; and not __fish_seen_subcommand_from $commands" -a create -d 'Create a resource (server, secret, secretbackend, llm, agent, project, user, group, rbac, serverattachment, prompt)'
|
||||||
complete -c mcpctl -n "not __mcpctl_has_project; and not __fish_seen_subcommand_from $commands" -a edit -d 'Edit a resource in your default editor (server, project)'
|
complete -c mcpctl -n "not __mcpctl_has_project; and not __fish_seen_subcommand_from $commands" -a edit -d 'Edit a resource in your default editor (server, project)'
|
||||||
@@ -242,7 +243,7 @@ complete -c mcpctl -n "not __mcpctl_has_project; and not __fish_seen_subcommand_
|
|||||||
# Project-scoped commands (with --project)
|
# Project-scoped commands (with --project)
|
||||||
complete -c mcpctl -n "__mcpctl_has_project; and not __fish_seen_subcommand_from $project_commands" -a get -d 'List resources (servers, projects, instances, all)'
|
complete -c mcpctl -n "__mcpctl_has_project; and not __fish_seen_subcommand_from $project_commands" -a get -d 'List resources (servers, projects, instances, all)'
|
||||||
complete -c mcpctl -n "__mcpctl_has_project; and not __fish_seen_subcommand_from $project_commands" -a describe -d 'Show detailed information about a resource'
|
complete -c mcpctl -n "__mcpctl_has_project; and not __fish_seen_subcommand_from $project_commands" -a describe -d 'Show detailed information about a resource'
|
||||||
complete -c mcpctl -n "__mcpctl_has_project; and not __fish_seen_subcommand_from $project_commands" -a delete -d 'Delete a resource (server, instance, secret, project, user, group, rbac)'
|
complete -c mcpctl -n "__mcpctl_has_project; and not __fish_seen_subcommand_from $project_commands" -a delete -d 'Delete a resource (server, instance, secret, project, user, group, rbac, personality)'
|
||||||
complete -c mcpctl -n "__mcpctl_has_project; and not __fish_seen_subcommand_from $project_commands" -a logs -d 'Get logs from an MCP server instance'
|
complete -c mcpctl -n "__mcpctl_has_project; and not __fish_seen_subcommand_from $project_commands" -a logs -d 'Get logs from an MCP server instance'
|
||||||
complete -c mcpctl -n "__mcpctl_has_project; and not __fish_seen_subcommand_from $project_commands" -a create -d 'Create a resource (server, secret, secretbackend, llm, agent, project, user, group, rbac, serverattachment, prompt)'
|
complete -c mcpctl -n "__mcpctl_has_project; and not __fish_seen_subcommand_from $project_commands" -a create -d 'Create a resource (server, secret, secretbackend, llm, agent, project, user, group, rbac, serverattachment, prompt)'
|
||||||
complete -c mcpctl -n "__mcpctl_has_project; and not __fish_seen_subcommand_from $project_commands" -a edit -d 'Edit a resource in your default editor (server, project)'
|
complete -c mcpctl -n "__mcpctl_has_project; and not __fish_seen_subcommand_from $project_commands" -a edit -d 'Edit a resource in your default editor (server, project)'
|
||||||
@@ -251,7 +252,7 @@ complete -c mcpctl -n "__mcpctl_has_project; and not __fish_seen_subcommand_from
|
|||||||
|
|
||||||
# Resource types — only when resource type not yet selected
|
# Resource types — only when resource type not yet selected
|
||||||
complete -c mcpctl -n "__fish_seen_subcommand_from get describe delete patch; and __mcpctl_needs_resource_type" -a "$resources" -d 'Resource type'
|
complete -c mcpctl -n "__fish_seen_subcommand_from get describe delete patch; and __mcpctl_needs_resource_type" -a "$resources" -d 'Resource type'
|
||||||
complete -c mcpctl -n "__fish_seen_subcommand_from edit; and __mcpctl_needs_resource_type" -a 'servers secrets projects groups rbac prompts promptrequests' -d 'Resource type'
|
complete -c mcpctl -n "__fish_seen_subcommand_from edit; and __mcpctl_needs_resource_type" -a 'servers secrets projects groups rbac prompts promptrequests personalities' -d 'Resource type'
|
||||||
complete -c mcpctl -n "__fish_seen_subcommand_from approve; and __mcpctl_needs_resource_type" -a 'promptrequest' -d 'Resource type'
|
complete -c mcpctl -n "__fish_seen_subcommand_from approve; and __mcpctl_needs_resource_type" -a 'promptrequest' -d 'Resource type'
|
||||||
|
|
||||||
# Resource names — after resource type is selected
|
# Resource names — after resource type is selected
|
||||||
@@ -287,7 +288,7 @@ complete -c mcpctl -n "__mcpctl_subcmd_active config claude-generate" -l stdout
|
|||||||
complete -c mcpctl -n "__mcpctl_subcmd_active config impersonate" -l quit -d 'Stop impersonating and return to original identity'
|
complete -c mcpctl -n "__mcpctl_subcmd_active config impersonate" -l quit -d 'Stop impersonating and return to original identity'
|
||||||
|
|
||||||
# create subcommands
|
# create subcommands
|
||||||
set -l create_cmds server secret llm agent secretbackend project user group rbac mcptoken prompt serverattachment promptrequest
|
set -l create_cmds server secret llm agent secretbackend project user group rbac mcptoken prompt personality serverattachment promptrequest
|
||||||
complete -c mcpctl -n "__fish_seen_subcommand_from create; and not __fish_seen_subcommand_from $create_cmds" -a server -d 'Create an MCP server definition'
|
complete -c mcpctl -n "__fish_seen_subcommand_from create; and not __fish_seen_subcommand_from $create_cmds" -a server -d 'Create an MCP server definition'
|
||||||
complete -c mcpctl -n "__fish_seen_subcommand_from create; and not __fish_seen_subcommand_from $create_cmds" -a secret -d 'Create a secret'
|
complete -c mcpctl -n "__fish_seen_subcommand_from create; and not __fish_seen_subcommand_from $create_cmds" -a secret -d 'Create a secret'
|
||||||
complete -c mcpctl -n "__fish_seen_subcommand_from create; and not __fish_seen_subcommand_from $create_cmds" -a llm -d 'Register a server-managed LLM (anthropic, openai, vllm, ollama, deepseek, gemini-cli)'
|
complete -c mcpctl -n "__fish_seen_subcommand_from create; and not __fish_seen_subcommand_from $create_cmds" -a llm -d 'Register a server-managed LLM (anthropic, openai, vllm, ollama, deepseek, gemini-cli)'
|
||||||
@@ -298,7 +299,8 @@ complete -c mcpctl -n "__fish_seen_subcommand_from create; and not __fish_seen_s
|
|||||||
complete -c mcpctl -n "__fish_seen_subcommand_from create; and not __fish_seen_subcommand_from $create_cmds" -a group -d 'Create a group'
|
complete -c mcpctl -n "__fish_seen_subcommand_from create; and not __fish_seen_subcommand_from $create_cmds" -a group -d 'Create a group'
|
||||||
complete -c mcpctl -n "__fish_seen_subcommand_from create; and not __fish_seen_subcommand_from $create_cmds" -a rbac -d 'Create an RBAC binding definition'
|
complete -c mcpctl -n "__fish_seen_subcommand_from create; and not __fish_seen_subcommand_from $create_cmds" -a rbac -d 'Create an RBAC binding definition'
|
||||||
complete -c mcpctl -n "__fish_seen_subcommand_from create; and not __fish_seen_subcommand_from $create_cmds" -a mcptoken -d 'Create a project-scoped API token for HTTP-mode mcplocal. The raw token is printed once.'
|
complete -c mcpctl -n "__fish_seen_subcommand_from create; and not __fish_seen_subcommand_from $create_cmds" -a mcptoken -d 'Create a project-scoped API token for HTTP-mode mcplocal. The raw token is printed once.'
|
||||||
complete -c mcpctl -n "__fish_seen_subcommand_from create; and not __fish_seen_subcommand_from $create_cmds" -a prompt -d 'Create an approved prompt'
|
complete -c mcpctl -n "__fish_seen_subcommand_from create; and not __fish_seen_subcommand_from $create_cmds" -a prompt -d 'Create an approved prompt (scope: project, agent, or global)'
|
||||||
|
complete -c mcpctl -n "__fish_seen_subcommand_from create; and not __fish_seen_subcommand_from $create_cmds" -a personality -d 'Create a personality overlay on an agent'
|
||||||
complete -c mcpctl -n "__fish_seen_subcommand_from create; and not __fish_seen_subcommand_from $create_cmds" -a serverattachment -d 'Attach a server to a project'
|
complete -c mcpctl -n "__fish_seen_subcommand_from create; and not __fish_seen_subcommand_from $create_cmds" -a serverattachment -d 'Attach a server to a project'
|
||||||
complete -c mcpctl -n "__fish_seen_subcommand_from create; and not __fish_seen_subcommand_from $create_cmds" -a promptrequest -d 'Create a prompt request (pending proposal that needs approval)'
|
complete -c mcpctl -n "__fish_seen_subcommand_from create; and not __fish_seen_subcommand_from $create_cmds" -a promptrequest -d 'Create a prompt request (pending proposal that needs approval)'
|
||||||
|
|
||||||
@@ -406,12 +408,18 @@ complete -c mcpctl -n "__mcpctl_subcmd_active create mcptoken" -l description -d
|
|||||||
complete -c mcpctl -n "__mcpctl_subcmd_active create mcptoken" -l force -d 'Revoke any existing active token with this name, then create a new one'
|
complete -c mcpctl -n "__mcpctl_subcmd_active create mcptoken" -l force -d 'Revoke any existing active token with this name, then create a new one'
|
||||||
|
|
||||||
# create prompt options
|
# create prompt options
|
||||||
complete -c mcpctl -n "__mcpctl_subcmd_active create prompt" -s p -l project -d 'Project name to scope the prompt to' -xa '(__mcpctl_project_names)'
|
complete -c mcpctl -n "__mcpctl_subcmd_active create prompt" -s p -l project -d 'Project to scope the prompt to' -xa '(__mcpctl_project_names)'
|
||||||
|
complete -c mcpctl -n "__mcpctl_subcmd_active create prompt" -l agent -d 'Agent to attach the prompt to directly (XOR with --project)' -x
|
||||||
complete -c mcpctl -n "__mcpctl_subcmd_active create prompt" -l content -d 'Prompt content text' -x
|
complete -c mcpctl -n "__mcpctl_subcmd_active create prompt" -l content -d 'Prompt content text' -x
|
||||||
complete -c mcpctl -n "__mcpctl_subcmd_active create prompt" -l content-file -d 'Read prompt content from file' -rF
|
complete -c mcpctl -n "__mcpctl_subcmd_active create prompt" -l content-file -d 'Read prompt content from file' -rF
|
||||||
complete -c mcpctl -n "__mcpctl_subcmd_active create prompt" -l priority -d 'Priority 1-10 (default: 5, higher = more important)' -x
|
complete -c mcpctl -n "__mcpctl_subcmd_active create prompt" -l priority -d 'Priority 1-10 (default: 5, higher = more important)' -x
|
||||||
complete -c mcpctl -n "__mcpctl_subcmd_active create prompt" -l link -d 'Link to MCP resource (format: project/server:uri)' -x
|
complete -c mcpctl -n "__mcpctl_subcmd_active create prompt" -l link -d 'Link to MCP resource (format: project/server:uri)' -x
|
||||||
|
|
||||||
|
# create personality options
|
||||||
|
complete -c mcpctl -n "__mcpctl_subcmd_active create personality" -l agent -d 'Agent that owns this personality (required)' -x
|
||||||
|
complete -c mcpctl -n "__mcpctl_subcmd_active create personality" -l description -d 'Description shown in `mcpctl get personalities`' -x
|
||||||
|
complete -c mcpctl -n "__mcpctl_subcmd_active create personality" -l priority -d 'Priority 1-10 (default: 5)' -x
|
||||||
|
|
||||||
# create serverattachment options
|
# create serverattachment options
|
||||||
complete -c mcpctl -n "__mcpctl_subcmd_active create serverattachment" -s p -l project -d 'Project name' -xa '(__mcpctl_project_names)'
|
complete -c mcpctl -n "__mcpctl_subcmd_active create serverattachment" -s p -l project -d 'Project name' -xa '(__mcpctl_project_names)'
|
||||||
|
|
||||||
@@ -483,6 +491,7 @@ complete -c mcpctl -n "__fish_seen_subcommand_from describe" -l show-values -d '
|
|||||||
|
|
||||||
# delete options
|
# delete options
|
||||||
complete -c mcpctl -n "__fish_seen_subcommand_from delete" -s p -l project -d 'Project name (for serverattachment)' -xa '(__mcpctl_project_names)'
|
complete -c mcpctl -n "__fish_seen_subcommand_from delete" -s p -l project -d 'Project name (for serverattachment)' -xa '(__mcpctl_project_names)'
|
||||||
|
complete -c mcpctl -n "__fish_seen_subcommand_from delete" -l agent -d 'Agent name (for personality delete-by-name)' -x
|
||||||
|
|
||||||
# logs options
|
# logs options
|
||||||
complete -c mcpctl -n "__fish_seen_subcommand_from logs" -s t -l tail -d 'Number of lines to show' -x
|
complete -c mcpctl -n "__fish_seen_subcommand_from logs" -s t -l tail -d 'Number of lines to show' -x
|
||||||
@@ -498,6 +507,7 @@ complete -c mcpctl -n "__fish_seen_subcommand_from chat" -l thread -d 'Resume an
|
|||||||
complete -c mcpctl -n "__fish_seen_subcommand_from chat" -l system -d 'Replace agent.systemPrompt for this session' -x
|
complete -c mcpctl -n "__fish_seen_subcommand_from chat" -l system -d 'Replace agent.systemPrompt for this session' -x
|
||||||
complete -c mcpctl -n "__fish_seen_subcommand_from chat" -l system-file -d 'Read --system text from a file' -x
|
complete -c mcpctl -n "__fish_seen_subcommand_from chat" -l system-file -d 'Read --system text from a file' -x
|
||||||
complete -c mcpctl -n "__fish_seen_subcommand_from chat" -l system-append -d 'Append to the agent system block for this session' -x
|
complete -c mcpctl -n "__fish_seen_subcommand_from chat" -l system-append -d 'Append to the agent system block for this session' -x
|
||||||
|
complete -c mcpctl -n "__fish_seen_subcommand_from chat" -l personality -d 'Personality overlay (additive prompts on top of the agent)' -x
|
||||||
complete -c mcpctl -n "__fish_seen_subcommand_from chat" -l temperature -d 'Sampling temperature (0..2)' -x
|
complete -c mcpctl -n "__fish_seen_subcommand_from chat" -l temperature -d 'Sampling temperature (0..2)' -x
|
||||||
complete -c mcpctl -n "__fish_seen_subcommand_from chat" -l top-p -d 'Nucleus sampling cutoff (0..1)' -x
|
complete -c mcpctl -n "__fish_seen_subcommand_from chat" -l top-p -d 'Nucleus sampling cutoff (0..1)' -x
|
||||||
complete -c mcpctl -n "__fish_seen_subcommand_from chat" -l top-k -d 'Top-K sampling (Anthropic; OpenAI ignores)' -x
|
complete -c mcpctl -n "__fish_seen_subcommand_from chat" -l top-k -d 'Top-K sampling (Anthropic; OpenAI ignores)' -x
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ const COMPLETION_HINTS: Record<string, CompletionHint> = {
|
|||||||
'describe.id': 'resource_names',
|
'describe.id': 'resource_names',
|
||||||
'delete.resource': 'resource_types',
|
'delete.resource': 'resource_types',
|
||||||
'delete.id': 'resource_names',
|
'delete.id': 'resource_names',
|
||||||
'edit.resource': { static: ['servers', 'secrets', 'projects', 'groups', 'rbac', 'prompts', 'promptrequests'] },
|
'edit.resource': { static: ['servers', 'secrets', 'projects', 'groups', 'rbac', 'prompts', 'promptrequests', 'personalities'] },
|
||||||
'edit.name-or-id': 'resource_names',
|
'edit.name-or-id': 'resource_names',
|
||||||
'patch.resource': 'resource_types',
|
'patch.resource': 'resource_types',
|
||||||
'patch.name': 'resource_names',
|
'patch.name': 'resource_names',
|
||||||
@@ -184,7 +184,7 @@ async function extractTree(): Promise<CmdInfo> {
|
|||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
const CANONICAL_RESOURCES = [
|
const CANONICAL_RESOURCES = [
|
||||||
'servers', 'instances', 'secrets', 'secretbackends', 'llms', 'agents', 'templates', 'projects',
|
'servers', 'instances', 'secrets', 'secretbackends', 'llms', 'agents', 'personalities', 'templates', 'projects',
|
||||||
'users', 'groups', 'rbac', 'prompts', 'promptrequests',
|
'users', 'groups', 'rbac', 'prompts', 'promptrequests',
|
||||||
'serverattachments', 'proxymodels', 'all',
|
'serverattachments', 'proxymodels', 'all',
|
||||||
];
|
];
|
||||||
@@ -196,6 +196,7 @@ const ALIAS_ENTRIES: [string, string][] = [
|
|||||||
['secretbackend', 'secretbackends'], ['sb', 'secretbackends'],
|
['secretbackend', 'secretbackends'], ['sb', 'secretbackends'],
|
||||||
['llm', 'llms'], ['llms', 'llms'],
|
['llm', 'llms'], ['llms', 'llms'],
|
||||||
['agent', 'agents'], ['agents', 'agents'],
|
['agent', 'agents'], ['agents', 'agents'],
|
||||||
|
['personality', 'personalities'], ['personalities', 'personalities'],
|
||||||
['template', 'templates'], ['tpl', 'templates'],
|
['template', 'templates'], ['tpl', 'templates'],
|
||||||
['project', 'projects'], ['proj', 'projects'],
|
['project', 'projects'], ['proj', 'projects'],
|
||||||
['user', 'users'],
|
['user', 'users'],
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ export function createChatCommand(deps: ChatCommandDeps): Command {
|
|||||||
.option('--system <text>', 'Replace agent.systemPrompt for this session')
|
.option('--system <text>', 'Replace agent.systemPrompt for this session')
|
||||||
.option('--system-file <path>', 'Read --system text from a file')
|
.option('--system-file <path>', 'Read --system text from a file')
|
||||||
.option('--system-append <text>', 'Append to the agent system block for this session')
|
.option('--system-append <text>', 'Append to the agent system block for this session')
|
||||||
|
.option('--personality <name>', 'Personality overlay (additive prompts on top of the agent)')
|
||||||
.option('--temperature <n>', 'Sampling temperature (0..2)', parseFloat)
|
.option('--temperature <n>', 'Sampling temperature (0..2)', parseFloat)
|
||||||
.option('--top-p <n>', 'Nucleus sampling cutoff (0..1)', parseFloat)
|
.option('--top-p <n>', 'Nucleus sampling cutoff (0..1)', parseFloat)
|
||||||
.option('--top-k <n>', 'Top-K sampling (Anthropic; OpenAI ignores)', parseFloatInt)
|
.option('--top-k <n>', 'Top-K sampling (Anthropic; OpenAI ignores)', parseFloatInt)
|
||||||
@@ -71,6 +72,7 @@ interface ChatOpts {
|
|||||||
system?: string;
|
system?: string;
|
||||||
systemFile?: string;
|
systemFile?: string;
|
||||||
systemAppend?: string;
|
systemAppend?: string;
|
||||||
|
personality?: string;
|
||||||
temperature?: number;
|
temperature?: number;
|
||||||
topP?: number;
|
topP?: number;
|
||||||
topK?: number;
|
topK?: number;
|
||||||
@@ -85,6 +87,7 @@ interface ChatOpts {
|
|||||||
interface Overrides {
|
interface Overrides {
|
||||||
systemOverride?: string;
|
systemOverride?: string;
|
||||||
systemAppend?: string;
|
systemAppend?: string;
|
||||||
|
personality?: string;
|
||||||
temperature?: number;
|
temperature?: number;
|
||||||
top_p?: number;
|
top_p?: number;
|
||||||
top_k?: number;
|
top_k?: number;
|
||||||
@@ -103,6 +106,7 @@ async function buildInitialOverrides(opts: ChatOpts): Promise<Overrides> {
|
|||||||
}
|
}
|
||||||
if (system !== undefined) out.systemOverride = system;
|
if (system !== undefined) out.systemOverride = system;
|
||||||
if (opts.systemAppend !== undefined) out.systemAppend = opts.systemAppend;
|
if (opts.systemAppend !== undefined) out.systemAppend = opts.systemAppend;
|
||||||
|
if (opts.personality !== undefined) out.personality = opts.personality;
|
||||||
if (opts.temperature !== undefined) out.temperature = opts.temperature;
|
if (opts.temperature !== undefined) out.temperature = opts.temperature;
|
||||||
if (opts.topP !== undefined) out.top_p = opts.topP;
|
if (opts.topP !== undefined) out.top_p = opts.topP;
|
||||||
if (opts.topK !== undefined) out.top_k = opts.topK;
|
if (opts.topK !== undefined) out.top_k = opts.topK;
|
||||||
@@ -298,10 +302,14 @@ async function handleSlash(
|
|||||||
}
|
}
|
||||||
|
|
||||||
function stripSession(o: Overrides): Record<string, unknown> {
|
function stripSession(o: Overrides): Record<string, unknown> {
|
||||||
// /save persists sampling defaults but not the per-session systemOverride / systemAppend.
|
// /save persists sampling defaults but not per-session persona controls
|
||||||
|
// (--system / --system-append) or the per-turn --personality overlay.
|
||||||
|
// The agent's defaultPersonality is set via PATCH /agents (or `mcpctl edit
|
||||||
|
// agent`) — it is NOT a sampling param.
|
||||||
const out: Record<string, unknown> = { ...o };
|
const out: Record<string, unknown> = { ...o };
|
||||||
delete out.systemOverride;
|
delete out.systemOverride;
|
||||||
delete out.systemAppend;
|
delete out.systemAppend;
|
||||||
|
delete out.personality;
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -669,6 +677,7 @@ interface AgentInfo {
|
|||||||
systemPrompt: string;
|
systemPrompt: string;
|
||||||
llm: { name: string };
|
llm: { name: string };
|
||||||
project: { name: string } | null;
|
project: { name: string } | null;
|
||||||
|
defaultPersonality?: { name: string } | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -702,6 +711,15 @@ async function printChatHeader(
|
|||||||
const tail = info.project !== null ? ` Project: ${info.project.name}` : '';
|
const tail = info.project !== null ? ` Project: ${info.project.name}` : '';
|
||||||
out(`LLM: ${info.llm.name}${tail}`);
|
out(`LLM: ${info.llm.name}${tail}`);
|
||||||
|
|
||||||
|
// Personality overlay: explicit --personality wins; otherwise agent's
|
||||||
|
// defaultPersonality (if set). Tells the user which prompt bundle is
|
||||||
|
// active before they type anything.
|
||||||
|
if (overrides.personality !== undefined) {
|
||||||
|
out(`Personality: ${overrides.personality} (--personality)`);
|
||||||
|
} else if (info.defaultPersonality) {
|
||||||
|
out(`Personality: ${info.defaultPersonality.name} (agent default)`);
|
||||||
|
}
|
||||||
|
|
||||||
if (overrides.systemOverride !== undefined) {
|
if (overrides.systemOverride !== undefined) {
|
||||||
out(`System prompt (--system replaces agent.systemPrompt):`);
|
out(`System prompt (--system replaces agent.systemPrompt):`);
|
||||||
out(indent(overrides.systemOverride));
|
out(indent(overrides.systemOverride));
|
||||||
|
|||||||
@@ -727,14 +727,18 @@ export function createCreateCommand(deps: CreateCommandDeps): Command {
|
|||||||
|
|
||||||
// --- create prompt ---
|
// --- create prompt ---
|
||||||
cmd.command('prompt')
|
cmd.command('prompt')
|
||||||
.description('Create an approved prompt')
|
.description('Create an approved prompt (scope: project, agent, or global)')
|
||||||
.argument('<name>', 'Prompt name (lowercase alphanumeric with hyphens)')
|
.argument('<name>', 'Prompt name (lowercase alphanumeric with hyphens)')
|
||||||
.option('-p, --project <name>', 'Project name to scope the prompt to')
|
.option('-p, --project <name>', 'Project to scope the prompt to')
|
||||||
|
.option('--agent <name>', 'Agent to attach the prompt to directly (XOR with --project)')
|
||||||
.option('--content <text>', 'Prompt content text')
|
.option('--content <text>', 'Prompt content text')
|
||||||
.option('--content-file <path>', 'Read prompt content from file')
|
.option('--content-file <path>', 'Read prompt content from file')
|
||||||
.option('--priority <number>', 'Priority 1-10 (default: 5, higher = more important)')
|
.option('--priority <number>', 'Priority 1-10 (default: 5, higher = more important)')
|
||||||
.option('--link <target>', 'Link to MCP resource (format: project/server:uri)')
|
.option('--link <target>', 'Link to MCP resource (format: project/server:uri)')
|
||||||
.action(async (name: string, opts) => {
|
.action(async (name: string, opts) => {
|
||||||
|
if (opts.project && opts.agent) {
|
||||||
|
throw new Error('--project and --agent are mutually exclusive');
|
||||||
|
}
|
||||||
let content = opts.content as string | undefined;
|
let content = opts.content as string | undefined;
|
||||||
if (opts.contentFile) {
|
if (opts.contentFile) {
|
||||||
const fs = await import('node:fs/promises');
|
const fs = await import('node:fs/promises');
|
||||||
@@ -756,6 +760,10 @@ export function createCreateCommand(deps: CreateCommandDeps): Command {
|
|||||||
if (!project) throw new Error(`Project '${opts.project as string}' not found`);
|
if (!project) throw new Error(`Project '${opts.project as string}' not found`);
|
||||||
body.projectId = project.id;
|
body.projectId = project.id;
|
||||||
}
|
}
|
||||||
|
if (opts.agent) {
|
||||||
|
// Send agent name; mcpd resolves it server-side.
|
||||||
|
body.agent = opts.agent;
|
||||||
|
}
|
||||||
if (opts.priority) {
|
if (opts.priority) {
|
||||||
const priority = Number(opts.priority);
|
const priority = Number(opts.priority);
|
||||||
if (isNaN(priority) || priority < 1 || priority > 10) {
|
if (isNaN(priority) || priority < 1 || priority > 10) {
|
||||||
@@ -771,6 +779,34 @@ export function createCreateCommand(deps: CreateCommandDeps): Command {
|
|||||||
log(`prompt '${prompt.name}' created (id: ${prompt.id})`);
|
log(`prompt '${prompt.name}' created (id: ${prompt.id})`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// --- create personality ---
|
||||||
|
cmd.command('personality')
|
||||||
|
.description('Create a personality overlay on an agent')
|
||||||
|
.argument('<name>', 'Personality name (lowercase alphanumeric with hyphens)')
|
||||||
|
.option('--agent <name>', 'Agent that owns this personality (required)')
|
||||||
|
.option('--description <text>', 'Description shown in `mcpctl get personalities`')
|
||||||
|
.option('--priority <number>', 'Priority 1-10 (default: 5)')
|
||||||
|
.action(async (name: string, opts) => {
|
||||||
|
const agentName = opts.agent as string | undefined;
|
||||||
|
if (!agentName) {
|
||||||
|
throw new Error('--agent is required');
|
||||||
|
}
|
||||||
|
const body: Record<string, unknown> = { name };
|
||||||
|
if (opts.description) body.description = opts.description;
|
||||||
|
if (opts.priority) {
|
||||||
|
const priority = Number(opts.priority);
|
||||||
|
if (isNaN(priority) || priority < 1 || priority > 10) {
|
||||||
|
throw new Error('--priority must be a number between 1 and 10');
|
||||||
|
}
|
||||||
|
body.priority = priority;
|
||||||
|
}
|
||||||
|
const personality = await client.post<{ id: string; name: string }>(
|
||||||
|
`/api/v1/agents/${encodeURIComponent(agentName)}/personalities`,
|
||||||
|
body,
|
||||||
|
);
|
||||||
|
log(`personality '${personality.name}' created on agent '${agentName}' (id: ${personality.id})`);
|
||||||
|
});
|
||||||
|
|
||||||
// --- create serverattachment ---
|
// --- create serverattachment ---
|
||||||
cmd.command('serverattachment')
|
cmd.command('serverattachment')
|
||||||
.alias('sa')
|
.alias('sa')
|
||||||
|
|||||||
@@ -11,11 +11,12 @@ export function createDeleteCommand(deps: DeleteCommandDeps): Command {
|
|||||||
const { client, log } = deps;
|
const { client, log } = deps;
|
||||||
|
|
||||||
return new Command('delete')
|
return new Command('delete')
|
||||||
.description('Delete a resource (server, instance, secret, project, user, group, rbac)')
|
.description('Delete a resource (server, instance, secret, project, user, group, rbac, personality)')
|
||||||
.argument('<resource>', 'resource type')
|
.argument('<resource>', 'resource type')
|
||||||
.argument('<id>', 'resource ID or name')
|
.argument('<id>', 'resource ID or name')
|
||||||
.option('-p, --project <name>', 'Project name (for serverattachment)')
|
.option('-p, --project <name>', 'Project name (for serverattachment)')
|
||||||
.action(async (resourceArg: string, idOrName: string, opts: { project?: string }) => {
|
.option('--agent <name>', 'Agent name (for personality delete-by-name)')
|
||||||
|
.action(async (resourceArg: string, idOrName: string, opts: { project?: string; agent?: string }) => {
|
||||||
const resource = resolveResource(resourceArg);
|
const resource = resolveResource(resourceArg);
|
||||||
|
|
||||||
// Serverattachments: delete serverattachment <server> --project <project>
|
// Serverattachments: delete serverattachment <server> --project <project>
|
||||||
@@ -29,6 +30,28 @@ export function createDeleteCommand(deps: DeleteCommandDeps): Command {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Personalities: names are unique per-agent, so by-name delete requires --agent
|
||||||
|
// (or pass a CUID directly).
|
||||||
|
if (resource === 'personalities') {
|
||||||
|
let personalityId: string;
|
||||||
|
if (/^c[a-z0-9]{24}/.test(idOrName)) {
|
||||||
|
personalityId = idOrName;
|
||||||
|
} else {
|
||||||
|
if (!opts.agent) {
|
||||||
|
throw new Error('--agent is required to delete a personality by name (or pass the id).');
|
||||||
|
}
|
||||||
|
const items = await client.get<Array<{ id: string; name: string }>>(
|
||||||
|
`/api/v1/agents/${encodeURIComponent(opts.agent)}/personalities`,
|
||||||
|
);
|
||||||
|
const match = items.find((i) => i.name === idOrName);
|
||||||
|
if (!match) throw new Error(`personality '${idOrName}' not found on agent '${opts.agent}'`);
|
||||||
|
personalityId = match.id;
|
||||||
|
}
|
||||||
|
await client.delete(`/api/v1/personalities/${personalityId}`);
|
||||||
|
log(`personality '${idOrName}' deleted.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Mcptokens: names are scoped to a project, so require --project unless the caller passes a CUID
|
// Mcptokens: names are scoped to a project, so require --project unless the caller passes a CUID
|
||||||
if (resource === 'mcptokens') {
|
if (resource === 'mcptokens') {
|
||||||
let tokenId: string;
|
let tokenId: string;
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ export function createEditCommand(deps: EditCommandDeps): Command {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const validResources = ['servers', 'secrets', 'projects', 'groups', 'rbac', 'prompts', 'promptrequests'];
|
const validResources = ['servers', 'secrets', 'projects', 'groups', 'rbac', 'prompts', 'promptrequests', 'personalities'];
|
||||||
if (!validResources.includes(resource)) {
|
if (!validResources.includes(resource)) {
|
||||||
log(`Error: unknown resource type '${resourceArg}'`);
|
log(`Error: unknown resource type '${resourceArg}'`);
|
||||||
process.exitCode = 1;
|
process.exitCode = 1;
|
||||||
|
|||||||
@@ -159,6 +159,25 @@ const agentColumns: Column<AgentRow>[] = [
|
|||||||
{ header: 'ID', key: 'id' },
|
{ header: 'ID', key: 'id' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
interface PersonalityRow {
|
||||||
|
id: string;
|
||||||
|
name: string;
|
||||||
|
description: string;
|
||||||
|
agentId: string;
|
||||||
|
agentName: string;
|
||||||
|
priority: number;
|
||||||
|
promptCount: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
const personalityColumns: Column<PersonalityRow>[] = [
|
||||||
|
{ header: 'NAME', key: 'name' },
|
||||||
|
{ header: 'AGENT', key: 'agentName', width: 24 },
|
||||||
|
{ header: 'PROMPTS', key: (r) => String(r.promptCount), width: 8 },
|
||||||
|
{ header: 'PRIORITY', key: (r) => String(r.priority), width: 8 },
|
||||||
|
{ header: 'DESCRIPTION', key: (r) => truncate(r.description, 40) || '-', width: 40 },
|
||||||
|
{ header: 'ID', key: 'id' },
|
||||||
|
];
|
||||||
|
|
||||||
function truncate(s: string, max: number): string {
|
function truncate(s: string, max: number): string {
|
||||||
if (s.length <= max) return s;
|
if (s.length <= max) return s;
|
||||||
return s.slice(0, max - 1) + '…';
|
return s.slice(0, max - 1) + '…';
|
||||||
@@ -345,6 +364,8 @@ function getColumnsForResource(resource: string): Column<Record<string, unknown>
|
|||||||
return llmColumns as unknown as Column<Record<string, unknown>>[];
|
return llmColumns as unknown as Column<Record<string, unknown>>[];
|
||||||
case 'agents':
|
case 'agents':
|
||||||
return agentColumns as unknown as Column<Record<string, unknown>>[];
|
return agentColumns as unknown as Column<Record<string, unknown>>[];
|
||||||
|
case 'personalities':
|
||||||
|
return personalityColumns as unknown as Column<Record<string, unknown>>[];
|
||||||
default:
|
default:
|
||||||
return [
|
return [
|
||||||
{ header: 'ID', key: 'id' as keyof Record<string, unknown> },
|
{ header: 'ID', key: 'id' as keyof Record<string, unknown> },
|
||||||
@@ -370,6 +391,7 @@ const RESOURCE_KIND: Record<string, string> = {
|
|||||||
secretbackends: 'secretbackend',
|
secretbackends: 'secretbackend',
|
||||||
llms: 'llm',
|
llms: 'llm',
|
||||||
agents: 'agent',
|
agents: 'agent',
|
||||||
|
personalities: 'personality',
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -38,6 +38,8 @@ export const RESOURCE_ALIASES: Record<string, string> = {
|
|||||||
llms: 'llms',
|
llms: 'llms',
|
||||||
agent: 'agents',
|
agent: 'agents',
|
||||||
agents: 'agents',
|
agents: 'agents',
|
||||||
|
personality: 'personalities',
|
||||||
|
personalities: 'personalities',
|
||||||
thread: 'threads',
|
thread: 'threads',
|
||||||
threads: 'threads',
|
threads: 'threads',
|
||||||
all: 'all',
|
all: 'all',
|
||||||
|
|||||||
@@ -14,6 +14,24 @@ export function registerPersonalityRoutes(
|
|||||||
app: FastifyInstance,
|
app: FastifyInstance,
|
||||||
service: PersonalityService,
|
service: PersonalityService,
|
||||||
): void {
|
): void {
|
||||||
|
app.get<{ Querystring: { agent?: string } }>(
|
||||||
|
'/api/v1/personalities',
|
||||||
|
async (request, reply) => {
|
||||||
|
try {
|
||||||
|
if (request.query.agent !== undefined) {
|
||||||
|
return await service.listForAgent(request.query.agent);
|
||||||
|
}
|
||||||
|
return await service.listAll();
|
||||||
|
} catch (err) {
|
||||||
|
if (err instanceof NotFoundError) {
|
||||||
|
reply.code(404);
|
||||||
|
return { error: err.message };
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
app.get<{ Params: { agentName: string } }>(
|
app.get<{ Params: { agentName: string } }>(
|
||||||
'/api/v1/agents/:agentName/personalities',
|
'/api/v1/agents/:agentName/personalities',
|
||||||
async (request, reply) => {
|
async (request, reply) => {
|
||||||
|
|||||||
@@ -54,6 +54,18 @@ export class PersonalityService {
|
|||||||
private readonly promptRepo: IPromptRepository,
|
private readonly promptRepo: IPromptRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
|
async listAll(): Promise<PersonalityView[]> {
|
||||||
|
const rows = await this.repo.findAll();
|
||||||
|
const agents = new Map<string, string>();
|
||||||
|
for (const r of rows) {
|
||||||
|
if (!agents.has(r.agentId)) {
|
||||||
|
const agent = await this.agentRepo.findById(r.agentId);
|
||||||
|
agents.set(r.agentId, agent?.name ?? r.agentId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Promise.all(rows.map((r) => this.toView(r, agents.get(r.agentId) ?? r.agentId)));
|
||||||
|
}
|
||||||
|
|
||||||
async listForAgent(agentName: string): Promise<PersonalityView[]> {
|
async listForAgent(agentName: string): Promise<PersonalityView[]> {
|
||||||
const agent = await this.agentRepo.findByName(agentName);
|
const agent = await this.agentRepo.findByName(agentName);
|
||||||
if (agent === null) throw new NotFoundError(`Agent not found: ${agentName}`);
|
if (agent === null) throw new NotFoundError(`Agent not found: ${agentName}`);
|
||||||
|
|||||||
Reference in New Issue
Block a user