mirror of
https://github.com/memohai/Memoh.git
synced 2026-04-27 07:16:19 +09:00
feat(command): extend slash command system with new commands and UX improvements
Add 9 new command groups (/model, /memory, /search, /browser, /usage, /email, /heartbeat, /skill, /fs) and improve existing commands by hiding internal UUIDs, resolving IDs to human-readable names in /settings, and switching /schedule to name-based references.
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
stdpath "path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -34,6 +35,7 @@ import (
|
||||
"github.com/memohai/memoh/internal/channel/identities"
|
||||
"github.com/memohai/memoh/internal/channel/inbound"
|
||||
"github.com/memohai/memoh/internal/channel/route"
|
||||
"github.com/memohai/memoh/internal/command"
|
||||
"github.com/memohai/memoh/internal/config"
|
||||
ctr "github.com/memohai/memoh/internal/containerd"
|
||||
"github.com/memohai/memoh/internal/conversation"
|
||||
@@ -423,6 +425,21 @@ func provideChannelRouter(
|
||||
bindService *bind.Service,
|
||||
mediaService *media.Service,
|
||||
inboxService *inbox.Service,
|
||||
subagentService *subagent.Service,
|
||||
scheduleService *schedule.Service,
|
||||
settingsService *settings.Service,
|
||||
mcpConnService *mcp.ConnectionService,
|
||||
modelsService *models.Service,
|
||||
providersService *providers.Service,
|
||||
memProvService *memprovider.Service,
|
||||
searchProvService *searchproviders.Service,
|
||||
browserCtxService *browsercontexts.Service,
|
||||
emailService *emailpkg.Service,
|
||||
emailOutboxService *emailpkg.OutboxService,
|
||||
heartbeatService *heartbeat.Service,
|
||||
queries *dbsqlc.Queries,
|
||||
containerdHandler *handlers.ContainerdHandler,
|
||||
manager *mcp.Manager,
|
||||
rc *boot.RuntimeConfig,
|
||||
) *inbound.ChannelInboundProcessor {
|
||||
adapter, ok := registry.Get(qq.Type)
|
||||
@@ -440,6 +457,26 @@ func provideChannelRouter(
|
||||
processor.SetMediaService(mediaService)
|
||||
processor.SetStreamObserver(local.NewRouteHubBroadcaster(hub))
|
||||
processor.SetInboxService(inboxService)
|
||||
processor.SetCommandHandler(command.NewHandler(
|
||||
log,
|
||||
&command.BotMemberRoleAdapter{BotService: botService},
|
||||
subagentService,
|
||||
scheduleService,
|
||||
settingsService,
|
||||
mcpConnService,
|
||||
inboxService,
|
||||
modelsService,
|
||||
providersService,
|
||||
memProvService,
|
||||
searchProvService,
|
||||
browserCtxService,
|
||||
emailService,
|
||||
emailOutboxService,
|
||||
heartbeatService,
|
||||
queries,
|
||||
&commandSkillLoaderAdapter{handler: containerdHandler},
|
||||
&commandContainerFSAdapter{manager: manager},
|
||||
))
|
||||
return processor
|
||||
}
|
||||
|
||||
@@ -928,3 +965,54 @@ func (a *gatewayAssetLoaderAdapter) OpenForGateway(ctx context.Context, botID, c
|
||||
}
|
||||
return reader, strings.TrimSpace(asset.Mime), nil
|
||||
}
|
||||
|
||||
// commandSkillLoaderAdapter bridges handlers.ContainerdHandler to command.SkillLoader.
|
||||
type commandSkillLoaderAdapter struct {
|
||||
handler *handlers.ContainerdHandler
|
||||
}
|
||||
|
||||
func (a *commandSkillLoaderAdapter) LoadSkills(ctx context.Context, botID string) ([]command.Skill, error) {
|
||||
items, err := a.handler.LoadSkills(ctx, botID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
skills := make([]command.Skill, len(items))
|
||||
for i, item := range items {
|
||||
skills[i] = command.Skill{Name: item.Name, Description: item.Description}
|
||||
}
|
||||
return skills, nil
|
||||
}
|
||||
|
||||
// commandContainerFSAdapter bridges mcp.Manager to command.ContainerFS.
|
||||
type commandContainerFSAdapter struct {
|
||||
manager *mcp.Manager
|
||||
}
|
||||
|
||||
func (a *commandContainerFSAdapter) ListDir(ctx context.Context, botID, dirPath string) ([]command.FSEntry, error) {
|
||||
client, err := a.manager.MCPClient(ctx, botID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
entries, err := client.ListDir(ctx, dirPath, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
result := make([]command.FSEntry, len(entries))
|
||||
for i, e := range entries {
|
||||
name := stdpath.Base(e.GetPath())
|
||||
result[i] = command.FSEntry{Name: name, IsDir: e.GetIsDir(), Size: e.GetSize()}
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func (a *commandContainerFSAdapter) ReadFile(ctx context.Context, botID, filePath string) (string, error) {
|
||||
client, err := a.manager.MCPClient(ctx, botID)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
resp, err := client.ReadFile(ctx, filePath, 0, 0)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return resp.GetContent(), nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user