From 6d28f27c1ea29adac18e4ff5db7dc3bceb82ab0d Mon Sep 17 00:00:00 2001 From: devproje Date: Wed, 19 Aug 2026 03:49:50 +0900 Subject: [PATCH] feat: run remote tools on the client --- README.md | 18 +- api/mininaru/v1/mininaru.proto | 41 + bot/discord/handlers/message.go | 17 +- cli/main.go | 10 +- cli/pair.go | 1 + cli/preference.go | 4 + cli/remote.go | 162 +++- cli/remote_test.go | 56 ++ cli/setup.go | 2 + cli/skill.go | 8 + config/client.go | 14 + config/client_test.go | 29 + docs/ARCHITECTURE.md | 30 +- modules/tools.go | 28 + modules/tools_test.go | 35 + rpc/gen/mininaru/v1/mininaru.pb.go | 1031 ++++++++++++++++++----- rpc/gen/mininaru/v1/mininaru_grpc.pb.go | 240 ++++-- rpc/pairing_test.go | 13 +- rpc/service.go | 110 ++- 19 files changed, 1565 insertions(+), 284 deletions(-) create mode 100644 cli/remote_test.go diff --git a/README.md b/README.md index e452aa8..29fad9a 100644 --- a/README.md +++ b/README.md @@ -708,19 +708,27 @@ mininaru pair naru.example.com:9090 \ ``` Successful pairing writes the server address to `client.json`, so ordinary -commands use it automatically. `--server` overrides that default: +commands use it automatically. Setup also records `mode: client`, which routes +chat, prompts, agent and skill reads, and session commands to that server. +`--server` overrides that default: ```sh mininaru mininaru -p 'summarise the current session' --session mininaru session list mininaru session usage +mininaru agent list +mininaru skill list +mininaru skill show mininaru --server naru.example.com:9090 ``` The TUI streams answer and reasoning deltas, tool progress, cancellation, and -dangerous-tool approval over one bidirectional RPC. Sessions, history, tool -logs, compaction, and token usage stay in the server's SQLite database. +dangerous-tool approval over one bidirectional RPC. The model and session stay +on the server, while tools are advertised and executed by the client. Builtin +tools therefore operate on the client machine and MCP tools come from the +client's `mcp.json`. Tool results and logs return to the server-owned session. +One-shot `-p` still refuses dangerous tools because it has no approval UI. Manage paired devices on the server host: @@ -842,6 +850,10 @@ Run `/pair code:` in Discord within 10 minutes. The paired Discord user becomes an admin. Admins can add regular users with `/user add`; users are scoped to that configured bot. +File, search, and shell tools approved through Discord are always rooted at the +server process user's home directory. They do not inherit the directory from +which `mininaru serve` happened to start. + The bot answers when an authorized user mentions it in a server channel, and answers every authorized message in a DM without requiring a mention. A mention from someone who is not paired is ignored without a reply, so an unauthorized diff --git a/api/mininaru/v1/mininaru.proto b/api/mininaru/v1/mininaru.proto index 338fbbe..dc555f3 100644 --- a/api/mininaru/v1/mininaru.proto +++ b/api/mininaru/v1/mininaru.proto @@ -11,6 +11,8 @@ service PairingService { service MininaruService { rpc ListAgents(ListAgentsRequest) returns (ListAgentsResponse); + rpc ListSkills(ListSkillsRequest) returns (ListSkillsResponse); + rpc GetSkill(GetSkillRequest) returns (Skill); rpc ListSessions(ListSessionsRequest) returns (ListSessionsResponse); rpc CreateSession(CreateSessionRequest) returns (Session); rpc GetSession(GetSessionRequest) returns (SessionDetail); @@ -114,6 +116,23 @@ message ListAgentsResponse { string default_agent_id = 2; } +message Skill { + string name = 1; + string description = 2; + string scope = 3; + string body = 4; +} + +message ListSkillsRequest {} + +message ListSkillsResponse { + repeated Skill skills = 1; +} + +message GetSkillRequest { + string name = 1; +} + message ListSessionsRequest { string agent = 1; } @@ -166,6 +185,20 @@ message ChatStart { string session_id = 1; string content = 2; string thinking = 3; + repeated ToolDefinition tools = 4; +} + +message ToolDefinition { + string name = 1; + string description = 2; + string parameters_json = 3; + string permission = 4; +} + +message ToolResult { + string request_id = 1; + string result = 2; + string error = 3; } message ApprovalDecision { @@ -185,6 +218,7 @@ message ChatClientEvent { ChatStart start = 1; ApprovalDecision approval = 2; Empty cancel = 3; + ToolResult tool_result = 4; } } @@ -212,6 +246,12 @@ message ApprovalRequest { string arguments = 3; } +message ToolRequest { + string request_id = 1; + string tool_name = 2; + string arguments = 3; +} + message ChatCompleted { Message message = 1; Usage usage = 2; @@ -231,5 +271,6 @@ message ChatServerEvent { ApprovalRequest approval = 5; ChatCompleted completed = 6; ChatFailed failed = 7; + ToolRequest tool_request = 8; } } diff --git a/bot/discord/handlers/message.go b/bot/discord/handlers/message.go index 99ca1b5..3846c8a 100644 --- a/bot/discord/handlers/message.go +++ b/bot/discord/handlers/message.go @@ -5,6 +5,7 @@ package handlers import ( "context" + "os" "strings" "sync" "unicode" @@ -245,6 +246,7 @@ func (d *Discord) answerFor(ctx context.Context, channelId, sourceChannelId, sou var defs []modules.Def var message *core.Message var replyTo string + var home string var err error @@ -292,7 +294,20 @@ func (d *Discord) answerFor(ctx context.Context, channelId, sourceChannelId, sou status.log("✗", "`"+label+"` — "+toolFailureReason(event.Error)) } if role == core.DiscordRoleAdmin { - defs = modules.DefaultTools() + home, err = os.UserHomeDir() + if err != nil { + indicator.stop() + status.finish("❌", "Failed") + d.sendReplyTo(channelId, replyTo, conversationFailure("resolving the tool workspace", err)) + return + } + defs, err = modules.DefaultToolsAt(home) + if err != nil { + indicator.stop() + status.finish("❌", "Failed") + d.sendReplyTo(channelId, replyTo, conversationFailure("opening the tool workspace", err)) + return + } message, err = target.ChatInput(ctx, session, content, parts, defs, onReasoning, onTool, func(ctx context.Context, def modules.Def, arguments string) (bool, error) { return d.approve(ctx, channelId, userId, def, arguments) diff --git a/cli/main.go b/cli/main.go index b9cb08b..3a1185e 100644 --- a/cli/main.go +++ b/cli/main.go @@ -265,12 +265,7 @@ func execute(cmd *cobra.Command, args []string) error { } } - if serverRef == "" { - serverRef = config.Client.Server.Address - } - if serverRef != "" { - return executeRemote(cmd.Context(), args, content) - } + serverRef = activeServerAddress() if config.Client.Tools.Enabled { err = withProgress(cmd.Context(), "connecting to mcp servers", func() error { @@ -280,6 +275,9 @@ func execute(cmd *cobra.Command, args []string) error { return err } } + if serverRef != "" { + return executeRemote(cmd.Context(), args, content) + } agent, err = resolveAgent() if err != nil { diff --git a/cli/pair.go b/cli/pair.go index 0c4796d..272218c 100644 --- a/cli/pair.go +++ b/cli/pair.go @@ -89,6 +89,7 @@ func pairWithServer(ctx context.Context, address, name, expected string) error { } config.Client.Server.Address = address + config.Client.Mode = config.ModeClient err = config.ClientSave() if err != nil { return err diff --git a/cli/preference.go b/cli/preference.go index 80ecd7b..a4974be 100644 --- a/cli/preference.go +++ b/cli/preference.go @@ -528,6 +528,10 @@ func agentListExecute(cmd *cobra.Command, args []string) error { var cur *core.NaruAgent var mark string + if activeServerAddress() != "" { + return remoteAgentListExecute(cmd.Context()) + } + all = core.AgentAll() if len(all) == 0 { uiEmpty("no agents yet, add one with `mininaru agent add`") diff --git a/cli/remote.go b/cli/remote.go index 326d8ac..64dfb17 100644 --- a/cli/remote.go +++ b/cli/remote.go @@ -5,6 +5,7 @@ package main import ( "context" + "encoding/json" "fmt" "io" "os" @@ -28,6 +29,9 @@ func activeServerAddress() string { if serverRef != "" { return serverRef } + if !config.RemoteClient() { + return "" + } return config.Client.Server.Address } @@ -45,6 +49,86 @@ func remoteConnect(ctx context.Context) (*grpc.ClientConn, mininaruv1.MininaruSe return connection, mininaruv1.NewMininaruServiceClient(connection), nil } +func remoteAgentListExecute(ctx context.Context) error { + var connection *grpc.ClientConn + var client mininaruv1.MininaruServiceClient + var response *mininaruv1.ListAgentsResponse + var agent *mininaruv1.Agent + var mark string + var rows *uiRows + + var err error + + connection, client, err = remoteConnect(ctx) + if err != nil { + return err + } + defer connection.Close() + response, err = client.ListAgents(ctx, &mininaruv1.ListAgentsRequest{}) + if err != nil { + return err + } + rows = uiTable("ID", "NAME", "MODEL", "PROVIDER", "") + for _, agent = range response.GetAgents() { + mark = "" + if agent.GetId() == response.GetDefaultAgentId() { + mark = "[global]" + } + rows.row(agent.GetId(), agent.GetName(), agent.GetModel(), agent.GetProvider(), mark) + } + rows.flush() + + return nil +} + +func remoteSkillListExecute(ctx context.Context) error { + var connection *grpc.ClientConn + var client mininaruv1.MininaruServiceClient + var response *mininaruv1.ListSkillsResponse + var skill *mininaruv1.Skill + var rows *uiRows + + var err error + + connection, client, err = remoteConnect(ctx) + if err != nil { + return err + } + defer connection.Close() + response, err = client.ListSkills(ctx, &mininaruv1.ListSkillsRequest{}) + if err != nil { + return err + } + rows = uiTable("NAME", "SCOPE", "DESCRIPTION") + for _, skill = range response.GetSkills() { + rows.row(skill.GetName(), skill.GetScope(), skill.GetDescription()) + } + rows.flush() + + return nil +} + +func remoteSkillShowExecute(ctx context.Context, name string) error { + var connection *grpc.ClientConn + var client mininaruv1.MininaruServiceClient + var skill *mininaruv1.Skill + + var err error + + connection, client, err = remoteConnect(ctx) + if err != nil { + return err + } + defer connection.Close() + skill, err = client.GetSkill(ctx, &mininaruv1.GetSkillRequest{Name: name}) + if err != nil { + return err + } + fmt.Println(skill.GetBody()) + + return nil +} + func coreMessage(message *mininaruv1.Message) *core.Message { if message == nil { return nil @@ -131,11 +215,65 @@ func remoteApproval(ctx context.Context, stream mininaruv1.MininaruService_ChatC RequestId: request.GetRequestId(), Choice: choice}}}) } +func remoteToolDefinitions(defs []modules.Def) ([]*mininaruv1.ToolDefinition, error) { + var def modules.Def + var raw []byte + var result []*mininaruv1.ToolDefinition + + var err error + + for _, def = range defs { + raw, err = json.Marshal(def.Parameters) + if err != nil { + return nil, err + } + result = append(result, &mininaruv1.ToolDefinition{Name: def.Name, Description: def.Description, + ParametersJson: string(raw), Permission: def.Permission.String()}) + } + + return result, nil +} + +func executeLocalTool(ctx context.Context, request *mininaruv1.ToolRequest, defs []modules.Def, + approve core.ToolApprovalFunc) (string, error) { + var def modules.Def + var allowed bool + + var err error + + for _, def = range defs { + if def.Name != request.GetToolName() { + continue + } + if def.Permission == modules.PermissionDangerous { + if approve == nil { + return "", fmt.Errorf("dangerous tool %q requires user approval", def.Name) + } + allowed, err = approve(ctx, def, request.GetArguments()) + if err != nil { + return "", err + } + if !allowed { + return "", fmt.Errorf("user denied dangerous tool %q", def.Name) + } + } + + return def.Execute(ctx, request.GetArguments()) + } + + return "", fmt.Errorf("unknown local tool %q", request.GetToolName()) +} + func (r *remoteBackend) Chat(ctx context.Context, session *core.Session, agent *core.NaruAgent, content string, onContent, onReasoning func(string), onTool core.ToolEventFunc, approve core.ToolApprovalFunc) (*core.Message, error) { var stream mininaruv1.MininaruService_ChatClient var event *mininaruv1.ChatServerEvent var failed *mininaruv1.ChatFailed + var defs []modules.Def + var advertised []*mininaruv1.ToolDefinition + var request *mininaruv1.ToolRequest + var result string + var resultError string var err error @@ -144,8 +282,16 @@ func (r *remoteBackend) Chat(ctx context.Context, session *core.Session, agent * return nil, err } + if config.Client.Tools.Enabled { + defs = modules.DefaultTools() + advertised, err = remoteToolDefinitions(defs) + if err != nil { + return nil, err + } + } + err = stream.Send(&mininaruv1.ChatClientEvent{Event: &mininaruv1.ChatClientEvent_Start{Start: &mininaruv1.ChatStart{ - SessionId: session.Id, Content: content, Thinking: config.Client.Thinking.Level}}}) + SessionId: session.Id, Content: content, Thinking: config.Client.Thinking.Level, Tools: advertised}}}) if err != nil { return nil, err } @@ -173,6 +319,20 @@ func (r *remoteBackend) Chat(ctx context.Context, session *core.Session, agent * return nil, err } } + request = event.GetToolRequest() + if request != nil { + result = "" + result, err = executeLocalTool(ctx, request, defs, approve) + resultError = "" + if err != nil { + resultError = err.Error() + } + err = stream.Send(&mininaruv1.ChatClientEvent{Event: &mininaruv1.ChatClientEvent_ToolResult{ToolResult: &mininaruv1.ToolResult{ + RequestId: request.GetRequestId(), Result: result, Error: resultError}}}) + if err != nil { + return nil, err + } + } if event.GetCompleted() != nil { return coreMessage(event.GetCompleted().GetMessage()), nil } diff --git a/cli/remote_test.go b/cli/remote_test.go new file mode 100644 index 0000000..4bbcb2d --- /dev/null +++ b/cli/remote_test.go @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: 2026 Wonhyeok Kim (Project_IO) +// SPDX-License-Identifier: GPL-3.0-or-later + +package main + +import ( + "context" + "testing" + + "github.com/devproje/mininaru/core" + "github.com/devproje/mininaru/modules" + mininaruv1 "github.com/devproje/mininaru/rpc/gen/mininaru/v1" +) + +func TestRemoteToolRunsOnTheClientAfterLocalApproval(t *testing.T) { + var executed bool + var approved bool + var defs []modules.Def + var result string + + var err error + + defs = []modules.Def{{Name: "local", Permission: modules.PermissionDangerous, + Execute: func(ctx context.Context, arguments string) (string, error) { + executed = true + return arguments, nil + }}} + result, err = executeLocalTool(context.Background(), &mininaruv1.ToolRequest{ToolName: "local", Arguments: "client-data"}, defs, + func(ctx context.Context, def modules.Def, arguments string) (bool, error) { + approved = true + return true, nil + }) + if err != nil { + t.Fatal(err) + } + if !approved || !executed || result != "client-data" { + t.Fatalf("approved=%t executed=%t result=%q", approved, executed, result) + } +} + +func TestRemoteToolRefusesDangerousWorkWithoutAnApprovalUI(t *testing.T) { + var executed bool + var defs []modules.Def + + var err error + + defs = []modules.Def{{Name: "local", Permission: modules.PermissionDangerous, + Execute: func(ctx context.Context, arguments string) (string, error) { + executed = true + return "", nil + }}} + _, err = executeLocalTool(context.Background(), &mininaruv1.ToolRequest{ToolName: "local"}, defs, core.ToolApprovalFunc(nil)) + if err == nil || executed { + t.Fatalf("err=%v executed=%t", err, executed) + } +} diff --git a/cli/setup.go b/cli/setup.go index ac767ec..480a95e 100644 --- a/cli/setup.go +++ b/cli/setup.go @@ -270,6 +270,8 @@ func setupServer(cmd *cobra.Command) error { var err error + config.Client.Mode = config.ModeServer + prov, err = setupProvider() if err != nil { return err diff --git a/cli/skill.go b/cli/skill.go index 6ccf3ae..40941cd 100644 --- a/cli/skill.go +++ b/cli/skill.go @@ -57,6 +57,10 @@ func skillListExecute(cmd *cobra.Command, args []string) error { var current modules.Skill var rows *uiRows + if activeServerAddress() != "" { + return remoteSkillListExecute(cmd.Context()) + } + all = modules.SkillAll() if len(all) == 0 { uiEmpty("no skills installed") @@ -80,6 +84,10 @@ func skillShowExecute(cmd *cobra.Command, args []string) error { var err error + if activeServerAddress() != "" { + return remoteSkillShowExecute(cmd.Context(), args[0]) + } + result, err = modules.SkillResult(args[0], "") if err != nil { return err diff --git a/config/client.go b/config/client.go index 28fc62a..d4ed636 100644 --- a/config/client.go +++ b/config/client.go @@ -33,6 +33,7 @@ type Server struct { } type ClientConfig struct { + Mode string `json:"mode,omitempty"` Thinking Thinking `json:"thinking"` Context Context `json:"context"` Tools Tools `json:"tools"` @@ -44,6 +45,11 @@ const CLIENT_PATH = "client.json" const NoUpdateCheckEnv = "MININARU_NO_UPDATE_CHECK" +const ( + ModeClient = "client" + ModeServer = "server" +) + const ( ThinkingOff = "off" ThinkingLow = "low" @@ -93,6 +99,14 @@ func UpdateCheckEnabled() bool { return Client.Update.Check } +func RemoteClient() bool { + if Client.Mode == ModeClient { + return true + } + + return Client.Mode == "" && Client.Server.Address != "" +} + func ClientInit() error { var path string var buf []byte diff --git a/config/client_test.go b/config/client_test.go index d08a857..2455dd0 100644 --- a/config/client_test.go +++ b/config/client_test.go @@ -72,3 +72,32 @@ func TestCompactionCanBeTurnedOffInConfig(t *testing.T) { t.Fatal("compact false in the config was not honoured") } } + +func TestClientModeUsesThePairedServer(t *testing.T) { + Client = defaultClient + Client.Mode = ModeClient + Client.Server.Address = "naru.example.com:9090" + + if !RemoteClient() { + t.Fatal("client mode did not use the paired server") + } +} + +func TestServerModeStaysLocalWithAStoredAddress(t *testing.T) { + Client = defaultClient + Client.Mode = ModeServer + Client.Server.Address = "naru.example.com:9090" + + if RemoteClient() { + t.Fatal("server mode used a stored client address") + } +} + +func TestLegacyPairedConfigStillUsesTheServer(t *testing.T) { + Client = defaultClient + Client.Server.Address = "naru.example.com:9090" + + if !RemoteClient() { + t.Fatal("legacy paired config stopped using the server") + } +} diff --git a/docs/ARCHITECTURE.md b/docs/ARCHITECTURE.md index 51c5a27..a61a457 100644 --- a/docs/ARCHITECTURE.md +++ b/docs/ARCHITECTURE.md @@ -547,6 +547,11 @@ this exists to remove comes straight back. The consequence is that allowing `bash_exec` for a session hands over arbitrary commands for that session, so the choice renders the tool name inside the label rather than saying "this tool". +Discord administrator turns root file, search, and shell tools at the server +process user's home directory. The root is captured in that turn's tool +definitions rather than changing the process working directory, so concurrent +gRPC clients and other front ends keep their own workspace. + The list lives on the `client` behind a `sync.Mutex` and never touches disk. The mutex is not decorative: the approval callback runs on the goroutine `sendPrompt` started, while `Update` runs on the bubbletea loop, and before this the two only @@ -740,15 +745,22 @@ delta followed by `data: [DONE]`. The native API in `api/mininaru/v1/mininaru.proto` is deliberately separate from the OpenAI-compatible HTTP surface. HTTP callers supply their whole history and receive only safe tools. A paired gRPC client names a server-owned -session and drives `Instance.ChatWithTools`, so it receives persisted history, -reasoning deltas, tool events, approval requests, compaction, and usage from the -same path as the local TUI. - -The `Chat` RPC is bidirectional. Its first client event must be `start`; later -client events answer a tool approval or cancel the turn. Server events carry -content, reasoning, tool progress, an approval request, and exactly one -terminal completion or failure. Losing the HTTP/2 stream cancels the core -context, so a disconnected client cannot leave a model turn running. +session and advertises the tool definitions discovered on that client. The +server drives `Instance.ChatWithTools`, but each execution request crosses the +stream and runs against the client's working directory and MCP sessions. The +result returns to the server for model continuation and persisted tool logs. + +The `Chat` RPC is bidirectional. Its first client event must be `start` and +carries the local tool schema; later events return a tool result or cancel the +turn. Server events carry content, reasoning, persisted tool progress, a local +tool execution request, and exactly one terminal completion or failure. The +TUI applies its approval menu before executing a dangerous local tool. `-p` +has no approval callback and refuses it. Losing the HTTP/2 stream cancels the +core context, so a disconnected client cannot leave a model turn running. + +Agent and skill list/show calls, plus session and usage calls, read server +state in client mode. Provider, MCP, bot, web, and TUI preference management +remain local; MCP configuration affects the tools advertised by that client. Pairing and normal RPCs share a TLS 1.3 listener but not an authorization policy. `PairingService` accepts a connection without a client certificate, diff --git a/modules/tools.go b/modules/tools.go index c427494..974be20 100644 --- a/modules/tools.go +++ b/modules/tools.go @@ -60,6 +60,34 @@ func DefaultTools() []Def { return tools } +func DefaultToolsAt(root string) ([]Def, error) { + var resolved string + var rooted []Def + var replacement map[string]Def + var tools []Def + var index int + + var err error + + resolved, err = toolRoot(root) + if err != nil { + return nil, err + } + rooted = []Def{FileRead(resolved), FileWrite(resolved), FileEdit(resolved), Glob(resolved), Grep(resolved), BashExec(resolved)} + replacement = make(map[string]Def) + for index = range rooted { + replacement[rooted[index].Name] = rooted[index] + } + tools = DefaultTools() + for index = range tools { + if replacement[tools[index].Name].Name != "" { + tools[index] = replacement[tools[index].Name] + } + } + + return tools, nil +} + func SafeTools() []Def { var def Def var tools []Def diff --git a/modules/tools_test.go b/modules/tools_test.go index 85c9693..f11056d 100644 --- a/modules/tools_test.go +++ b/modules/tools_test.go @@ -5,10 +5,45 @@ package modules import ( "context" + "os" "strings" "testing" ) +func TestDefaultToolsAtRootsFileAccessAtTheGivenDirectory(t *testing.T) { + var root string + var defs []Def + var def Def + var result string + + var err error + + root = t.TempDir() + err = os.WriteFile(root+"/inside.txt", []byte("home-root"), 0600) + if err != nil { + t.Fatal(err) + } + defs, err = DefaultToolsAt(root) + if err != nil { + t.Fatal(err) + } + for _, def = range defs { + if def.Name != "file_read" { + continue + } + result, err = def.Execute(context.Background(), `{"path":"inside.txt"}`) + if err != nil { + t.Fatal(err) + } + if !strings.Contains(result, "home-root") { + t.Fatalf("file_read result = %q", result) + } + return + } + + t.Fatal("file_read tool not found") +} + func TestCurrentTime(t *testing.T) { var result string diff --git a/rpc/gen/mininaru/v1/mininaru.pb.go b/rpc/gen/mininaru/v1/mininaru.pb.go index 1ff5034..33373eb 100644 --- a/rpc/gen/mininaru/v1/mininaru.pb.go +++ b/rpc/gen/mininaru/v1/mininaru.pb.go @@ -131,7 +131,8 @@ type Empty struct { func (x *Empty) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -149,7 +150,8 @@ func (*Empty) ProtoMessage() {} func (x *Empty) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -178,7 +180,8 @@ type BeginPairingRequest struct { func (x *BeginPairingRequest) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -196,7 +199,8 @@ func (*BeginPairingRequest) ProtoMessage() {} func (x *BeginPairingRequest) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -241,7 +245,8 @@ type BeginPairingResponse struct { func (x *BeginPairingResponse) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -259,7 +264,8 @@ func (*BeginPairingResponse) ProtoMessage() {} func (x *BeginPairingResponse) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -315,7 +321,8 @@ type WatchPairingRequest struct { func (x *WatchPairingRequest) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -333,7 +340,8 @@ func (*WatchPairingRequest) ProtoMessage() {} func (x *WatchPairingRequest) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -371,7 +379,8 @@ type PairingEvent struct { func (x *PairingEvent) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -389,7 +398,8 @@ func (*PairingEvent) ProtoMessage() {} func (x *PairingEvent) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -448,7 +458,8 @@ type Agent struct { func (x *Agent) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -466,7 +477,8 @@ func (*Agent) ProtoMessage() {} func (x *Agent) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -524,7 +536,8 @@ type Session struct { func (x *Session) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -542,7 +555,8 @@ func (*Session) ProtoMessage() {} func (x *Session) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -597,7 +611,8 @@ type Message struct { func (x *Message) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -615,7 +630,8 @@ func (*Message) ProtoMessage() {} func (x *Message) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -699,7 +715,8 @@ type ToolCall struct { func (x *ToolCall) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -717,7 +734,8 @@ func (*ToolCall) ProtoMessage() {} func (x *ToolCall) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -806,7 +824,8 @@ type UsageLine struct { func (x *UsageLine) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -824,7 +843,8 @@ func (*UsageLine) ProtoMessage() {} func (x *UsageLine) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -900,7 +920,8 @@ type Usage struct { func (x *Usage) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -918,7 +939,8 @@ func (*Usage) ProtoMessage() {} func (x *Usage) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -994,7 +1016,8 @@ type ListAgentsRequest struct { func (x *ListAgentsRequest) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -1012,7 +1035,8 @@ func (*ListAgentsRequest) ProtoMessage() {} func (x *ListAgentsRequest) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -1041,7 +1065,8 @@ type ListAgentsResponse struct { func (x *ListAgentsResponse) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -1059,7 +1084,8 @@ func (*ListAgentsResponse) ProtoMessage() {} func (x *ListAgentsResponse) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) @@ -1092,6 +1118,242 @@ func (x *ListAgentsResponse) GetDefaultAgentId() string { return "" } +type Skill struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + Scope string `protobuf:"bytes,3,opt,name=scope,proto3" json:"scope,omitempty"` + Body string `protobuf:"bytes,4,opt,name=body,proto3" json:"body,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *Skill) Reset() { + var ( + mi *protoimpl. + MessageInfo + ms messageState + ) + + *x = Skill{} + mi = &file_mininaru_v1_mininaru_proto_msgTypes[13] + ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *Skill) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Skill) ProtoMessage() {} + +func (x *Skill) ProtoReflect() protoreflect.Message { + var ( + mi *protoimpl. + MessageInfo + ms messageState + ) + + mi = &file_mininaru_v1_mininaru_proto_msgTypes[13] + if x != nil { + ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (*Skill) Descriptor() ([]byte, []int) { + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{13} +} + +func (x *Skill) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *Skill) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *Skill) GetScope() string { + if x != nil { + return x.Scope + } + return "" +} + +func (x *Skill) GetBody() string { + if x != nil { + return x.Body + } + return "" +} + +type ListSkillsRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListSkillsRequest) Reset() { + var ( + mi *protoimpl. + MessageInfo + ms messageState + ) + + *x = ListSkillsRequest{} + mi = &file_mininaru_v1_mininaru_proto_msgTypes[14] + ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListSkillsRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListSkillsRequest) ProtoMessage() {} + +func (x *ListSkillsRequest) ProtoReflect() protoreflect.Message { + var ( + mi *protoimpl. + MessageInfo + ms messageState + ) + + mi = &file_mininaru_v1_mininaru_proto_msgTypes[14] + if x != nil { + ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (*ListSkillsRequest) Descriptor() ([]byte, []int) { + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{14} +} + +type ListSkillsResponse struct { + state protoimpl.MessageState `protogen:"open.v1"` + Skills []*Skill `protobuf:"bytes,1,rep,name=skills,proto3" json:"skills,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ListSkillsResponse) Reset() { + var ( + mi *protoimpl. + MessageInfo + ms messageState + ) + + *x = ListSkillsResponse{} + mi = &file_mininaru_v1_mininaru_proto_msgTypes[15] + ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ListSkillsResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ListSkillsResponse) ProtoMessage() {} + +func (x *ListSkillsResponse) ProtoReflect() protoreflect.Message { + var ( + mi *protoimpl. + MessageInfo + ms messageState + ) + + mi = &file_mininaru_v1_mininaru_proto_msgTypes[15] + if x != nil { + ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (*ListSkillsResponse) Descriptor() ([]byte, []int) { + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{15} +} + +func (x *ListSkillsResponse) GetSkills() []*Skill { + if x != nil { + return x.Skills + } + return nil +} + +type GetSkillRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *GetSkillRequest) Reset() { + var ( + mi *protoimpl. + MessageInfo + ms messageState + ) + + *x = GetSkillRequest{} + mi = &file_mininaru_v1_mininaru_proto_msgTypes[16] + ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *GetSkillRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetSkillRequest) ProtoMessage() {} + +func (x *GetSkillRequest) ProtoReflect() protoreflect.Message { + var ( + mi *protoimpl. + MessageInfo + ms messageState + ) + + mi = &file_mininaru_v1_mininaru_proto_msgTypes[16] + if x != nil { + ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (*GetSkillRequest) Descriptor() ([]byte, []int) { + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{16} +} + +func (x *GetSkillRequest) GetName() string { + if x != nil { + return x.Name + } + return "" +} + type ListSessionsRequest struct { state protoimpl.MessageState `protogen:"open.v1"` Agent string `protobuf:"bytes,1,opt,name=agent,proto3" json:"agent,omitempty"` @@ -1101,12 +1363,13 @@ type ListSessionsRequest struct { func (x *ListSessionsRequest) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) *x = ListSessionsRequest{} - mi = &file_mininaru_v1_mininaru_proto_msgTypes[13] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[17] ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1119,11 +1382,12 @@ func (*ListSessionsRequest) ProtoMessage() {} func (x *ListSessionsRequest) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) - mi = &file_mininaru_v1_mininaru_proto_msgTypes[13] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[17] if x != nil { ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1135,7 +1399,7 @@ func (x *ListSessionsRequest) ProtoReflect() protoreflect.Message { } func (*ListSessionsRequest) Descriptor() ([]byte, []int) { - return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{13} + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{17} } func (x *ListSessionsRequest) GetAgent() string { @@ -1154,12 +1418,13 @@ type ListSessionsResponse struct { func (x *ListSessionsResponse) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) *x = ListSessionsResponse{} - mi = &file_mininaru_v1_mininaru_proto_msgTypes[14] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[18] ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1172,11 +1437,12 @@ func (*ListSessionsResponse) ProtoMessage() {} func (x *ListSessionsResponse) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) - mi = &file_mininaru_v1_mininaru_proto_msgTypes[14] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[18] if x != nil { ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1188,7 +1454,7 @@ func (x *ListSessionsResponse) ProtoReflect() protoreflect.Message { } func (*ListSessionsResponse) Descriptor() ([]byte, []int) { - return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{14} + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{18} } func (x *ListSessionsResponse) GetSessions() []*Session { @@ -1208,12 +1474,13 @@ type CreateSessionRequest struct { func (x *CreateSessionRequest) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) *x = CreateSessionRequest{} - mi = &file_mininaru_v1_mininaru_proto_msgTypes[15] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[19] ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1226,11 +1493,12 @@ func (*CreateSessionRequest) ProtoMessage() {} func (x *CreateSessionRequest) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) - mi = &file_mininaru_v1_mininaru_proto_msgTypes[15] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[19] if x != nil { ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1242,7 +1510,7 @@ func (x *CreateSessionRequest) ProtoReflect() protoreflect.Message { } func (*CreateSessionRequest) Descriptor() ([]byte, []int) { - return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{15} + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{19} } func (x *CreateSessionRequest) GetAgent() string { @@ -1268,12 +1536,13 @@ type GetSessionRequest struct { func (x *GetSessionRequest) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) *x = GetSessionRequest{} - mi = &file_mininaru_v1_mininaru_proto_msgTypes[16] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[20] ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1286,11 +1555,12 @@ func (*GetSessionRequest) ProtoMessage() {} func (x *GetSessionRequest) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) - mi = &file_mininaru_v1_mininaru_proto_msgTypes[16] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[20] if x != nil { ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1302,7 +1572,7 @@ func (x *GetSessionRequest) ProtoReflect() protoreflect.Message { } func (*GetSessionRequest) Descriptor() ([]byte, []int) { - return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{16} + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{20} } func (x *GetSessionRequest) GetSessionId() string { @@ -1327,12 +1597,13 @@ type SessionDetail struct { func (x *SessionDetail) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) *x = SessionDetail{} - mi = &file_mininaru_v1_mininaru_proto_msgTypes[17] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[21] ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1345,11 +1616,12 @@ func (*SessionDetail) ProtoMessage() {} func (x *SessionDetail) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) - mi = &file_mininaru_v1_mininaru_proto_msgTypes[17] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[21] if x != nil { ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1361,7 +1633,7 @@ func (x *SessionDetail) ProtoReflect() protoreflect.Message { } func (*SessionDetail) Descriptor() ([]byte, []int) { - return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{17} + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{21} } func (x *SessionDetail) GetSession() *Session { @@ -1423,12 +1695,13 @@ type RenameSessionRequest struct { func (x *RenameSessionRequest) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) *x = RenameSessionRequest{} - mi = &file_mininaru_v1_mininaru_proto_msgTypes[18] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[22] ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1441,11 +1714,12 @@ func (*RenameSessionRequest) ProtoMessage() {} func (x *RenameSessionRequest) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) - mi = &file_mininaru_v1_mininaru_proto_msgTypes[18] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[22] if x != nil { ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1457,7 +1731,7 @@ func (x *RenameSessionRequest) ProtoReflect() protoreflect.Message { } func (*RenameSessionRequest) Descriptor() ([]byte, []int) { - return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{18} + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{22} } func (x *RenameSessionRequest) GetSessionId() string { @@ -1483,12 +1757,13 @@ type DeleteSessionRequest struct { func (x *DeleteSessionRequest) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) *x = DeleteSessionRequest{} - mi = &file_mininaru_v1_mininaru_proto_msgTypes[19] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[23] ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1501,11 +1776,12 @@ func (*DeleteSessionRequest) ProtoMessage() {} func (x *DeleteSessionRequest) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) - mi = &file_mininaru_v1_mininaru_proto_msgTypes[19] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[23] if x != nil { ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1517,7 +1793,7 @@ func (x *DeleteSessionRequest) ProtoReflect() protoreflect.Message { } func (*DeleteSessionRequest) Descriptor() ([]byte, []int) { - return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{19} + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{23} } func (x *DeleteSessionRequest) GetSessionId() string { @@ -1536,12 +1812,13 @@ type GetUsageRequest struct { func (x *GetUsageRequest) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) *x = GetUsageRequest{} - mi = &file_mininaru_v1_mininaru_proto_msgTypes[20] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[24] ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1554,11 +1831,12 @@ func (*GetUsageRequest) ProtoMessage() {} func (x *GetUsageRequest) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) - mi = &file_mininaru_v1_mininaru_proto_msgTypes[20] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[24] if x != nil { ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1570,7 +1848,7 @@ func (x *GetUsageRequest) ProtoReflect() protoreflect.Message { } func (*GetUsageRequest) Descriptor() ([]byte, []int) { - return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{20} + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{24} } func (x *GetUsageRequest) GetSessionId() string { @@ -1589,12 +1867,13 @@ type CompactSessionRequest struct { func (x *CompactSessionRequest) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) *x = CompactSessionRequest{} - mi = &file_mininaru_v1_mininaru_proto_msgTypes[21] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[25] ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1607,11 +1886,12 @@ func (*CompactSessionRequest) ProtoMessage() {} func (x *CompactSessionRequest) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) - mi = &file_mininaru_v1_mininaru_proto_msgTypes[21] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[25] if x != nil { ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1623,7 +1903,7 @@ func (x *CompactSessionRequest) ProtoReflect() protoreflect.Message { } func (*CompactSessionRequest) Descriptor() ([]byte, []int) { - return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{21} + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{25} } func (x *CompactSessionRequest) GetSessionId() string { @@ -1642,12 +1922,13 @@ type CompactSessionResponse struct { func (x *CompactSessionResponse) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) *x = CompactSessionResponse{} - mi = &file_mininaru_v1_mininaru_proto_msgTypes[22] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[26] ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1660,11 +1941,12 @@ func (*CompactSessionResponse) ProtoMessage() {} func (x *CompactSessionResponse) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) - mi = &file_mininaru_v1_mininaru_proto_msgTypes[22] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[26] if x != nil { ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1676,7 +1958,7 @@ func (x *CompactSessionResponse) ProtoReflect() protoreflect.Message { } func (*CompactSessionResponse) Descriptor() ([]byte, []int) { - return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{22} + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{26} } func (x *CompactSessionResponse) GetCompacted() bool { @@ -1691,18 +1973,20 @@ type ChatStart struct { SessionId string `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` Content string `protobuf:"bytes,2,opt,name=content,proto3" json:"content,omitempty"` Thinking string `protobuf:"bytes,3,opt,name=thinking,proto3" json:"thinking,omitempty"` + Tools []*ToolDefinition `protobuf:"bytes,4,rep,name=tools,proto3" json:"tools,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } func (x *ChatStart) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) *x = ChatStart{} - mi = &file_mininaru_v1_mininaru_proto_msgTypes[23] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[27] ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1715,11 +1999,12 @@ func (*ChatStart) ProtoMessage() {} func (x *ChatStart) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) - mi = &file_mininaru_v1_mininaru_proto_msgTypes[23] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[27] if x != nil { ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1731,7 +2016,7 @@ func (x *ChatStart) ProtoReflect() protoreflect.Message { } func (*ChatStart) Descriptor() ([]byte, []int) { - return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{23} + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{27} } func (x *ChatStart) GetSessionId() string { @@ -1755,6 +2040,163 @@ func (x *ChatStart) GetThinking() string { return "" } +func (x *ChatStart) GetTools() []*ToolDefinition { + if x != nil { + return x.Tools + } + return nil +} + +type ToolDefinition struct { + state protoimpl.MessageState `protogen:"open.v1"` + Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"` + Description string `protobuf:"bytes,2,opt,name=description,proto3" json:"description,omitempty"` + ParametersJson string `protobuf:"bytes,3,opt,name=parameters_json,json=parametersJson,proto3" json:"parameters_json,omitempty"` + Permission string `protobuf:"bytes,4,opt,name=permission,proto3" json:"permission,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ToolDefinition) Reset() { + var ( + mi *protoimpl. + MessageInfo + ms messageState + ) + + *x = ToolDefinition{} + mi = &file_mininaru_v1_mininaru_proto_msgTypes[28] + ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ToolDefinition) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ToolDefinition) ProtoMessage() {} + +func (x *ToolDefinition) ProtoReflect() protoreflect.Message { + var ( + mi *protoimpl. + MessageInfo + ms messageState + ) + + mi = &file_mininaru_v1_mininaru_proto_msgTypes[28] + if x != nil { + ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (*ToolDefinition) Descriptor() ([]byte, []int) { + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{28} +} + +func (x *ToolDefinition) GetName() string { + if x != nil { + return x.Name + } + return "" +} + +func (x *ToolDefinition) GetDescription() string { + if x != nil { + return x.Description + } + return "" +} + +func (x *ToolDefinition) GetParametersJson() string { + if x != nil { + return x.ParametersJson + } + return "" +} + +func (x *ToolDefinition) GetPermission() string { + if x != nil { + return x.Permission + } + return "" +} + +type ToolResult struct { + state protoimpl.MessageState `protogen:"open.v1"` + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + Result string `protobuf:"bytes,2,opt,name=result,proto3" json:"result,omitempty"` + Error string `protobuf:"bytes,3,opt,name=error,proto3" json:"error,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ToolResult) Reset() { + var ( + mi *protoimpl. + MessageInfo + ms messageState + ) + + *x = ToolResult{} + mi = &file_mininaru_v1_mininaru_proto_msgTypes[29] + ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ToolResult) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ToolResult) ProtoMessage() {} + +func (x *ToolResult) ProtoReflect() protoreflect.Message { + var ( + mi *protoimpl. + MessageInfo + ms messageState + ) + + mi = &file_mininaru_v1_mininaru_proto_msgTypes[29] + if x != nil { + ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (*ToolResult) Descriptor() ([]byte, []int) { + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{29} +} + +func (x *ToolResult) GetRequestId() string { + if x != nil { + return x.RequestId + } + return "" +} + +func (x *ToolResult) GetResult() string { + if x != nil { + return x.Result + } + return "" +} + +func (x *ToolResult) GetError() string { + if x != nil { + return x.Error + } + return "" +} + type ApprovalDecision struct { state protoimpl.MessageState `protogen:"open.v1"` RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` @@ -1765,12 +2207,13 @@ type ApprovalDecision struct { func (x *ApprovalDecision) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) *x = ApprovalDecision{} - mi = &file_mininaru_v1_mininaru_proto_msgTypes[24] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[30] ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1783,11 +2226,12 @@ func (*ApprovalDecision) ProtoMessage() {} func (x *ApprovalDecision) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) - mi = &file_mininaru_v1_mininaru_proto_msgTypes[24] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[30] if x != nil { ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1799,7 +2243,7 @@ func (x *ApprovalDecision) ProtoReflect() protoreflect.Message { } func (*ApprovalDecision) Descriptor() ([]byte, []int) { - return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{24} + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{30} } func (x *ApprovalDecision) GetRequestId() string { @@ -1825,12 +2269,13 @@ type ChatClientEvent struct { func (x *ChatClientEvent) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) *x = ChatClientEvent{} - mi = &file_mininaru_v1_mininaru_proto_msgTypes[25] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[31] ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1843,11 +2288,12 @@ func (*ChatClientEvent) ProtoMessage() {} func (x *ChatClientEvent) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) - mi = &file_mininaru_v1_mininaru_proto_msgTypes[25] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[31] if x != nil { ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1859,7 +2305,7 @@ func (x *ChatClientEvent) ProtoReflect() protoreflect.Message { } func (*ChatClientEvent) Descriptor() ([]byte, []int) { - return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{25} + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{31} } func (x *ChatClientEvent) GetEvent() isChatClientEvent_Event { @@ -1911,6 +2357,20 @@ func (x *ChatClientEvent) GetCancel() *Empty { return nil } +func (x *ChatClientEvent) GetToolResult() *ToolResult { + var ( + xValue *ChatClientEvent_ToolResult + ok bool + ) + + if x != nil { + if xValue, ok = x.Event.(*ChatClientEvent_ToolResult); ok { + return xValue.ToolResult + } + } + return nil +} + type isChatClientEvent_Event interface { isChatClientEvent_Event() } @@ -1927,12 +2387,18 @@ type ChatClientEvent_Cancel struct { Cancel *Empty `protobuf:"bytes,3,opt,name=cancel,proto3,oneof"` } +type ChatClientEvent_ToolResult struct { + ToolResult *ToolResult `protobuf:"bytes,4,opt,name=tool_result,json=toolResult,proto3,oneof"` +} + func (*ChatClientEvent_Start) isChatClientEvent_Event() {} func (*ChatClientEvent_Approval) isChatClientEvent_Event() {} func (*ChatClientEvent_Cancel) isChatClientEvent_Event() {} +func (*ChatClientEvent_ToolResult) isChatClientEvent_Event() {} + type ChatStarted struct { state protoimpl.MessageState `protogen:"open.v1"` TurnId string `protobuf:"bytes,1,opt,name=turn_id,json=turnId,proto3" json:"turn_id,omitempty"` @@ -1942,12 +2408,13 @@ type ChatStarted struct { func (x *ChatStarted) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) *x = ChatStarted{} - mi = &file_mininaru_v1_mininaru_proto_msgTypes[26] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[32] ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1960,11 +2427,12 @@ func (*ChatStarted) ProtoMessage() {} func (x *ChatStarted) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) - mi = &file_mininaru_v1_mininaru_proto_msgTypes[26] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[32] if x != nil { ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1976,7 +2444,7 @@ func (x *ChatStarted) ProtoReflect() protoreflect.Message { } func (*ChatStarted) Descriptor() ([]byte, []int) { - return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{26} + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{32} } func (x *ChatStarted) GetTurnId() string { @@ -1995,12 +2463,13 @@ type TextDelta struct { func (x *TextDelta) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) *x = TextDelta{} - mi = &file_mininaru_v1_mininaru_proto_msgTypes[27] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[33] ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2013,11 +2482,12 @@ func (*TextDelta) ProtoMessage() {} func (x *TextDelta) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) - mi = &file_mininaru_v1_mininaru_proto_msgTypes[27] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[33] if x != nil { ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2029,7 +2499,7 @@ func (x *TextDelta) ProtoReflect() protoreflect.Message { } func (*TextDelta) Descriptor() ([]byte, []int) { - return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{27} + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{33} } func (x *TextDelta) GetText() string { @@ -2054,12 +2524,13 @@ type ToolEvent struct { func (x *ToolEvent) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) *x = ToolEvent{} - mi = &file_mininaru_v1_mininaru_proto_msgTypes[28] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[34] ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2072,11 +2543,12 @@ func (*ToolEvent) ProtoMessage() {} func (x *ToolEvent) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) - mi = &file_mininaru_v1_mininaru_proto_msgTypes[28] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[34] if x != nil { ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2088,7 +2560,7 @@ func (x *ToolEvent) ProtoReflect() protoreflect.Message { } func (*ToolEvent) Descriptor() ([]byte, []int) { - return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{28} + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{34} } func (x *ToolEvent) GetPhase() string { @@ -2151,12 +2623,13 @@ type ApprovalRequest struct { func (x *ApprovalRequest) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) *x = ApprovalRequest{} - mi = &file_mininaru_v1_mininaru_proto_msgTypes[29] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[35] ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2169,11 +2642,12 @@ func (*ApprovalRequest) ProtoMessage() {} func (x *ApprovalRequest) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) - mi = &file_mininaru_v1_mininaru_proto_msgTypes[29] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[35] if x != nil { ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2185,7 +2659,7 @@ func (x *ApprovalRequest) ProtoReflect() protoreflect.Message { } func (*ApprovalRequest) Descriptor() ([]byte, []int) { - return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{29} + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{35} } func (x *ApprovalRequest) GetRequestId() string { @@ -2209,6 +2683,77 @@ func (x *ApprovalRequest) GetArguments() string { return "" } +type ToolRequest struct { + state protoimpl.MessageState `protogen:"open.v1"` + RequestId string `protobuf:"bytes,1,opt,name=request_id,json=requestId,proto3" json:"request_id,omitempty"` + ToolName string `protobuf:"bytes,2,opt,name=tool_name,json=toolName,proto3" json:"tool_name,omitempty"` + Arguments string `protobuf:"bytes,3,opt,name=arguments,proto3" json:"arguments,omitempty"` + unknownFields protoimpl.UnknownFields + sizeCache protoimpl.SizeCache +} + +func (x *ToolRequest) Reset() { + var ( + mi *protoimpl. + MessageInfo + ms messageState + ) + + *x = ToolRequest{} + mi = &file_mininaru_v1_mininaru_proto_msgTypes[36] + ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *ToolRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ToolRequest) ProtoMessage() {} + +func (x *ToolRequest) ProtoReflect() protoreflect.Message { + var ( + mi *protoimpl. + MessageInfo + ms messageState + ) + + mi = &file_mininaru_v1_mininaru_proto_msgTypes[36] + if x != nil { + ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +func (*ToolRequest) Descriptor() ([]byte, []int) { + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{36} +} + +func (x *ToolRequest) GetRequestId() string { + if x != nil { + return x.RequestId + } + return "" +} + +func (x *ToolRequest) GetToolName() string { + if x != nil { + return x.ToolName + } + return "" +} + +func (x *ToolRequest) GetArguments() string { + if x != nil { + return x.Arguments + } + return "" +} + type ChatCompleted struct { state protoimpl.MessageState `protogen:"open.v1"` Message *Message `protobuf:"bytes,1,opt,name=message,proto3" json:"message,omitempty"` @@ -2219,12 +2764,13 @@ type ChatCompleted struct { func (x *ChatCompleted) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) *x = ChatCompleted{} - mi = &file_mininaru_v1_mininaru_proto_msgTypes[30] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[37] ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2237,11 +2783,12 @@ func (*ChatCompleted) ProtoMessage() {} func (x *ChatCompleted) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) - mi = &file_mininaru_v1_mininaru_proto_msgTypes[30] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[37] if x != nil { ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2253,7 +2800,7 @@ func (x *ChatCompleted) ProtoReflect() protoreflect.Message { } func (*ChatCompleted) Descriptor() ([]byte, []int) { - return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{30} + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{37} } func (x *ChatCompleted) GetMessage() *Message { @@ -2280,12 +2827,13 @@ type ChatFailed struct { func (x *ChatFailed) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) *x = ChatFailed{} - mi = &file_mininaru_v1_mininaru_proto_msgTypes[31] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[38] ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2298,11 +2846,12 @@ func (*ChatFailed) ProtoMessage() {} func (x *ChatFailed) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) - mi = &file_mininaru_v1_mininaru_proto_msgTypes[31] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[38] if x != nil { ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2314,7 +2863,7 @@ func (x *ChatFailed) ProtoReflect() protoreflect.Message { } func (*ChatFailed) Descriptor() ([]byte, []int) { - return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{31} + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{38} } func (x *ChatFailed) GetCode() string { @@ -2340,12 +2889,13 @@ type ChatServerEvent struct { func (x *ChatServerEvent) Reset() { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) *x = ChatServerEvent{} - mi = &file_mininaru_v1_mininaru_proto_msgTypes[32] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[39] ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2358,11 +2908,12 @@ func (*ChatServerEvent) ProtoMessage() {} func (x *ChatServerEvent) ProtoReflect() protoreflect.Message { var ( - mi *protoimpl.MessageInfo + mi *protoimpl. + MessageInfo ms messageState ) - mi = &file_mininaru_v1_mininaru_proto_msgTypes[32] + mi = &file_mininaru_v1_mininaru_proto_msgTypes[39] if x != nil { ms = protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2374,7 +2925,7 @@ func (x *ChatServerEvent) ProtoReflect() protoreflect.Message { } func (*ChatServerEvent) Descriptor() ([]byte, []int) { - return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{32} + return file_mininaru_v1_mininaru_proto_rawDescGZIP(), []int{39} } func (x *ChatServerEvent) GetEvent() isChatServerEvent_Event { @@ -2482,6 +3033,20 @@ func (x *ChatServerEvent) GetFailed() *ChatFailed { return nil } +func (x *ChatServerEvent) GetToolRequest() *ToolRequest { + var ( + xValue *ChatServerEvent_ToolRequest + ok bool + ) + + if x != nil { + if xValue, ok = x.Event.(*ChatServerEvent_ToolRequest); ok { + return xValue.ToolRequest + } + } + return nil +} + type isChatServerEvent_Event interface { isChatServerEvent_Event() } @@ -2514,6 +3079,10 @@ type ChatServerEvent_Failed struct { Failed *ChatFailed `protobuf:"bytes,7,opt,name=failed,proto3,oneof"` } +type ChatServerEvent_ToolRequest struct { + ToolRequest *ToolRequest `protobuf:"bytes,8,opt,name=tool_request,json=toolRequest,proto3,oneof"` +} + func (*ChatServerEvent_Started) isChatServerEvent_Event() {} func (*ChatServerEvent_Content) isChatServerEvent_Event() {} @@ -2528,6 +3097,8 @@ func (*ChatServerEvent_Completed) isChatServerEvent_Event() {} func (*ChatServerEvent_Failed) isChatServerEvent_Event() {} +func (*ChatServerEvent_ToolRequest) isChatServerEvent_Event() {} + var File_mininaru_v1_mininaru_proto protoreflect.FileDescriptor const file_mininaru_v1_mininaru_proto_rawDesc = "" + @@ -2600,7 +3171,17 @@ const file_mininaru_v1_mininaru_proto_rawDesc = "" + "\x11ListAgentsRequest\"j\n" + "\x12ListAgentsResponse\x12*\n" + "\x06agents\x18\x01 \x03(\v2\x12.mininaru.v1.AgentR\x06agents\x12(\n" + - "\x10default_agent_id\x18\x02 \x01(\tR\x0edefaultAgentId\"+\n" + + "\x10default_agent_id\x18\x02 \x01(\tR\x0edefaultAgentId\"g\n" + + "\x05Skill\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12 \n" + + "\vdescription\x18\x02 \x01(\tR\vdescription\x12\x14\n" + + "\x05scope\x18\x03 \x01(\tR\x05scope\x12\x12\n" + + "\x04body\x18\x04 \x01(\tR\x04body\"\x13\n" + + "\x11ListSkillsRequest\"@\n" + + "\x12ListSkillsResponse\x12*\n" + + "\x06skills\x18\x01 \x03(\v2\x12.mininaru.v1.SkillR\x06skills\"%\n" + + "\x0fGetSkillRequest\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\"+\n" + "\x13ListSessionsRequest\x12\x14\n" + "\x05agent\x18\x01 \x01(\tR\x05agent\"H\n" + "\x14ListSessionsResponse\x120\n" + @@ -2634,20 +3215,36 @@ const file_mininaru_v1_mininaru_proto_rawDesc = "" + "\n" + "session_id\x18\x01 \x01(\tR\tsessionId\"6\n" + "\x16CompactSessionResponse\x12\x1c\n" + - "\tcompacted\x18\x01 \x01(\bR\tcompacted\"`\n" + + "\tcompacted\x18\x01 \x01(\bR\tcompacted\"\x93\x01\n" + "\tChatStart\x12\x1d\n" + "\n" + "session_id\x18\x01 \x01(\tR\tsessionId\x12\x18\n" + "\acontent\x18\x02 \x01(\tR\acontent\x12\x1a\n" + - "\bthinking\x18\x03 \x01(\tR\bthinking\"f\n" + + "\bthinking\x18\x03 \x01(\tR\bthinking\x121\n" + + "\x05tools\x18\x04 \x03(\v2\x1b.mininaru.v1.ToolDefinitionR\x05tools\"\x8f\x01\n" + + "\x0eToolDefinition\x12\x12\n" + + "\x04name\x18\x01 \x01(\tR\x04name\x12 \n" + + "\vdescription\x18\x02 \x01(\tR\vdescription\x12'\n" + + "\x0fparameters_json\x18\x03 \x01(\tR\x0eparametersJson\x12\x1e\n" + + "\n" + + "permission\x18\x04 \x01(\tR\n" + + "permission\"Y\n" + + "\n" + + "ToolResult\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x16\n" + + "\x06result\x18\x02 \x01(\tR\x06result\x12\x14\n" + + "\x05error\x18\x03 \x01(\tR\x05error\"f\n" + "\x10ApprovalDecision\x12\x1d\n" + "\n" + "request_id\x18\x01 \x01(\tR\trequestId\x123\n" + - "\x06choice\x18\x02 \x01(\x0e2\x1b.mininaru.v1.ApprovalChoiceR\x06choice\"\xb5\x01\n" + + "\x06choice\x18\x02 \x01(\x0e2\x1b.mininaru.v1.ApprovalChoiceR\x06choice\"\xf1\x01\n" + "\x0fChatClientEvent\x12.\n" + "\x05start\x18\x01 \x01(\v2\x16.mininaru.v1.ChatStartH\x00R\x05start\x12;\n" + "\bapproval\x18\x02 \x01(\v2\x1d.mininaru.v1.ApprovalDecisionH\x00R\bapproval\x12,\n" + - "\x06cancel\x18\x03 \x01(\v2\x12.mininaru.v1.EmptyH\x00R\x06cancelB\a\n" + + "\x06cancel\x18\x03 \x01(\v2\x12.mininaru.v1.EmptyH\x00R\x06cancel\x12:\n" + + "\vtool_result\x18\x04 \x01(\v2\x17.mininaru.v1.ToolResultH\x00R\n" + + "toolResultB\a\n" + "\x05event\"&\n" + "\vChatStarted\x12\x17\n" + "\aturn_id\x18\x01 \x01(\tR\x06turnId\"\x1f\n" + @@ -2665,6 +3262,11 @@ const file_mininaru_v1_mininaru_proto_rawDesc = "" + "\n" + "request_id\x18\x01 \x01(\tR\trequestId\x12\x1b\n" + "\ttool_name\x18\x02 \x01(\tR\btoolName\x12\x1c\n" + + "\targuments\x18\x03 \x01(\tR\targuments\"g\n" + + "\vToolRequest\x12\x1d\n" + + "\n" + + "request_id\x18\x01 \x01(\tR\trequestId\x12\x1b\n" + + "\ttool_name\x18\x02 \x01(\tR\btoolName\x12\x1c\n" + "\targuments\x18\x03 \x01(\tR\targuments\"i\n" + "\rChatCompleted\x12.\n" + "\amessage\x18\x01 \x01(\v2\x14.mininaru.v1.MessageR\amessage\x12(\n" + @@ -2672,7 +3274,7 @@ const file_mininaru_v1_mininaru_proto_rawDesc = "" + "\n" + "ChatFailed\x12\x12\n" + "\x04code\x18\x01 \x01(\tR\x04code\x12\x18\n" + - "\amessage\x18\x02 \x01(\tR\amessage\"\x95\x03\n" + + "\amessage\x18\x02 \x01(\tR\amessage\"\xd4\x03\n" + "\x0fChatServerEvent\x124\n" + "\astarted\x18\x01 \x01(\v2\x18.mininaru.v1.ChatStartedH\x00R\astarted\x122\n" + "\acontent\x18\x02 \x01(\v2\x16.mininaru.v1.TextDeltaH\x00R\acontent\x126\n" + @@ -2680,7 +3282,8 @@ const file_mininaru_v1_mininaru_proto_rawDesc = "" + "\x04tool\x18\x04 \x01(\v2\x16.mininaru.v1.ToolEventH\x00R\x04tool\x12:\n" + "\bapproval\x18\x05 \x01(\v2\x1c.mininaru.v1.ApprovalRequestH\x00R\bapproval\x12:\n" + "\tcompleted\x18\x06 \x01(\v2\x1a.mininaru.v1.ChatCompletedH\x00R\tcompleted\x121\n" + - "\x06failed\x18\a \x01(\v2\x17.mininaru.v1.ChatFailedH\x00R\x06failedB\a\n" + + "\x06failed\x18\a \x01(\v2\x17.mininaru.v1.ChatFailedH\x00R\x06failed\x12=\n" + + "\ftool_request\x18\b \x01(\v2\x18.mininaru.v1.ToolRequestH\x00R\vtoolRequestB\a\n" + "\x05event*\x99\x01\n" + "\fPairingState\x12\x1d\n" + "\x19PAIRING_STATE_UNSPECIFIED\x10\x00\x12\x19\n" + @@ -2695,10 +3298,13 @@ const file_mininaru_v1_mininaru_proto_rawDesc = "" + "\x17APPROVAL_CHOICE_SESSION\x10\x032\xa6\x01\n" + "\x0ePairingService\x12L\n" + "\x05Begin\x12 .mininaru.v1.BeginPairingRequest\x1a!.mininaru.v1.BeginPairingResponse\x12F\n" + - "\x05Watch\x12 .mininaru.v1.WatchPairingRequest\x1a\x19.mininaru.v1.PairingEvent0\x012\xbc\x05\n" + + "\x05Watch\x12 .mininaru.v1.WatchPairingRequest\x1a\x19.mininaru.v1.PairingEvent0\x012\xc9\x06\n" + "\x0fMininaruService\x12M\n" + "\n" + - "ListAgents\x12\x1e.mininaru.v1.ListAgentsRequest\x1a\x1f.mininaru.v1.ListAgentsResponse\x12S\n" + + "ListAgents\x12\x1e.mininaru.v1.ListAgentsRequest\x1a\x1f.mininaru.v1.ListAgentsResponse\x12M\n" + + "\n" + + "ListSkills\x12\x1e.mininaru.v1.ListSkillsRequest\x1a\x1f.mininaru.v1.ListSkillsResponse\x12<\n" + + "\bGetSkill\x12\x1c.mininaru.v1.GetSkillRequest\x1a\x12.mininaru.v1.Skill\x12S\n" + "\fListSessions\x12 .mininaru.v1.ListSessionsRequest\x1a!.mininaru.v1.ListSessionsResponse\x12H\n" + "\rCreateSession\x12!.mininaru.v1.CreateSessionRequest\x1a\x14.mininaru.v1.Session\x12H\n" + "\n" + @@ -2722,7 +3328,7 @@ func file_mininaru_v1_mininaru_proto_rawDescGZIP() []byte { } var file_mininaru_v1_mininaru_proto_enumTypes = make([]protoimpl.EnumInfo, 2) -var file_mininaru_v1_mininaru_proto_msgTypes = make([]protoimpl.MessageInfo, 33) +var file_mininaru_v1_mininaru_proto_msgTypes = make([]protoimpl.MessageInfo, 40) var file_mininaru_v1_mininaru_proto_goTypes = []any{ (PairingState)(0), // 0: mininaru.v1.PairingState (ApprovalChoice)(0), // 1: mininaru.v1.ApprovalChoice @@ -2739,76 +3345,91 @@ var file_mininaru_v1_mininaru_proto_goTypes = []any{ (*Usage)(nil), // 12: mininaru.v1.Usage (*ListAgentsRequest)(nil), // 13: mininaru.v1.ListAgentsRequest (*ListAgentsResponse)(nil), // 14: mininaru.v1.ListAgentsResponse - (*ListSessionsRequest)(nil), // 15: mininaru.v1.ListSessionsRequest - (*ListSessionsResponse)(nil), // 16: mininaru.v1.ListSessionsResponse - (*CreateSessionRequest)(nil), // 17: mininaru.v1.CreateSessionRequest - (*GetSessionRequest)(nil), // 18: mininaru.v1.GetSessionRequest - (*SessionDetail)(nil), // 19: mininaru.v1.SessionDetail - (*RenameSessionRequest)(nil), // 20: mininaru.v1.RenameSessionRequest - (*DeleteSessionRequest)(nil), // 21: mininaru.v1.DeleteSessionRequest - (*GetUsageRequest)(nil), // 22: mininaru.v1.GetUsageRequest - (*CompactSessionRequest)(nil), // 23: mininaru.v1.CompactSessionRequest - (*CompactSessionResponse)(nil), // 24: mininaru.v1.CompactSessionResponse - (*ChatStart)(nil), // 25: mininaru.v1.ChatStart - (*ApprovalDecision)(nil), // 26: mininaru.v1.ApprovalDecision - (*ChatClientEvent)(nil), // 27: mininaru.v1.ChatClientEvent - (*ChatStarted)(nil), // 28: mininaru.v1.ChatStarted - (*TextDelta)(nil), // 29: mininaru.v1.TextDelta - (*ToolEvent)(nil), // 30: mininaru.v1.ToolEvent - (*ApprovalRequest)(nil), // 31: mininaru.v1.ApprovalRequest - (*ChatCompleted)(nil), // 32: mininaru.v1.ChatCompleted - (*ChatFailed)(nil), // 33: mininaru.v1.ChatFailed - (*ChatServerEvent)(nil), // 34: mininaru.v1.ChatServerEvent + (*Skill)(nil), // 15: mininaru.v1.Skill + (*ListSkillsRequest)(nil), // 16: mininaru.v1.ListSkillsRequest + (*ListSkillsResponse)(nil), // 17: mininaru.v1.ListSkillsResponse + (*GetSkillRequest)(nil), // 18: mininaru.v1.GetSkillRequest + (*ListSessionsRequest)(nil), // 19: mininaru.v1.ListSessionsRequest + (*ListSessionsResponse)(nil), // 20: mininaru.v1.ListSessionsResponse + (*CreateSessionRequest)(nil), // 21: mininaru.v1.CreateSessionRequest + (*GetSessionRequest)(nil), // 22: mininaru.v1.GetSessionRequest + (*SessionDetail)(nil), // 23: mininaru.v1.SessionDetail + (*RenameSessionRequest)(nil), // 24: mininaru.v1.RenameSessionRequest + (*DeleteSessionRequest)(nil), // 25: mininaru.v1.DeleteSessionRequest + (*GetUsageRequest)(nil), // 26: mininaru.v1.GetUsageRequest + (*CompactSessionRequest)(nil), // 27: mininaru.v1.CompactSessionRequest + (*CompactSessionResponse)(nil), // 28: mininaru.v1.CompactSessionResponse + (*ChatStart)(nil), // 29: mininaru.v1.ChatStart + (*ToolDefinition)(nil), // 30: mininaru.v1.ToolDefinition + (*ToolResult)(nil), // 31: mininaru.v1.ToolResult + (*ApprovalDecision)(nil), // 32: mininaru.v1.ApprovalDecision + (*ChatClientEvent)(nil), // 33: mininaru.v1.ChatClientEvent + (*ChatStarted)(nil), // 34: mininaru.v1.ChatStarted + (*TextDelta)(nil), // 35: mininaru.v1.TextDelta + (*ToolEvent)(nil), // 36: mininaru.v1.ToolEvent + (*ApprovalRequest)(nil), // 37: mininaru.v1.ApprovalRequest + (*ToolRequest)(nil), // 38: mininaru.v1.ToolRequest + (*ChatCompleted)(nil), // 39: mininaru.v1.ChatCompleted + (*ChatFailed)(nil), // 40: mininaru.v1.ChatFailed + (*ChatServerEvent)(nil), // 41: mininaru.v1.ChatServerEvent } var file_mininaru_v1_mininaru_proto_depIdxs = []int32{ 0, // 0: mininaru.v1.PairingEvent.state:type_name -> mininaru.v1.PairingState 11, // 1: mininaru.v1.Usage.lines:type_name -> mininaru.v1.UsageLine 7, // 2: mininaru.v1.ListAgentsResponse.agents:type_name -> mininaru.v1.Agent - 8, // 3: mininaru.v1.ListSessionsResponse.sessions:type_name -> mininaru.v1.Session - 8, // 4: mininaru.v1.SessionDetail.session:type_name -> mininaru.v1.Session - 7, // 5: mininaru.v1.SessionDetail.agent:type_name -> mininaru.v1.Agent - 9, // 6: mininaru.v1.SessionDetail.messages:type_name -> mininaru.v1.Message - 10, // 7: mininaru.v1.SessionDetail.tool_calls:type_name -> mininaru.v1.ToolCall - 1, // 8: mininaru.v1.ApprovalDecision.choice:type_name -> mininaru.v1.ApprovalChoice - 25, // 9: mininaru.v1.ChatClientEvent.start:type_name -> mininaru.v1.ChatStart - 26, // 10: mininaru.v1.ChatClientEvent.approval:type_name -> mininaru.v1.ApprovalDecision - 2, // 11: mininaru.v1.ChatClientEvent.cancel:type_name -> mininaru.v1.Empty - 9, // 12: mininaru.v1.ChatCompleted.message:type_name -> mininaru.v1.Message - 12, // 13: mininaru.v1.ChatCompleted.usage:type_name -> mininaru.v1.Usage - 28, // 14: mininaru.v1.ChatServerEvent.started:type_name -> mininaru.v1.ChatStarted - 29, // 15: mininaru.v1.ChatServerEvent.content:type_name -> mininaru.v1.TextDelta - 29, // 16: mininaru.v1.ChatServerEvent.reasoning:type_name -> mininaru.v1.TextDelta - 30, // 17: mininaru.v1.ChatServerEvent.tool:type_name -> mininaru.v1.ToolEvent - 31, // 18: mininaru.v1.ChatServerEvent.approval:type_name -> mininaru.v1.ApprovalRequest - 32, // 19: mininaru.v1.ChatServerEvent.completed:type_name -> mininaru.v1.ChatCompleted - 33, // 20: mininaru.v1.ChatServerEvent.failed:type_name -> mininaru.v1.ChatFailed - 3, // 21: mininaru.v1.PairingService.Begin:input_type -> mininaru.v1.BeginPairingRequest - 5, // 22: mininaru.v1.PairingService.Watch:input_type -> mininaru.v1.WatchPairingRequest - 13, // 23: mininaru.v1.MininaruService.ListAgents:input_type -> mininaru.v1.ListAgentsRequest - 15, // 24: mininaru.v1.MininaruService.ListSessions:input_type -> mininaru.v1.ListSessionsRequest - 17, // 25: mininaru.v1.MininaruService.CreateSession:input_type -> mininaru.v1.CreateSessionRequest - 18, // 26: mininaru.v1.MininaruService.GetSession:input_type -> mininaru.v1.GetSessionRequest - 20, // 27: mininaru.v1.MininaruService.RenameSession:input_type -> mininaru.v1.RenameSessionRequest - 21, // 28: mininaru.v1.MininaruService.DeleteSession:input_type -> mininaru.v1.DeleteSessionRequest - 22, // 29: mininaru.v1.MininaruService.GetUsage:input_type -> mininaru.v1.GetUsageRequest - 23, // 30: mininaru.v1.MininaruService.CompactSession:input_type -> mininaru.v1.CompactSessionRequest - 27, // 31: mininaru.v1.MininaruService.Chat:input_type -> mininaru.v1.ChatClientEvent - 4, // 32: mininaru.v1.PairingService.Begin:output_type -> mininaru.v1.BeginPairingResponse - 6, // 33: mininaru.v1.PairingService.Watch:output_type -> mininaru.v1.PairingEvent - 14, // 34: mininaru.v1.MininaruService.ListAgents:output_type -> mininaru.v1.ListAgentsResponse - 16, // 35: mininaru.v1.MininaruService.ListSessions:output_type -> mininaru.v1.ListSessionsResponse - 8, // 36: mininaru.v1.MininaruService.CreateSession:output_type -> mininaru.v1.Session - 19, // 37: mininaru.v1.MininaruService.GetSession:output_type -> mininaru.v1.SessionDetail - 8, // 38: mininaru.v1.MininaruService.RenameSession:output_type -> mininaru.v1.Session - 2, // 39: mininaru.v1.MininaruService.DeleteSession:output_type -> mininaru.v1.Empty - 12, // 40: mininaru.v1.MininaruService.GetUsage:output_type -> mininaru.v1.Usage - 24, // 41: mininaru.v1.MininaruService.CompactSession:output_type -> mininaru.v1.CompactSessionResponse - 34, // 42: mininaru.v1.MininaruService.Chat:output_type -> mininaru.v1.ChatServerEvent - 32, // [32:43] is the sub-list for method output_type - 21, // [21:32] is the sub-list for method input_type - 21, // [21:21] is the sub-list for extension type_name - 21, // [21:21] is the sub-list for extension extendee - 0, // [0:21] is the sub-list for field type_name + 15, // 3: mininaru.v1.ListSkillsResponse.skills:type_name -> mininaru.v1.Skill + 8, // 4: mininaru.v1.ListSessionsResponse.sessions:type_name -> mininaru.v1.Session + 8, // 5: mininaru.v1.SessionDetail.session:type_name -> mininaru.v1.Session + 7, // 6: mininaru.v1.SessionDetail.agent:type_name -> mininaru.v1.Agent + 9, // 7: mininaru.v1.SessionDetail.messages:type_name -> mininaru.v1.Message + 10, // 8: mininaru.v1.SessionDetail.tool_calls:type_name -> mininaru.v1.ToolCall + 30, // 9: mininaru.v1.ChatStart.tools:type_name -> mininaru.v1.ToolDefinition + 1, // 10: mininaru.v1.ApprovalDecision.choice:type_name -> mininaru.v1.ApprovalChoice + 29, // 11: mininaru.v1.ChatClientEvent.start:type_name -> mininaru.v1.ChatStart + 32, // 12: mininaru.v1.ChatClientEvent.approval:type_name -> mininaru.v1.ApprovalDecision + 2, // 13: mininaru.v1.ChatClientEvent.cancel:type_name -> mininaru.v1.Empty + 31, // 14: mininaru.v1.ChatClientEvent.tool_result:type_name -> mininaru.v1.ToolResult + 9, // 15: mininaru.v1.ChatCompleted.message:type_name -> mininaru.v1.Message + 12, // 16: mininaru.v1.ChatCompleted.usage:type_name -> mininaru.v1.Usage + 34, // 17: mininaru.v1.ChatServerEvent.started:type_name -> mininaru.v1.ChatStarted + 35, // 18: mininaru.v1.ChatServerEvent.content:type_name -> mininaru.v1.TextDelta + 35, // 19: mininaru.v1.ChatServerEvent.reasoning:type_name -> mininaru.v1.TextDelta + 36, // 20: mininaru.v1.ChatServerEvent.tool:type_name -> mininaru.v1.ToolEvent + 37, // 21: mininaru.v1.ChatServerEvent.approval:type_name -> mininaru.v1.ApprovalRequest + 39, // 22: mininaru.v1.ChatServerEvent.completed:type_name -> mininaru.v1.ChatCompleted + 40, // 23: mininaru.v1.ChatServerEvent.failed:type_name -> mininaru.v1.ChatFailed + 38, // 24: mininaru.v1.ChatServerEvent.tool_request:type_name -> mininaru.v1.ToolRequest + 3, // 25: mininaru.v1.PairingService.Begin:input_type -> mininaru.v1.BeginPairingRequest + 5, // 26: mininaru.v1.PairingService.Watch:input_type -> mininaru.v1.WatchPairingRequest + 13, // 27: mininaru.v1.MininaruService.ListAgents:input_type -> mininaru.v1.ListAgentsRequest + 16, // 28: mininaru.v1.MininaruService.ListSkills:input_type -> mininaru.v1.ListSkillsRequest + 18, // 29: mininaru.v1.MininaruService.GetSkill:input_type -> mininaru.v1.GetSkillRequest + 19, // 30: mininaru.v1.MininaruService.ListSessions:input_type -> mininaru.v1.ListSessionsRequest + 21, // 31: mininaru.v1.MininaruService.CreateSession:input_type -> mininaru.v1.CreateSessionRequest + 22, // 32: mininaru.v1.MininaruService.GetSession:input_type -> mininaru.v1.GetSessionRequest + 24, // 33: mininaru.v1.MininaruService.RenameSession:input_type -> mininaru.v1.RenameSessionRequest + 25, // 34: mininaru.v1.MininaruService.DeleteSession:input_type -> mininaru.v1.DeleteSessionRequest + 26, // 35: mininaru.v1.MininaruService.GetUsage:input_type -> mininaru.v1.GetUsageRequest + 27, // 36: mininaru.v1.MininaruService.CompactSession:input_type -> mininaru.v1.CompactSessionRequest + 33, // 37: mininaru.v1.MininaruService.Chat:input_type -> mininaru.v1.ChatClientEvent + 4, // 38: mininaru.v1.PairingService.Begin:output_type -> mininaru.v1.BeginPairingResponse + 6, // 39: mininaru.v1.PairingService.Watch:output_type -> mininaru.v1.PairingEvent + 14, // 40: mininaru.v1.MininaruService.ListAgents:output_type -> mininaru.v1.ListAgentsResponse + 17, // 41: mininaru.v1.MininaruService.ListSkills:output_type -> mininaru.v1.ListSkillsResponse + 15, // 42: mininaru.v1.MininaruService.GetSkill:output_type -> mininaru.v1.Skill + 20, // 43: mininaru.v1.MininaruService.ListSessions:output_type -> mininaru.v1.ListSessionsResponse + 8, // 44: mininaru.v1.MininaruService.CreateSession:output_type -> mininaru.v1.Session + 23, // 45: mininaru.v1.MininaruService.GetSession:output_type -> mininaru.v1.SessionDetail + 8, // 46: mininaru.v1.MininaruService.RenameSession:output_type -> mininaru.v1.Session + 2, // 47: mininaru.v1.MininaruService.DeleteSession:output_type -> mininaru.v1.Empty + 12, // 48: mininaru.v1.MininaruService.GetUsage:output_type -> mininaru.v1.Usage + 28, // 49: mininaru.v1.MininaruService.CompactSession:output_type -> mininaru.v1.CompactSessionResponse + 41, // 50: mininaru.v1.MininaruService.Chat:output_type -> mininaru.v1.ChatServerEvent + 38, // [38:51] is the sub-list for method output_type + 25, // [25:38] is the sub-list for method input_type + 25, // [25:25] is the sub-list for extension type_name + 25, // [25:25] is the sub-list for extension extendee + 0, // [0:25] is the sub-list for field type_name } func init() { file_mininaru_v1_mininaru_proto_init() } @@ -2817,12 +3438,13 @@ func file_mininaru_v1_mininaru_proto_init() { if File_mininaru_v1_mininaru_proto != nil { return } - file_mininaru_v1_mininaru_proto_msgTypes[25].OneofWrappers = []any{ + file_mininaru_v1_mininaru_proto_msgTypes[31].OneofWrappers = []any{ (*ChatClientEvent_Start)(nil), (*ChatClientEvent_Approval)(nil), (*ChatClientEvent_Cancel)(nil), + (*ChatClientEvent_ToolResult)(nil), } - file_mininaru_v1_mininaru_proto_msgTypes[32].OneofWrappers = []any{ + file_mininaru_v1_mininaru_proto_msgTypes[39].OneofWrappers = []any{ (*ChatServerEvent_Started)(nil), (*ChatServerEvent_Content)(nil), (*ChatServerEvent_Reasoning)(nil), @@ -2830,6 +3452,7 @@ func file_mininaru_v1_mininaru_proto_init() { (*ChatServerEvent_Approval)(nil), (*ChatServerEvent_Completed)(nil), (*ChatServerEvent_Failed)(nil), + (*ChatServerEvent_ToolRequest)(nil), } type x struct{} @@ -2838,7 +3461,7 @@ func file_mininaru_v1_mininaru_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: unsafe.Slice(unsafe.StringData(file_mininaru_v1_mininaru_proto_rawDesc), len(file_mininaru_v1_mininaru_proto_rawDesc)), NumEnums: 2, - NumMessages: 33, + NumMessages: 40, NumExtensions: 0, NumServices: 2, }, diff --git a/rpc/gen/mininaru/v1/mininaru_grpc.pb.go b/rpc/gen/mininaru/v1/mininaru_grpc.pb.go index 206eb16..d4b4991 100644 --- a/rpc/gen/mininaru/v1/mininaru_grpc.pb.go +++ b/rpc/gen/mininaru/v1/mininaru_grpc.pb.go @@ -32,9 +32,10 @@ func NewPairingServiceClient(cc grpc.ClientConnInterface) PairingServiceClient { func (c *pairingServiceClient) Begin(ctx context.Context, in *BeginPairingRequest, opts ...grpc.CallOption) (*BeginPairingResponse, error) { var ( - cOpts []grpc.CallOption - out *BeginPairingResponse - err error + cOpts []grpc. + CallOption + out *BeginPairingResponse + err error ) cOpts = append([]grpc.CallOption{grpc.StaticMethod()}, opts...) @@ -48,10 +49,15 @@ func (c *pairingServiceClient) Begin(ctx context.Context, in *BeginPairingReques func (c *pairingServiceClient) Watch(ctx context.Context, in *WatchPairingRequest, opts ...grpc.CallOption) (grpc.ServerStreamingClient[PairingEvent], error) { var ( - cOpts []grpc.CallOption - stream grpc.ClientStream - x *grpc.GenericClientStream[WatchPairingRequest, PairingEvent] - err error + cOpts []grpc. + CallOption + stream grpc. + ClientStream + x *grpc. + GenericClientStream[WatchPairingRequest, + + PairingEvent] + err error ) cOpts = append([]grpc.CallOption{grpc.StaticMethod()}, opts...) @@ -106,8 +112,9 @@ func RegisterPairingServiceServer(s grpc.ServiceRegistrar, srv PairingServiceSer func _PairingService_Begin_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { var ( - in *BeginPairingRequest - info *grpc.UnaryServerInfo + in *BeginPairingRequest + info *grpc. + UnaryServerInfo handler func(ctx context.Context, req interface{}) (interface{}, error) err error ) @@ -165,6 +172,8 @@ var PairingService_ServiceDesc = grpc.ServiceDesc{ const ( MininaruService_ListAgents_FullMethodName = "/mininaru.v1.MininaruService/ListAgents" + MininaruService_ListSkills_FullMethodName = "/mininaru.v1.MininaruService/ListSkills" + MininaruService_GetSkill_FullMethodName = "/mininaru.v1.MininaruService/GetSkill" MininaruService_ListSessions_FullMethodName = "/mininaru.v1.MininaruService/ListSessions" MininaruService_CreateSession_FullMethodName = "/mininaru.v1.MininaruService/CreateSession" MininaruService_GetSession_FullMethodName = "/mininaru.v1.MininaruService/GetSession" @@ -177,6 +186,8 @@ const ( type MininaruServiceClient interface { ListAgents(ctx context.Context, in *ListAgentsRequest, opts ...grpc.CallOption) (*ListAgentsResponse, error) + ListSkills(ctx context.Context, in *ListSkillsRequest, opts ...grpc.CallOption) (*ListSkillsResponse, error) + GetSkill(ctx context.Context, in *GetSkillRequest, opts ...grpc.CallOption) (*Skill, error) ListSessions(ctx context.Context, in *ListSessionsRequest, opts ...grpc.CallOption) (*ListSessionsResponse, error) CreateSession(ctx context.Context, in *CreateSessionRequest, opts ...grpc.CallOption) (*Session, error) GetSession(ctx context.Context, in *GetSessionRequest, opts ...grpc.CallOption) (*SessionDetail, error) @@ -197,9 +208,10 @@ func NewMininaruServiceClient(cc grpc.ClientConnInterface) MininaruServiceClient func (c *mininaruServiceClient) ListAgents(ctx context.Context, in *ListAgentsRequest, opts ...grpc.CallOption) (*ListAgentsResponse, error) { var ( - cOpts []grpc.CallOption - out *ListAgentsResponse - err error + cOpts []grpc. + CallOption + out *ListAgentsResponse + err error ) cOpts = append([]grpc.CallOption{grpc.StaticMethod()}, opts...) @@ -211,11 +223,46 @@ func (c *mininaruServiceClient) ListAgents(ctx context.Context, in *ListAgentsRe return out, nil } +func (c *mininaruServiceClient) ListSkills(ctx context.Context, in *ListSkillsRequest, opts ...grpc.CallOption) (*ListSkillsResponse, error) { + var ( + cOpts []grpc. + CallOption + out *ListSkillsResponse + err error + ) + + cOpts = append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out = new(ListSkillsResponse) + err = c.cc.Invoke(ctx, MininaruService_ListSkills_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *mininaruServiceClient) GetSkill(ctx context.Context, in *GetSkillRequest, opts ...grpc.CallOption) (*Skill, error) { + var ( + cOpts []grpc. + CallOption + out *Skill + err error + ) + + cOpts = append([]grpc.CallOption{grpc.StaticMethod()}, opts...) + out = new(Skill) + err = c.cc.Invoke(ctx, MininaruService_GetSkill_FullMethodName, in, out, cOpts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *mininaruServiceClient) ListSessions(ctx context.Context, in *ListSessionsRequest, opts ...grpc.CallOption) (*ListSessionsResponse, error) { var ( - cOpts []grpc.CallOption - out *ListSessionsResponse - err error + cOpts []grpc. + CallOption + out *ListSessionsResponse + err error ) cOpts = append([]grpc.CallOption{grpc.StaticMethod()}, opts...) @@ -229,9 +276,10 @@ func (c *mininaruServiceClient) ListSessions(ctx context.Context, in *ListSessio func (c *mininaruServiceClient) CreateSession(ctx context.Context, in *CreateSessionRequest, opts ...grpc.CallOption) (*Session, error) { var ( - cOpts []grpc.CallOption - out *Session - err error + cOpts []grpc. + CallOption + out *Session + err error ) cOpts = append([]grpc.CallOption{grpc.StaticMethod()}, opts...) @@ -245,9 +293,10 @@ func (c *mininaruServiceClient) CreateSession(ctx context.Context, in *CreateSes func (c *mininaruServiceClient) GetSession(ctx context.Context, in *GetSessionRequest, opts ...grpc.CallOption) (*SessionDetail, error) { var ( - cOpts []grpc.CallOption - out *SessionDetail - err error + cOpts []grpc. + CallOption + out *SessionDetail + err error ) cOpts = append([]grpc.CallOption{grpc.StaticMethod()}, opts...) @@ -261,9 +310,10 @@ func (c *mininaruServiceClient) GetSession(ctx context.Context, in *GetSessionRe func (c *mininaruServiceClient) RenameSession(ctx context.Context, in *RenameSessionRequest, opts ...grpc.CallOption) (*Session, error) { var ( - cOpts []grpc.CallOption - out *Session - err error + cOpts []grpc. + CallOption + out *Session + err error ) cOpts = append([]grpc.CallOption{grpc.StaticMethod()}, opts...) @@ -277,9 +327,10 @@ func (c *mininaruServiceClient) RenameSession(ctx context.Context, in *RenameSes func (c *mininaruServiceClient) DeleteSession(ctx context.Context, in *DeleteSessionRequest, opts ...grpc.CallOption) (*Empty, error) { var ( - cOpts []grpc.CallOption - out *Empty - err error + cOpts []grpc. + CallOption + out *Empty + err error ) cOpts = append([]grpc.CallOption{grpc.StaticMethod()}, opts...) @@ -293,9 +344,10 @@ func (c *mininaruServiceClient) DeleteSession(ctx context.Context, in *DeleteSes func (c *mininaruServiceClient) GetUsage(ctx context.Context, in *GetUsageRequest, opts ...grpc.CallOption) (*Usage, error) { var ( - cOpts []grpc.CallOption - out *Usage - err error + cOpts []grpc. + CallOption + out *Usage + err error ) cOpts = append([]grpc.CallOption{grpc.StaticMethod()}, opts...) @@ -309,9 +361,10 @@ func (c *mininaruServiceClient) GetUsage(ctx context.Context, in *GetUsageReques func (c *mininaruServiceClient) CompactSession(ctx context.Context, in *CompactSessionRequest, opts ...grpc.CallOption) (*CompactSessionResponse, error) { var ( - cOpts []grpc.CallOption - out *CompactSessionResponse - err error + cOpts []grpc. + CallOption + out *CompactSessionResponse + err error ) cOpts = append([]grpc.CallOption{grpc.StaticMethod()}, opts...) @@ -325,10 +378,15 @@ func (c *mininaruServiceClient) CompactSession(ctx context.Context, in *CompactS func (c *mininaruServiceClient) Chat(ctx context.Context, opts ...grpc.CallOption) (grpc.BidiStreamingClient[ChatClientEvent, ChatServerEvent], error) { var ( - cOpts []grpc.CallOption - stream grpc.ClientStream - x *grpc.GenericClientStream[ChatClientEvent, ChatServerEvent] - err error + cOpts []grpc. + CallOption + stream grpc. + ClientStream + x *grpc. + GenericClientStream[ChatClientEvent, + + ChatServerEvent] + err error ) cOpts = append([]grpc.CallOption{grpc.StaticMethod()}, opts...) @@ -344,6 +402,8 @@ type MininaruService_ChatClient = grpc.BidiStreamingClient[ChatClientEvent, Chat type MininaruServiceServer interface { ListAgents(context.Context, *ListAgentsRequest) (*ListAgentsResponse, error) + ListSkills(context.Context, *ListSkillsRequest) (*ListSkillsResponse, error) + GetSkill(context.Context, *GetSkillRequest) (*Skill, error) ListSessions(context.Context, *ListSessionsRequest) (*ListSessionsResponse, error) CreateSession(context.Context, *CreateSessionRequest) (*Session, error) GetSession(context.Context, *GetSessionRequest) (*SessionDetail, error) @@ -360,6 +420,12 @@ type UnimplementedMininaruServiceServer struct{} func (UnimplementedMininaruServiceServer) ListAgents(context.Context, *ListAgentsRequest) (*ListAgentsResponse, error) { return nil, status.Error(codes.Unimplemented, "method ListAgents not implemented") } +func (UnimplementedMininaruServiceServer) ListSkills(context.Context, *ListSkillsRequest) (*ListSkillsResponse, error) { + return nil, status.Error(codes.Unimplemented, "method ListSkills not implemented") +} +func (UnimplementedMininaruServiceServer) GetSkill(context.Context, *GetSkillRequest) (*Skill, error) { + return nil, status.Error(codes.Unimplemented, "method GetSkill not implemented") +} func (UnimplementedMininaruServiceServer) ListSessions(context.Context, *ListSessionsRequest) (*ListSessionsResponse, error) { return nil, status.Error(codes.Unimplemented, "method ListSessions not implemented") } @@ -405,8 +471,9 @@ func RegisterMininaruServiceServer(s grpc.ServiceRegistrar, srv MininaruServiceS func _MininaruService_ListAgents_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { var ( - in *ListAgentsRequest - info *grpc.UnaryServerInfo + in *ListAgentsRequest + info *grpc. + UnaryServerInfo handler func(ctx context.Context, req interface{}) (interface{}, error) err error ) @@ -428,10 +495,63 @@ func _MininaruService_ListAgents_Handler(srv interface{}, ctx context.Context, d return interceptor(ctx, in, info, handler) } +func _MininaruService_ListSkills_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + var ( + in *ListSkillsRequest + info *grpc. + UnaryServerInfo + handler func(ctx context.Context, req interface{}) (interface{}, error) + err error + ) + + in = new(ListSkillsRequest) + if err = dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MininaruServiceServer).ListSkills(ctx, in) + } + info = &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: MininaruService_ListSkills_FullMethodName, + } + handler = func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MininaruServiceServer).ListSkills(ctx, req.(*ListSkillsRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _MininaruService_GetSkill_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + var ( + in *GetSkillRequest + info *grpc. + UnaryServerInfo + handler func(ctx context.Context, req interface{}) (interface{}, error) + err error + ) + + in = new(GetSkillRequest) + if err = dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(MininaruServiceServer).GetSkill(ctx, in) + } + info = &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: MininaruService_GetSkill_FullMethodName, + } + handler = func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(MininaruServiceServer).GetSkill(ctx, req.(*GetSkillRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _MininaruService_ListSessions_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { var ( - in *ListSessionsRequest - info *grpc.UnaryServerInfo + in *ListSessionsRequest + info *grpc. + UnaryServerInfo handler func(ctx context.Context, req interface{}) (interface{}, error) err error ) @@ -455,8 +575,9 @@ func _MininaruService_ListSessions_Handler(srv interface{}, ctx context.Context, func _MininaruService_CreateSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { var ( - in *CreateSessionRequest - info *grpc.UnaryServerInfo + in *CreateSessionRequest + info *grpc. + UnaryServerInfo handler func(ctx context.Context, req interface{}) (interface{}, error) err error ) @@ -480,8 +601,9 @@ func _MininaruService_CreateSession_Handler(srv interface{}, ctx context.Context func _MininaruService_GetSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { var ( - in *GetSessionRequest - info *grpc.UnaryServerInfo + in *GetSessionRequest + info *grpc. + UnaryServerInfo handler func(ctx context.Context, req interface{}) (interface{}, error) err error ) @@ -505,8 +627,9 @@ func _MininaruService_GetSession_Handler(srv interface{}, ctx context.Context, d func _MininaruService_RenameSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { var ( - in *RenameSessionRequest - info *grpc.UnaryServerInfo + in *RenameSessionRequest + info *grpc. + UnaryServerInfo handler func(ctx context.Context, req interface{}) (interface{}, error) err error ) @@ -530,8 +653,9 @@ func _MininaruService_RenameSession_Handler(srv interface{}, ctx context.Context func _MininaruService_DeleteSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { var ( - in *DeleteSessionRequest - info *grpc.UnaryServerInfo + in *DeleteSessionRequest + info *grpc. + UnaryServerInfo handler func(ctx context.Context, req interface{}) (interface{}, error) err error ) @@ -555,8 +679,9 @@ func _MininaruService_DeleteSession_Handler(srv interface{}, ctx context.Context func _MininaruService_GetUsage_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { var ( - in *GetUsageRequest - info *grpc.UnaryServerInfo + in *GetUsageRequest + info *grpc. + UnaryServerInfo handler func(ctx context.Context, req interface{}) (interface{}, error) err error ) @@ -580,8 +705,9 @@ func _MininaruService_GetUsage_Handler(srv interface{}, ctx context.Context, dec func _MininaruService_CompactSession_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { var ( - in *CompactSessionRequest - info *grpc.UnaryServerInfo + in *CompactSessionRequest + info *grpc. + UnaryServerInfo handler func(ctx context.Context, req interface{}) (interface{}, error) err error ) @@ -617,6 +743,14 @@ var MininaruService_ServiceDesc = grpc.ServiceDesc{ MethodName: "ListAgents", Handler: _MininaruService_ListAgents_Handler, }, + { + MethodName: "ListSkills", + Handler: _MininaruService_ListSkills_Handler, + }, + { + MethodName: "GetSkill", + Handler: _MininaruService_GetSkill_Handler, + }, { MethodName: "ListSessions", Handler: _MininaruService_ListSessions_Handler, diff --git a/rpc/pairing_test.go b/rpc/pairing_test.go index 05419fe..657e1b3 100644 --- a/rpc/pairing_test.go +++ b/rpc/pairing_test.go @@ -50,6 +50,10 @@ func (s *testChatStream) Send(event *mininaruv1.ChatServerEvent) error { s.incoming <- &mininaruv1.ChatClientEvent{Event: &mininaruv1.ChatClientEvent_Approval{Approval: &mininaruv1.ApprovalDecision{ RequestId: event.GetApproval().GetRequestId(), Choice: mininaruv1.ApprovalChoice_APPROVAL_CHOICE_DENY}}} } + if s.autoDeny && event.GetToolRequest() != nil { + s.incoming <- &mininaruv1.ChatClientEvent{Event: &mininaruv1.ChatClientEvent_ToolResult{ToolResult: &mininaruv1.ToolResult{ + RequestId: event.GetToolRequest().GetRequestId(), Error: "user denied dangerous tool"}}} + } return nil } @@ -526,7 +530,7 @@ func TestChatStreamsAndPersistsServerSession(t *testing.T) { } } -func TestChatCarriesToolApprovalOverTheStream(t *testing.T) { +func TestChatRunsAdvertisedToolsOnTheClient(t *testing.T) { var calls atomic.Int32 var upstream *httptest.Server var registry *core.Registry @@ -572,14 +576,15 @@ func TestChatCarriesToolApprovalOverTheStream(t *testing.T) { defer cancel() stream = testChatStream{ctx: ctx, incoming: make(chan *mininaruv1.ChatClientEvent, 1), autoDeny: true} stream.incoming <- &mininaruv1.ChatClientEvent{Event: &mininaruv1.ChatClientEvent_Start{Start: &mininaruv1.ChatStart{ - SessionId: session.Id, Content: "run it", Thinking: config.ThinkingOff}}} + SessionId: session.Id, Content: "run it", Thinking: config.ThinkingOff, Tools: []*mininaruv1.ToolDefinition{{ + Name: "bash_exec", Description: "run a command", ParametersJson: `{"type":"object"}`, Permission: "dangerous"}}}}} err = (&mininaruService{registry: registry, slots: make(chan struct{}, 1)}).Chat(&stream) if err != nil { t.Fatal(err) } for _, event = range stream.outgoing { - if event.GetApproval() != nil && event.GetApproval().GetToolName() == "bash_exec" { + if event.GetToolRequest() != nil && event.GetToolRequest().GetToolName() == "bash_exec" { requested = true } if event.GetCompleted() != nil { @@ -587,7 +592,7 @@ func TestChatCarriesToolApprovalOverTheStream(t *testing.T) { } } if !requested { - t.Fatal("dangerous tool produced no approval request") + t.Fatal("advertised tool produced no client execution request") } if completed == nil || completed.GetMessage().GetContent() != "denied safely" { t.Fatalf("completed = %#v", completed) diff --git a/rpc/service.go b/rpc/service.go index 9b4eb0e..044d35d 100644 --- a/rpc/service.go +++ b/rpc/service.go @@ -5,13 +5,13 @@ package rpc import ( "context" + "encoding/json" "errors" "fmt" "io" "sync" "time" - "github.com/devproje/mininaru/config" "github.com/devproje/mininaru/core" "github.com/devproje/mininaru/modules" mininaruv1 "github.com/devproje/mininaru/rpc/gen/mininaru/v1" @@ -51,6 +51,19 @@ func rpcAgent(agent *core.NaruAgent) *mininaruv1.Agent { return &mininaruv1.Agent{Id: agent.Id, Name: agent.Name, Model: agent.Model, Provider: providerName} } +func rpcSkill(skill *modules.Skill, includeBody bool) *mininaruv1.Skill { + var body string + + if skill == nil { + return nil + } + if includeBody { + body = skill.Body + } + + return &mininaruv1.Skill{Name: skill.Name, Description: skill.Description, Scope: skill.Scope, Body: body} +} + func rpcSession(session *core.Session) *mininaruv1.Session { if session == nil { return nil @@ -134,6 +147,36 @@ func (s *mininaruService) ListAgents(ctx context.Context, request *mininaruv1.Li return &response, nil } +func (s *mininaruService) ListSkills(ctx context.Context, request *mininaruv1.ListSkillsRequest) (*mininaruv1.ListSkillsResponse, error) { + var response mininaruv1.ListSkillsResponse + var skill modules.Skill + + for _, skill = range modules.SkillAll() { + response.Skills = append(response.Skills, rpcSkill(&skill, false)) + } + + return &response, nil +} + +func (s *mininaruService) GetSkill(ctx context.Context, request *mininaruv1.GetSkillRequest) (*mininaruv1.Skill, error) { + var skill *modules.Skill + var body string + + var err error + + skill = modules.SkillFind(request.GetName()) + if skill == nil { + return nil, status.Error(codes.NotFound, "skill not found") + } + body, err = modules.SkillResult(skill.Name, "") + if err != nil { + return nil, status.Error(codes.Internal, err.Error()) + } + skill = &modules.Skill{Name: skill.Name, Description: skill.Description, Scope: skill.Scope, Body: body} + + return rpcSkill(skill, true), nil +} + func (s *mininaruService) ListSessions(ctx context.Context, request *mininaruv1.ListSessionsRequest) (*mininaruv1.ListSessionsResponse, error) { var instance *core.Instance var sessions []*core.Session @@ -419,6 +462,66 @@ func chatApprover(ctx context.Context, stream mininaruv1.MininaruService_ChatSer } } +func remoteToolExecute(ctx context.Context, stream mininaruv1.MininaruService_ChatServer, + incoming <-chan *mininaruv1.ChatClientEvent, sendMu *sync.Mutex, name string) func(context.Context, string) (string, error) { + return func(callCtx context.Context, arguments string) (string, error) { + var requestId string + var event *mininaruv1.ChatClientEvent + var result *mininaruv1.ToolResult + + var err error + + requestId = uuid.NewString() + sendMu.Lock() + err = stream.Send(&mininaruv1.ChatServerEvent{Event: &mininaruv1.ChatServerEvent_ToolRequest{ToolRequest: &mininaruv1.ToolRequest{ + RequestId: requestId, ToolName: name, Arguments: arguments}}}) + sendMu.Unlock() + if err != nil { + return "", err + } + for { + select { + case event = <-incoming: + result = event.GetToolResult() + if result == nil || result.GetRequestId() != requestId { + continue + } + if result.GetError() != "" { + return "", errors.New(result.GetError()) + } + return result.GetResult(), nil + case <-callCtx.Done(): + return "", callCtx.Err() + case <-ctx.Done(): + return "", ctx.Err() + } + } + } +} + +func remoteToolDefs(ctx context.Context, stream mininaruv1.MininaruService_ChatServer, + incoming <-chan *mininaruv1.ChatClientEvent, sendMu *sync.Mutex, advertised []*mininaruv1.ToolDefinition) ([]modules.Def, error) { + var item *mininaruv1.ToolDefinition + var parameters map[string]any + var defs []modules.Def + var def modules.Def + + var err error + + for _, item = range advertised { + parameters = nil + err = json.Unmarshal([]byte(item.GetParametersJson()), ¶meters) + if err != nil { + return nil, status.Error(codes.InvalidArgument, "invalid tool parameters") + } + def = modules.Def{Name: item.GetName(), Description: item.GetDescription(), Parameters: parameters, + Execute: remoteToolExecute(ctx, stream, incoming, sendMu, item.GetName())} + defs = append(defs, def) + } + + return defs, nil +} + func errorsIsContext(err error) bool { return errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) } @@ -488,8 +591,9 @@ func (s *mininaruService) Chat(stream mininaruv1.MininaruService_ChatServer) err return err } - if config.Client.Tools.Enabled { - defs = modules.DefaultTools() + defs, err = remoteToolDefs(chatCtx, stream, incoming, &sendMu, start.GetTools()) + if err != nil { + return err } message, err = instance.ChatWithTools(chatCtx, session, start.GetContent(), defs, start.GetThinking(),