alemonjs 2.1.73 → 2.1.75

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.
@@ -32,6 +32,7 @@ export declare class Router<P extends string = string, E extends string = string
32
32
  eventName: string;
33
33
  routes: {
34
34
  path: string;
35
+ description: string;
35
36
  importerCount: number;
36
37
  }[];
37
38
  }[];
@@ -53,6 +53,7 @@ function normalizeRouteConfig(config) {
53
53
  }
54
54
  return {
55
55
  path: normalizeRoutePath(path),
56
+ description: config.description,
56
57
  events: config.events,
57
58
  platforms: config.platforms,
58
59
  schema: config.schema
@@ -68,6 +69,94 @@ function normalizeResConfig(config, defaults) {
68
69
  function getImporterLabel(importer, index) {
69
70
  return importer.name || `anonymous_${index + 1}`;
70
71
  }
72
+ function formatRouteDescription(description) {
73
+ return typeof description === 'string' && description.trim() ? description.trim() : undefined;
74
+ }
75
+ function formatArgRuleHint(arg, displayIndex) {
76
+ const rules = arg.rules ?? [];
77
+ const parts = [];
78
+ const typeRule = rules.find(rule => rule.type);
79
+ const requiredRule = rules.find(rule => rule.required);
80
+ if (requiredRule) {
81
+ parts.push('必填');
82
+ }
83
+ else {
84
+ parts.push('可选');
85
+ }
86
+ if (typeRule?.type === 'number') {
87
+ parts.push('数字');
88
+ }
89
+ else if (typeRule?.type === 'enum') {
90
+ parts.push(`枚举: ${(typeRule.enum ?? []).join(' / ')}`);
91
+ }
92
+ else if (typeRule?.type === 'range') {
93
+ parts.push('区间');
94
+ }
95
+ else if (typeRule?.type === 'rest') {
96
+ parts.push('剩余文本');
97
+ }
98
+ else {
99
+ parts.push('文本');
100
+ }
101
+ if (typeof typeRule?.min === 'number') {
102
+ parts.push(`最小 ${typeRule.min}`);
103
+ }
104
+ if (typeof typeRule?.max === 'number') {
105
+ parts.push(`最大 ${typeRule.max}`);
106
+ }
107
+ const suffix = arg.description ? `,${arg.description}` : '';
108
+ return `参数${displayIndex} \`${arg.name}\`:${parts.join(',')}${suffix}`;
109
+ }
110
+ function buildSchemaHints(schema) {
111
+ const args = schema?.args ?? [];
112
+ if (args.length === 0) {
113
+ return [];
114
+ }
115
+ return args.map((arg, index) => formatArgRuleHint(arg, index + 1));
116
+ }
117
+ function quoteCommand(command) {
118
+ return command ? `\`${command}\`` : '';
119
+ }
120
+ function buildFallbackReply(params) {
121
+ const lines = [];
122
+ const commandText = quoteCommand(params.suggestedKey);
123
+ if (commandText) {
124
+ lines.push(`我猜你想用的是 ${commandText}。`);
125
+ lines.push(`可以直接输入:${commandText}`);
126
+ }
127
+ else {
128
+ lines.push('我还没完全认出你这条指令。');
129
+ }
130
+ if (params.description) {
131
+ lines.push(params.description);
132
+ }
133
+ if (params.usage && params.usage !== params.suggestedKey) {
134
+ lines.push(`如果你想继续,可以这样写:\`${params.usage}\``);
135
+ }
136
+ return lines;
137
+ }
138
+ function buildValidationReply(params) {
139
+ const lines = [];
140
+ const commandText = quoteCommand(params.commandKey);
141
+ if (commandText) {
142
+ lines.push(`我已经识别到你想用的是 ${commandText}。`);
143
+ }
144
+ lines.push(params.error || '这条指令的参数还不完整。');
145
+ if (params.description) {
146
+ lines.push(params.description);
147
+ }
148
+ if (params.usage) {
149
+ lines.push(`你可以这样输入:\`${params.usage}\``);
150
+ }
151
+ else if (commandText) {
152
+ lines.push(`请继续补全 ${commandText} 所需的参数。`);
153
+ }
154
+ if (params.schemaHints && params.schemaHints.length > 0) {
155
+ lines.push('参数说明:');
156
+ lines.push(...params.schemaHints);
157
+ }
158
+ return lines;
159
+ }
71
160
  function normalizeInteractionKey(messageText) {
72
161
  return String(messageText ?? '')
73
162
  .trim()
@@ -345,6 +434,7 @@ class Router {
345
434
  eventName,
346
435
  routes: [...routes.two.values(), ...routes.one.values()].map(route => ({
347
436
  path: route.config.path,
437
+ description: route?.config?.description,
348
438
  importerCount: route.importers.length
349
439
  }))
350
440
  }));
@@ -542,14 +632,14 @@ class Router {
542
632
  return;
543
633
  }
544
634
  const eventName = String(event.name ?? '');
545
- const routeKeys = this.inspect()
635
+ const routeMetas = this.inspect()
546
636
  .filter(item => item.eventName === eventName)
547
637
  .flatMap(item => item.routes)
548
638
  .filter(route => {
549
639
  const routeEntry = this.routes.get(eventName)?.one.get(route.path) ?? this.routes.get(eventName)?.two.get(route.path);
550
640
  return routeEntry ? applicableScopeIds.includes(routeEntry.scopeId) : false;
551
- })
552
- .map(route => route.path);
641
+ });
642
+ const routeKeys = routeMetas.map(route => route.path);
553
643
  const fallback = checkFallbackHint(typeof event.MessageText === 'string' ? event.MessageText : undefined, routeKeys, fallbackOptions);
554
644
  if (!fallback.matched) {
555
645
  await next();
@@ -558,7 +648,18 @@ class Router {
558
648
  const [message] = useMessage();
559
649
  const md = Format.createMarkdown();
560
650
  const format = Format.create();
561
- md.addText(fallback.message ?? '未匹配到可用指令');
651
+ const suggestedRoute = fallback.suggestedKey ? routeMetas.find(route => route.path === fallback.suggestedKey) : undefined;
652
+ const replyLines = buildFallbackReply({
653
+ suggestedKey: fallback.suggestedKey,
654
+ description: formatRouteDescription(suggestedRoute?.description),
655
+ usage: suggestedRoute?.path
656
+ });
657
+ replyLines.forEach((line, index) => {
658
+ if (index > 0) {
659
+ md.addNewline();
660
+ }
661
+ md.addText(line);
662
+ });
562
663
  format.addMarkdown(md);
563
664
  void message.send({ format });
564
665
  }
@@ -570,15 +671,24 @@ class Router {
570
671
  const [message] = useMessage();
571
672
  const md = Format.createMarkdown();
572
673
  const format = Format.create();
573
- md.addText(validation && !validation.valid ? validation.error : '参数校验失败');
574
- if (validation && !validation.valid && validation.usage) {
575
- md.addNewline();
576
- md.addText(`应使用:${validation.usage}`);
577
- }
578
- else if (result.commandKey) {
579
- md.addNewline();
580
- md.addText(`请补全 \`${result.commandKey}\` 所需参数。`);
581
- }
674
+ const routeEntry = (result.eventName && result.matchedPath
675
+ ? this.routes.get(result.eventName)?.one.get(result.matchedPath) ?? this.routes.get(result.eventName)?.two.get(result.matchedPath)
676
+ : undefined) ?? undefined;
677
+ const description = formatRouteDescription(routeEntry?.config.description);
678
+ const schemaHints = buildSchemaHints(routeEntry?.config.schema);
679
+ const replyLines = buildValidationReply({
680
+ error: validation && !validation.valid ? validation.error : '参数校验失败',
681
+ commandKey: result.commandKey,
682
+ description,
683
+ usage: validation && !validation.valid ? validation.usage : undefined,
684
+ schemaHints
685
+ });
686
+ replyLines.forEach((line, index) => {
687
+ if (index > 0) {
688
+ md.addNewline();
689
+ }
690
+ md.addText(line);
691
+ });
582
692
  format.addMarkdown(md);
583
693
  void message.send({ format });
584
694
  }
@@ -20,6 +20,7 @@ export type RouteNext = () => Promise<void> | undefined;
20
20
  export type RouteExecutable = (event: Record<string, unknown>, next: RouteNext) => Promise<boolean | undefined> | boolean | undefined;
21
21
  export type RouteHandlerConfig<P extends string = string, E extends string = string> = {
22
22
  path?: string;
23
+ description?: string;
23
24
  events?: readonly E[];
24
25
  platforms?: readonly P[];
25
26
  schema?: RouteSchema;
@@ -52,6 +53,7 @@ export type RouteDefinition<P extends string = string, E extends string = string
52
53
  export type RouteDefinitions<P extends string = string, E extends string = string> = RouteDefinition<P, E> | RouteDefinition<P, E>[];
53
54
  export type NormalizedRouteConfig<P extends string = string, E extends string = string> = {
54
55
  path?: string;
56
+ description?: string;
55
57
  events?: readonly E[];
56
58
  platforms?: readonly P[];
57
59
  schema?: RouteSchema;
@@ -27,6 +27,7 @@ export type RouteRule = {
27
27
  };
28
28
  export type RouteArgSchema = {
29
29
  name: string;
30
+ description?: string;
30
31
  defaultValue?: RouteSchemaValue;
31
32
  rules?: RouteRule[];
32
33
  };
@@ -13,6 +13,10 @@ export type DataButton = {
13
13
  userIds?: string[];
14
14
  roleIds?: string[];
15
15
  };
16
+ style?: 'gray' | 'blue' | 'purple' | string;
17
+ rawData: {
18
+ [key: string]: any;
19
+ };
16
20
  };
17
21
  };
18
22
  export type DataButtonRow = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "alemonjs",
3
- "version": "2.1.73",
3
+ "version": "2.1.75",
4
4
  "description": "bot script",
5
5
  "author": "lemonade",
6
6
  "license": "MIT",