• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kshard / thinker / 24100701194

07 Apr 2026 07:37PM UTC coverage: 59.441% (-0.2%) from 59.626%
24100701194

push

github

web-flow
(fea) Update README and cosmetic fixes to APIs (#62)

* Update README
* Usability improvements on APIs 
* minor release [x.Y.z]

65 of 122 new or added lines in 5 files covered. (53.28%)

702 of 1181 relevant lines covered (59.44%)

0.65 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

77.14
/command/seq.go
1
//
2
// Copyright (C) 2025 - 2026Dmitry Kolesnikov
3
//
4
// This file may be modified and distributed under the terms
5
// of the MIT license.  See the LICENSE file for details.
6
// https://github.com/kshard/thinker
7
//
8

9
package command
10

11
import (
12
        "context"
13
        "encoding/json"
14
        "fmt"
15
        "strings"
16

17
        "github.com/kshard/chatter"
18
        "github.com/kshard/thinker"
19
        "github.com/modelcontextprotocol/go-sdk/mcp"
20
)
21

22
type SeqRegistry struct {
23
        regs []*Registry
24
        cmds chatter.Registry
25
}
26

27
var _ thinker.Registry = (*SeqRegistry)(nil)
28

29
func NewSeqRegistry() *SeqRegistry {
1✔
30
        return &SeqRegistry{
1✔
31
                regs: make([]*Registry, 0),
1✔
32
                cmds: chatter.Registry{},
1✔
33
        }
1✔
34
}
1✔
35

36
func (r *SeqRegistry) Bind(reg *Registry) {
1✔
37
        r.regs = append(r.regs, reg)
1✔
38
}
1✔
39

40
func (r *SeqRegistry) Context() chatter.Registry {
1✔
41
        if len(r.cmds) > 0 {
2✔
42
                return r.cmds
1✔
43
        }
1✔
44

45
        seq := make([]chatter.Cmd, 0)
1✔
46
        for _, reg := range r.regs {
2✔
47
                seq = append(seq, reg.Context()...)
1✔
48
        }
1✔
49

50
        r.cmds = seq
1✔
51
        return r.cmds
1✔
52
}
53

54
func (r *SeqRegistry) Invoke(reply *chatter.Reply) (phase thinker.Phase, msg chatter.Message, err error) {
1✔
55
        ctx := context.Background()
1✔
56
        answer, err := reply.Invoke(func(name string, args json.RawMessage) (json.RawMessage, error) {
2✔
57
                seq := strings.SplitN(name, kSchemaSplit, 2)
1✔
58
                if len(seq) != 2 {
2✔
59
                        return pack(
1✔
60
                                fmt.Appendf(nil, "invalid tool name %s, missing the prefix", name),
1✔
61
                        )
1✔
62
                }
1✔
63
                id, tool := seq[0], seq[1]
1✔
64

1✔
65
                var srv Server
1✔
66
                var exists bool
1✔
67
                for _, reg := range r.regs {
2✔
68
                        srv, exists = reg.servers[id]
1✔
69
                        if !exists {
2✔
70
                                continue
1✔
71
                        }
72
                }
73
                if !exists {
2✔
74
                        return pack(
1✔
75
                                fmt.Appendf(nil, "tool %s is not available in any attached MCP server", name),
1✔
76
                        )
1✔
77
                }
1✔
78

79
                // Unmarshal arguments to pass to MCP
80
                var arguments map[string]any
1✔
81
                if len(args) > 0 {
2✔
82
                        if err := json.Unmarshal(args, &arguments); err != nil {
1✔
NEW
83
                                return pack(
×
NEW
84
                                        fmt.Appendf(nil, "failed to parse arguments for tool %s: %v", name, err),
×
NEW
85
                                )
×
NEW
86
                        }
×
87
                }
88

89
                // Call the tool via MCP using the actual tool name (without prefix)
90
                result, err := srv.CallTool(ctx, &mcp.CallToolParams{
1✔
91
                        Name:      tool,
1✔
92
                        Arguments: arguments,
1✔
93
                })
1✔
94
                if err != nil {
1✔
NEW
95
                        return pack(
×
NEW
96
                                fmt.Appendf(nil, "the tool %s execution is failed: %s", name, err),
×
NEW
97
                        )
×
NEW
98
                }
×
99

100
                // Handle tool execution errors
101
                if result.IsError {
1✔
NEW
102
                        errorMsg := "tool execution failed"
×
NEW
103
                        if len(result.Content) > 0 {
×
NEW
104
                                if text, ok := result.Content[0].(*mcp.TextContent); ok {
×
NEW
105
                                        errorMsg = text.Text
×
NEW
106
                                }
×
107
                        }
NEW
108
                        return pack([]byte(errorMsg))
×
109
                }
110

111
                // Extract and pack the result
112
                output := extractContent(result)
1✔
113
                return pack(output)
1✔
114
        })
115

116
        if err != nil {
1✔
NEW
117
                return thinker.AGENT_ABORT, nil, err
×
NEW
118
        }
×
119

120
        return thinker.AGENT_ASK, &answer, nil
1✔
121
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc