mirror of
https://github.com/memohai/Memoh.git
synced 2026-04-25 07:00:48 +09:00
d46269de89
Make slash commands easier to navigate in chat by splitting help into levels, compacting list output, and surfacing current selections for model, search, memory, and browser settings. Also route /status to the active conversation session and add an access inspector so users can understand their current command and ACL context.
97 lines
2.0 KiB
Go
97 lines
2.0 KiB
Go
package command
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
"unicode/utf8"
|
|
)
|
|
|
|
const defaultListLimit = 12
|
|
|
|
// formatItems renders a list of records as a Markdown-style list.
|
|
// Each record is rendered on a single line so long lists stay readable in IM.
|
|
func formatItems(items [][]kv) string {
|
|
if len(items) == 0 {
|
|
return ""
|
|
}
|
|
var b strings.Builder
|
|
for i, record := range items {
|
|
if len(record) == 0 {
|
|
continue
|
|
}
|
|
if i > 0 {
|
|
b.WriteByte('\n')
|
|
}
|
|
fmt.Fprintf(&b, "- %s", record[0].value)
|
|
extras := make([]string, 0, len(record)-1)
|
|
for _, pair := range record[1:] {
|
|
if strings.TrimSpace(pair.value) == "" {
|
|
continue
|
|
}
|
|
extras = append(extras, fmt.Sprintf("%s: %s", pair.key, pair.value))
|
|
}
|
|
if len(extras) > 0 {
|
|
fmt.Fprintf(&b, " | %s", strings.Join(extras, " | "))
|
|
}
|
|
}
|
|
return b.String()
|
|
}
|
|
|
|
func formatLimitedItems(items [][]kv, limit int, hint string) string {
|
|
if len(items) == 0 {
|
|
return ""
|
|
}
|
|
if limit <= 0 {
|
|
limit = defaultListLimit
|
|
}
|
|
total := len(items)
|
|
if total <= limit {
|
|
return formatItems(items)
|
|
}
|
|
shown := items[:limit]
|
|
result := formatItems(shown)
|
|
suffix := fmt.Sprintf("Showing %d of %d items.", len(shown), total)
|
|
if strings.TrimSpace(hint) != "" {
|
|
suffix += " " + strings.TrimSpace(hint)
|
|
}
|
|
return result + "\n\n" + suffix
|
|
}
|
|
|
|
// formatKV renders key-value pairs as a simple Markdown list.
|
|
//
|
|
// Example output:
|
|
//
|
|
// - ID: abc123
|
|
// - Name: mybot
|
|
func formatKV(pairs []kv) string {
|
|
var b strings.Builder
|
|
for _, p := range pairs {
|
|
fmt.Fprintf(&b, "- %s: %s\n", p.key, p.value)
|
|
}
|
|
return b.String()
|
|
}
|
|
|
|
type kv struct {
|
|
key string
|
|
value string
|
|
}
|
|
|
|
// truncate shortens a string to at most maxLen runes, appending "..." if truncated.
|
|
func truncate(s string, maxLen int) string {
|
|
if utf8.RuneCountInString(s) <= maxLen {
|
|
return s
|
|
}
|
|
if maxLen <= 3 {
|
|
return string([]rune(s)[:maxLen])
|
|
}
|
|
return string([]rune(s)[:maxLen-3]) + "..."
|
|
}
|
|
|
|
// boolStr returns "yes" or "no".
|
|
func boolStr(b bool) string {
|
|
if b {
|
|
return "yes"
|
|
}
|
|
return "no"
|
|
}
|