1
0
mirror of https://github.com/fumiama/go-onebot-agent.git synced 2026-06-05 02:00:23 +08:00

feat: GetAction return multiple reqs

This commit is contained in:
源文雨
2025-09-22 22:23:17 +08:00
parent d45d7d3ec5
commit a21b15d4c1
3 changed files with 83 additions and 75 deletions

View File

@@ -13,55 +13,50 @@
## OneBot 11 协议
> 输入输出均为 JSON 格式的一系列 Object代表一系列事件或响应以换行符分隔。
> 所有可能的字段由对应的 Golang 结构体给出。
> 所有可能的字段如下type 由对应的 Golang 类型给出。
### 输入
事件 (Event) 是输入的基本单位,
```go
type Event struct {
Time int64 `json:"time"` // 事件发生的时间戳
PostType string `json:"post_type"` // 上报类型: message / notice / request
MessageType string `json:"message_type"` // message 类型: group / private
SubType string `json:"sub_type"` // message 子类型: normal (一般消息) / notice (灰色小字通知)
MessageID int64 `json:"message_id"` // 消息 ID, 唯一标识该事件
GroupID int64 `json:"group_id"` // QQ群号
UserID int64 `json:"user_id"` // 事件发送者QQ号
TargetID int64 `json:"target_id"`
SelfID int64 `json:"self_id"` // 收到事件的QQ号 (你的ID)
NoticeType string `json:"notice_type,omitempty"`
OperatorID int64 `json:"operator_id"` // This field is used for Notice Event
File *File `json:"file,omitempty"`
RequestType string `json:"request_type,omitempty"`
Flag string `json:"flag,omitempty"`
Comment string `json:"comment,omitempty"` // This field is used for Request Event
Sender *User `json:"sender,omitempty"` // 事件发送者个人信息
Message json.RawMessage `json:"message,omitempty"` // JSON 格式的消息内容
}
```
|key|type|说明|
|---|---|---|
|time|int64|事件发生的时间戳|
|post_type|string|上报类型: message / notice / request|
|message_type|string|message 类型: group / private|
|sub_type|string|message 子类型: normal (一般消息) / notice (灰色小字通知)|
|message_id|int64|消息 ID, 唯一标识该事件|
|group_id|int64|QQ群号|
|user_id|int64|事件发送者QQ号|
|target_id|int64|后述|
|self_id|int64|收到事件的QQ号 (你的ID)|
|notice_type|string|后述|
|operator_id|int64|For Notice Event|
|file|*File|后述|
|request_type|string|后述|
|flag|string|后述|
|comment|string|For Request Event|
|sender|*User|事件发送者个人信息|
|message|json.RawMessage|JSON 格式的消息内容|
其中,文件 (File) 标识一个聊天文件,
```go
type File struct {
ID string `json:"id"`
Name string `json:"name"`
Size int64 `json:"size"`
BusID int64 `json:"busid"`
}
```
|key|type|
|---|---|
|id|string|
|name|string|
|size|int64|
用户 (User) 标识一个QQ用户
```go
type User struct {
ID int64 `json:"user_id"`
NickName string `json:"nickname"`
Sex string `json:"sex"` // "male"、"female"、"unknown"
Age int `json:"age"`
Area string `json:"area"` // 地区
// 以下为群聊特有字段
Card string `json:"card"` // 群名片/备注
Title string `json:"title"` // 专属头衔
Level string `json:"level"` // 群聊等级
Role string `json:"role"` // "owner"、"admin"、"member"
}
```
|key|type|说明|
|---|---|---|
|user_id|int64|用户QQ号|
|nickname|string|昵称|
|sex|string|"male"、"female"、"unknown"|
|age|int|年龄|
|area|string|地区|
|card|string|群名片/备注(群聊特有|
|title|string|专属头衔(群聊特有)|
|level|string|群聊等级(群聊特有)|
|role|string|"owner"、"admin"、"member"(群聊特有)|
#### 详细事件种类
|类型|post_type|message_type|sub_type|message_id|group_id|user_id|target_id|self_id|notice_type|operator_id|file|request_type|flag|comment|sender|message|
@@ -113,4 +108,4 @@ type User struct {
```
你可以调用的全部 API 如下表。注意:即使之前的记录显示你曾调用过某 API但如果现在列表中不存在此 API你就不能调用。
%v
%v

View File

@@ -4,7 +4,7 @@ package goba
import (
"encoding/json"
"fmt"
"io"
"strings"
"github.com/fumiama/deepinfra"
"github.com/fumiama/deepinfra/chat"
@@ -26,16 +26,23 @@ type Agent struct {
nickname, sex string
chars string
perm *Perm
manualaddreq bool
}
// NewAgent characteristics 最好是 MD 格式, defaultprompt 是上下文为空时的默认项, 建议为 Event JSON
// NewAgent 创建一个 Agent 实例。
//
// - characteristics 推荐使用 Markdown 格式,描述 Agent 个性。
// - defaultprompt 为上下文为空时的默认提示,建议为事件的 JSON一般不会用到因此也可留空。
// - manualaddreq 表示是否由用户手动添加请求。
func NewAgent(
id int64, batchcap, itemscap int,
nickname, sex, characteristics, defaultprompt string,
manualaddreq bool,
) (ag Agent) {
ag = Agent{
id: id, nickname: nickname, sex: sex, chars: characteristics,
log: chat.NewLog[fmt.Stringer](batchcap, itemscap, "\n", defaultprompt),
log: chat.NewLog[fmt.Stringer](batchcap, itemscap, "\n", defaultprompt),
manualaddreq: manualaddreq,
}
_ = ag.LoadPermTable()
return
@@ -55,16 +62,12 @@ func (ag *Agent) AddRequest(grp int64, req *zero.APIRequest) {
//
// Note:
//
// 1. The response may be empty, meaning that LLM do not want
// to react with these events. In this case, this function will
// return io.EOF and the context will be left no change.
//
// 2. If LLM returns an invalid action, ErrPermissionDenied will be returned
// with complete req, caller may decide whether to use this req by themselves.
// Whatever, this req will not be added into the context. You may call
// AddRequest to add it but it is not recommended.
// - If LLM returns an invalid action, ErrPermissionDenied will be returned
// with complete reqs before invalid call, caller may decide whether to use
// these reqs by themselves. Whatever, invalid req will not be added into
// the context. You may call AddRequest to add it but it is not recommended.
func (ag *Agent) GetAction(api deepinfra.API, p model.Protocol, grp int64, role PermRole, isusersystem bool) (
req zero.APIRequest, err error,
reqs []zero.APIRequest, err error,
) {
sysp, err := ag.system(role)
if err != nil {
@@ -77,15 +80,25 @@ func (ag *Agent) GetAction(api deepinfra.API, p model.Protocol, grp int64, role
if err != nil {
return
}
err = json.Unmarshal([]byte(resp), &req)
if err == nil && req.Action == "" {
err = io.EOF
}
if !ag.perm.allow(role, req.Action) {
err = errors.Wrap(ErrPermissionDenied, req.Action)
} else {
ag.AddRequest(grp, &req)
reqs = make([]zero.APIRequest, 0, 2)
dec := json.NewDecoder(strings.NewReader(resp))
for dec.More() {
r := zero.APIRequest{}
err = dec.Decode(&r)
if err != nil {
break
}
if r.Action == "" {
continue
}
switch {
case !ag.perm.allow(role, r.Action):
err = errors.Wrap(ErrPermissionDenied, r.Action)
return
case !ag.manualaddreq:
ag.AddRequest(grp, &r)
}
reqs = append(reqs, r)
}
return

View File

@@ -10,17 +10,17 @@ import (
// Event is the simplified OneBot event that dumped to the agent in JSON format
type Event struct {
Time int64 `json:"time"` // 事件发生的时间戳
PostType string `json:"post_type"` // 上报类型: message / notice / request
MessageType string `json:"message_type"` // message 类型: group / private
SubType string `json:"sub_type"` // message 子类型: normal (一般消息) / notice (灰色小字通知)
MessageID int64 `json:"message_id"` // 消息 ID, 唯一标识该事件
GroupID int64 `json:"group_id"` // QQ群号
UserID int64 `json:"user_id"` // 事件发送者QQ号
TargetID int64 `json:"target_id"`
Time int64 `json:"time"` // 事件发生的时间戳
PostType string `json:"post_type"` // 上报类型: message / notice / request
MessageType string `json:"message_type"` // message 类型: group / private
SubType string `json:"sub_type,omitempty"` // message 子类型: normal (一般消息) / notice (灰色小字通知)
MessageID int64 `json:"message_id"` // 消息 ID, 唯一标识该事件
GroupID int64 `json:"group_id,omitempty"` // QQ群号
UserID int64 `json:"user_id"` // 事件发送者QQ号
TargetID int64 `json:"target_id,omitempty"`
SelfID int64 `json:"self_id"` // 收到事件的QQ号 (你的ID)
NoticeType string `json:"notice_type,omitempty"`
OperatorID int64 `json:"operator_id"` // This field is used for Notice Event
OperatorID int64 `json:"operator_id,omitempty"` // This field is used for Notice Event
File *zero.File `json:"file,omitempty"`
RequestType string `json:"request_type,omitempty"`
Flag string `json:"flag,omitempty"`