@zhin.js/core 1.3.1 → 1.3.2
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 +59 -4
- package/lib/adapter.d.ts +19 -1
- package/lib/adapter.d.ts.map +1 -1
- package/lib/adapter.js +39 -5
- package/lib/adapter.js.map +1 -1
- package/lib/built/adapter-process.d.ts +11 -1
- package/lib/built/adapter-process.d.ts.map +1 -1
- package/lib/built/adapter-process.js +43 -1
- package/lib/built/adapter-process.js.map +1 -1
- package/lib/built/command.d.ts +2 -0
- package/lib/built/command.d.ts.map +1 -1
- package/lib/built/command.js +13 -1
- package/lib/built/command.js.map +1 -1
- package/lib/built/endpoint-commands.d.ts +4 -0
- package/lib/built/endpoint-commands.d.ts.map +1 -0
- package/lib/built/endpoint-commands.js +102 -0
- package/lib/built/endpoint-commands.js.map +1 -0
- package/lib/built/endpoint-lifecycle-service.d.ts +27 -0
- package/lib/built/endpoint-lifecycle-service.d.ts.map +1 -0
- package/lib/built/endpoint-lifecycle-service.js +219 -0
- package/lib/built/endpoint-lifecycle-service.js.map +1 -0
- package/lib/built/endpoint-manager.d.ts +35 -0
- package/lib/built/endpoint-manager.d.ts.map +1 -0
- package/lib/built/endpoint-manager.js +2 -0
- package/lib/built/endpoint-manager.js.map +1 -0
- package/lib/built/generated-qrcode.d.ts +25 -0
- package/lib/built/generated-qrcode.d.ts.map +1 -0
- package/lib/built/generated-qrcode.js +46 -0
- package/lib/built/generated-qrcode.js.map +1 -0
- package/lib/built/html-renderer-loader.d.ts +12 -0
- package/lib/built/html-renderer-loader.d.ts.map +1 -0
- package/lib/built/html-renderer-loader.js +29 -0
- package/lib/built/html-renderer-loader.js.map +1 -0
- package/lib/built/html-segment-fallback.d.ts +2 -1
- package/lib/built/html-segment-fallback.d.ts.map +1 -1
- package/lib/built/html-segment-fallback.js.map +1 -1
- package/lib/built/introspection-format.d.ts +11 -0
- package/lib/built/introspection-format.d.ts.map +1 -0
- package/lib/built/introspection-format.js +28 -0
- package/lib/built/introspection-format.js.map +1 -0
- package/lib/built/login-assist.d.ts +1 -1
- package/lib/built/login-assist.d.ts.map +1 -1
- package/lib/built/management-command-guard.d.ts +11 -0
- package/lib/built/management-command-guard.d.ts.map +1 -0
- package/lib/built/management-command-guard.js +21 -0
- package/lib/built/management-command-guard.js.map +1 -0
- package/lib/built/outbound-media-contract.d.ts +23 -0
- package/lib/built/outbound-media-contract.d.ts.map +1 -0
- package/lib/built/outbound-media-contract.js +11 -0
- package/lib/built/outbound-media-contract.js.map +1 -0
- package/lib/built/outbound-media-utils.d.ts +10 -0
- package/lib/built/outbound-media-utils.d.ts.map +1 -0
- package/lib/built/outbound-media-utils.js +63 -0
- package/lib/built/outbound-media-utils.js.map +1 -0
- package/lib/built/qrcode-segment.d.ts +19 -0
- package/lib/built/qrcode-segment.d.ts.map +1 -0
- package/lib/built/qrcode-segment.js +79 -0
- package/lib/built/qrcode-segment.js.map +1 -0
- package/lib/built/rich-segments/adapter-policies.d.ts +10 -0
- package/lib/built/rich-segments/adapter-policies.d.ts.map +1 -0
- package/lib/built/rich-segments/adapter-policies.js +28 -0
- package/lib/built/rich-segments/adapter-policies.js.map +1 -0
- package/lib/built/rich-segments/base.d.ts +12 -0
- package/lib/built/rich-segments/base.d.ts.map +1 -0
- package/lib/built/rich-segments/base.js +25 -0
- package/lib/built/rich-segments/base.js.map +1 -0
- package/lib/built/rich-segments/builtins.d.ts +5 -0
- package/lib/built/rich-segments/builtins.d.ts.map +1 -0
- package/lib/built/rich-segments/builtins.js +41 -0
- package/lib/built/rich-segments/builtins.js.map +1 -0
- package/lib/built/rich-segments/capabilities.d.ts +7 -0
- package/lib/built/rich-segments/capabilities.d.ts.map +1 -0
- package/lib/built/rich-segments/capabilities.js +40 -0
- package/lib/built/rich-segments/capabilities.js.map +1 -0
- package/lib/built/rich-segments/html-segment.d.ts +16 -0
- package/lib/built/rich-segments/html-segment.d.ts.map +1 -0
- package/lib/built/rich-segments/html-segment.js +66 -0
- package/lib/built/rich-segments/html-segment.js.map +1 -0
- package/lib/built/rich-segments/index.d.ts +14 -0
- package/lib/built/rich-segments/index.d.ts.map +1 -0
- package/lib/built/rich-segments/index.js +14 -0
- package/lib/built/rich-segments/index.js.map +1 -0
- package/lib/built/rich-segments/markdown-segment.d.ts +15 -0
- package/lib/built/rich-segments/markdown-segment.d.ts.map +1 -0
- package/lib/built/rich-segments/markdown-segment.js +62 -0
- package/lib/built/rich-segments/markdown-segment.js.map +1 -0
- package/lib/built/rich-segments/markdown-to-text.d.ts +4 -0
- package/lib/built/rich-segments/markdown-to-text.d.ts.map +1 -0
- package/lib/built/rich-segments/markdown-to-text.js +28 -0
- package/lib/built/rich-segments/markdown-to-text.js.map +1 -0
- package/lib/built/rich-segments/qrcode-segment.d.ts +19 -0
- package/lib/built/rich-segments/qrcode-segment.d.ts.map +1 -0
- package/lib/built/rich-segments/qrcode-segment.js +74 -0
- package/lib/built/rich-segments/qrcode-segment.js.map +1 -0
- package/lib/built/rich-segments/registry.d.ts +17 -0
- package/lib/built/rich-segments/registry.d.ts.map +1 -0
- package/lib/built/rich-segments/registry.js +53 -0
- package/lib/built/rich-segments/registry.js.map +1 -0
- package/lib/built/rich-segments/resolve.d.ts +6 -0
- package/lib/built/rich-segments/resolve.d.ts.map +1 -0
- package/lib/built/rich-segments/resolve.js +88 -0
- package/lib/built/rich-segments/resolve.js.map +1 -0
- package/lib/built/rich-segments/tts-segment.d.ts +14 -0
- package/lib/built/rich-segments/tts-segment.d.ts.map +1 -0
- package/lib/built/rich-segments/tts-segment.js +52 -0
- package/lib/built/rich-segments/tts-segment.js.map +1 -0
- package/lib/built/rich-segments/types.d.ts +85 -0
- package/lib/built/rich-segments/types.d.ts.map +1 -0
- package/lib/built/rich-segments/types.js +18 -0
- package/lib/built/rich-segments/types.js.map +1 -0
- package/lib/built/schema-endpoint-manager.d.ts +18 -0
- package/lib/built/schema-endpoint-manager.d.ts.map +1 -0
- package/lib/built/schema-endpoint-manager.js +74 -0
- package/lib/built/schema-endpoint-manager.js.map +1 -0
- package/lib/built/speech-loader.d.ts +13 -0
- package/lib/built/speech-loader.d.ts.map +1 -0
- package/lib/built/speech-loader.js +28 -0
- package/lib/built/speech-loader.js.map +1 -0
- package/lib/index.d.ts +14 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +13 -0
- package/lib/index.js.map +1 -1
- package/lib/message.d.ts +8 -0
- package/lib/message.d.ts.map +1 -1
- package/lib/message.js.map +1 -1
- package/lib/plugin.d.ts.map +1 -1
- package/lib/plugin.js +3 -16
- package/lib/plugin.js.map +1 -1
- package/lib/prompt.js +1 -1
- package/lib/prompt.js.map +1 -1
- package/lib/utils.d.ts +21 -11
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +29 -2
- package/lib/utils.js.map +1 -1
- package/package.json +8 -6
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-to-text.d.ts","sourceRoot":"","sources":["../../../src/built/rich-segments/markdown-to-text.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAkBtD;AAED,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAM1D"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/** 将 Markdown 转为可读纯文本(出站 text 降级用) */
|
|
2
|
+
export function markdownToPlainText(md) {
|
|
3
|
+
let text = md;
|
|
4
|
+
text = text.replace(/```[\s\S]*?```/g, (block) => {
|
|
5
|
+
const inner = block.replace(/^```[^\n]*\n?/, '').replace(/\n?```$/, '');
|
|
6
|
+
return inner.trim() ? `${inner.trim()}\n` : '';
|
|
7
|
+
});
|
|
8
|
+
text = text.replace(/`([^`]+)`/g, '$1');
|
|
9
|
+
text = text.replace(/!\[[^\]]*\]\([^)]*\)/g, '');
|
|
10
|
+
text = text.replace(/\[([^\]]+)\]\([^)]*\)/g, '$1');
|
|
11
|
+
text = text.replace(/^#{1,6}\s+/gm, '');
|
|
12
|
+
text = text.replace(/^\s*>\s?/gm, '');
|
|
13
|
+
text = text.replace(/^\s*[-*+]\s+/gm, '');
|
|
14
|
+
text = text.replace(/\*\*([^*]+)\*\*/g, '$1');
|
|
15
|
+
text = text.replace(/__([^_]+)__/g, '$1');
|
|
16
|
+
text = text.replace(/\*([^*]+)\*/g, '$1');
|
|
17
|
+
text = text.replace(/_([^_]+)_/g, '$1');
|
|
18
|
+
text = text.replace(/~~([^~]+)~~/g, '$1');
|
|
19
|
+
return text.trim();
|
|
20
|
+
}
|
|
21
|
+
export function markdownToHtmlForRender(md) {
|
|
22
|
+
const escaped = md
|
|
23
|
+
.replace(/&/g, '&')
|
|
24
|
+
.replace(/</g, '<')
|
|
25
|
+
.replace(/>/g, '>');
|
|
26
|
+
return `<pre style="white-space:pre-wrap;font-family:sans-serif;font-size:14px;line-height:1.5;padding:16px;">${escaped}</pre>`;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=markdown-to-text.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown-to-text.js","sourceRoot":"","sources":["../../../src/built/rich-segments/markdown-to-text.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,MAAM,UAAU,mBAAmB,CAAC,EAAU;IAC5C,IAAI,IAAI,GAAG,EAAE,CAAC;IACd,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,iBAAiB,EAAE,CAAC,KAAK,EAAE,EAAE;QAC/C,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,eAAe,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QACxE,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;IACjD,CAAC,CAAC,CAAC;IACH,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IACxC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC;IACjD,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,wBAAwB,EAAE,IAAI,CAAC,CAAC;IACpD,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;IACxC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IACtC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC;IAC1C,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,IAAI,CAAC,CAAC;IAC9C,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IAC1C,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IAC1C,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IACxC,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IAC1C,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,EAAU;IAChD,MAAM,OAAO,GAAG,EAAE;SACf,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACzB,OAAO,yGAAyG,OAAO,QAAQ,CAAC;AAClI,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { MessageElement } from '../../types.js';
|
|
2
|
+
import { type GenerateQrCodeOptions } from '../generated-qrcode.js';
|
|
3
|
+
import { RichSegment } from './base.js';
|
|
4
|
+
import type { RichSegmentRenderContext, RichSegmentRenderResult } from './types.js';
|
|
5
|
+
export interface QrcodeSegmentData extends GenerateQrCodeOptions {
|
|
6
|
+
text: string;
|
|
7
|
+
/** process origin 模式终端渲染时使用 */
|
|
8
|
+
small?: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function readQrcodeSegmentData(data: Record<string, unknown>): QrcodeSegmentData;
|
|
11
|
+
export declare class QrcodeSegment extends RichSegment<QrcodeSegmentData> {
|
|
12
|
+
readonly segmentType: "qrcode";
|
|
13
|
+
readonly type: "qrcode";
|
|
14
|
+
render(mode: string, _ctx?: RichSegmentRenderContext): Promise<RichSegmentRenderResult>;
|
|
15
|
+
}
|
|
16
|
+
export declare function wrapQrcodeSegment(data: Record<string, unknown>): QrcodeSegment;
|
|
17
|
+
/** process endpoint:origin qrcode 段 → 终端 ASCII + 文本占位 */
|
|
18
|
+
export declare function interpretOriginQrcodeForProcess(content: MessageElement | string | (MessageElement | string)[]): Promise<MessageElement | string | (MessageElement | string)[]>;
|
|
19
|
+
//# sourceMappingURL=qrcode-segment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qrcode-segment.d.ts","sourceRoot":"","sources":["../../../src/built/rich-segments/qrcode-segment.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAmB,KAAK,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AACrF,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,KAAK,EAAE,wBAAwB,EAAE,uBAAuB,EAAE,MAAM,YAAY,CAAC;AAGpF,MAAM,WAAW,iBAAkB,SAAQ,qBAAqB;IAC9D,IAAI,EAAE,MAAM,CAAC;IACb,+BAA+B;IAC/B,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,iBAAiB,CAkBtF;AAED,qBAAa,aAAc,SAAQ,WAAW,CAAC,iBAAiB,CAAC;IAC/D,QAAQ,CAAC,WAAW,EAAG,QAAQ,CAAU;IACzC,QAAQ,CAAC,IAAI,EAAG,QAAQ,CAAU;IAE5B,MAAM,CACV,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,wBAAwB,GAC9B,OAAO,CAAC,uBAAuB,CAAC;CAmBpC;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,aAAa,CAE9E;AAED,yDAAyD;AACzD,wBAAsB,+BAA+B,CACnD,OAAO,EAAE,cAAc,GAAG,MAAM,GAAG,CAAC,cAAc,GAAG,MAAM,CAAC,EAAE,GAC7D,OAAO,CAAC,cAAc,GAAG,MAAM,GAAG,CAAC,cAAc,GAAG,MAAM,CAAC,EAAE,CAAC,CA0BhE"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { segment } from '../../utils.js';
|
|
2
|
+
import { GeneratedQrCode } from '../generated-qrcode.js';
|
|
3
|
+
import { RichSegment } from './base.js';
|
|
4
|
+
import { RICH_SEGMENT_MODE } from './types.js';
|
|
5
|
+
export function readQrcodeSegmentData(data) {
|
|
6
|
+
const text = typeof data.text === 'string' ? data.text : '';
|
|
7
|
+
if (!text) {
|
|
8
|
+
throw new Error('qrcode segment: missing data.text');
|
|
9
|
+
}
|
|
10
|
+
return {
|
|
11
|
+
text,
|
|
12
|
+
width: typeof data.width === 'number' ? data.width : undefined,
|
|
13
|
+
margin: typeof data.margin === 'number' ? data.margin : undefined,
|
|
14
|
+
errorCorrectionLevel: data.errorCorrectionLevel === 'L'
|
|
15
|
+
|| data.errorCorrectionLevel === 'M'
|
|
16
|
+
|| data.errorCorrectionLevel === 'Q'
|
|
17
|
+
|| data.errorCorrectionLevel === 'H'
|
|
18
|
+
? data.errorCorrectionLevel
|
|
19
|
+
: undefined,
|
|
20
|
+
small: data.small === true ? true : undefined,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export class QrcodeSegment extends RichSegment {
|
|
24
|
+
segmentType = 'qrcode';
|
|
25
|
+
type = 'qrcode';
|
|
26
|
+
async render(mode, _ctx) {
|
|
27
|
+
if (mode === RICH_SEGMENT_MODE.ORIGIN) {
|
|
28
|
+
return this.toJSON();
|
|
29
|
+
}
|
|
30
|
+
if (mode === RICH_SEGMENT_MODE.TEXT) {
|
|
31
|
+
return segment.text(`[二维码] ${this.data.text}`);
|
|
32
|
+
}
|
|
33
|
+
if (mode === RICH_SEGMENT_MODE.IMAGE) {
|
|
34
|
+
const qr = await GeneratedQrCode.generate(this.data.text, this.data);
|
|
35
|
+
return segment('image', {
|
|
36
|
+
url: qr.toDataUrl(),
|
|
37
|
+
base64: qr.toString('base64'),
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
return this.render(RICH_SEGMENT_MODE.TEXT, _ctx);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export function wrapQrcodeSegment(data) {
|
|
44
|
+
return new QrcodeSegment(readQrcodeSegmentData(data));
|
|
45
|
+
}
|
|
46
|
+
/** process endpoint:origin qrcode 段 → 终端 ASCII + 文本占位 */
|
|
47
|
+
export async function interpretOriginQrcodeForProcess(content) {
|
|
48
|
+
const items = Array.isArray(content) ? content : [content];
|
|
49
|
+
const out = [];
|
|
50
|
+
let changed = false;
|
|
51
|
+
for (const item of items) {
|
|
52
|
+
if (typeof item === 'string') {
|
|
53
|
+
out.push(item);
|
|
54
|
+
continue;
|
|
55
|
+
}
|
|
56
|
+
if (item.type !== 'qrcode') {
|
|
57
|
+
out.push(item);
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
changed = true;
|
|
61
|
+
const payload = readQrcodeSegmentData(item.data ?? {});
|
|
62
|
+
const qr = await GeneratedQrCode.generate(payload.text, payload);
|
|
63
|
+
await qr.printToTerminal({ small: payload.small ?? true });
|
|
64
|
+
out.push(segment.text(`[二维码] ${payload.text}`));
|
|
65
|
+
}
|
|
66
|
+
if (!changed)
|
|
67
|
+
return content;
|
|
68
|
+
if (out.length === 0)
|
|
69
|
+
return segment.text('');
|
|
70
|
+
if (out.length === 1)
|
|
71
|
+
return out[0];
|
|
72
|
+
return out;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=qrcode-segment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"qrcode-segment.js","sourceRoot":"","sources":["../../../src/built/rich-segments/qrcode-segment.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { OutboundRichSegmentPolicy, RichSegmentKindDefinition } from './types.js';
|
|
2
|
+
export declare class RichSegmentRegistry {
|
|
3
|
+
#private;
|
|
4
|
+
register(definition: RichSegmentKindDefinition): void;
|
|
5
|
+
has(kind: string): boolean;
|
|
6
|
+
get(kind: string): RichSegmentKindDefinition | undefined;
|
|
7
|
+
list(): RichSegmentKindDefinition[];
|
|
8
|
+
buildDefaultPolicy(): OutboundRichSegmentPolicy;
|
|
9
|
+
resolveMode(policy: OutboundRichSegmentPolicy, kind: string): string;
|
|
10
|
+
wrap(kind: string, data: Record<string, unknown>): import("./types.js").RichSegmentLike;
|
|
11
|
+
/** 测试隔离:清空后需重新 register builtins */
|
|
12
|
+
clearForTests(): void;
|
|
13
|
+
}
|
|
14
|
+
export declare const RICH_SEGMENT_FALLBACK_MODE = "origin";
|
|
15
|
+
export declare const richSegmentRegistry: RichSegmentRegistry;
|
|
16
|
+
export declare function registerRichSegmentKind(definition: RichSegmentKindDefinition): void;
|
|
17
|
+
//# sourceMappingURL=registry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/built/rich-segments/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EACzB,yBAAyB,EAC1B,MAAM,YAAY,CAAC;AAEpB,qBAAa,mBAAmB;;IAG9B,QAAQ,CAAC,UAAU,EAAE,yBAAyB,GAAG,IAAI;IAYrD,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI1B,GAAG,CAAC,IAAI,EAAE,MAAM,GAAG,yBAAyB,GAAG,SAAS;IAIxD,IAAI,IAAI,yBAAyB,EAAE;IAInC,kBAAkB,IAAI,yBAAyB;IAQ/C,WAAW,CAAC,MAAM,EAAE,yBAAyB,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM;IASpE,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAQhD,oCAAoC;IACpC,aAAa,IAAI,IAAI;CAGtB;AAED,eAAO,MAAM,0BAA0B,WAAW,CAAC;AAEnD,eAAO,MAAM,mBAAmB,qBAA4B,CAAC;AAE7D,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,yBAAyB,GAAG,IAAI,CAEnF"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
export class RichSegmentRegistry {
|
|
2
|
+
#kinds = new Map();
|
|
3
|
+
register(definition) {
|
|
4
|
+
if (this.#kinds.has(definition.kind)) {
|
|
5
|
+
throw new Error(`Rich segment kind already registered: ${definition.kind}`);
|
|
6
|
+
}
|
|
7
|
+
if (!definition.modes.includes(definition.defaultMode)) {
|
|
8
|
+
throw new Error(`Rich segment ${definition.kind}: defaultMode "${definition.defaultMode}" not in modes`);
|
|
9
|
+
}
|
|
10
|
+
this.#kinds.set(definition.kind, definition);
|
|
11
|
+
}
|
|
12
|
+
has(kind) {
|
|
13
|
+
return this.#kinds.has(kind);
|
|
14
|
+
}
|
|
15
|
+
get(kind) {
|
|
16
|
+
return this.#kinds.get(kind);
|
|
17
|
+
}
|
|
18
|
+
list() {
|
|
19
|
+
return [...this.#kinds.values()];
|
|
20
|
+
}
|
|
21
|
+
buildDefaultPolicy() {
|
|
22
|
+
const policy = {};
|
|
23
|
+
for (const def of this.#kinds.values()) {
|
|
24
|
+
policy[def.kind] = def.defaultMode;
|
|
25
|
+
}
|
|
26
|
+
return policy;
|
|
27
|
+
}
|
|
28
|
+
resolveMode(policy, kind) {
|
|
29
|
+
const def = this.#kinds.get(kind);
|
|
30
|
+
const requested = policy[kind] ?? def?.defaultMode ?? RICH_SEGMENT_FALLBACK_MODE;
|
|
31
|
+
if (def && !def.modes.includes(requested)) {
|
|
32
|
+
return def.defaultMode;
|
|
33
|
+
}
|
|
34
|
+
return requested;
|
|
35
|
+
}
|
|
36
|
+
wrap(kind, data) {
|
|
37
|
+
const def = this.#kinds.get(kind);
|
|
38
|
+
if (!def) {
|
|
39
|
+
throw new Error(`Unknown rich segment kind: ${kind}`);
|
|
40
|
+
}
|
|
41
|
+
return def.wrap(data);
|
|
42
|
+
}
|
|
43
|
+
/** 测试隔离:清空后需重新 register builtins */
|
|
44
|
+
clearForTests() {
|
|
45
|
+
this.#kinds.clear();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
export const RICH_SEGMENT_FALLBACK_MODE = 'origin';
|
|
49
|
+
export const richSegmentRegistry = new RichSegmentRegistry();
|
|
50
|
+
export function registerRichSegmentKind(definition) {
|
|
51
|
+
richSegmentRegistry.register(definition);
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/built/rich-segments/registry.ts"],"names":[],"mappings":"AAKA,MAAM,OAAO,mBAAmB;IACrB,MAAM,GAAG,IAAI,GAAG,EAAqC,CAAC;IAE/D,QAAQ,CAAC,UAAqC;QAC5C,IAAI,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;YACrC,MAAM,IAAI,KAAK,CAAC,yCAAyC,UAAU,CAAC,IAAI,EAAE,CAAC,CAAC;QAC9E,CAAC;QACD,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YACvD,MAAM,IAAI,KAAK,CACb,gBAAgB,UAAU,CAAC,IAAI,kBAAkB,UAAU,CAAC,WAAW,gBAAgB,CACxF,CAAC;QACJ,CAAC;QACD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;IAC/C,CAAC;IAED,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,GAAG,CAAC,IAAY;QACd,OAAO,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,IAAI;QACF,OAAO,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;IACnC,CAAC;IAED,kBAAkB;QAChB,MAAM,MAAM,GAA8B,EAAE,CAAC;QAC7C,KAAK,MAAM,GAAG,IAAI,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,CAAC;YACvC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,WAAW,CAAC;QACrC,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,WAAW,CAAC,MAAiC,EAAE,IAAY;QACzD,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,GAAG,EAAE,WAAW,IAAI,0BAA0B,CAAC;QACjF,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1C,OAAO,GAAG,CAAC,WAAW,CAAC;QACzB,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,IAAI,CAAC,IAAY,EAAE,IAA6B;QAC9C,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,CAAC,GAAG,EAAE,CAAC;YACT,MAAM,IAAI,KAAK,CAAC,8BAA8B,IAAI,EAAE,CAAC,CAAC;QACxD,CAAC;QACD,OAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACxB,CAAC;IAED,oCAAoC;IACpC,aAAa;QACX,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;IACtB,CAAC;CACF;AAED,MAAM,CAAC,MAAM,0BAA0B,GAAG,QAAQ,CAAC;AAEnD,MAAM,CAAC,MAAM,mBAAmB,GAAG,IAAI,mBAAmB,EAAE,CAAC;AAE7D,MAAM,UAAU,uBAAuB,CAAC,UAAqC;IAC3E,mBAAmB,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC;AAC3C,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { SendContent } from '../../types.js';
|
|
2
|
+
import type { OutboundRichSegmentPolicy, RichSegmentRenderContext } from './types.js';
|
|
3
|
+
export declare function hasRichSegment(content: SendContent | undefined): boolean;
|
|
4
|
+
/** 按 Adapter 出站策略在 renderSendMessage 首步统一渲染富媒体段 */
|
|
5
|
+
export declare function resolveRichSegments(content: SendContent, policy: OutboundRichSegmentPolicy, ctx?: RichSegmentRenderContext): Promise<SendContent>;
|
|
6
|
+
//# sourceMappingURL=resolve.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../../../src/built/rich-segments/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAkB,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAGlE,OAAO,KAAK,EAAE,yBAAyB,EAAE,wBAAwB,EAAE,MAAM,YAAY,CAAC;AA8CtF,wBAAgB,cAAc,CAAC,OAAO,EAAE,WAAW,GAAG,SAAS,GAAG,OAAO,CAMxE;AAED,mDAAmD;AACnD,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,WAAW,EACpB,MAAM,EAAE,yBAAyB,EACjC,GAAG,CAAC,EAAE,wBAAwB,GAC7B,OAAO,CAAC,WAAW,CAAC,CAsCtB"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { isRichSegment, richSegmentKind } from './base.js';
|
|
2
|
+
import { richSegmentRegistry } from './registry.js';
|
|
3
|
+
import { RICH_SEGMENT_MODE } from './types.js';
|
|
4
|
+
import { CONTENT_CHAIN_STAGE } from '@zhin.js/logger';
|
|
5
|
+
function asArray(content) {
|
|
6
|
+
return Array.isArray(content) ? content : [content];
|
|
7
|
+
}
|
|
8
|
+
function packSegments(out) {
|
|
9
|
+
if (out.length === 0)
|
|
10
|
+
return { type: 'text', data: { text: '' } };
|
|
11
|
+
if (out.length === 1)
|
|
12
|
+
return out[0];
|
|
13
|
+
return out;
|
|
14
|
+
}
|
|
15
|
+
function appendRendered(out, rendered) {
|
|
16
|
+
if (Array.isArray(rendered)) {
|
|
17
|
+
out.push(...rendered);
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
out.push(rendered);
|
|
21
|
+
}
|
|
22
|
+
function primarySegmentType(rendered) {
|
|
23
|
+
if (typeof rendered === 'string')
|
|
24
|
+
return 'text';
|
|
25
|
+
if (Array.isArray(rendered)) {
|
|
26
|
+
const first = rendered[0];
|
|
27
|
+
if (typeof first === 'string')
|
|
28
|
+
return 'text';
|
|
29
|
+
const t = first?.type;
|
|
30
|
+
return typeof t === 'string' ? t : 'unknown';
|
|
31
|
+
}
|
|
32
|
+
const t = rendered.type;
|
|
33
|
+
return typeof t === 'string' ? t : 'unknown';
|
|
34
|
+
}
|
|
35
|
+
function detectRichSegmentFallback(mode, renderedType) {
|
|
36
|
+
if (mode === RICH_SEGMENT_MODE.IMAGE && renderedType !== 'image')
|
|
37
|
+
return true;
|
|
38
|
+
if (mode === RICH_SEGMENT_MODE.AUDIO && renderedType !== 'audio')
|
|
39
|
+
return true;
|
|
40
|
+
if (mode === RICH_SEGMENT_MODE.FILE && renderedType !== 'file')
|
|
41
|
+
return true;
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
export function hasRichSegment(content) {
|
|
45
|
+
if (content == null)
|
|
46
|
+
return false;
|
|
47
|
+
return asArray(content).some((item) => {
|
|
48
|
+
if (typeof item === 'string')
|
|
49
|
+
return false;
|
|
50
|
+
return richSegmentKind(item) != null || isRichSegment(item);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
/** 按 Adapter 出站策略在 renderSendMessage 首步统一渲染富媒体段 */
|
|
54
|
+
export async function resolveRichSegments(content, policy, ctx) {
|
|
55
|
+
if (!hasRichSegment(content)) {
|
|
56
|
+
return content;
|
|
57
|
+
}
|
|
58
|
+
const items = asArray(content);
|
|
59
|
+
const out = [];
|
|
60
|
+
for (const item of items) {
|
|
61
|
+
if (typeof item === 'string') {
|
|
62
|
+
out.push(item);
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const kind = isRichSegment(item) ? item.segmentType : richSegmentKind(item);
|
|
66
|
+
if (!kind || !richSegmentRegistry.has(kind)) {
|
|
67
|
+
out.push(item);
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
const rich = isRichSegment(item)
|
|
71
|
+
? item
|
|
72
|
+
: richSegmentRegistry.wrap(kind, item.data ?? {});
|
|
73
|
+
const mode = richSegmentRegistry.resolveMode(policy, kind);
|
|
74
|
+
const rendered = await rich.render(mode, ctx);
|
|
75
|
+
const renderedType = primarySegmentType(rendered);
|
|
76
|
+
const fallback = detectRichSegmentFallback(mode, renderedType);
|
|
77
|
+
ctx?.logContentChain?.({
|
|
78
|
+
stage: CONTENT_CHAIN_STAGE.RICH_SEGMENT,
|
|
79
|
+
kind,
|
|
80
|
+
mode,
|
|
81
|
+
fallback,
|
|
82
|
+
result: renderedType,
|
|
83
|
+
});
|
|
84
|
+
appendRendered(out, rendered);
|
|
85
|
+
}
|
|
86
|
+
return packSegments(out);
|
|
87
|
+
}
|
|
88
|
+
//# sourceMappingURL=resolve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../../src/built/rich-segments/resolve.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { RichSegment } from './base.js';
|
|
2
|
+
import type { RichSegmentRenderContext, RichSegmentRenderResult } from './types.js';
|
|
3
|
+
export interface TtsSegmentData {
|
|
4
|
+
text: string;
|
|
5
|
+
voice?: string;
|
|
6
|
+
provider?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare class TtsSegment extends RichSegment<TtsSegmentData> {
|
|
9
|
+
readonly segmentType: "tts";
|
|
10
|
+
readonly type: "tts";
|
|
11
|
+
render(mode: string, ctx?: RichSegmentRenderContext): Promise<RichSegmentRenderResult>;
|
|
12
|
+
}
|
|
13
|
+
export declare function wrapTtsSegment(data: Record<string, unknown>): TtsSegment;
|
|
14
|
+
//# sourceMappingURL=tts-segment.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tts-segment.d.ts","sourceRoot":"","sources":["../../../src/built/rich-segments/tts-segment.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,KAAK,EACV,wBAAwB,EACxB,uBAAuB,EAExB,MAAM,YAAY,CAAC;AAGpB,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AASD,qBAAa,UAAW,SAAQ,WAAW,CAAC,cAAc,CAAC;IACzD,QAAQ,CAAC,WAAW,EAAG,KAAK,CAAU;IACtC,QAAQ,CAAC,IAAI,EAAG,KAAK,CAAU;IAEzB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,wBAAwB,GAAG,OAAO,CAAC,uBAAuB,CAAC;CAqC7F;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,UAAU,CAMxE"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { segment } from '../../utils.js';
|
|
2
|
+
import { RichSegment } from './base.js';
|
|
3
|
+
import { RICH_SEGMENT_MODE } from './types.js';
|
|
4
|
+
async function resolveSpeechPipeline(ctx) {
|
|
5
|
+
if (!ctx?.resolveCapability)
|
|
6
|
+
return undefined;
|
|
7
|
+
return ctx.resolveCapability('speech');
|
|
8
|
+
}
|
|
9
|
+
export class TtsSegment extends RichSegment {
|
|
10
|
+
segmentType = 'tts';
|
|
11
|
+
type = 'tts';
|
|
12
|
+
async render(mode, ctx) {
|
|
13
|
+
if (mode === RICH_SEGMENT_MODE.ORIGIN) {
|
|
14
|
+
return this.toJSON();
|
|
15
|
+
}
|
|
16
|
+
const text = typeof this.data.text === 'string' ? this.data.text : '';
|
|
17
|
+
if (mode === RICH_SEGMENT_MODE.TEXT) {
|
|
18
|
+
return segment.text(text);
|
|
19
|
+
}
|
|
20
|
+
if (mode === RICH_SEGMENT_MODE.AUDIO) {
|
|
21
|
+
if (!text.trim()) {
|
|
22
|
+
return segment.text('');
|
|
23
|
+
}
|
|
24
|
+
const pipeline = await resolveSpeechPipeline(ctx);
|
|
25
|
+
if (!pipeline) {
|
|
26
|
+
return this.render(RICH_SEGMENT_MODE.TEXT, ctx);
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
const result = await pipeline.synthesize({
|
|
30
|
+
text,
|
|
31
|
+
voice: typeof this.data.voice === 'string' ? this.data.voice : undefined,
|
|
32
|
+
provider: typeof this.data.provider === 'string' ? this.data.provider : undefined,
|
|
33
|
+
});
|
|
34
|
+
const base64 = result.data.toString('base64');
|
|
35
|
+
const mime = result.format === 'wav' ? 'audio/wav' : 'audio/mpeg';
|
|
36
|
+
return segment('audio', { url: `data:${mime};base64,${base64}`, format: result.format });
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return this.render(RICH_SEGMENT_MODE.TEXT, ctx);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return this.render(RICH_SEGMENT_MODE.TEXT, ctx);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export function wrapTtsSegment(data) {
|
|
46
|
+
return new TtsSegment({
|
|
47
|
+
text: String(data.text ?? ''),
|
|
48
|
+
voice: typeof data.voice === 'string' ? data.voice : undefined,
|
|
49
|
+
provider: typeof data.provider === 'string' ? data.provider : undefined,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=tts-segment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tts-segment.js","sourceRoot":"","sources":["../../../src/built/rich-segments/tts-segment.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { MessageElement } from '../../types.js';
|
|
2
|
+
import type { ContentChainLogFields } from '@zhin.js/logger';
|
|
3
|
+
/** 内置 kind 常量(外部可增删,registry 为 SSOT) */
|
|
4
|
+
export declare const BUILTIN_RICH_SEGMENT_KINDS: {
|
|
5
|
+
readonly QRCODE: "qrcode";
|
|
6
|
+
readonly HTML: "html";
|
|
7
|
+
readonly MARKDOWN: "markdown";
|
|
8
|
+
readonly TTS: "tts";
|
|
9
|
+
};
|
|
10
|
+
export type BuiltinRichSegmentKind = (typeof BUILTIN_RICH_SEGMENT_KINDS)[keyof typeof BUILTIN_RICH_SEGMENT_KINDS];
|
|
11
|
+
/** 通用 mode 名;各 kind 在 registry 中声明支持的子集 */
|
|
12
|
+
export declare const RICH_SEGMENT_MODE: {
|
|
13
|
+
readonly ORIGIN: "origin";
|
|
14
|
+
readonly TEXT: "text";
|
|
15
|
+
readonly IMAGE: "image";
|
|
16
|
+
readonly FILE: "file";
|
|
17
|
+
readonly URL: "url";
|
|
18
|
+
readonly AUDIO: "audio";
|
|
19
|
+
readonly VIDEO: "video";
|
|
20
|
+
};
|
|
21
|
+
export type RichSegmentMode = (typeof RICH_SEGMENT_MODE)[keyof typeof RICH_SEGMENT_MODE] | string;
|
|
22
|
+
/** 任意已注册 kind → 渲染 mode */
|
|
23
|
+
export type OutboundRichSegmentPolicy = Record<string, string>;
|
|
24
|
+
/** @deprecated 使用 OutboundRichSegmentPolicy;保留别名便于迁移 */
|
|
25
|
+
export type RichSegmentKind = string;
|
|
26
|
+
export type RichRenderMode = string;
|
|
27
|
+
/** html-renderer 可选包契约 */
|
|
28
|
+
export interface HtmlRendererForRichSegment {
|
|
29
|
+
render(html: string, options?: {
|
|
30
|
+
width?: number;
|
|
31
|
+
format?: 'png';
|
|
32
|
+
backgroundColor?: string;
|
|
33
|
+
}): Promise<{
|
|
34
|
+
format: string;
|
|
35
|
+
data: Buffer | string;
|
|
36
|
+
}>;
|
|
37
|
+
}
|
|
38
|
+
/** speech 可选包契约(@zhin.js/speech) */
|
|
39
|
+
export interface SpeechPipelineForRichSegment {
|
|
40
|
+
transcribe(input: {
|
|
41
|
+
data: Buffer;
|
|
42
|
+
mimeType?: string;
|
|
43
|
+
}): Promise<string>;
|
|
44
|
+
synthesize(input: {
|
|
45
|
+
text: string;
|
|
46
|
+
voice?: string;
|
|
47
|
+
format?: 'mp3' | 'wav';
|
|
48
|
+
speed?: number;
|
|
49
|
+
provider?: string;
|
|
50
|
+
}): Promise<{
|
|
51
|
+
data: Buffer;
|
|
52
|
+
format: 'mp3' | 'wav';
|
|
53
|
+
}>;
|
|
54
|
+
}
|
|
55
|
+
/** 未来 media-pipeline / ffmpeg 等 optional 包可复用同一 id */
|
|
56
|
+
export type RichSegmentCapabilityId = 'html-renderer' | 'speech' | 'media-pipeline' | string;
|
|
57
|
+
export interface RichSegmentRenderContext {
|
|
58
|
+
/** 按 id 懒加载能力(core 或 optional 包 register loader) */
|
|
59
|
+
resolveCapability: <T>(id: RichSegmentCapabilityId) => Promise<T | undefined>;
|
|
60
|
+
/** @deprecated 请用 resolveCapability('html-renderer') */
|
|
61
|
+
getHtmlRenderer?: () => Promise<HtmlRendererForRichSegment | undefined>;
|
|
62
|
+
/** 可选:rich_segment stage 结构化日志 */
|
|
63
|
+
logContentChain?: (fields: ContentChainLogFields) => void;
|
|
64
|
+
warn?: (message: string) => void;
|
|
65
|
+
}
|
|
66
|
+
export type RichSegmentRenderResult = MessageElement | MessageElement[];
|
|
67
|
+
export interface RichSegmentLike {
|
|
68
|
+
readonly segmentType: string;
|
|
69
|
+
render(mode: string, ctx?: RichSegmentRenderContext): Promise<RichSegmentRenderResult>;
|
|
70
|
+
}
|
|
71
|
+
export interface RichSegmentKindDefinition {
|
|
72
|
+
kind: string;
|
|
73
|
+
/** policy 未指定时使用的 mode */
|
|
74
|
+
defaultMode: string;
|
|
75
|
+
/** 该 kind 支持的 mode 列表(policy 非法值会回退 defaultMode) */
|
|
76
|
+
modes: readonly string[];
|
|
77
|
+
wrap: (data: Record<string, unknown>) => RichSegmentLike;
|
|
78
|
+
}
|
|
79
|
+
export interface RichSegmentCapabilityLoaderOptions {
|
|
80
|
+
warn?: (message: string) => void;
|
|
81
|
+
getConfig?: () => Record<string, unknown> | undefined;
|
|
82
|
+
logContentChain?: RichSegmentRenderContext['logContentChain'];
|
|
83
|
+
}
|
|
84
|
+
export type RichSegmentCapabilityLoader = (options: RichSegmentCapabilityLoaderOptions) => Promise<unknown>;
|
|
85
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/built/rich-segments/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAE7D,wCAAwC;AACxC,eAAO,MAAM,0BAA0B;;;;;CAK7B,CAAC;AAEX,MAAM,MAAM,sBAAsB,GAChC,CAAC,OAAO,0BAA0B,CAAC,CAAC,MAAM,OAAO,0BAA0B,CAAC,CAAC;AAE/E,2CAA2C;AAC3C,eAAO,MAAM,iBAAiB;;;;;;;;CAQpB,CAAC;AAEX,MAAM,MAAM,eAAe,GAAG,CAAC,OAAO,iBAAiB,CAAC,CAAC,MAAM,OAAO,iBAAiB,CAAC,GAAG,MAAM,CAAC;AAElG,2BAA2B;AAC3B,MAAM,MAAM,yBAAyB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAE/D,wDAAwD;AACxD,MAAM,MAAM,eAAe,GAAG,MAAM,CAAC;AACrC,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC;AAEpC,0BAA0B;AAC1B,MAAM,WAAW,0BAA0B;IACzC,MAAM,CACJ,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,KAAK,CAAC;QAAC,eAAe,CAAC,EAAE,MAAM,CAAA;KAAE,GACrE,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAC,CAAC;CACvD;AAED,oCAAoC;AACpC,MAAM,WAAW,4BAA4B;IAC3C,UAAU,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACxE,UAAU,CAAC,KAAK,EAAE;QAChB,IAAI,EAAE,MAAM,CAAC;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,MAAM,CAAC,EAAE,KAAK,GAAG,KAAK,CAAC;QACvB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;KACnB,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,KAAK,GAAG,KAAK,CAAA;KAAE,CAAC,CAAC;CACtD;AAED,sDAAsD;AACtD,MAAM,MAAM,uBAAuB,GAAG,eAAe,GAAG,QAAQ,GAAG,gBAAgB,GAAG,MAAM,CAAC;AAE7F,MAAM,WAAW,wBAAwB;IACvC,oDAAoD;IACpD,iBAAiB,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,uBAAuB,KAAK,OAAO,CAAC,CAAC,GAAG,SAAS,CAAC,CAAC;IAC9E,wDAAwD;IACxD,eAAe,CAAC,EAAE,MAAM,OAAO,CAAC,0BAA0B,GAAG,SAAS,CAAC,CAAC;IACxE,kCAAkC;IAClC,eAAe,CAAC,EAAE,CAAC,MAAM,EAAE,qBAAqB,KAAK,IAAI,CAAC;IAC1D,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CAClC;AAED,MAAM,MAAM,uBAAuB,GAAG,cAAc,GAAG,cAAc,EAAE,CAAC;AAExE,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,wBAAwB,GAAG,OAAO,CAAC,uBAAuB,CAAC,CAAC;CACxF;AAED,MAAM,WAAW,yBAAyB;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,0BAA0B;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,oDAAoD;IACpD,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,eAAe,CAAC;CAC1D;AAED,MAAM,WAAW,kCAAkC;IACjD,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACjC,SAAS,CAAC,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IACtD,eAAe,CAAC,EAAE,wBAAwB,CAAC,iBAAiB,CAAC,CAAC;CAC/D;AAED,MAAM,MAAM,2BAA2B,GAAG,CACxC,OAAO,EAAE,kCAAkC,KACxC,OAAO,CAAC,OAAO,CAAC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/** 内置 kind 常量(外部可增删,registry 为 SSOT) */
|
|
2
|
+
export const BUILTIN_RICH_SEGMENT_KINDS = {
|
|
3
|
+
QRCODE: 'qrcode',
|
|
4
|
+
HTML: 'html',
|
|
5
|
+
MARKDOWN: 'markdown',
|
|
6
|
+
TTS: 'tts',
|
|
7
|
+
};
|
|
8
|
+
/** 通用 mode 名;各 kind 在 registry 中声明支持的子集 */
|
|
9
|
+
export const RICH_SEGMENT_MODE = {
|
|
10
|
+
ORIGIN: 'origin',
|
|
11
|
+
TEXT: 'text',
|
|
12
|
+
IMAGE: 'image',
|
|
13
|
+
FILE: 'file',
|
|
14
|
+
URL: 'url',
|
|
15
|
+
AUDIO: 'audio',
|
|
16
|
+
VIDEO: 'video',
|
|
17
|
+
};
|
|
18
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/built/rich-segments/types.ts"],"names":[],"mappings":"AAGA,wCAAwC;AACxC,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,MAAM,EAAE,QAAQ;IAChB,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,UAAU;IACpB,GAAG,EAAE,KAAK;CACF,CAAC;AAKX,2CAA2C;AAC3C,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAC/B,MAAM,EAAE,QAAQ;IAChB,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,MAAM;IACZ,GAAG,EAAE,KAAK;IACV,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;CACN,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { Schema } from '@zhin.js/schema';
|
|
2
|
+
import { Adapter } from '../adapter.js';
|
|
3
|
+
import type { EndpointConfigRecord, EndpointManager, ProvisionContext } from './endpoint-manager.js';
|
|
4
|
+
export declare class SchemaEndpointManager implements EndpointManager {
|
|
5
|
+
private readonly adapter;
|
|
6
|
+
private readonly schema;
|
|
7
|
+
constructor(adapter: Adapter, schema: Schema);
|
|
8
|
+
supportsProvision(): boolean;
|
|
9
|
+
listEndpoints(): EndpointConfigRecord[];
|
|
10
|
+
addEndpoint(ctx: ProvisionContext): Promise<EndpointConfigRecord>;
|
|
11
|
+
editEndpoint(name: string, ctx: ProvisionContext): Promise<EndpointConfigRecord>;
|
|
12
|
+
removeEndpoint(name: string): Promise<boolean>;
|
|
13
|
+
startEndpoint(name: string, ctx: ProvisionContext): Promise<void>;
|
|
14
|
+
stopEndpoint(name: string): Promise<boolean>;
|
|
15
|
+
}
|
|
16
|
+
export declare function resolveEndpointManager(adapter: Adapter): EndpointManager | null;
|
|
17
|
+
export declare function adapterSupportsProvision(adapter: Adapter): boolean;
|
|
18
|
+
//# sourceMappingURL=schema-endpoint-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema-endpoint-manager.d.ts","sourceRoot":"","sources":["../../src/built/schema-endpoint-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAGxC,OAAO,KAAK,EACV,oBAAoB,EACpB,eAAe,EACf,gBAAgB,EACjB,MAAM,uBAAuB,CAAC;AAU/B,qBAAa,qBAAsB,YAAW,eAAe;IAEzD,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;gBADN,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,MAAM;IAGjC,iBAAiB,IAAI,OAAO;IAI5B,aAAa,IAAI,oBAAoB,EAAE;IAIjC,WAAW,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAYjE,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IAgBhF,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAI9C,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAMjE,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAGnD;AAED,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,eAAe,GAAG,IAAI,CAW/E;AAED,wBAAgB,wBAAwB,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAGlE"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { Prompt } from '../prompt.js';
|
|
2
|
+
function readConfigEndpoints(root, context) {
|
|
3
|
+
const configService = root.inject('config');
|
|
4
|
+
const raw = configService?.getRaw(configService.primaryFile);
|
|
5
|
+
return (raw?.endpoints ?? []).filter((e) => e.context === context);
|
|
6
|
+
}
|
|
7
|
+
export class SchemaEndpointManager {
|
|
8
|
+
adapter;
|
|
9
|
+
schema;
|
|
10
|
+
constructor(adapter, schema) {
|
|
11
|
+
this.adapter = adapter;
|
|
12
|
+
this.schema = schema;
|
|
13
|
+
}
|
|
14
|
+
supportsProvision() {
|
|
15
|
+
return true;
|
|
16
|
+
}
|
|
17
|
+
listEndpoints() {
|
|
18
|
+
return readConfigEndpoints(this.adapter.plugin.root, String(this.adapter.name));
|
|
19
|
+
}
|
|
20
|
+
async addEndpoint(ctx) {
|
|
21
|
+
const prompt = new Prompt(this.adapter.plugin, ctx.message);
|
|
22
|
+
await ctx.onStatusUpdate(`请按提示填写 ${String(this.adapter.name)} endpoint 配置:`);
|
|
23
|
+
const name = await prompt.text('Endpoint 名称(zhin.config endpoints[].name):');
|
|
24
|
+
const fields = await prompt.getValueWithSchema(this.schema);
|
|
25
|
+
return {
|
|
26
|
+
context: String(this.adapter.name),
|
|
27
|
+
name: name.trim(),
|
|
28
|
+
...fields,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
async editEndpoint(name, ctx) {
|
|
32
|
+
const existing = this.listEndpoints().find((e) => e.name === name);
|
|
33
|
+
if (!existing) {
|
|
34
|
+
throw new Error(`配置中不存在 ${String(this.adapter.name)}/${name}`);
|
|
35
|
+
}
|
|
36
|
+
await ctx.onStatusUpdate(`编辑 ${String(this.adapter.name)}/${name},留空字段将保留原值。`);
|
|
37
|
+
const prompt = new Prompt(this.adapter.plugin, ctx.message);
|
|
38
|
+
const fields = await prompt.getValueWithSchema(this.schema);
|
|
39
|
+
return {
|
|
40
|
+
...existing,
|
|
41
|
+
...fields,
|
|
42
|
+
context: String(this.adapter.name),
|
|
43
|
+
name,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
async removeEndpoint(name) {
|
|
47
|
+
return this.listEndpoints().some((e) => e.name === name);
|
|
48
|
+
}
|
|
49
|
+
async startEndpoint(name, ctx) {
|
|
50
|
+
const rec = this.listEndpoints().find((e) => e.name === name);
|
|
51
|
+
if (!rec)
|
|
52
|
+
throw new Error(`配置中不存在 ${String(this.adapter.name)}/${name}`);
|
|
53
|
+
await ctx.onStatusUpdate(`正在连接 ${String(this.adapter.name)}/${name}…`);
|
|
54
|
+
}
|
|
55
|
+
async stopEndpoint(name) {
|
|
56
|
+
return this.adapter.endpoints.has(name);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export function resolveEndpointManager(adapter) {
|
|
60
|
+
const custom = adapter.getEndpointManager?.();
|
|
61
|
+
if (custom)
|
|
62
|
+
return custom;
|
|
63
|
+
const schema = adapter.getEndpointConfigSchema?.() ??
|
|
64
|
+
adapter.constructor.endpointConfigSchema;
|
|
65
|
+
if (schema) {
|
|
66
|
+
return new SchemaEndpointManager(adapter, schema);
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
export function adapterSupportsProvision(adapter) {
|
|
71
|
+
const manager = resolveEndpointManager(adapter);
|
|
72
|
+
return manager?.supportsProvision() ?? false;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=schema-endpoint-manager.js.map
|