@my-life-buddies/buddy-runtime 0.0.3 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +106 -17
- package/dist/conversation/agent.js +2 -2
- package/dist/conversation/agent.js.map +1 -1
- package/dist/conversation/agentMessageLLMMessageConverter.d.ts +8 -0
- package/dist/conversation/agentMessageLLMMessageConverter.d.ts.map +1 -0
- package/dist/conversation/agentMessageLLMMessageConverter.js +48 -0
- package/dist/conversation/agentMessageLLMMessageConverter.js.map +1 -0
- package/dist/conversation/history.d.ts +0 -7
- package/dist/conversation/history.d.ts.map +1 -1
- package/dist/conversation/history.js +2 -15
- package/dist/conversation/history.js.map +1 -1
- package/dist/conversation/index.d.ts +14 -21
- package/dist/conversation/index.d.ts.map +1 -1
- package/dist/conversation/index.js +83 -110
- package/dist/conversation/index.js.map +1 -1
- package/dist/conversation/mlbMessageAgentMessageConverter.d.ts +36 -0
- package/dist/conversation/mlbMessageAgentMessageConverter.d.ts.map +1 -0
- package/dist/conversation/mlbMessageAgentMessageConverter.js +224 -0
- package/dist/conversation/mlbMessageAgentMessageConverter.js.map +1 -0
- package/dist/conversation/readMLBMessages.d.ts +29 -0
- package/dist/conversation/readMLBMessages.d.ts.map +1 -0
- package/dist/conversation/readMLBMessages.js +86 -0
- package/dist/conversation/readMLBMessages.js.map +1 -0
- package/dist/conversation/writeMLBMessage.d.ts +62 -0
- package/dist/conversation/writeMLBMessage.d.ts.map +1 -0
- package/dist/conversation/writeMLBMessage.js +212 -0
- package/dist/conversation/writeMLBMessage.js.map +1 -0
- package/dist/mlbClient.d.ts +7 -5
- package/dist/mlbClient.d.ts.map +1 -1
- package/dist/mlbClient.js +14 -3
- package/dist/mlbClient.js.map +1 -1
- package/dist/tools/dataAccess.d.ts +6 -1
- package/dist/tools/dataAccess.d.ts.map +1 -1
- package/dist/tools/dataAccess.js +29 -1
- package/dist/tools/dataAccess.js.map +1 -1
- package/dist/types.d.ts +4 -6
- package/dist/types.d.ts.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
MLB 搭子运行时。基于 [`@earendil-works/pi-agent-core`](https://www.npmjs.com/package/@earendil-works/pi-agent-core) 构建,负责搭子与 MLB 平台之间的全部交互:订阅事件流、拉取消息、驱动模型、写回回复、推送在线状态。开发者只需提供搭子的配置。
|
|
4
4
|
|
|
5
|
-
## 安装
|
|
5
|
+
## 1. 安装
|
|
6
6
|
|
|
7
7
|
```bash
|
|
8
8
|
npm install @my-life-buddies/buddy-runtime
|
|
@@ -10,7 +10,7 @@ npm install @my-life-buddies/buddy-runtime
|
|
|
10
10
|
|
|
11
11
|
要求 Node.js ≥ 22.19。
|
|
12
12
|
|
|
13
|
-
## 快速开始
|
|
13
|
+
## 2. 快速开始
|
|
14
14
|
|
|
15
15
|
```
|
|
16
16
|
my-buddy/
|
|
@@ -58,9 +58,9 @@ await BuddyServer.start({
|
|
|
58
58
|
|
|
59
59
|
完整示例见 [examples/aunt-tu/](examples/aunt-tu/)。
|
|
60
60
|
|
|
61
|
-
## API
|
|
61
|
+
## 3. API
|
|
62
62
|
|
|
63
|
-
### `BuddyServer.start(options)`
|
|
63
|
+
### 3.1 `BuddyServer.start(options)`
|
|
64
64
|
|
|
65
65
|
启动搭子进程,连接平台事件流。返回 `{ stop(): Promise<void> }`。
|
|
66
66
|
|
|
@@ -69,7 +69,7 @@ await BuddyServer.start({
|
|
|
69
69
|
| `options.model` | `string`,必填 | 模型 id,取值见平台 `GET /cli/models`。进程内所有会话共用。没填,或 id 在运行时内置的模型目录中不存在时,启动失败 |
|
|
70
70
|
| `options.buddy` | `(conversation: Conversation) => BuddyOptions \| Promise<BuddyOptions>` | 搭子配置工厂。每场会话在第一条消息到达时调用一次 |
|
|
71
71
|
|
|
72
|
-
### `BuddyOptions`
|
|
72
|
+
### 3.2 `BuddyOptions`
|
|
73
73
|
|
|
74
74
|
配置的形状与字段名与 pi-agent-core 的 `AgentOptions` / `AgentState` 一致,签名请参考 pi 的文档。
|
|
75
75
|
|
|
@@ -87,12 +87,12 @@ type BuddyOptions =
|
|
|
87
87
|
| `initialState.systemPrompt` | 系统提示。静态内容;每回合变化的信息不应写在这里。工程目录下有 `resources/` 时,运行时在末尾追加资料清单 |
|
|
88
88
|
| `initialState.tools` | 工具列表,类型为 pi 的 `AgentTool`。`label` 为必填,用作用户可见的状态行文案(空字符串表示不显示);`execute` 返回值的 `details` 为必填(可为 `undefined`);执行失败应直接抛出异常。工具名不得与内置工具或其他工具重复。先单独声明为 `AgentTool<typeof 参数 schema>` 再放入数组,`execute` 的参数才有类型;直接写在数组里时参数类型为 `unknown` |
|
|
89
89
|
| `initialState.thinkingLevel` | 思考级别,默认 `off`。模型不支持的级别在发请求前就近换成支持的一档。显式设了模型不支持的级别时,每场会话建立时打一条 warn |
|
|
90
|
-
| `transformContext` |
|
|
90
|
+
| `transformContext` | 历史裁剪。入参是这场会话完整的 Agent 历史,平台交代的场合也在其中,消息从哪来、长什么样见下方「4. 会话历史」一节;返回值只用于这一次模型请求,不改动历史;抛出异常时使用原历史 |
|
|
91
91
|
| `beforeToolCall` / `afterToolCall` / `shouldStopAfterTurn` / `prepareNextTurnWithContext` / `thinkingBudgets` / `toolExecution` | 原样传递给 pi |
|
|
92
92
|
|
|
93
93
|
密钥、会话历史、会话标识与插话策略由运行时统一管理,不对开发者开放。模型通过 `BuddyServer.start` 的 `model` 选择。
|
|
94
94
|
|
|
95
|
-
### `Conversation`:给开发者调用的方法
|
|
95
|
+
### 3.3 `Conversation`:给开发者调用的方法
|
|
96
96
|
|
|
97
97
|
工厂拿到的对象。上面的属性和方法由开发者在代码里调用,不会注册给模型;要让模型用到,开发者自己包成工具放进 `initialState.tools`,见下方 `remember` 的例子。
|
|
98
98
|
|
|
@@ -105,6 +105,9 @@ interface Conversation {
|
|
|
105
105
|
write(key: string, text: string): Promise<void>; // 覆盖写一条
|
|
106
106
|
delete(key: string): Promise<void>; // 删一条,删不存在的也算成功
|
|
107
107
|
};
|
|
108
|
+
readonly dataAccess: {
|
|
109
|
+
query(request: { datasets: string[]; memberId?: string }): Promise<DatasetAccessResult[]>; // 读用户授权的数据,见 3.4.2
|
|
110
|
+
};
|
|
108
111
|
}
|
|
109
112
|
|
|
110
113
|
interface MemoryEntry {
|
|
@@ -141,21 +144,19 @@ await BuddyServer.start({
|
|
|
141
144
|
|
|
142
145
|
完整示例见 [examples/aunt-tu/](examples/aunt-tu/):`taste_read` / `taste_write` 两个工具用 `memory` 记每个人爱吃什么、不爱吃什么。
|
|
143
146
|
|
|
144
|
-
`dataAccess.query`
|
|
147
|
+
`dataAccess.query` 读取用户授权给搭子的数据,用法见 3.4.2。
|
|
145
148
|
|
|
146
|
-
### 内置工具:运行时注册给模型
|
|
149
|
+
### 3.4 内置工具:运行时注册给模型
|
|
147
150
|
|
|
148
151
|
以下工具由运行时注册到 Agent,排在开发者工具之前,由模型调用。开发者不需要注册,也不能再注册同名工具;系统提示中可按名称引用。
|
|
149
152
|
|
|
150
153
|
| 工具 | 何时注册 | 做什么 |
|
|
151
154
|
|---|---|---|
|
|
152
|
-
| `data_access_query` | 搭子声明过至少一个 Dataset | 按需读取当前会话用户授权的数据;单次最多 8 个 Dataset,响应上限 512 KiB |
|
|
153
|
-
| `widget_create` / `widget_write` / `widget_read` / `widget_delete` / `widget_send` | 搭子在平台上登记了小挂件类型 | 建小挂件、写 / 读 / 删记录、把小挂件发进聊天流 |
|
|
154
155
|
| `read_resource` | 工程目录下有 `resources/`,且其中有 `.md` | 按资料清单里的相对路径读一篇资料 |
|
|
156
|
+
| `data_access_query` | 搭子声明过至少一个 Dataset | 按需读取当前会话用户授权的数据;单次最多 8 个 Dataset,响应上限 512 KiB |
|
|
157
|
+
| `widget_create` / `widget_write` / `widget_read` / `widget_delete` / `widget_send` | 搭子在平台上登记了小挂件类型 | 建小挂件、写 / 读 / 删记录、把小挂件发进聊天 |
|
|
155
158
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
#### 资料
|
|
159
|
+
#### 3.4.1 资料
|
|
159
160
|
|
|
160
161
|
资料放在工程目录下的 `resources/` 里,是一篇篇 `.md` 文件。运行时自动让模型按需读取,开发者不需要写代码。
|
|
161
162
|
|
|
@@ -174,7 +175,77 @@ my-buddy/ 工程目录
|
|
|
174
175
|
|
|
175
176
|
完整示例见 [examples/stacy-sims/](examples/stacy-sims/)。
|
|
176
177
|
|
|
177
|
-
####
|
|
178
|
+
#### 3.4.2 授权数据
|
|
179
|
+
|
|
180
|
+
经用户同意,搭子可以读取用户授权数据。数据按 Dataset 分项,每项内容与字段固定,用户逐项授权。开发者要做的是声明需要哪些 Dataset;查询工具由运行时注册给模型,开发者的工具里也能直接查。
|
|
181
|
+
|
|
182
|
+
**声明需要哪些数据**
|
|
183
|
+
|
|
184
|
+
通过平台 CLI 接口 `PUT /cli/buddies/:id/data-requirements` 提交完整清单,每次提交覆盖上一次:
|
|
185
|
+
|
|
186
|
+
```json
|
|
187
|
+
{
|
|
188
|
+
"datasets": [
|
|
189
|
+
{ "id": "health.sleep", "purpose": "根据你最近的睡眠调整作息建议" }
|
|
190
|
+
]
|
|
191
|
+
}
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
- `id`:从下表选。
|
|
195
|
+
- `purpose`:写给用户看的用途,1~200 字。用户在 App 里看到这句话,再决定是否同意。
|
|
196
|
+
- 改了某项的 `purpose`,用户之前的同意失效,要重新同意;从清单里删掉的数据,搭子立即读不到。
|
|
197
|
+
- 声明或改动之后,重启搭子进程,模型才能看到新的清单。
|
|
198
|
+
|
|
199
|
+
目前支持的 Dataset:
|
|
200
|
+
|
|
201
|
+
| Dataset | 内容 | `data.items` 每条的字段 |
|
|
202
|
+
|---|---|---|
|
|
203
|
+
| `health.sleep` | 睡眠,每天一条 | `date`、`totalSleepMinutes`、`sleepStartLocal`、`sleepEndLocal`、`awakeMinutes`、`coreSleepMinutes`、`deepSleepMinutes`、`remSleepMinutes`、`unspecifiedSleepMinutes` |
|
|
204
|
+
| `health.workouts` | 运动记录,每次一条 | `id`、`date`、`startAt`、`type`、`durationMinutes`、`calories`、`sourceApp` |
|
|
205
|
+
| `health.distance` | 距离与配速,对应一次运动 | `workoutId`、`date`、`startAt`、`distanceKm`、`paceSecondsPerKm` |
|
|
206
|
+
| `health.heartRate` | 心率,对应一段睡眠或一次运动 | `context`(`sleep` / `workout`)、`referenceId`、`date`、`startAt`、`beatsPerMinute` |
|
|
207
|
+
| `health.hrv` | 心率变异性 | `date`、`milliseconds` |
|
|
208
|
+
| `health.respiratoryRate` | 呼吸频率 | `date`、`breathsPerMinute` |
|
|
209
|
+
| `health.oxygenSaturation` | 血氧 | `date`、`percent` |
|
|
210
|
+
| `health.environmentalAudioExposure` | 环境音量 | `date`、`decibels` |
|
|
211
|
+
|
|
212
|
+
部分字段可能缺失,取值前先判断。
|
|
213
|
+
|
|
214
|
+
**让模型去查**
|
|
215
|
+
|
|
216
|
+
声明过至少一项数据,模型就有了 `data_access_query` 工具,工具说明里列着开发者声明的数据与用途。开发者可以在系统提示里写明什么时候查,例如「聊到作息时,先用 data_access_query 查 health.sleep」。
|
|
217
|
+
|
|
218
|
+
**在自己的工具里查**
|
|
219
|
+
|
|
220
|
+
调用 `conversation.dataAccess.query`:
|
|
221
|
+
|
|
222
|
+
```ts
|
|
223
|
+
const [sleep] = await conversation.dataAccess.query({ datasets: ["health.sleep"] });
|
|
224
|
+
if (sleep.status === "available") {
|
|
225
|
+
// sleep.data.items 是每天一条的睡眠记录
|
|
226
|
+
}
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
- `datasets`:一次最多 8 个。
|
|
230
|
+
- `memberId`:私聊不传;群聊必须传,即群消息前缀 `[名字 #m_…]` 里的 `m_…`,查的是这位成员的数据。传错时直接抛出异常。
|
|
231
|
+
|
|
232
|
+
**查询结果**
|
|
233
|
+
|
|
234
|
+
每个 Dataset 各有一个状态,一个读不到不影响其他。只有 `available` 带 `data`:
|
|
235
|
+
|
|
236
|
+
| 状态 | 意思 |
|
|
237
|
+
|---|---|
|
|
238
|
+
| `available` | 读到了 |
|
|
239
|
+
| `notDeclared` | 搭子没有声明这项数据 |
|
|
240
|
+
| `notGranted` | 用户没有同意,或改过用途后用户还没重新同意 |
|
|
241
|
+
| `disabledInGroup` | 这位成员在这个群里关掉了这项数据 |
|
|
242
|
+
| `unavailable` | 平台上还没有这位用户的这项数据,或数据已过期 |
|
|
243
|
+
|
|
244
|
+
**数据只在这一轮回复里可见**
|
|
245
|
+
|
|
246
|
+
一轮回复里只要查过授权数据,这一轮结束后,聊天记录和会话历史里这一轮的工具参数、工具结果与 thinking,都会换成「查了哪些数据、各是什么状态」,给用户看的回复照常保留。开发者自己写进 `memory` 或小挂件的内容不会被替换,不要把查到的数据写进去。
|
|
247
|
+
|
|
248
|
+
#### 3.4.3 小挂件
|
|
178
249
|
|
|
179
250
|
开发者通过平台 CLI 接口给搭子登记小挂件类型:`PUT /cli/buddies/:id/widget-types/:typeId/schema` 交 schema,每个模块写一句 `description` 给模型读,每条记录的形状是一份 JSON Schema;`PUT /cli/buddies/:id/widget-types/:typeId/page` 交展示页面,单个 HTML 文件。
|
|
180
251
|
|
|
@@ -182,7 +253,25 @@ my-buddy/ 工程目录
|
|
|
182
253
|
|
|
183
254
|
用法见 [examples/aunt-tu/](examples/aunt-tu/)。
|
|
184
255
|
|
|
185
|
-
##
|
|
256
|
+
## 4. 会话历史:MLBMessage → AgentMessage → LLMMessage
|
|
257
|
+
|
|
258
|
+
开发者不需要保存会话历史,也不需要把聊天里的消息换成模型消息,这些由运行时完成。每场会话的消息都保存在平台上,搭子进程重启后历史照样在。从平台上的 `MLBMessage` 到模型收到的 `LLMMessage`:
|
|
259
|
+
|
|
260
|
+
```
|
|
261
|
+
MLBMessage[] → AgentMessage[] → transformContext() → AgentMessage[] → convertToLlm() → LLMMessage[] → LLM
|
|
262
|
+
▲ (1) │ ▲ (2) (3) │
|
|
263
|
+
└─────(5)──────┘ └──────────────────────────────────────(4)───────────────────────────────────────┘
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
1. 平台上的 `MLBMessage` 换成 pi 的 `AgentMessage`,追加进会话历史。一条消息只换一次:会话起来时换一遍平台上已有的全部消息,之后来一条换一条。什么消息换成什么,见 4.1。
|
|
267
|
+
2. `transformContext()`:开发者可选。入参是完整的会话历史,返回值只用于这一次请求,不改动历史。
|
|
268
|
+
3. `convertToLlm()`:运行时实现,开发者不能替换,做什么见 4.3。换出来的 `LLMMessage`(即 pi-ai 的 `Message`)连同 `systemPrompt` 与 `tools` 发给模型。
|
|
269
|
+
4. 模型的回复,以及它调用工具得到的结果,直接追加进会话历史,不经过 (1)。
|
|
270
|
+
5. 经 (4) 追加进历史的消息,运行时再换成 `MLBMessage` 写回平台;经 (1) 从平台来的不会写回。用户在聊天里看到的回复就是这一步写上去的。用过授权数据的那一轮,写回前先脱敏,见 3.4.2。搭子重启后,这些消息经 (1) 取回。
|
|
271
|
+
|
|
272
|
+
(1) 在消息到来时发生;(2)、(3) 在每次请求模型前都完整跑一遍,一轮回复里模型可能请求好几次,比如调完工具接着说,每次都从当时完整的会话历史重新算;(4)、(5) 在模型每说完一段、每跑完一步工具时发生。
|
|
273
|
+
|
|
274
|
+
## 5. 环境变量
|
|
186
275
|
|
|
187
276
|
| 变量 | 说明 |
|
|
188
277
|
|---|---|
|
|
@@ -193,7 +282,7 @@ my-buddy/ 工程目录
|
|
|
193
282
|
|
|
194
283
|
搭子的档案(名称、头像、简介)由平台保存:注册时通过 `POST /cli/buddies` 提交,修改通过 `PUT /cli/buddies/:id/meta`。搭子进程不监听端口、不接收入站请求。从非回环地址连接网关时,平台将其识别为 `<id>-dev` 分身,会话与正式身份隔离。
|
|
195
284
|
|
|
196
|
-
## 开发
|
|
285
|
+
## 6. 开发
|
|
197
286
|
|
|
198
287
|
- `npm run dev`:以 `node --watch` 启动,文件变更后自动重启。停止时需终止整个进程树(`pkill -f "node --watch .* src/main.ts"`),仅终止子进程会被父进程重新拉起。
|
|
199
288
|
- 会话消息拉取遇到临时网络错误时会主动指数退避重试(1 秒起步、最高 30 秒);新的 SSE 通知会取消等待并立即重拉。
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
// 不管:Agent 建好之后的事(回合、事件分发在 index.ts)。
|
|
8
8
|
import { Agent } from "@earendil-works/pi-agent-core";
|
|
9
9
|
import { clampThinkingLevel, getSupportedThinkingLevels } from "@earendil-works/pi-ai";
|
|
10
|
-
import {
|
|
10
|
+
import { agentMessagesToLLMMessages } from "./agentMessageLLMMessageConverter.js";
|
|
11
11
|
import { errorText } from "../log.js";
|
|
12
12
|
import { dataAccessTool, DataAccessUsageTracker } from "../tools/dataAccess.js";
|
|
13
13
|
import { readResourceTool, resourceCatalog } from "../tools/resource.js";
|
|
@@ -90,7 +90,7 @@ export async function createAgent(deps) {
|
|
|
90
90
|
return base;
|
|
91
91
|
},
|
|
92
92
|
convertToLlm: (messages) => {
|
|
93
|
-
const llmMessages =
|
|
93
|
+
const llmMessages = agentMessagesToLLMMessages(messages);
|
|
94
94
|
log.info("convertToLlm 出参", { convoKey: key, messageCount: llmMessages.length });
|
|
95
95
|
return llmMessages;
|
|
96
96
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/conversation/agent.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,uEAAuE;AACvE,0FAA0F;AAC1F,6DAA6D;AAC7D,iGAAiG;AACjG,oDAAoD;AACpD,sCAAsC;AAEtC,OAAO,EAAE,KAAK,EAAE,MAAM,+BAA+B,CAAC;AAEtD,OAAO,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AAEvF,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"agent.js","sourceRoot":"","sources":["../../src/conversation/agent.ts"],"names":[],"mappings":"AAAA,wCAAwC;AACxC,uEAAuE;AACvE,0FAA0F;AAC1F,6DAA6D;AAC7D,iGAAiG;AACjG,oDAAoD;AACpD,sCAAsC;AAEtC,OAAO,EAAE,KAAK,EAAE,MAAM,+BAA+B,CAAC;AAEtD,OAAO,EAAE,kBAAkB,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAC;AAEvF,OAAO,EAAE,0BAA0B,EAAE,MAAM,sCAAsC,CAAC;AAClF,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEtC,OAAO,EAAE,cAAc,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEzE,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AA2BlD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAe;IAChD,MAAM,eAAe,GAAG,IAAI,sBAAsB,EAAE,CAAC;IACrD,MAAM,YAAY,GAAiB;QAClC,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,GAAG,EAAE,IAAI,CAAC,GAAG;QACb,MAAM,EAAE;YACP,IAAI,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC;YAC5C,KAAK,EAAE,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,CAAC;YAClE,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC;SACxD;QACD,UAAU,EAAE;YACX,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC;SACnG;KACD,CAAC;IACF,MAAM,OAAO,GAAiB,MAAM,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IAC/D,MAAM,CAAC,KAAK,EAAE,YAAY,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,gBAAgB,EAAE,CAAC,CAAC,CAAC;IAC/F,MAAM,SAAS,GAAG,YAAY,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,eAAe,EAAE,YAAY,CAAC,CAAC,CAAC;IAC1H,MAAM,KAAK,GAAgB;QAC1B,GAAG,SAAS;QACZ,GAAG,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC;QAC5C,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACxE,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,IAAI,EAAE,CAAC;KACrC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC1B,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACrB,CAAC;IACD,MAAM,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;IAC1B,MAAM,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC,aAAa,CAAC;IACzD,IAAI,aAAa,KAAK,SAAS,EAAE,CAAC;QACjC,MAAM,SAAS,GAAG,0BAA0B,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACzD,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;YACxC,GAAG,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,KAAK,CAAC,EAAE,YAAY,aAAa,EAAE,EAAE;gBACxD,QAAQ,EAAE,GAAG;gBACb,SAAS;gBACT,kDAAkD;gBAClD,oDAAoD;gBACpD,KAAK,EAAE,aAAa,KAAK,KAAK,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,kBAAkB,CAAC,IAAI,CAAC,KAAK,EAAE,aAAa,CAAC;aAClG,CAAC,CAAC;QACJ,CAAC;IACF,CAAC;IACD,MAAM,OAAO,GAAG,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;IAChD,MAAM,YAAY,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAC9C,MAAM,SAAS,GAAG,OAAO,CAAC,cAAc,CAAC;IACzC,MAAM,QAAQ,GAAG,OAAO,CAAC,aAAa,CAAC;IACvC,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC;QACvB,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,SAAS,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK;QAC3B,SAAS,EAAE,SAAS,IAAI,CAAC,OAAO,IAAI,GAAG,EAAE;QACzC,YAAY,EAAE;YACb,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,mDAAmD;YACnD,YAAY,EAAE,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,YAAY,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,CAAC,YAAY,OAAO,OAAO,EAAE;YACvH,KAAK;YACL,aAAa,EAAE,OAAO,CAAC,YAAY,CAAC,aAAa,IAAI,KAAK;SAC1D;QACD,YAAY,EAAE,KAAK;QACnB,YAAY,EAAE,KAAK;QACnB,4CAA4C;QAC5C,kCAAkC;QAClC,gBAAgB,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE;YAC5C,GAAG,CAAC,IAAI,CAAC,qBAAqB,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,YAAY,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;YAClF,IAAI,YAAY,KAAK,SAAS;gBAAE,OAAO,QAAQ,CAAC;YAChD,IAAI,IAAI,GAAG,QAAQ,CAAC;YACpB,IAAI,CAAC;gBACJ,IAAI,GAAG,MAAM,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;YAC7C,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACZ,GAAG,CAAC,IAAI,CAAC,+BAA+B,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;gBAClF,IAAI,GAAG,QAAQ,CAAC;YACjB,CAAC;YACD,GAAG,CAAC,IAAI,CAAC,yBAAyB,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;YAClF,OAAO,IAAI,CAAC;QACb,CAAC;QACD,YAAY,EAAE,CAAC,QAAQ,EAAE,EAAE;YAC1B,MAAM,WAAW,GAAG,0BAA0B,CAAC,QAAQ,CAAC,CAAC;YACzD,GAAG,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,YAAY,EAAE,WAAW,CAAC,MAAM,EAAE,CAAC,CAAC;YACjF,OAAO,WAAW,CAAC;QACpB,CAAC;QACD,4CAA4C;QAC5C,SAAS,EAAE,GAAG,EAAE;YACf,GAAG,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC;YACvC,OAAO,SAAS,CAAC;QAClB,CAAC;QACD,cAAc,EACb,SAAS,KAAK,SAAS;YACtB,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,CAC3B,eAAe,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,IAAI,EAAE;gBAC1D,IAAI,CAAC;oBACJ,OAAO,MAAM,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBACzC,CAAC;gBAAC,OAAO,CAAC,EAAE,CAAC;oBACZ,GAAG,CAAC,IAAI,CAAC,4BAA4B,EAAE,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;oBAC5G,OAAO,SAAS,CAAC;gBAClB,CAAC;YACF,CAAC,CAAC;QACL,aAAa,EACZ,QAAQ,KAAK,SAAS;YACrB,CAAC,CAAC,SAAS;YACX,CAAC,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE,CAAC,eAAe,CAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,GAAG,EAAE,CAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QACzG,mBAAmB,EAAE,OAAO,CAAC,mBAAmB;QAChD,0BAA0B,EAAE,OAAO,CAAC,0BAA0B;QAC9D,eAAe,EAAE,OAAO,CAAC,eAAe;QACxC,aAAa,EAAE,OAAO,CAAC,aAAa;KACpC,CAAC,CAAC;IACH,KAAK,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IACvD,OAAO,EAAE,KAAK,EAAE,eAAe,EAAE,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { AgentMessage } from "@earendil-works/pi-agent-core";
|
|
2
|
+
import type { Message } from "@earendil-works/pi-ai";
|
|
3
|
+
/**
|
|
4
|
+
* note 变 user;相邻两条 user 合并成一条(正文中间隔一个换行);user / assistant / toolResult 原样。
|
|
5
|
+
* 返回的是新数组,合并出来的也是新对象,不改传进来的消息。
|
|
6
|
+
*/
|
|
7
|
+
export declare const agentMessagesToLLMMessages: (messages: AgentMessage[]) => Message[];
|
|
8
|
+
//# sourceMappingURL=agentMessageLLMMessageConverter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentMessageLLMMessageConverter.d.ts","sourceRoot":"","sources":["../../src/conversation/agentMessageLLMMessageConverter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,+BAA+B,CAAC;AAClE,OAAO,KAAK,EAAgB,OAAO,EAA4B,MAAM,uBAAuB,CAAC;AAE7F;;;GAGG;AACH,eAAO,MAAM,0BAA0B,GAAI,UAAU,YAAY,EAAE,KAAG,OAAO,EAa5E,CAAC"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// AgentMessage → LLMMessage 的换算:交给 pi 的 convertToLlm,每次请求模型前把 Agent 历史(经开发者 transformContext 之后的)换成模型收的消息(pi-ai 的 Message)。
|
|
2
|
+
// MLBMessage 与 AgentMessage 之间的换算不在这里,在 mlbMessageAgentMessageConverter.ts。
|
|
3
|
+
/**
|
|
4
|
+
* note 变 user;相邻两条 user 合并成一条(正文中间隔一个换行);user / assistant / toolResult 原样。
|
|
5
|
+
* 返回的是新数组,合并出来的也是新对象,不改传进来的消息。
|
|
6
|
+
*/
|
|
7
|
+
export const agentMessagesToLLMMessages = (messages) => {
|
|
8
|
+
const out = [];
|
|
9
|
+
for (const m of messages) {
|
|
10
|
+
const next = agentMessageToLLMMessage(m);
|
|
11
|
+
if (next === undefined)
|
|
12
|
+
continue;
|
|
13
|
+
const prev = out[out.length - 1];
|
|
14
|
+
if (next.role === "user" && prev !== undefined && prev.role === "user") {
|
|
15
|
+
out[out.length - 1] = mergeUsers(prev, next);
|
|
16
|
+
}
|
|
17
|
+
else {
|
|
18
|
+
out.push(next);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
return out;
|
|
22
|
+
};
|
|
23
|
+
/** 一条 AgentMessage 到模型那边是什么:note 变 user;pi harness 自己并进来的那几种 role(bashExecution / custom / …)这个运行时不产生,照 pi 默认 convertToLlm 的做法不给模型 */
|
|
24
|
+
function agentMessageToLLMMessage(m) {
|
|
25
|
+
switch (m.role) {
|
|
26
|
+
case "note":
|
|
27
|
+
return { role: "user", content: [{ type: "text", text: m.text }], timestamp: m.timestamp };
|
|
28
|
+
case "user":
|
|
29
|
+
case "assistant":
|
|
30
|
+
case "toolResult":
|
|
31
|
+
return m;
|
|
32
|
+
default:
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function mergeUsers(a, b) {
|
|
37
|
+
const blocks = [...userBlocks(a), ...userBlocks(b)];
|
|
38
|
+
const text = blocks
|
|
39
|
+
.filter((block) => block.type === "text")
|
|
40
|
+
.map((block) => block.text)
|
|
41
|
+
.join("\n");
|
|
42
|
+
const images = blocks.filter((block) => block.type === "image");
|
|
43
|
+
return { role: "user", content: [{ type: "text", text }, ...images], timestamp: a.timestamp };
|
|
44
|
+
}
|
|
45
|
+
function userBlocks(m) {
|
|
46
|
+
return typeof m.content === "string" ? [{ type: "text", text: m.content }] : m.content;
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=agentMessageLLMMessageConverter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agentMessageLLMMessageConverter.js","sourceRoot":"","sources":["../../src/conversation/agentMessageLLMMessageConverter.ts"],"names":[],"mappings":"AAAA,4HAA4H;AAC5H,4EAA4E;AAK5E;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,QAAwB,EAAa,EAAE;IACjF,MAAM,GAAG,GAAc,EAAE,CAAC;IAC1B,KAAK,MAAM,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC1B,MAAM,IAAI,GAAG,wBAAwB,CAAC,CAAC,CAAC,CAAC;QACzC,IAAI,IAAI,KAAK,SAAS;YAAE,SAAS;QACjC,MAAM,IAAI,GAAG,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QACjC,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;YACxE,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;QAC9C,CAAC;aAAM,CAAC;YACP,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC;IACF,CAAC;IACD,OAAO,GAAG,CAAC;AACZ,CAAC,CAAC;AAEF,sIAAsI;AACtI,SAAS,wBAAwB,CAAC,CAAe;IAChD,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;QAChB,KAAK,MAAM;YACV,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC;QAC5F,KAAK,MAAM,CAAC;QACZ,KAAK,WAAW,CAAC;QACjB,KAAK,YAAY;YAChB,OAAO,CAAC,CAAC;QACV;YACC,OAAO,SAAS,CAAC;IACnB,CAAC;AACF,CAAC;AAED,SAAS,UAAU,CAAC,CAAc,EAAE,CAAc;IACjD,MAAM,MAAM,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IACpD,MAAM,IAAI,GAAG,MAAM;SACjB,MAAM,CAAC,CAAC,KAAK,EAAwB,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC;SAC9D,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC;SAC1B,IAAI,CAAC,IAAI,CAAC,CAAC;IACb,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAyB,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;IACvF,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE,GAAG,MAAM,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC;AAC/F,CAAC;AAED,SAAS,UAAU,CAAC,CAAc;IACjC,OAAO,OAAO,CAAC,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;AACxF,CAAC"}
|
|
@@ -8,8 +8,6 @@ export declare function splitForRebuild(records: MLBMessage[]): {
|
|
|
8
8
|
history: MLBMessage[];
|
|
9
9
|
pending: MLBMessage[];
|
|
10
10
|
};
|
|
11
|
-
/** 一批记录里最大的 seq;空批回原游标 */
|
|
12
|
-
export declare function maxSeq(records: MLBMessage[], from: number): number;
|
|
13
11
|
/** 对方的记录里要处理的:不是搭子写的,有正文或是转发卡 */
|
|
14
12
|
export declare function theirsOf(records: MLBMessage[]): MLBMessage[];
|
|
15
13
|
/**
|
|
@@ -17,9 +15,4 @@ export declare function theirsOf(records: MLBMessage[]): MLBMessage[];
|
|
|
17
15
|
* 该不该答只看平台下发的 shouldReply(旧平台叫 reply,没有 shouldReply 时照认),运行时不判、不让模型猜
|
|
18
16
|
*/
|
|
19
17
|
export declare function wantsReply(records: MLBMessage[]): boolean;
|
|
20
|
-
/** 一批增量:游标之后的是新的(fresh),其中对方的(theirs)交给回合 */
|
|
21
|
-
export declare function incoming(batch: MLBMessage[], pulledSeq: number): {
|
|
22
|
-
fresh: MLBMessage[];
|
|
23
|
-
theirs: MLBMessage[];
|
|
24
|
-
};
|
|
25
18
|
//# sourceMappingURL=history.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/conversation/history.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG;IAAE,OAAO,EAAE,UAAU,EAAE,CAAC;IAAC,OAAO,EAAE,UAAU,EAAE,CAAA;CAAE,CAIvG;AAED,
|
|
1
|
+
{"version":3,"file":"history.d.ts","sourceRoot":"","sources":["../../src/conversation/history.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG;IAAE,OAAO,EAAE,UAAU,EAAE,CAAC;IAAC,OAAO,EAAE,UAAU,EAAE,CAAA;CAAE,CAIvG;AAED,iCAAiC;AACjC,wBAAgB,QAAQ,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,UAAU,EAAE,CAE5D;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,OAAO,CAEzD"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// 拉回来的平台记录怎么分拣:哪些灌进历史、哪些是搭子还没回应过的、哪些是对方的、要不要开口。纯函数,不碰 Agent。
|
|
2
|
-
//
|
|
3
|
-
//
|
|
2
|
+
// 管:首次拉取(重建)的切分;挑出对方的记录;「要不要开口」的判定(重建与平时同一条)。
|
|
3
|
+
// 不管:拉取、游标与只交新消息(readMLBMessages.ts)、记录换成 pi 消息的形状(mlbMessageAgentMessageConverter.ts)、分拣之后怎么处理(index.ts)。
|
|
4
4
|
/**
|
|
5
5
|
* 首次拉取(重建):以搭子最后一次写的记录为界。之前的整段是历史,照原样灌;之后的是搭子还没回应过的,
|
|
6
6
|
* 交给回合按平时同一条规矩处理(wantsReply)。不看「最后一条」:拉取时平台追加的 context、
|
|
@@ -12,14 +12,6 @@ export function splitForRebuild(records) {
|
|
|
12
12
|
last--;
|
|
13
13
|
return { history: records.slice(0, last + 1), pending: records.slice(last + 1) };
|
|
14
14
|
}
|
|
15
|
-
/** 一批记录里最大的 seq;空批回原游标 */
|
|
16
|
-
export function maxSeq(records, from) {
|
|
17
|
-
let seq = from;
|
|
18
|
-
for (const m of records)
|
|
19
|
-
if (m.seq > seq)
|
|
20
|
-
seq = m.seq;
|
|
21
|
-
return seq;
|
|
22
|
-
}
|
|
23
15
|
/** 对方的记录里要处理的:不是搭子写的,有正文或是转发卡 */
|
|
24
16
|
export function theirsOf(records) {
|
|
25
17
|
return records.filter((m) => m.author !== "buddy" && ((m.text ?? "") !== "" || m.messagesCard !== undefined));
|
|
@@ -31,9 +23,4 @@ export function theirsOf(records) {
|
|
|
31
23
|
export function wantsReply(records) {
|
|
32
24
|
return records.some((m) => m.author === "user" && (m.shouldReply === true || (m.shouldReply === undefined && m.reply === true)));
|
|
33
25
|
}
|
|
34
|
-
/** 一批增量:游标之后的是新的(fresh),其中对方的(theirs)交给回合 */
|
|
35
|
-
export function incoming(batch, pulledSeq) {
|
|
36
|
-
const fresh = batch.filter((m) => m.seq > pulledSeq);
|
|
37
|
-
return { fresh, theirs: theirsOf(fresh) };
|
|
38
|
-
}
|
|
39
26
|
//# sourceMappingURL=history.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"history.js","sourceRoot":"","sources":["../../src/conversation/history.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,8CAA8C;AAC9C,
|
|
1
|
+
{"version":3,"file":"history.js","sourceRoot":"","sources":["../../src/conversation/history.ts"],"names":[],"mappings":"AAAA,6DAA6D;AAC7D,8CAA8C;AAC9C,2GAA2G;AAI3G;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,OAAqB;IACpD,IAAI,IAAI,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC;IAC9B,OAAO,IAAI,IAAI,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,OAAO;QAAE,IAAI,EAAE,CAAC;IAC7D,OAAO,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC;AAClF,CAAC;AAED,iCAAiC;AACjC,MAAM,UAAU,QAAQ,CAAC,OAAqB;IAC7C,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC;AAC/G,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,OAAqB;IAC/C,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,IAAI,CAAC,CAAC,CAAC,WAAW,KAAK,IAAI,IAAI,CAAC,CAAC,CAAC,WAAW,KAAK,SAAS,IAAI,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC;AAClI,CAAC"}
|
|
@@ -26,18 +26,12 @@ export interface ConversationHandleDeps {
|
|
|
26
26
|
export declare class ConversationHandle {
|
|
27
27
|
private readonly deps;
|
|
28
28
|
private readonly identity;
|
|
29
|
-
private readonly
|
|
30
|
-
private readonly
|
|
29
|
+
private readonly reader;
|
|
30
|
+
private readonly writer;
|
|
31
31
|
/** 懒建:第一次拉到消息时跑 factory 再 new */
|
|
32
32
|
private agent;
|
|
33
33
|
private dataAccessUsage;
|
|
34
|
-
/**
|
|
35
|
-
private pullChain;
|
|
36
|
-
private pullRetry;
|
|
37
|
-
private pullRetryDelay;
|
|
38
|
-
/** 读方向游标:已经拉到并处理过的最大 seq(含自己写的) */
|
|
39
|
-
private pulledSeq;
|
|
40
|
-
/** 首次拉取(after=0 全量灌历史)做过没有 */
|
|
34
|
+
/** 首次拉到的整批灌进历史(重建)做过没有 */
|
|
41
35
|
private rebuilt;
|
|
42
36
|
/** 忙时听见的、不用开口的旁听消息,回合收尾再进历史 */
|
|
43
37
|
private heard;
|
|
@@ -51,7 +45,7 @@ export declare class ConversationHandle {
|
|
|
51
45
|
private _closed;
|
|
52
46
|
private _lastActivity;
|
|
53
47
|
constructor(deps: ConversationHandleDeps);
|
|
54
|
-
/**
|
|
48
|
+
/** 正在跑回合(含收尾:等发平台的队列清空) */
|
|
55
49
|
get busy(): boolean;
|
|
56
50
|
/** 最近一次有消息进来或回合收尾的时刻,server 按它做空闲淘汰 */
|
|
57
51
|
get lastActivity(): number;
|
|
@@ -59,27 +53,25 @@ export declare class ConversationHandle {
|
|
|
59
53
|
get closed(): boolean;
|
|
60
54
|
/** 测试探针:Agent 当前的历史;还没建 Agent 时是空数组 */
|
|
61
55
|
get transcript(): readonly AgentMessage[];
|
|
62
|
-
/** SSE message
|
|
56
|
+
/** SSE message 到了:让 reader 拉一次。已退役的直接忽略 */
|
|
63
57
|
notify(): void;
|
|
64
58
|
/**
|
|
65
59
|
* SSE delete 到了(或 server 空闲淘汰、stop、会话起不来):先标退役,再打断正在跑的回合,等回合收尾。可以重复调。
|
|
66
60
|
*/
|
|
67
61
|
close(): Promise<void>;
|
|
68
|
-
/**
|
|
62
|
+
/** 标退役:不再拉、取消拉取重试;发平台的队列丢掉没发的字与写回、打断重发等待(回合收尾才不会被它拖住) */
|
|
69
63
|
private retire;
|
|
70
64
|
/**
|
|
71
|
-
*
|
|
72
|
-
* 平台的场合交代(context)是流里的一条记录,跟别的记录一起拉到;会话没了只靠 SSE delete
|
|
65
|
+
* reader 交来一批:第一次走重建,之后走 ingest。
|
|
66
|
+
* 平台的场合交代(context)是流里的一条记录,跟别的记录一起拉到;会话没了只靠 SSE delete 事件收,这里不判。
|
|
73
67
|
*/
|
|
74
|
-
private
|
|
75
|
-
private schedulePullRetry;
|
|
76
|
-
private cancelPullRetry;
|
|
68
|
+
private onMessages;
|
|
77
69
|
/**
|
|
78
|
-
* 首次拉取:建 Agent
|
|
70
|
+
* 首次拉取:建 Agent,以搭子最后一次写的记录为界,之前的整段按消息时间的先后灌进 state.messages(不经事件,天然不会被写回平台);
|
|
79
71
|
* 之后的是搭子还没回应过的,交给 admit 按平时同一条规矩处理:有该答的就起回合,没有就只进历史。
|
|
80
72
|
*/
|
|
81
73
|
private rebuild;
|
|
82
|
-
/**
|
|
74
|
+
/** 一批新记录(reader 只交比上一批晚的,自己写回的也在里面):对方的交给 admit */
|
|
83
75
|
private ingest;
|
|
84
76
|
/**
|
|
85
77
|
* 搭子还没回应过的对方记录(重建时是搭子最后一次说话之后的那段,平时是这批新来的),换成 user 消息分发。
|
|
@@ -90,12 +82,13 @@ export declare class ConversationHandle {
|
|
|
90
82
|
/**
|
|
91
83
|
* 跑一个回合。messages 有值就 prompt 它们;没值(收尾时发现队列里还有消息)就直接 continue。
|
|
92
84
|
* prompt 完把回合中 steer 进来的消化完;一句话没说就 followUp 一条 note 提醒再跑一次。
|
|
93
|
-
* 收尾:heard 进历史、
|
|
85
|
+
* 收尾:replying 关掉、等发平台的队列清空(每条写回的消息都拿到了平台定的时间)、heard 进历史、
|
|
86
|
+
* 这一轮进历史的消息按时间排好,才算不忙——排完的顺序跟手机上、跟重建出来的一样。
|
|
94
87
|
* 收尾期间又有人 steer(busy 还是 true,走不了 prompt),就接着再跑一个回合把它消化掉。
|
|
95
88
|
*/
|
|
96
89
|
private runTurn;
|
|
97
90
|
/**
|
|
98
|
-
* Agent 事件 →
|
|
91
|
+
* Agent 事件 → 发平台的队列。pi 会等这个函数返回再往下走,所以只做同步入队,网络在队列自己的链上;
|
|
99
92
|
* 抛错会让 pi 把整个回合判失败,所以整体 try/catch。退役后的事件直接丢。
|
|
100
93
|
*/
|
|
101
94
|
private onEvent;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/conversation/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/conversation/index.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAqB,YAAY,EAAE,QAAQ,EAAE,MAAM,+BAA+B,CAAC;AAC/F,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAIxD,OAAO,KAAK,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAI7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,eAAe,EAA2B,MAAM,aAAa,CAAC;AAMvG,MAAM,WAAW,sBAAsB;IACtC,uBAAuB;IACvB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,SAAS,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC;IAClB,QAAQ,EAAE,QAAQ,CAAC;IACnB,oEAAoE;IACpE,KAAK,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,WAAW,EAAE,MAAM,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;IACzC,+DAA+D;IAC/D,SAAS,EAAE,QAAQ,EAAE,CAAC;IACtB,6BAA6B;IAC7B,gBAAgB,EAAE,MAAM,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;IACnD,OAAO,EAAE,YAAY,CAAC;IACtB,GAAG,EAAE,WAAW,CAAC;IACjB,uDAAuD;IACvD,aAAa,EAAE,MAAM,IAAI,CAAC;CAC1B;AAKD,qBAAa,kBAAkB;IAC9B,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAyB;IAC9C,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAgB;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IAEzC,iCAAiC;IACjC,OAAO,CAAC,KAAK,CAAoB;IACjC,OAAO,CAAC,eAAe,CAAqC;IAC5D,0BAA0B;IAC1B,OAAO,CAAC,OAAO,CAAS;IACxB,+BAA+B;IAC/B,OAAO,CAAC,KAAK,CAAsB;IACnC,8BAA8B;IAC9B,OAAO,CAAC,IAAI,CAA4B;IACxC,sCAAsC;IACtC,OAAO,CAAC,KAAK,CAAS;IACtB,iFAAiF;IACjF,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,aAAa,CAAc;gBAEvB,IAAI,EAAE,sBAAsB;IAkBxC,2BAA2B;IAC3B,IAAI,IAAI,IAAI,OAAO,CAElB;IAED,uCAAuC;IACvC,IAAI,YAAY,IAAI,MAAM,CAEzB;IAED,uBAAuB;IACvB,IAAI,MAAM,IAAI,OAAO,CAEpB;IAED,uCAAuC;IACvC,IAAI,UAAU,IAAI,SAAS,YAAY,EAAE,CAExC;IAED,2CAA2C;IAC3C,MAAM,IAAI,IAAI;IAMd;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAM5B,yDAAyD;IACzD,OAAO,CAAC,MAAM;IAQd;;;OAGG;YACW,UAAU;IAgBxB;;;OAGG;YACW,OAAO;IAgBrB,mDAAmD;IACnD,OAAO,CAAC,MAAM;IAMd;;;;OAIG;IACH,OAAO,CAAC,KAAK;IAiBb;;;;;;OAMG;YACW,OAAO;IA+CrB;;;OAGG;IACH,OAAO,CAAC,OAAO;CAqEf"}
|