feat(tools): link thoughts and learnings
This commit is contained in:
@@ -0,0 +1,152 @@
|
||||
package tools
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/modelcontextprotocol/go-sdk/mcp"
|
||||
|
||||
"git.warky.dev/wdevs/amcs/internal/store"
|
||||
thoughttypes "git.warky.dev/wdevs/amcs/internal/types"
|
||||
)
|
||||
|
||||
type ThoughtLearningLinksTool struct {
|
||||
store *store.DB
|
||||
}
|
||||
|
||||
type LinkThoughtLearningInput struct {
|
||||
ThoughtID string `json:"thought_id" jsonschema:"UUID of the thought to link"`
|
||||
LearningID int64 `json:"learning_id" jsonschema:"numeric id of the learning to link"`
|
||||
Relation string `json:"relation,omitempty" jsonschema:"relationship label, e.g. source, derived_from, related; defaults to source"`
|
||||
}
|
||||
|
||||
type LinkThoughtLearningOutput struct {
|
||||
Linked bool `json:"linked"`
|
||||
}
|
||||
|
||||
type UnlinkThoughtLearningInput struct {
|
||||
ThoughtID string `json:"thought_id" jsonschema:"UUID of the thought"`
|
||||
LearningID int64 `json:"learning_id" jsonschema:"numeric id of the learning"`
|
||||
}
|
||||
|
||||
type UnlinkThoughtLearningOutput struct {
|
||||
Unlinked bool `json:"unlinked"`
|
||||
}
|
||||
|
||||
type GetThoughtLearningsInput struct {
|
||||
ThoughtID string `json:"thought_id" jsonschema:"UUID of the thought"`
|
||||
}
|
||||
|
||||
type GetThoughtLearningsOutput struct {
|
||||
Learnings []thoughttypes.LinkedLearning `json:"learnings"`
|
||||
}
|
||||
|
||||
type GetLearningThoughtsInput struct {
|
||||
LearningID int64 `json:"learning_id" jsonschema:"numeric id of the learning"`
|
||||
}
|
||||
|
||||
type GetLearningThoughtsOutput struct {
|
||||
Thoughts []thoughttypes.LinkedLearningThought `json:"thoughts"`
|
||||
}
|
||||
|
||||
func NewThoughtLearningLinksTool(db *store.DB) *ThoughtLearningLinksTool {
|
||||
return &ThoughtLearningLinksTool{store: db}
|
||||
}
|
||||
|
||||
func (t *ThoughtLearningLinksTool) Link(ctx context.Context, _ *mcp.CallToolRequest, in LinkThoughtLearningInput) (*mcp.CallToolResult, LinkThoughtLearningOutput, error) {
|
||||
if err := t.ensureConfigured(); err != nil {
|
||||
return nil, LinkThoughtLearningOutput{}, err
|
||||
}
|
||||
|
||||
thoughtGUID, err := parseUUID(in.ThoughtID)
|
||||
if err != nil {
|
||||
return nil, LinkThoughtLearningOutput{}, err
|
||||
}
|
||||
if in.LearningID <= 0 {
|
||||
return nil, LinkThoughtLearningOutput{}, errRequiredField("learning_id")
|
||||
}
|
||||
relation := strings.TrimSpace(in.Relation)
|
||||
if relation == "" {
|
||||
relation = "source"
|
||||
}
|
||||
|
||||
if _, err := t.store.GetThought(ctx, thoughtGUID); err != nil {
|
||||
return nil, LinkThoughtLearningOutput{}, errEntityNotFound("thought", "thought_id", in.ThoughtID)
|
||||
}
|
||||
if _, err := t.store.GetLearning(ctx, in.LearningID); err != nil {
|
||||
return nil, LinkThoughtLearningOutput{}, errEntityNotFound("learning", "learning_id", strconv.FormatInt(in.LearningID, 10))
|
||||
}
|
||||
|
||||
if err := t.store.LinkThoughtLearning(ctx, thoughtGUID, in.LearningID, relation); err != nil {
|
||||
return nil, LinkThoughtLearningOutput{}, err
|
||||
}
|
||||
return nil, LinkThoughtLearningOutput{Linked: true}, nil
|
||||
}
|
||||
|
||||
func (t *ThoughtLearningLinksTool) Unlink(ctx context.Context, _ *mcp.CallToolRequest, in UnlinkThoughtLearningInput) (*mcp.CallToolResult, UnlinkThoughtLearningOutput, error) {
|
||||
if err := t.ensureConfigured(); err != nil {
|
||||
return nil, UnlinkThoughtLearningOutput{}, err
|
||||
}
|
||||
|
||||
thoughtGUID, err := parseUUID(in.ThoughtID)
|
||||
if err != nil {
|
||||
return nil, UnlinkThoughtLearningOutput{}, err
|
||||
}
|
||||
if in.LearningID <= 0 {
|
||||
return nil, UnlinkThoughtLearningOutput{}, errRequiredField("learning_id")
|
||||
}
|
||||
|
||||
if err := t.store.UnlinkThoughtLearning(ctx, thoughtGUID, in.LearningID); err != nil {
|
||||
return nil, UnlinkThoughtLearningOutput{}, err
|
||||
}
|
||||
return nil, UnlinkThoughtLearningOutput{Unlinked: true}, nil
|
||||
}
|
||||
|
||||
func (t *ThoughtLearningLinksTool) GetThoughtLearnings(ctx context.Context, _ *mcp.CallToolRequest, in GetThoughtLearningsInput) (*mcp.CallToolResult, GetThoughtLearningsOutput, error) {
|
||||
if err := t.ensureConfigured(); err != nil {
|
||||
return nil, GetThoughtLearningsOutput{}, err
|
||||
}
|
||||
|
||||
thoughtGUID, err := parseUUID(in.ThoughtID)
|
||||
if err != nil {
|
||||
return nil, GetThoughtLearningsOutput{}, err
|
||||
}
|
||||
|
||||
if _, err := t.store.GetThought(ctx, thoughtGUID); err != nil {
|
||||
return nil, GetThoughtLearningsOutput{}, errEntityNotFound("thought", "thought_id", in.ThoughtID)
|
||||
}
|
||||
|
||||
learnings, err := t.store.GetLinkedLearnings(ctx, thoughtGUID)
|
||||
if err != nil {
|
||||
return nil, GetThoughtLearningsOutput{}, err
|
||||
}
|
||||
return nil, GetThoughtLearningsOutput{Learnings: learnings}, nil
|
||||
}
|
||||
|
||||
func (t *ThoughtLearningLinksTool) GetLearningThoughts(ctx context.Context, _ *mcp.CallToolRequest, in GetLearningThoughtsInput) (*mcp.CallToolResult, GetLearningThoughtsOutput, error) {
|
||||
if err := t.ensureConfigured(); err != nil {
|
||||
return nil, GetLearningThoughtsOutput{}, err
|
||||
}
|
||||
|
||||
if in.LearningID <= 0 {
|
||||
return nil, GetLearningThoughtsOutput{}, errRequiredField("learning_id")
|
||||
}
|
||||
|
||||
if _, err := t.store.GetLearning(ctx, in.LearningID); err != nil {
|
||||
return nil, GetLearningThoughtsOutput{}, errEntityNotFound("learning", "learning_id", strconv.FormatInt(in.LearningID, 10))
|
||||
}
|
||||
|
||||
thoughts, err := t.store.GetLinkedThoughtsForLearning(ctx, in.LearningID)
|
||||
if err != nil {
|
||||
return nil, GetLearningThoughtsOutput{}, err
|
||||
}
|
||||
return nil, GetLearningThoughtsOutput{Thoughts: thoughts}, nil
|
||||
}
|
||||
|
||||
func (t *ThoughtLearningLinksTool) ensureConfigured() error {
|
||||
if t == nil || t.store == nil {
|
||||
return errInvalidInput("thought learning links tool is not configured")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user