@napuketto/adapter 0.6.0 → 0.7.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/dist/milky/index.d.mts +49 -45
- package/dist/milky/index.d.mts.map +1 -1
- package/dist/milky/index.mjs +66 -5
- package/dist/milky/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/milky/index.d.mts
CHANGED
|
@@ -42,6 +42,51 @@ declare class MessageSeqIndex {
|
|
|
42
42
|
private evict;
|
|
43
43
|
}
|
|
44
44
|
//#endregion
|
|
45
|
+
//#region src/milky/action/error-map.d.ts
|
|
46
|
+
/** KernelErrorCode → Milky retcode 映射表(-400/-403 规范语义,其余自定负数)。 */
|
|
47
|
+
type MilkyErrorCodeMap = Record<KernelErrorCode, number>;
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region src/milky/action/base-action.d.ts
|
|
50
|
+
/** Milky 动作结果(retcode 为规范负数族;transport 原样组装信封)。 */
|
|
51
|
+
interface MilkyActionResult<T> {
|
|
52
|
+
status: "ok" | "failed";
|
|
53
|
+
retcode: number;
|
|
54
|
+
data: T | null;
|
|
55
|
+
message: string;
|
|
56
|
+
}
|
|
57
|
+
declare abstract class MilkyAction<TPayload, TReturn> {
|
|
58
|
+
abstract readonly name: string;
|
|
59
|
+
abstract readonly schema: ZodType<TPayload>;
|
|
60
|
+
protected abstract readonly errorCodeMap: MilkyErrorCodeMap;
|
|
61
|
+
protected abstract _handle(payload: TPayload): Promise<TReturn>;
|
|
62
|
+
/** 校验并执行(HTTP /api 入口;WS /event 不承载动作)。 */
|
|
63
|
+
handle(payload: unknown): Promise<MilkyActionResult<TReturn>>;
|
|
64
|
+
}
|
|
65
|
+
//#endregion
|
|
66
|
+
//#region src/milky/config.d.ts
|
|
67
|
+
/** Milky 配置 schema。 */
|
|
68
|
+
declare const milkyConfigSchema: z.ZodObject<{
|
|
69
|
+
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
70
|
+
host: z.ZodDefault<z.ZodString>;
|
|
71
|
+
port: z.ZodDefault<z.ZodNumber>;
|
|
72
|
+
token: z.ZodDefault<z.ZodString>;
|
|
73
|
+
eventModes: z.ZodDefault<z.ZodArray<z.ZodEnum<{
|
|
74
|
+
sse: "sse";
|
|
75
|
+
ws: "ws";
|
|
76
|
+
}>>>;
|
|
77
|
+
webhooks: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
78
|
+
cacheDir: z.ZodOptional<z.ZodString>;
|
|
79
|
+
}, z.core.$strip>;
|
|
80
|
+
/** Milky 配置类型(由 schema 推导)。 */
|
|
81
|
+
type MilkyConfig = z.infer<typeof milkyConfigSchema>;
|
|
82
|
+
//#endregion
|
|
83
|
+
//#region src/milky/transport.d.ts
|
|
84
|
+
/** 校准 logger 最小面(webhook 失败 / 配置异常提示;缺省静默)。 */
|
|
85
|
+
interface MilkyLoggerLike {
|
|
86
|
+
warn(obj: unknown, msg?: string): void;
|
|
87
|
+
info(obj: unknown, msg?: string): void;
|
|
88
|
+
}
|
|
89
|
+
//#endregion
|
|
45
90
|
//#region src/milky/api.d.ts
|
|
46
91
|
/** MilkyApi 构造参数。 */
|
|
47
92
|
interface MilkyApiOptions {
|
|
@@ -69,6 +114,8 @@ interface MilkyApiOptions {
|
|
|
69
114
|
implVersion: string;
|
|
70
115
|
/** 发送媒体 http(s)/base64 URI 下载缓存目录(缺省 = 远程媒体发送不可用)。 */
|
|
71
116
|
mediaDir?: string;
|
|
117
|
+
/** 动作层可观测出口(P2 批次一:forward 临时消息撤回失败 warn;缺省静默)。 */
|
|
118
|
+
logger?: MilkyLoggerLike;
|
|
72
119
|
}
|
|
73
120
|
declare class MilkyApi {
|
|
74
121
|
readonly msgApi: MsgApi;
|
|
@@ -89,6 +136,8 @@ declare class MilkyApi {
|
|
|
89
136
|
readonly qqVersion: string;
|
|
90
137
|
readonly implVersion: string;
|
|
91
138
|
readonly mediaDir: string | undefined;
|
|
139
|
+
/** 动作层可观测出口(缺省静默)。 */
|
|
140
|
+
readonly logger: MilkyLoggerLike | undefined;
|
|
92
141
|
/** message_seq ↔ msgId 双向映射(接收链路 record,动作侧反查)。 */
|
|
93
142
|
readonly seqIndex: MessageSeqIndex;
|
|
94
143
|
constructor(opts: MilkyApiOptions, seqIndex: MessageSeqIndex);
|
|
@@ -118,57 +167,12 @@ declare class MilkyApi {
|
|
|
118
167
|
}>;
|
|
119
168
|
}
|
|
120
169
|
//#endregion
|
|
121
|
-
//#region src/milky/action/error-map.d.ts
|
|
122
|
-
/** KernelErrorCode → Milky retcode 映射表(-400/-403 规范语义,其余自定负数)。 */
|
|
123
|
-
type MilkyErrorCodeMap = Record<KernelErrorCode, number>;
|
|
124
|
-
//#endregion
|
|
125
|
-
//#region src/milky/action/base-action.d.ts
|
|
126
|
-
/** Milky 动作结果(retcode 为规范负数族;transport 原样组装信封)。 */
|
|
127
|
-
interface MilkyActionResult<T> {
|
|
128
|
-
status: "ok" | "failed";
|
|
129
|
-
retcode: number;
|
|
130
|
-
data: T | null;
|
|
131
|
-
message: string;
|
|
132
|
-
}
|
|
133
|
-
declare abstract class MilkyAction<TPayload, TReturn> {
|
|
134
|
-
abstract readonly name: string;
|
|
135
|
-
abstract readonly schema: ZodType<TPayload>;
|
|
136
|
-
protected abstract readonly errorCodeMap: MilkyErrorCodeMap;
|
|
137
|
-
protected abstract _handle(payload: TPayload): Promise<TReturn>;
|
|
138
|
-
/** 校验并执行(HTTP /api 入口;WS /event 不承载动作)。 */
|
|
139
|
-
handle(payload: unknown): Promise<MilkyActionResult<TReturn>>;
|
|
140
|
-
}
|
|
141
|
-
//#endregion
|
|
142
170
|
//#region src/milky/action/index.d.ts
|
|
143
171
|
/** Milky 动作注册表(P0+P1 49 动作)。 */
|
|
144
172
|
declare function createMilkyActionRegistry(opts: {
|
|
145
173
|
api: MilkyApi;
|
|
146
174
|
}): ActionRegistry<MilkyAction<unknown, unknown>>;
|
|
147
175
|
//#endregion
|
|
148
|
-
//#region src/milky/config.d.ts
|
|
149
|
-
/** Milky 配置 schema。 */
|
|
150
|
-
declare const milkyConfigSchema: z.ZodObject<{
|
|
151
|
-
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
152
|
-
host: z.ZodDefault<z.ZodString>;
|
|
153
|
-
port: z.ZodDefault<z.ZodNumber>;
|
|
154
|
-
token: z.ZodDefault<z.ZodString>;
|
|
155
|
-
eventModes: z.ZodDefault<z.ZodArray<z.ZodEnum<{
|
|
156
|
-
sse: "sse";
|
|
157
|
-
ws: "ws";
|
|
158
|
-
}>>>;
|
|
159
|
-
webhooks: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
160
|
-
cacheDir: z.ZodOptional<z.ZodString>;
|
|
161
|
-
}, z.core.$strip>;
|
|
162
|
-
/** Milky 配置类型(由 schema 推导)。 */
|
|
163
|
-
type MilkyConfig = z.infer<typeof milkyConfigSchema>;
|
|
164
|
-
//#endregion
|
|
165
|
-
//#region src/milky/transport.d.ts
|
|
166
|
-
/** 校准 logger 最小面(webhook 失败 / 配置异常提示;缺省静默)。 */
|
|
167
|
-
interface MilkyLoggerLike {
|
|
168
|
-
warn(obj: unknown, msg?: string): void;
|
|
169
|
-
info(obj: unknown, msg?: string): void;
|
|
170
|
-
}
|
|
171
|
-
//#endregion
|
|
172
176
|
//#region src/milky/adapter.d.ts
|
|
173
177
|
/** 适配器构造参数(api 相关字段继承 MilkyApiOptions)。 */
|
|
174
178
|
interface MilkyAdapterOptions extends MilkyApiOptions {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/milky/helper/seq-index.ts","../../src/milky/
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../../src/milky/helper/seq-index.ts","../../src/milky/action/error-map.ts","../../src/milky/action/base-action.ts","../../src/milky/config.ts","../../src/milky/transport.ts","../../src/milky/api.ts","../../src/milky/action/index.ts","../../src/milky/adapter.ts"],"mappings":";;;;;;UAuBiB;EACb,UAAU;EACV;EACA;;cAGS;;mBAEQ;;mBAEA;;mBAEA;;EAGjB,OAAO,KAAK;;EAeZ,aAAa,UAAU,UAAU,iBAAiB;;;;;EAQlD,iBACI,mBACD;IAAc;IAAoB;IAAkB;;;UAgB/C;;;;;EAQR,cAAc,eAAe,OAAO;;EAepC,eAAe,gBAAgB;;UAKvB;;;;;KClGA,oBAAoB,OAAO;;;;UCItB,kBAAkB;EAC/B;EACA;EACA,MAAM;EACN;;uBAYkB,YAAY,UAAU;oBACtB;oBACA,QAAQ,QAAQ;8BACN,cAAc;qBAEvB,QAAQ,SAAS,WAAW,QAAQ;;EAGjD,OAAO,mBAAmB,QAAQ,kBAAkB;;;;;cC5BjD,mBAAiB,EAAA;;;;;;;;;;;GAe5B,EAAA,KAAA;;KAGU,cAAc,EAAE,aAAa;;;;UCQxB;EACb,KAAK,cAAc;EACnB,KAAK,cAAc;;;;;UCVN;EACb,QAAQ;EACR,UAAU;EACV,WAAW;EACX,YAAY;;EAEZ,gBAAgB;EAChB,WAAW;EACX,QAAQ;EACR,gBAAgB;EAChB,cAAc;;EAEd;IAAQ;IAAa;IAAkB;;;EAEvC,aAAa;;EAEb;;EAEA;;EAEA;;EAEA,SAAS;;cAGA;WACA,QAAQ;WACR,UAAU;WACV,WAAW;WACX,YAAY;WACZ,gBAAgB;WAChB,WAAW;WACX,QAAQ;WACR,gBAAgB;WAChB,cAAc;WACd;IAAQ;IAAa;IAAkB;;WACvC,YAAY;WACZ;WACA;WACA;;WAEA,QAAQ;;WAER,UAAU;EAEnB,YAAY,MAAM,iBAAiB,UAAU;;EAoB7C,SAAS,iBAAiB,QAAQ;;EAKlC,SAAS,iBAAiB,QAAQ;;;;;EAQ5B,kBAAkB,uBAAuB;;;;;EAiBzC,YAAY,oCAAoC,aAAa,QAAQ;;;;;EAqBrE,kBACF,MAAM,MACN,aACA,UAAU,mBACX;;EAeG,kBACF,MAAM,MACN,gBACD;IAAU;IAAqB;;;;;;iBC/FtB,0BAA0B;EACtC,KAAK;IACL,eAAe;;;;UCzBF,4BAA4B;EACzC,QAAQ,eAAe;EACvB,aAAa;;EAEb,YAAY;;EAEZ,eAAe;;EAEf,eAAe;;EAEf,SAAS;;cAGA,8BAA8B,oBAAoB;WAClD;mBAEQ;mBACA;mBACA;mBACA;mBACA;mBACA;;WAER,UAAU,kBAAkB;UAC7B;UACA;EAER,YAAY,MAAM;;UAoBJ;;UAuBA;;UAMA;;UASN;;UA4BA;;UAQM;;UAuBA;;UAeN;;UASM;;UAWN;;UAkBM;;UASA;;UAgBA;;UAkBN;;UAWM;;UAaN;;UAcA"}
|
package/dist/milky/index.mjs
CHANGED
|
@@ -27,6 +27,8 @@ var MilkyApi = class {
|
|
|
27
27
|
qqVersion;
|
|
28
28
|
implVersion;
|
|
29
29
|
mediaDir;
|
|
30
|
+
/** 动作层可观测出口(缺省静默)。 */
|
|
31
|
+
logger;
|
|
30
32
|
/** message_seq ↔ msgId 双向映射(接收链路 record,动作侧反查)。 */
|
|
31
33
|
seqIndex;
|
|
32
34
|
constructor(opts, seqIndex) {
|
|
@@ -44,6 +46,7 @@ var MilkyApi = class {
|
|
|
44
46
|
this.qqVersion = opts.qqVersion;
|
|
45
47
|
this.implVersion = opts.implVersion;
|
|
46
48
|
this.mediaDir = opts.mediaDir;
|
|
49
|
+
this.logger = opts.logger;
|
|
47
50
|
this.seqIndex = seqIndex;
|
|
48
51
|
}
|
|
49
52
|
/** uin → uid(私聊目标 / at 段发送转换 / 群管动作的 uid 入参)。 */
|
|
@@ -939,8 +942,8 @@ async function writeBase64(payload, mediaDir) {
|
|
|
939
942
|
* 跳过——规范兼容性要求「数组中未知项跳过」)。forward 接收段不经 canonical:
|
|
940
943
|
* kernel 无 MULTI_FORWARD 分支,adapter 从 RawMessage 提取 resId 后经
|
|
941
944
|
* incomingForwardSegment + ctx 注入。
|
|
942
|
-
* 发送方向:OutgoingSegment → canonical(10
|
|
943
|
-
*
|
|
945
|
+
* 发送方向:OutgoingSegment → canonical(10 种全映射;forward 顶层段不走本转换器,
|
|
946
|
+
* 由 sendMilkyMessage 分流到组装链——本转换器内 forward 报错只拦截混发/嵌套)。
|
|
944
947
|
*/
|
|
945
948
|
/** uin 字符串 → Milky user_id(非有限正数 = 转换失败)。 */
|
|
946
949
|
function toUserId(uin) {
|
|
@@ -1114,7 +1117,9 @@ function rawToPayload(raw) {
|
|
|
1114
1117
|
/**
|
|
1115
1118
|
* OutgoingSegment 数组 → canonical 元素(同步映射;媒体 URI 解析与 at uin→uid
|
|
1116
1119
|
* 由调用方在返回值上继续处理)。
|
|
1117
|
-
* forward
|
|
1120
|
+
* forward 在此报错:顶层 forward 已由 sendMilkyMessage 分流到组装链(message.ts,
|
|
1121
|
+
* P2 批次一),命中本分支 = forward 与其他段混发漏网或嵌套 forward(组装链内逐项
|
|
1122
|
+
* 转换经过此处)——均显式拒绝。
|
|
1118
1123
|
*/
|
|
1119
1124
|
function outgoingSegmentsToCanonical(segments) {
|
|
1120
1125
|
const elements = [];
|
|
@@ -1179,7 +1184,7 @@ function outgoingSegmentsToCanonical(segments) {
|
|
|
1179
1184
|
raw: seg.data.json_payload
|
|
1180
1185
|
});
|
|
1181
1186
|
break;
|
|
1182
|
-
case "forward": throw kernelError("forward
|
|
1187
|
+
case "forward": throw kernelError("forward 段不可与其他消息段混发或嵌套(顶层 forward 须单独发送)", "INVALID_PARAM");
|
|
1183
1188
|
}
|
|
1184
1189
|
return {
|
|
1185
1190
|
elements,
|
|
@@ -1399,14 +1404,70 @@ async function recallBySeq(peer, seq, api) {
|
|
|
1399
1404
|
if (msgId === void 0) throw kernelError(`消息 ${seq} 不存在`, "NOT_FOUND");
|
|
1400
1405
|
await api.msgApi.recallMessage(peer, [msgId]);
|
|
1401
1406
|
}
|
|
1402
|
-
/** 发送核心:segments → canonical(URI/ID 转换)→ sendMessage → 回查输出。
|
|
1407
|
+
/** 发送核心:segments → canonical(URI/ID 转换)→ sendMessage → 回查输出。
|
|
1408
|
+
* forward 段分流到组装链(P2 批次一,临时消息法)。 */
|
|
1403
1409
|
async function sendMilkyMessage(peer, segments, api) {
|
|
1410
|
+
if (segments.some((s) => s.type === "forward")) return await sendForwardComposition(peer, segments, api);
|
|
1404
1411
|
const { elements, atUins } = outgoingSegmentsToCanonical(segments);
|
|
1405
1412
|
const resolved = await resolveElements(elements, atUins, api);
|
|
1406
1413
|
if (resolved.length === 0) throw kernelError("消息内容为空(全部消息段不可用)", "INVALID_PARAM");
|
|
1407
1414
|
const { msgId } = await api.msgApi.sendMessage(peer, resolved);
|
|
1408
1415
|
return await api.resolveSentOutput(peer, msgId);
|
|
1409
1416
|
}
|
|
1417
|
+
/**
|
|
1418
|
+
* forward 段组装链(P2 批次一,milky.md §0.6):仅支持单 forward 单独发。
|
|
1419
|
+
* 临时消息法:逐条发送 messages[i].segments → sendForwardMessage(buildMultiForwardMsg
|
|
1420
|
+
* 以目标 peer 的真实消息组装 → sendMsg)→ best-effort 撤回临时消息 → 回查输出。
|
|
1421
|
+
*
|
|
1422
|
+
* 已知差异(规范语义 vs kernel 出口,待实机联调):节点发送者恒为机器人自己
|
|
1423
|
+
* (user_id / sender_name / time 不参与组装);title / preview / summary / prompt 忽略。
|
|
1424
|
+
*/
|
|
1425
|
+
async function sendForwardComposition(peer, segments, api) {
|
|
1426
|
+
if (segments.length !== 1) throw kernelError("forward 段必须单独发送(不支持与其他消息段混发)", "INVALID_PARAM");
|
|
1427
|
+
const [forward] = segments;
|
|
1428
|
+
if (forward === void 0 || forward.type !== "forward") throw kernelError("forward 组装链收到非 forward 段", "UNKNOWN");
|
|
1429
|
+
const messages = narrowForwardMessages(forward);
|
|
1430
|
+
const srcMsgIds = [];
|
|
1431
|
+
for (const [i, item] of messages.entries()) {
|
|
1432
|
+
const { elements, atUins } = outgoingSegmentsToCanonical(item.segments);
|
|
1433
|
+
const resolved = await resolveElements(elements, atUins, api);
|
|
1434
|
+
if (resolved.length === 0) throw kernelError(`forward 第 ${i + 1} 条消息无可用内容段`, "INVALID_PARAM");
|
|
1435
|
+
const { msgId } = await api.msgApi.sendMessage(peer, resolved);
|
|
1436
|
+
srcMsgIds.push(msgId);
|
|
1437
|
+
}
|
|
1438
|
+
const { msgId } = await api.msgApi.sendForwardMessage(peer, peer, srcMsgIds);
|
|
1439
|
+
await recallTempMessages(peer, srcMsgIds, api);
|
|
1440
|
+
return await api.resolveSentOutput(peer, msgId);
|
|
1441
|
+
}
|
|
1442
|
+
/**
|
|
1443
|
+
* forward 段载荷收窄(入口 schema 只保证 data 为 record):messages 非空数组,
|
|
1444
|
+
* 项内 segments 非空数组。user_id / sender_name / time 不参与组装不校验
|
|
1445
|
+
* (丢弃字段不设门槛);title / preview / summary / prompt 忽略。
|
|
1446
|
+
*/
|
|
1447
|
+
function narrowForwardMessages(forward) {
|
|
1448
|
+
const raw = forward.data.messages;
|
|
1449
|
+
if (!Array.isArray(raw) || raw.length === 0) throw kernelError("forward 段 messages 必须是非空数组", "INVALID_PARAM");
|
|
1450
|
+
const out = [];
|
|
1451
|
+
for (const item of raw) {
|
|
1452
|
+
if (typeof item !== "object" || item === null) throw kernelError("forward 段 messages 项必须是对象", "INVALID_PARAM");
|
|
1453
|
+
const segments = item.segments;
|
|
1454
|
+
if (!Array.isArray(segments) || segments.length === 0) throw kernelError("forward 段 messages 项的 segments 必须是非空数组", "INVALID_PARAM");
|
|
1455
|
+
out.push(item);
|
|
1456
|
+
}
|
|
1457
|
+
return out;
|
|
1458
|
+
}
|
|
1459
|
+
/** 临时消息清理(best-effort:失败只留可见垃圾,转发已发出——warn 可观测不抛)。 */
|
|
1460
|
+
async function recallTempMessages(peer, msgIds, api) {
|
|
1461
|
+
try {
|
|
1462
|
+
await api.msgApi.recallMessage(peer, msgIds);
|
|
1463
|
+
} catch (e) {
|
|
1464
|
+
api.logger?.warn({
|
|
1465
|
+
peer: peer.peerUid,
|
|
1466
|
+
count: msgIds.length,
|
|
1467
|
+
error: e instanceof Error ? e.message : String(e)
|
|
1468
|
+
}, "milky: forward 临时消息撤回失败(转发已发出)");
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1410
1471
|
/** 元素二次解析:at uin→uid + 远程媒体 URI 落盘(reply seq 已在映射层兜底原样)。 */
|
|
1411
1472
|
async function resolveElements(elements, atUins, api) {
|
|
1412
1473
|
const uinToUid = await resolveAtUins(atUins, api);
|