@kmchai/cortico-bot-gateway 0.1.0 → 0.1.1
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/CHANGELOG.md +5 -0
- package/README.md +1 -1
- package/index.ts +2 -2
- package/package.json +1 -1
- package/persona/persona.ts +24 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
## 0.1.1
|
|
2
|
+
|
|
3
|
+
- 主 session 重新声明 `outputTap`,把挂载 World 的接收器扇进来。语音 World 的概率自动朗读此前在网关 bot 里完全拿不到主 session 正文,只有显式 `voice_speak` 工具能出声;现在纯文本回复能按语音 World 的概率触发。
|
|
4
|
+
|
|
1
5
|
## 0.1.0
|
|
2
6
|
|
|
3
7
|
- 初版网关 bot:人设、情绪基调、能力路由与 `end_turn`。
|
|
8
|
+
- 显示名统一为 `Kmch AI · 网关`(bot 默认名与 Persona 页标签)。
|
|
4
9
|
- 声明 `console`、`qq`、`voice`、`service` 四个 World。
|
|
5
10
|
- 前缀写入 QQ 语音交付链:`voice_speak({ silent: true })` → `[blob log:…]` → `qq_draft` → `qq_confirm`;失败退回文字。
|
|
6
11
|
- 记忆未实现:只留 `memoryDir`、`FileBlobStore` 与 `MEMORY.seed.md`,不提供记忆工具或页面。
|
package/README.md
CHANGED
|
@@ -31,6 +31,6 @@ Live2D 的安装、启用与配置状态,并链接到对应的 World 页或扩
|
|
|
31
31
|
|
|
32
32
|
- 工具只有各 World 的加 `end_turn`;不提供记忆工具,也没有 Memory 页。
|
|
33
33
|
- `MEMORY.md` 只是以后挂记忆的落点,v0.1 不读写它。
|
|
34
|
-
- 是否自动朗读由语音 World
|
|
34
|
+
- 是否自动朗读由语音 World 的概率决定,网关不重复掷骰子;主 session 把挂载 World 的 `outputTap` 扇进来,语音才拿得到正文。
|
|
35
35
|
- QQ 语音走显式工具链:`voice_speak({ silent: true })` → `[blob log:…]` →
|
|
36
36
|
`qq_draft({ voice, to })` → `qq_confirm`;失败时退回文字。
|
package/index.ts
CHANGED
|
@@ -25,7 +25,7 @@ function gatewayPages(loaded: LoadedConfig<GatewayConfig>, worlds: World[]): Web
|
|
|
25
25
|
{
|
|
26
26
|
id: 'persona:gateway',
|
|
27
27
|
kind: 'persona',
|
|
28
|
-
label: '网关',
|
|
28
|
+
label: 'Kmch AI · 网关',
|
|
29
29
|
panels: [{ id: 'gateway', title: '能力', getMethods: ['status'] }],
|
|
30
30
|
invoke: async (panel, method) => {
|
|
31
31
|
if (panel !== 'gateway' || method !== 'status') {
|
|
@@ -58,7 +58,7 @@ const definition: BotDefinition<GatewayConfig> = {
|
|
|
58
58
|
declares: DECLARES,
|
|
59
59
|
defaults: () => ({
|
|
60
60
|
...structuredClone(CORE_DEFAULTS),
|
|
61
|
-
displayName: 'Kmch AI',
|
|
61
|
+
displayName: 'Kmch AI · 网关',
|
|
62
62
|
rounds: { soft: 6, hard: 12 },
|
|
63
63
|
}),
|
|
64
64
|
build,
|
package/package.json
CHANGED
package/persona/persona.ts
CHANGED
|
@@ -7,6 +7,7 @@ import { join } from 'node:path';
|
|
|
7
7
|
import type {
|
|
8
8
|
BlobStore,
|
|
9
9
|
CoreApi,
|
|
10
|
+
OutputTap,
|
|
10
11
|
Persona,
|
|
11
12
|
PrefixSegment,
|
|
12
13
|
RoundCaps,
|
|
@@ -16,6 +17,7 @@ import type {
|
|
|
16
17
|
ToolDef,
|
|
17
18
|
World,
|
|
18
19
|
} from 'cortico/core/types.ts';
|
|
20
|
+
import { defaultExternalizes } from 'cortico/core/types.ts';
|
|
19
21
|
import { renderTemplate } from 'cortico/core/template.ts';
|
|
20
22
|
import { readTextFile } from 'cortico/core/util.ts';
|
|
21
23
|
import { FileBlobStore } from './blobs.ts';
|
|
@@ -89,6 +91,7 @@ export class GatewayPersona implements Persona {
|
|
|
89
91
|
}
|
|
90
92
|
|
|
91
93
|
declareSessions(): SessionDecl[] {
|
|
94
|
+
const self = this;
|
|
92
95
|
return [
|
|
93
96
|
{
|
|
94
97
|
id: MAIN,
|
|
@@ -96,12 +99,33 @@ export class GatewayPersona implements Persona {
|
|
|
96
99
|
rounds: this.opts.rounds,
|
|
97
100
|
persistent: true,
|
|
98
101
|
receivesEvents: true,
|
|
102
|
+
// World 的接收器扇入主 session;语音的自动朗读靠它拿到正文。
|
|
103
|
+
get outputTap() { return self.outputTap(); },
|
|
99
104
|
// World 的工具在前、自有工具在后:工具表顺序影响请求前缀的缓存命中。
|
|
100
105
|
tools: () => [...this.opts.worlds.flatMap((w) => w.tools()), endTurnTool()],
|
|
101
106
|
},
|
|
102
107
|
];
|
|
103
108
|
}
|
|
104
109
|
|
|
110
|
+
/**
|
|
111
|
+
* 主 session 的输出旁路:挂载 World 的接收器扇成一个 tap。没有任何接收器时不声明。
|
|
112
|
+
* 每批投递时现取,World 运行中挂载/卸载即生效。
|
|
113
|
+
*/
|
|
114
|
+
private outputTap(): OutputTap | undefined {
|
|
115
|
+
const taps = this.opts.worlds.flatMap((world) => {
|
|
116
|
+
const tap = world.outputTap?.();
|
|
117
|
+
return tap ? [tap] : [];
|
|
118
|
+
});
|
|
119
|
+
if (taps.length === 0) return undefined;
|
|
120
|
+
if (taps.length === 1) return taps[0];
|
|
121
|
+
return {
|
|
122
|
+
onEvent: (event) => { for (const tap of taps) tap.onEvent(event); },
|
|
123
|
+
externalizes: (event) => taps.some((tap) => (tap.externalizes?.(event) ?? defaultExternalizes(event))),
|
|
124
|
+
onRoundEnd: () => { for (const tap of taps) tap.onRoundEnd?.(); },
|
|
125
|
+
onAbort: (reason) => { for (const tap of taps) tap.onAbort?.(reason); },
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
105
129
|
/** 自有工具名;装配层据此拒绝与之撞名的 World。 */
|
|
106
130
|
ownToolNames(): string[] {
|
|
107
131
|
return GATEWAY_TOOL_DECLS.map((decl) => decl.name);
|