@zhin.js/plugin-lottery 1.0.0 → 1.0.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.
Files changed (272) hide show
  1. package/README.md +25 -26
  2. package/agent/tools/compute_recommend.ts +2 -2
  3. package/agent/tools/get_model_state.ts +2 -2
  4. package/agent/tools/history.ts +2 -2
  5. package/agent/tools/list_pending.ts +2 -2
  6. package/agent/tools/save_prediction.ts +2 -2
  7. package/agent/tools/stats_snapshot.ts +2 -2
  8. package/agent/tools/sync.ts +2 -2
  9. package/commands/lottery/[game:string=].ts +25 -0
  10. package/commands/lottery-backtest/[game:string=].ts +34 -0
  11. package/commands/lottery-history/[game:string].ts +20 -0
  12. package/commands/lottery-stats/[game:string].ts +34 -0
  13. package/commands/lottery-today.ts +15 -0
  14. package/commands/lottery-train/[game:string=].ts +34 -0
  15. package/lib/command-helpers.d.ts +8 -0
  16. package/lib/command-helpers.d.ts.map +1 -0
  17. package/lib/command-helpers.js +24 -0
  18. package/lib/command-helpers.js.map +1 -0
  19. package/lib/config.d.ts +30 -0
  20. package/lib/config.d.ts.map +1 -0
  21. package/lib/config.js +52 -0
  22. package/lib/config.js.map +1 -0
  23. package/lib/db-store.d.ts +10 -0
  24. package/lib/db-store.d.ts.map +1 -0
  25. package/lib/db-store.js +30 -0
  26. package/lib/db-store.js.map +1 -0
  27. package/lib/evaluate/adaptive-sim.d.ts +1 -1
  28. package/lib/evaluate/adaptive-sim.d.ts.map +1 -1
  29. package/lib/evaluate/adaptive-sim.js +5 -1
  30. package/lib/evaluate/adaptive-sim.js.map +1 -1
  31. package/lib/evaluate/backtest.d.ts +1 -1
  32. package/lib/evaluate/backtest.d.ts.map +1 -1
  33. package/lib/evaluate/backtest.js.map +1 -1
  34. package/lib/evaluate/hit-rate.d.ts +0 -1
  35. package/lib/evaluate/hit-rate.d.ts.map +1 -1
  36. package/lib/evaluate/hit-rate.js +0 -2
  37. package/lib/evaluate/hit-rate.js.map +1 -1
  38. package/lib/evaluate/review-pending.d.ts +1 -1
  39. package/lib/evaluate/review-pending.d.ts.map +1 -1
  40. package/lib/evaluate/review-pending.js.map +1 -1
  41. package/lib/evaluate/tracker.d.ts +1 -2
  42. package/lib/evaluate/tracker.d.ts.map +1 -1
  43. package/lib/evaluate/tracker.js +4 -0
  44. package/lib/evaluate/tracker.js.map +1 -1
  45. package/lib/evaluate/train-weights.d.ts +2 -2
  46. package/lib/evaluate/train-weights.d.ts.map +1 -1
  47. package/lib/evaluate/train-weights.js.map +1 -1
  48. package/lib/evaluate/weight-guard.d.ts +1 -1
  49. package/lib/evaluate/weight-guard.d.ts.map +1 -1
  50. package/lib/evaluate/weight-guard.js.map +1 -1
  51. package/lib/games/kl8-groups.d.ts +0 -1
  52. package/lib/games/kl8-groups.d.ts.map +1 -1
  53. package/lib/games/kl8-groups.js +2 -2
  54. package/lib/games/kl8-groups.js.map +1 -1
  55. package/lib/index.d.ts +7 -2
  56. package/lib/index.d.ts.map +1 -1
  57. package/lib/index.js +5 -214
  58. package/lib/index.js.map +1 -1
  59. package/lib/{src/lottery-agent-deps.d.ts → lottery-agent-deps.d.ts} +2 -2
  60. package/lib/lottery-agent-deps.d.ts.map +1 -0
  61. package/lib/lottery-agent-deps.js +22 -0
  62. package/lib/lottery-agent-deps.js.map +1 -0
  63. package/lib/lottery-tool-handlers.d.ts.map +1 -0
  64. package/lib/{src/lottery-tool-handlers.js → lottery-tool-handlers.js} +3 -3
  65. package/lib/lottery-tool-handlers.js.map +1 -0
  66. package/lib/memory-db.d.ts +7 -0
  67. package/lib/memory-db.d.ts.map +1 -0
  68. package/lib/memory-db.js +49 -0
  69. package/lib/memory-db.js.map +1 -0
  70. package/lib/pipeline.d.ts +1 -4
  71. package/lib/pipeline.d.ts.map +1 -1
  72. package/lib/pipeline.js +6 -9
  73. package/lib/pipeline.js.map +1 -1
  74. package/lib/push.d.ts +13 -2
  75. package/lib/push.d.ts.map +1 -1
  76. package/lib/push.js +22 -29
  77. package/lib/push.js.map +1 -1
  78. package/lib/recommend/game-pick.d.ts +0 -1
  79. package/lib/recommend/game-pick.d.ts.map +1 -1
  80. package/lib/recommend/game-pick.js +2 -2
  81. package/lib/recommend/game-pick.js.map +1 -1
  82. package/lib/recommend/report.d.ts +3 -6
  83. package/lib/recommend/report.d.ts.map +1 -1
  84. package/lib/recommend/report.js +5 -27
  85. package/lib/recommend/report.js.map +1 -1
  86. package/lib/runtime-state.d.ts +12 -0
  87. package/lib/runtime-state.d.ts.map +1 -0
  88. package/lib/runtime-state.js +13 -0
  89. package/lib/runtime-state.js.map +1 -0
  90. package/lib/stats/engine.d.ts +1 -1
  91. package/lib/stats/engine.d.ts.map +1 -1
  92. package/lib/stats/engine.js.map +1 -1
  93. package/lib/stats/pro-analysis.d.ts +1 -1
  94. package/lib/stats/pro-analysis.d.ts.map +1 -1
  95. package/lib/stats/pro-analysis.js.map +1 -1
  96. package/lib/stats/weights.d.ts +0 -1
  97. package/lib/stats/weights.d.ts.map +1 -1
  98. package/lib/stats/weights.js.map +1 -1
  99. package/lib/sync/run-sync.d.ts +1 -1
  100. package/lib/sync/run-sync.d.ts.map +1 -1
  101. package/lib/sync/run-sync.js.map +1 -1
  102. package/package.json +30 -7
  103. package/plugin.ts +106 -0
  104. package/schema.json +52 -0
  105. package/src/command-helpers.ts +35 -0
  106. package/src/config.ts +83 -0
  107. package/src/db-store.ts +34 -0
  108. package/src/index.ts +13 -216
  109. package/src/lottery-agent-deps.ts +14 -4
  110. package/src/lottery-tool-handlers.ts +3 -3
  111. package/src/memory-db.ts +60 -0
  112. package/src/pipeline.ts +4 -11
  113. package/src/push.ts +32 -31
  114. package/src/recommend/report.ts +0 -30
  115. package/src/runtime-state.ts +23 -0
  116. package/agent/schedules/daily_pipeline.ts +0 -34
  117. package/lib/agent/agent.d.ts +0 -3
  118. package/lib/agent/agent.d.ts.map +0 -1
  119. package/lib/agent/agent.js +0 -6
  120. package/lib/agent/agent.js.map +0 -1
  121. package/lib/agent/run-turn.d.ts +0 -14
  122. package/lib/agent/run-turn.d.ts.map +0 -1
  123. package/lib/agent/run-turn.js +0 -47
  124. package/lib/agent/run-turn.js.map +0 -1
  125. package/lib/agent/schedules/daily_pipeline.d.ts +0 -3
  126. package/lib/agent/schedules/daily_pipeline.d.ts.map +0 -1
  127. package/lib/agent/schedules/daily_pipeline.js +0 -36
  128. package/lib/agent/schedules/daily_pipeline.js.map +0 -1
  129. package/lib/agent/tools/compute_recommend.d.ts +0 -5
  130. package/lib/agent/tools/compute_recommend.d.ts.map +0 -1
  131. package/lib/agent/tools/compute_recommend.js +0 -11
  132. package/lib/agent/tools/compute_recommend.js.map +0 -1
  133. package/lib/agent/tools/get_model_state.d.ts +0 -5
  134. package/lib/agent/tools/get_model_state.d.ts.map +0 -1
  135. package/lib/agent/tools/get_model_state.js +0 -11
  136. package/lib/agent/tools/get_model_state.js.map +0 -1
  137. package/lib/agent/tools/history.d.ts +0 -6
  138. package/lib/agent/tools/history.d.ts.map +0 -1
  139. package/lib/agent/tools/history.js +0 -24
  140. package/lib/agent/tools/history.js.map +0 -1
  141. package/lib/agent/tools/list_pending.d.ts +0 -5
  142. package/lib/agent/tools/list_pending.d.ts.map +0 -1
  143. package/lib/agent/tools/list_pending.js +0 -11
  144. package/lib/agent/tools/list_pending.js.map +0 -1
  145. package/lib/agent/tools/save_prediction.d.ts +0 -6
  146. package/lib/agent/tools/save_prediction.d.ts.map +0 -1
  147. package/lib/agent/tools/save_prediction.js +0 -14
  148. package/lib/agent/tools/save_prediction.js.map +0 -1
  149. package/lib/agent/tools/stats_snapshot.d.ts +0 -5
  150. package/lib/agent/tools/stats_snapshot.d.ts.map +0 -1
  151. package/lib/agent/tools/stats_snapshot.js +0 -11
  152. package/lib/agent/tools/stats_snapshot.js.map +0 -1
  153. package/lib/agent/tools/sync.d.ts +0 -5
  154. package/lib/agent/tools/sync.d.ts.map +0 -1
  155. package/lib/agent/tools/sync.js +0 -19
  156. package/lib/agent/tools/sync.js.map +0 -1
  157. package/lib/evals/pipeline_smoke.eval.d.ts +0 -3
  158. package/lib/evals/pipeline_smoke.eval.d.ts.map +0 -1
  159. package/lib/evals/pipeline_smoke.eval.js +0 -8
  160. package/lib/evals/pipeline_smoke.eval.js.map +0 -1
  161. package/lib/src/agent/prompts.d.ts +0 -11
  162. package/lib/src/agent/prompts.d.ts.map +0 -1
  163. package/lib/src/agent/prompts.js +0 -11
  164. package/lib/src/agent/prompts.js.map +0 -1
  165. package/lib/src/agent/read-skills.d.ts +0 -3
  166. package/lib/src/agent/read-skills.d.ts.map +0 -1
  167. package/lib/src/agent/read-skills.js +0 -25
  168. package/lib/src/agent/read-skills.js.map +0 -1
  169. package/lib/src/agent/run-turn.d.ts +0 -14
  170. package/lib/src/agent/run-turn.d.ts.map +0 -1
  171. package/lib/src/agent/run-turn.js +0 -47
  172. package/lib/src/agent/run-turn.js.map +0 -1
  173. package/lib/src/db.d.ts +0 -33
  174. package/lib/src/db.d.ts.map +0 -1
  175. package/lib/src/db.js +0 -108
  176. package/lib/src/db.js.map +0 -1
  177. package/lib/src/evaluate/adaptive-sim.d.ts +0 -31
  178. package/lib/src/evaluate/adaptive-sim.d.ts.map +0 -1
  179. package/lib/src/evaluate/adaptive-sim.js +0 -159
  180. package/lib/src/evaluate/adaptive-sim.js.map +0 -1
  181. package/lib/src/evaluate/backtest.d.ts +0 -29
  182. package/lib/src/evaluate/backtest.d.ts.map +0 -1
  183. package/lib/src/evaluate/backtest.js +0 -87
  184. package/lib/src/evaluate/backtest.js.map +0 -1
  185. package/lib/src/evaluate/hit-rate.d.ts +0 -8
  186. package/lib/src/evaluate/hit-rate.d.ts.map +0 -1
  187. package/lib/src/evaluate/hit-rate.js +0 -118
  188. package/lib/src/evaluate/hit-rate.js.map +0 -1
  189. package/lib/src/evaluate/review-pending.d.ts +0 -13
  190. package/lib/src/evaluate/review-pending.d.ts.map +0 -1
  191. package/lib/src/evaluate/review-pending.js +0 -89
  192. package/lib/src/evaluate/review-pending.js.map +0 -1
  193. package/lib/src/evaluate/tracker.d.ts +0 -28
  194. package/lib/src/evaluate/tracker.d.ts.map +0 -1
  195. package/lib/src/evaluate/tracker.js +0 -269
  196. package/lib/src/evaluate/tracker.js.map +0 -1
  197. package/lib/src/evaluate/train-weights.d.ts +0 -28
  198. package/lib/src/evaluate/train-weights.d.ts.map +0 -1
  199. package/lib/src/evaluate/train-weights.js +0 -101
  200. package/lib/src/evaluate/train-weights.js.map +0 -1
  201. package/lib/src/evaluate/weight-guard.d.ts +0 -15
  202. package/lib/src/evaluate/weight-guard.d.ts.map +0 -1
  203. package/lib/src/evaluate/weight-guard.js +0 -46
  204. package/lib/src/evaluate/weight-guard.js.map +0 -1
  205. package/lib/src/games/kl8-groups.d.ts +0 -31
  206. package/lib/src/games/kl8-groups.d.ts.map +0 -1
  207. package/lib/src/games/kl8-groups.js +0 -62
  208. package/lib/src/games/kl8-groups.js.map +0 -1
  209. package/lib/src/games/registry.d.ts +0 -13
  210. package/lib/src/games/registry.d.ts.map +0 -1
  211. package/lib/src/games/registry.js +0 -45
  212. package/lib/src/games/registry.js.map +0 -1
  213. package/lib/src/index.d.ts +0 -3
  214. package/lib/src/index.d.ts.map +0 -1
  215. package/lib/src/index.js +0 -183
  216. package/lib/src/index.js.map +0 -1
  217. package/lib/src/lottery-agent-deps.d.ts.map +0 -1
  218. package/lib/src/lottery-agent-deps.js +0 -10
  219. package/lib/src/lottery-agent-deps.js.map +0 -1
  220. package/lib/src/lottery-tool-handlers.d.ts.map +0 -1
  221. package/lib/src/lottery-tool-handlers.js.map +0 -1
  222. package/lib/src/pipeline.d.ts +0 -36
  223. package/lib/src/pipeline.d.ts.map +0 -1
  224. package/lib/src/pipeline.js +0 -130
  225. package/lib/src/pipeline.js.map +0 -1
  226. package/lib/src/push.d.ts +0 -3
  227. package/lib/src/push.d.ts.map +0 -1
  228. package/lib/src/push.js +0 -31
  229. package/lib/src/push.js.map +0 -1
  230. package/lib/src/recommend/game-pick.d.ts +0 -14
  231. package/lib/src/recommend/game-pick.d.ts.map +0 -1
  232. package/lib/src/recommend/game-pick.js +0 -169
  233. package/lib/src/recommend/game-pick.js.map +0 -1
  234. package/lib/src/recommend/report.d.ts +0 -22
  235. package/lib/src/recommend/report.d.ts.map +0 -1
  236. package/lib/src/recommend/report.js +0 -176
  237. package/lib/src/recommend/report.js.map +0 -1
  238. package/lib/src/stats/engine.d.ts +0 -18
  239. package/lib/src/stats/engine.d.ts.map +0 -1
  240. package/lib/src/stats/engine.js +0 -122
  241. package/lib/src/stats/engine.js.map +0 -1
  242. package/lib/src/stats/pro-analysis.d.ts +0 -7
  243. package/lib/src/stats/pro-analysis.d.ts.map +0 -1
  244. package/lib/src/stats/pro-analysis.js +0 -121
  245. package/lib/src/stats/pro-analysis.js.map +0 -1
  246. package/lib/src/stats/weights.d.ts +0 -8
  247. package/lib/src/stats/weights.d.ts.map +0 -1
  248. package/lib/src/stats/weights.js +0 -25
  249. package/lib/src/stats/weights.js.map +0 -1
  250. package/lib/src/sync/fetch-official.d.ts +0 -4
  251. package/lib/src/sync/fetch-official.d.ts.map +0 -1
  252. package/lib/src/sync/fetch-official.js +0 -160
  253. package/lib/src/sync/fetch-official.js.map +0 -1
  254. package/lib/src/sync/run-sync.d.ts +0 -8
  255. package/lib/src/sync/run-sync.d.ts.map +0 -1
  256. package/lib/src/sync/run-sync.js +0 -29
  257. package/lib/src/sync/run-sync.js.map +0 -1
  258. package/lib/src/tools/agent-tools.d.ts +0 -15
  259. package/lib/src/tools/agent-tools.d.ts.map +0 -1
  260. package/lib/src/tools/agent-tools.js +0 -211
  261. package/lib/src/tools/agent-tools.js.map +0 -1
  262. package/lib/src/types.d.ts +0 -84
  263. package/lib/src/types.d.ts.map +0 -1
  264. package/lib/src/types.js +0 -3
  265. package/lib/src/types.js.map +0 -1
  266. package/lib/tools/agent-tools.d.ts +0 -15
  267. package/lib/tools/agent-tools.d.ts.map +0 -1
  268. package/lib/tools/agent-tools.js +0 -211
  269. package/lib/tools/agent-tools.js.map +0 -1
  270. package/lib/tsconfig.tsbuildinfo +0 -1
  271. package/src/agent/run-turn.ts +0 -74
  272. /package/lib/{src/lottery-tool-handlers.d.ts → lottery-tool-handlers.d.ts} +0 -0
package/src/index.ts CHANGED
@@ -1,216 +1,13 @@
1
- /**
2
- * @zhin.js/plugin-lottery — scheduled pipeline: sync → review → recommend → push
3
- */
4
- import { formatCompact, MessageCommand, Schema, usePlugin } from 'zhin.js';
5
- import type { GameId } from './types.js';
6
- import { parseGameId, resolveEnabledGames } from './games/registry.js';
7
- import {
8
- defineLotteryTables,
9
- loadDraws,
10
- type LotteryDb,
11
- } from './db.js';
12
- import {
13
- formatDailyReportText,
14
- loadTodayReport,
15
- } from './recommend/report.js';
16
- import { recommendGame, formatPickLine, formatPickStats } from './recommend/game-pick.js';
17
- import {
18
- loadAccuracySnapshot,
19
- loadGameWeights,
20
- } from './evaluate/tracker.js';
21
- import { setLotteryAgentDeps } from './lottery-agent-deps.js';
22
- import { formatPipelineReply, runLotteryPipeline } from './pipeline.js';
23
- import { formatBacktestSection, formatTrainReport, runBacktestForGames, trainAllGameWeights } from './evaluate/backtest.js';
24
- import { resolveKl8Config, type Kl8ConfigInput } from './games/kl8-groups.js';
25
-
26
- const plugin = usePlugin();
27
- const { logger, addCommand, useContext, onDispose, declareConfig } = plugin;
28
-
29
- const config = declareConfig(
30
- 'lottery',
31
- Schema.object({
32
- pickCount: Schema.number().default(5).min(1).max(10).description('KL8 pick count'),
33
- scheduleCron: Schema.string().default('0 0 18 * * *').description('Daily pipeline cron (sync→review→recommend→push)'),
34
- historyLimit: Schema.number().default(500).min(50).max(2000).description('Max draws kept per game'),
35
- scheduleEnabled: Schema.boolean().default(true).description('Enable scheduled pipeline'),
36
- agentEnabled: Schema.boolean().default(true).description('AI narrative on daily report (optional)'),
37
- backtestEnabled: Schema.boolean().default(true).description('Walk-forward backtest vs random baseline in report'),
38
- backtestWindow: Schema.number().default(50).min(10).max(300).description('Backtest periods per game'),
39
- backtestRandomTrials: Schema.number().default(64).min(10).max(500).description('Monte Carlo random trials per period'),
40
- backtestMinHistory: Schema.number().default(30).min(10).max(150).description('Min history before walk-forward'),
41
- backtestAdaptive: Schema.boolean().default(true).description('Per-period weight tuning in backtest simulation'),
42
- weightPersistEnabled: Schema.boolean().default(true).description('Persist simulated F/O/T weights to lottery_model_weights'),
43
- weightHoldoutFallback: Schema.boolean().default(true).description('Use DEFAULT weights when holdout adaptive loses to random'),
44
- kl8: Schema.object({
45
- pickCount: Schema.number().default(5).min(1).max(10).description('Numbers per KL8 group (选N)'),
46
- recommendGroups: Schema.number().default(3).min(1).max(10).description('KL8 recommendation rows per day'),
47
- groupStrategies: Schema.list(Schema.string()).default(['balanced', 'hot', 'cold']),
48
- }).description('KL8 multi-strategy groups'),
49
- games: Schema.list(Schema.string()).default(['kl8', 'ssq', 'dlt', 'fc3d', 'pl3', 'pl5']),
50
- }),
51
- );
52
-
53
- let _db: LotteryDb | null = null;
54
-
55
- function getDb(): LotteryDb | null {
56
- return _db;
57
- }
58
-
59
- function enabledGames(): GameId[] {
60
- return resolveEnabledGames(config.games as string[]);
61
- }
62
-
63
- function pipelineDeps() {
64
- const kl8 = resolveKl8Config(config.pickCount, config.kl8 as Kl8ConfigInput | undefined);
65
- return {
66
- getDb,
67
- plugin,
68
- enabledGames,
69
- historyLimit: config.historyLimit,
70
- pickCount: config.pickCount,
71
- kl8,
72
- agentEnabled: config.agentEnabled,
73
- backtest: {
74
- enabled: config.backtestEnabled,
75
- window: config.backtestWindow,
76
- randomTrials: config.backtestRandomTrials,
77
- minHistory: config.backtestMinHistory,
78
- adaptive: config.backtestAdaptive,
79
- },
80
- weightPersist: config.weightPersistEnabled,
81
- weightHoldoutFallback: config.weightHoldoutFallback,
82
- };
83
- }
84
-
85
- function refreshLotteryAgentDeps(): void {
86
- setLotteryAgentDeps({
87
- getDb: () => _db,
88
- getConfig: () => ({
89
- pickCount: config.pickCount,
90
- historyLimit: config.historyLimit,
91
- kl8: resolveKl8Config(config.pickCount, config.kl8 as Kl8ConfigInput | undefined),
92
- }),
93
- plugin,
94
- enabledGames,
95
- scheduleCron: () => config.scheduleCron,
96
- scheduleEnabled: () => config.scheduleEnabled,
97
- pipelinePush: true,
98
- });
99
- }
100
-
101
- refreshLotteryAgentDeps();
102
-
103
- useContext('database', (db: unknown) => {
104
- const d = db as { define: (n: string, s: Record<string, unknown>) => void };
105
- defineLotteryTables(d);
106
- _db = db as LotteryDb;
107
- refreshLotteryAgentDeps();
108
- logger.debug(formatCompact({ op: 'lottery-ready', schedule: config.scheduleEnabled }));
109
- });
110
-
111
- onDispose(() => {});
112
-
113
- // ─── Commands ───────────────────────────────────────────────────────────────
114
-
115
- addCommand(
116
- new MessageCommand('lottery [game:word]')
117
- .desc('Run full pipeline: sync → review → recommend (manual, no push)')
118
- .action(async (_msg, result) => {
119
- const gid = parseGameId(result.params.game ?? '');
120
- const out = await runLotteryPipeline(pipelineDeps(), { gameId: gid ?? undefined, push: false });
121
- return formatPipelineReply(out);
122
- }),
123
- );
124
-
125
- addCommand(
126
- new MessageCommand('lottery-train [game:word]')
127
- .desc('Full-history weight training: predict→compare→tune from DEFAULT, persist to DB')
128
- .action(async (_msg, result) => {
129
- const db = getDb();
130
- if (!db) return '数据库未就绪';
131
- const gid = parseGameId(result.params.game ?? '');
132
- const gameIds = gid ? [gid] : enabledGames();
133
- const results = await trainAllGameWeights(db, gameIds, {
134
- pickCount: config.pickCount,
135
- minHistory: config.backtestMinHistory,
136
- historyLimit: config.historyLimit,
137
- randomTrials: config.backtestRandomTrials,
138
- holdoutWindow: config.backtestWindow,
139
- holdoutFallback: config.weightHoldoutFallback,
140
- persist: true,
141
- });
142
- return formatTrainReport(results);
143
- }),
144
- );
145
-
146
- addCommand(
147
- new MessageCommand('lottery-backtest [game:word]')
148
- .desc('Walk-forward backtest: strategy vs random baseline (no betting)')
149
- .action(async (_msg, result) => {
150
- const db = getDb();
151
- if (!db) return '数据库未就绪';
152
- const gid = parseGameId(result.params.game ?? '');
153
- const gameIds = gid ? [gid] : enabledGames();
154
- const summaries = await runBacktestForGames(db, gameIds, {
155
- pickCount: config.pickCount,
156
- window: config.backtestWindow,
157
- randomTrials: config.backtestRandomTrials,
158
- minHistory: config.backtestMinHistory,
159
- historyLimit: config.historyLimit,
160
- adaptive: config.backtestAdaptive,
161
- });
162
- const text = formatBacktestSection(summaries);
163
- return text || '历史数据不足,请先执行 lottery 同步开奖';
164
- }),
165
- );
166
-
167
- addCommand(
168
- new MessageCommand('lottery-today')
169
- .desc('Show today published recommendation report')
170
- .action(async () => {
171
- const db = getDb();
172
- if (!db) return '数据库未就绪';
173
- const report = await loadTodayReport(db);
174
- if (!report) return '今日尚无推荐,可执行 lottery 或等待定时任务';
175
- return formatDailyReportText(report, '');
176
- }),
177
- );
178
-
179
- addCommand(
180
- new MessageCommand('lottery-stats <game:word>')
181
- .desc('Single-game stats snapshot (code engine)')
182
- .action(async (_msg, result) => {
183
- const gid = parseGameId(result.params.game ?? '');
184
- if (!gid) return '请指定玩法';
185
- const db = getDb();
186
- if (!db) return '数据库未就绪';
187
- const draws = await loadDraws(db, gid, config.historyLimit);
188
- if (!draws.length) return '暂无数据,请先 lottery';
189
- const kl8 = resolveKl8Config(config.pickCount, config.kl8 as Kl8ConfigInput | undefined);
190
- const pick = recommendGame(gid, draws, {
191
- pickCount: gid === 'kl8' ? kl8.pickCount : config.pickCount,
192
- tieSeed: 'stats',
193
- weights: await loadGameWeights(db, gid),
194
- accuracy: await loadAccuracySnapshot(db, gid),
195
- kl8: gid === 'kl8' ? kl8 : undefined,
196
- });
197
- return [formatPickLine(pick), formatPickStats(pick), `样本 ${draws.length} 期`].join('\n');
198
- }),
199
- );
200
-
201
- addCommand(
202
- new MessageCommand('lottery-history <game:word> [count:number=10]')
203
- .desc('List historical draw results')
204
- .action(async (_msg, result) => {
205
- const gid = parseGameId(result.params.game ?? '');
206
- if (!gid) return '请指定玩法';
207
- const db = getDb();
208
- if (!db) return '数据库未就绪';
209
- const count = Math.min(50, Math.max(1, Number(result.params.count) || 10));
210
- const draws = await loadDraws(db, gid, count);
211
- if (!draws.length) return '暂无数据';
212
- return draws.map((d) => `${d.issue} ${d.drawTime} ${JSON.stringify(d.numbers)}`).join('\n');
213
- }),
214
- );
215
-
216
- export default plugin;
1
+ export { resolveLotteryConfig, DEFAULT_LOTTERY_CONFIG } from './config.js';
2
+ export type { LotteryConfig } from './config.js';
3
+ export {
4
+ getLotteryDb,
5
+ registerLotteryDb,
6
+ setLotteryDb,
7
+ ensureLotteryMemoryDb,
8
+ resetLotteryDb,
9
+ } from './db-store.js';
10
+ export { createInMemoryLotteryDb } from './memory-db.js';
11
+ export { lotteryRuntimeToken, resolveLotteryRuntime } from './runtime-state.js';
12
+ export type { LotteryRuntime } from './runtime-state.js';
13
+ export { formatPipelineReply, runLotteryPipeline } from './pipeline.js';
@@ -2,7 +2,6 @@
2
2
  * Shared runtime deps for lottery agent/ authoring tools.
3
3
  * Set once from plugin index during init — never call getPlugin() from tool execute.
4
4
  */
5
- import type { Plugin } from 'zhin.js';
6
5
  import type { GameId } from './types.js';
7
6
  import type { LotteryDb } from './db.js';
8
7
  import type { Kl8Config } from './games/kl8-groups.js';
@@ -10,7 +9,6 @@ import type { Kl8Config } from './games/kl8-groups.js';
10
9
  export interface LotteryAgentDeps {
11
10
  getDb: () => LotteryDb | null;
12
11
  getConfig: () => { pickCount: number; historyLimit: number; kl8: Kl8Config };
13
- plugin: Plugin;
14
12
  enabledGames: () => GameId[];
15
13
  scheduleCron: () => string;
16
14
  scheduleEnabled: () => boolean;
@@ -18,12 +16,24 @@ export interface LotteryAgentDeps {
18
16
  }
19
17
 
20
18
  let _deps: LotteryAgentDeps | null = null;
19
+ const registrations: Array<{ readonly value: LotteryAgentDeps }> = [];
21
20
 
22
21
  export function setLotteryAgentDeps(deps: LotteryAgentDeps): void {
23
22
  _deps = deps;
24
23
  }
25
24
 
25
+ /** Generation-owned Agent dependency binding used by Plugin Runtime setup(). */
26
+ export function registerLotteryAgentDeps(deps: LotteryAgentDeps): () => void {
27
+ const registration = Object.freeze({ value: deps });
28
+ registrations.push(registration);
29
+ return () => {
30
+ const index = registrations.lastIndexOf(registration);
31
+ if (index >= 0) registrations.splice(index, 1);
32
+ };
33
+ }
34
+
26
35
  export function getLotteryAgentDeps(): LotteryAgentDeps {
27
- if (!_deps) throw new Error('lottery agent deps not initialized');
28
- return _deps;
36
+ const deps = registrations[registrations.length - 1]?.value ?? _deps;
37
+ if (!deps) throw new Error('lottery agent deps not initialized');
38
+ return deps;
29
39
  }
@@ -14,7 +14,7 @@ import {
14
14
  loadAgentMemory,
15
15
  } from './evaluate/tracker.js';
16
16
  import { saveDailyReport } from './recommend/report.js';
17
- import { pushTextToMasters } from './push.js';
17
+ import { pushLotteryReport, getLotteryOutboundPush } from './push.js';
18
18
  import { normalizeWeights } from './stats/weights.js';
19
19
  import { getLotteryAgentDeps } from './lottery-agent-deps.js';
20
20
 
@@ -142,8 +142,8 @@ export async function handlePublishReport(content: string, push?: boolean): Prom
142
142
  if (!text.includes(DISCLAIMER)) return 'content must include disclaimer';
143
143
  const date = new Date().toISOString().slice(0, 10);
144
144
  await saveDailyReport(db, { date, picks: [] as never[], disclaimer: DISCLAIMER, body: text }, text);
145
- const doPush = push === true;
146
- if (doPush) await pushTextToMasters(deps.plugin, text);
145
+ const doPush = push === true && Boolean(getLotteryOutboundPush());
146
+ if (doPush) await pushLotteryReport(text);
147
147
  return JSON.stringify({ ok: true, date, pushed: doPush });
148
148
  }
149
149
 
@@ -0,0 +1,60 @@
1
+ import type { LotteryDb, LotteryModel } from './db.js';
2
+ import {
3
+ DRAWS_TABLE,
4
+ REPORTS_TABLE,
5
+ } from './db.js';
6
+ import {
7
+ MEMORY_TABLE,
8
+ PREDICTIONS_TABLE,
9
+ WEIGHTS_TABLE,
10
+ } from './evaluate/tracker.js';
11
+
12
+ /** Minimal in-memory model matching LotteryModel (select/insert/delete). */
13
+ function createMemoryModel(): LotteryModel {
14
+ const rows: Record<string, unknown>[] = [];
15
+
16
+ function matches(row: Record<string, unknown>, query: Record<string, unknown>): boolean {
17
+ return Object.entries(query).every(([key, value]) => row[key] === value);
18
+ }
19
+
20
+ return {
21
+ select: () => ({
22
+ where: async (query: Record<string, unknown>) => rows.filter((row) => matches(row, query)),
23
+ }),
24
+ insert: async (row: Record<string, unknown>) => {
25
+ rows.push({ ...row });
26
+ return row;
27
+ },
28
+ delete: () => ({
29
+ where: async (query: Record<string, unknown>) => {
30
+ for (let i = rows.length - 1; i >= 0; i -= 1) {
31
+ if (matches(rows[i]!, query)) rows.splice(i, 1);
32
+ }
33
+ },
34
+ }),
35
+ };
36
+ }
37
+
38
+ const TABLE_NAMES = [
39
+ DRAWS_TABLE,
40
+ REPORTS_TABLE,
41
+ PREDICTIONS_TABLE,
42
+ WEIGHTS_TABLE,
43
+ MEMORY_TABLE,
44
+ ] as const;
45
+
46
+ /**
47
+ * Slice-2 fallback while Plugin Runtime has no DatabaseFeature Resource path.
48
+ * Enough for smoke: today/history/stats/train/backtest/pipeline no longer return「数据库未就绪」.
49
+ */
50
+ export function createInMemoryLotteryDb(): LotteryDb {
51
+ const models = new Map<string, LotteryModel>();
52
+ for (const name of TABLE_NAMES) {
53
+ models.set(name, createMemoryModel());
54
+ }
55
+ return {
56
+ models: {
57
+ get: (name: string) => models.get(name),
58
+ },
59
+ };
60
+ }
package/src/pipeline.ts CHANGED
@@ -1,10 +1,8 @@
1
- import type { Plugin } from 'zhin.js';
2
1
  import type { GameId } from './types.js';
3
2
  import { syncGame, type LotteryDb } from './db.js';
4
3
 
5
4
  import {
6
5
  buildDailyReport,
7
- explainReportWithAi,
8
6
  formatDailyReportText,
9
7
  hydrateReportPickWeights,
10
8
  resolveTodayReport,
@@ -18,17 +16,15 @@ import {
18
16
  runHoldoutBacktest,
19
17
  } from './evaluate/weight-guard.js';
20
18
  import { cancelTodayPendingPredictions } from './evaluate/tracker.js';
21
- import { pushTextToMasters } from './push.js';
19
+ import { pushLotteryReport, getLotteryOutboundPush } from './push.js';
22
20
  import type { Kl8Config } from './games/kl8-groups.js';
23
21
 
24
22
  export interface PipelineDeps {
25
23
  getDb: () => LotteryDb | null;
26
- plugin: Plugin;
27
24
  enabledGames: () => GameId[];
28
25
  historyLimit: number;
29
26
  pickCount: number;
30
27
  kl8: Kl8Config;
31
- agentEnabled: boolean;
32
28
  backtest: {
33
29
  enabled: boolean;
34
30
  window: number;
@@ -174,10 +170,7 @@ export async function runLotteryPipeline(
174
170
  }
175
171
  report.picks = await hydrateReportPickWeights(db, report.picks);
176
172
 
177
- let aiNote = '';
178
- if (deps.agentEnabled) {
179
- aiNote = await explainReportWithAi(deps.plugin, report);
180
- }
173
+ const aiNote = '';
181
174
  reportText = formatDailyReportText(report, aiNote);
182
175
  await saveDailyReport(db, report, aiNote);
183
176
  recommendText = weightPlan.fallbacks.some((g) => needPredict.includes(g))
@@ -186,8 +179,8 @@ export async function runLotteryPipeline(
186
179
  }
187
180
 
188
181
  let pushed = false;
189
- if (options.push && reportText) {
190
- await pushTextToMasters(deps.plugin, reportText);
182
+ if (options.push && reportText && getLotteryOutboundPush()) {
183
+ await pushLotteryReport(reportText);
191
184
  pushed = true;
192
185
  }
193
186
 
package/src/push.ts CHANGED
@@ -1,34 +1,35 @@
1
- import type { Plugin } from 'zhin.js';
1
+ export interface LotteryPushTarget {
2
+ readonly adapter: string;
3
+ readonly endpointId: string;
4
+ readonly channelType?: string;
5
+ readonly channelId: string;
6
+ }
7
+
8
+ export type LotteryOutboundPush = (text: string) => Promise<void>;
9
+
10
+ let _outboundPush: LotteryOutboundPush | null = null;
11
+ const registrations: Array<{ readonly value: LotteryOutboundPush | null }> = [];
12
+
13
+ export function setLotteryOutboundPush(push: LotteryOutboundPush | null): void {
14
+ _outboundPush = push;
15
+ }
2
16
 
3
- export async function pushTextToMasters(plugin: Plugin, text: string): Promise<void> {
4
- const root = plugin.root as {
5
- adapters?: string[];
6
- inject?: (key: string) => unknown;
17
+ /** Generation-safe registration used by Plugin Runtime setup(). */
18
+ export function registerLotteryOutboundPush(push: LotteryOutboundPush | null): () => void {
19
+ const registration = Object.freeze({ value: push });
20
+ registrations.push(registration);
21
+ return () => {
22
+ const index = registrations.lastIndexOf(registration);
23
+ if (index >= 0) registrations.splice(index, 1);
7
24
  };
8
- const inject = root.inject?.bind(root);
9
- if (!inject) return;
10
- const adapterNames = root.adapters ?? [];
11
- for (const adapterName of adapterNames) {
12
- const adapter = inject(adapterName) as {
13
- endpoints?: Map<string, { $config?: { master?: unknown; name?: string }; $id?: string }>;
14
- sendMessage?: (opts: Record<string, unknown>) => Promise<unknown>;
15
- } | null;
16
- if (!adapter?.endpoints || !adapter.sendMessage) continue;
17
- for (const [, endpoint] of adapter.endpoints) {
18
- const master = endpoint.$config?.master;
19
- if (master == null || master === '') continue;
20
- const endpointId = endpoint.$id ?? endpoint.$config?.name ?? '';
21
- try {
22
- await adapter.sendMessage({
23
- context: adapterName,
24
- endpoint: endpointId,
25
- type: 'private',
26
- id: String(master),
27
- content: text,
28
- });
29
- } catch (e) {
30
- plugin.logger.warn(`lottery push failed: ${e instanceof Error ? e.message : String(e)}`);
31
- }
32
- }
33
- }
25
+ }
26
+
27
+ export function getLotteryOutboundPush(): LotteryOutboundPush | null {
28
+ const active = registrations[registrations.length - 1];
29
+ return active ? active.value : _outboundPush;
30
+ }
31
+
32
+ /** Push through the generation-owned OutboundHost configured by plugin setup. */
33
+ export async function pushLotteryReport(text: string): Promise<void> {
34
+ await getLotteryOutboundPush()?.(text);
34
35
  }
@@ -6,7 +6,6 @@ import { resolveKl8Config, type Kl8Config } from '../games/kl8-groups.js';
6
6
  import { loadDraws, REPORTS_TABLE, parseStoredJson, type LotteryDb } from '../db.js';
7
7
 
8
8
  import { listPendingPredictions, loadAccuracySnapshot, loadGameWeights, savePrediction } from '../evaluate/tracker.js';
9
- import { formatWeights } from '../stats/weights.js';
10
9
 
11
10
  export interface LotteryConfigSlice {
12
11
  pickCount: number;
@@ -180,32 +179,3 @@ export async function hydrateReportPickWeights(db: LotteryDb, picks: GamePick[])
180
179
  }
181
180
  return out;
182
181
  }
183
-
184
- export async function explainReportWithAi(
185
- root: { inject?: (key: string) => unknown },
186
- report: DailyReport,
187
- ): Promise<string> {
188
- const ai = root.inject?.('ai') as
189
- | { ask?: (prompt: string, opts?: { systemPrompt?: string }) => Promise<string> }
190
- | undefined;
191
- if (!ai?.ask) return '';
192
- const summary = report.picks
193
- .map((p) => {
194
- const acc = p.stats.accuracy
195
- ? `历史命中${(p.stats.accuracy.avgHitRate * 100).toFixed(1)}%`
196
- : '';
197
- const w = p.stats.pro?.modelWeights ?? formatWeights(p.weights);
198
- const nums = p.gameId === 'kl8' && p.kl8Groups?.length
199
- ? p.kl8Groups.map((g) => `组${g.index}(${g.label}) ${g.numbers.join(',')}`).join('; ')
200
- : formatPickLine(p).replace('■ ', '').replace(/\n/g, ' ');
201
- return `${p.label}: ${nums} | ${p.stats.detail} | ${w} | ${acc}`;
202
- })
203
- .join('\n');
204
- const systemPrompt =
205
- '你是专业彩票数据分析师。根据统计形态、模型权重与历史命中率写解读(250字内)。不得修改推荐号码。';
206
- try {
207
- return await ai.ask(`请专业解读以下推荐:\n\n${summary}`, { systemPrompt });
208
- } catch {
209
- return '';
210
- }
211
- }
@@ -0,0 +1,23 @@
1
+ import { createToken } from '@zhin.js/plugin-runtime';
2
+ import type { LotteryDb } from './db.js';
3
+
4
+ export interface LotteryRuntime {
5
+ readonly db: LotteryDb;
6
+ }
7
+
8
+ export const lotteryRuntimeToken = createToken<LotteryRuntime>(
9
+ 'zhin.lottery.runtime',
10
+ 'Owner-scoped Lottery database',
11
+ );
12
+
13
+ export function resolveLotteryRuntime(context: {
14
+ owner?: { id?: unknown };
15
+ use<T>(token: typeof lotteryRuntimeToken): T;
16
+ }): LotteryRuntime | undefined {
17
+ try {
18
+ return context.use(lotteryRuntimeToken) as LotteryRuntime;
19
+ } catch (error) {
20
+ if (context.owner?.id) throw error;
21
+ return undefined;
22
+ }
23
+ }
@@ -1,34 +0,0 @@
1
- import { defineSchedule } from '@zhin.js/agent/schedules';
2
- import { formatCompact } from 'zhin.js';
3
- import { getLotteryAgentDeps } from '../../src/lottery-agent-deps.js';
4
- import { runLotteryPipeline } from '../../src/pipeline.js';
5
-
6
- export default defineSchedule({
7
- cron: '0 0 18 * * *',
8
- description: 'Daily lottery pipeline: sync → review → recommend → push',
9
- async execute() {
10
- const deps = getLotteryAgentDeps();
11
- if (!deps.scheduleEnabled()) return;
12
- const db = deps.getDb();
13
- if (!db) return;
14
- const cfg = deps.getConfig();
15
- const result = await runLotteryPipeline({
16
- getDb: deps.getDb,
17
- plugin: deps.plugin,
18
- enabledGames: deps.enabledGames,
19
- historyLimit: cfg.historyLimit,
20
- pickCount: cfg.pickCount,
21
- kl8: cfg.kl8,
22
- agentEnabled: true,
23
- backtest: { enabled: true, window: 50, randomTrials: 64, minHistory: 30, adaptive: true },
24
- weightPersist: true,
25
- weightHoldoutFallback: true,
26
- }, { push: deps.pipelinePush });
27
- deps.plugin.logger?.info?.(formatCompact({
28
- op: 'lottery-pipeline',
29
- sync: result.sync,
30
- review: result.review,
31
- pushed: result.pushed,
32
- }));
33
- },
34
- });
@@ -1,3 +0,0 @@
1
- declare const _default: import("@zhin.js/agent").AuthoringAgentDefinition;
2
- export default _default;
3
- //# sourceMappingURL=agent.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../agent/agent.ts"],"names":[],"mappings":";AAEA,wBAGG"}
@@ -1,6 +0,0 @@
1
- import { defineAgent } from '@zhin.js/agent';
2
- export default defineAgent({
3
- description: 'Multi-game lottery analysis pipeline: sync, review, recommend, publish.',
4
- keywords: ['lottery', 'caipiao', 'kl8', 'ssq'],
5
- });
6
- //# sourceMappingURL=agent.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"agent.js","sourceRoot":"","sources":["../../agent/agent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,eAAe,WAAW,CAAC;IACzB,WAAW,EAAE,yEAAyE;IACtF,QAAQ,EAAE,CAAC,SAAS,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,CAAC;CAC/C,CAAC,CAAC"}
@@ -1,14 +0,0 @@
1
- import type { Plugin } from 'zhin.js';
2
- import type { LotteryAgentContext, LotteryAgentTask } from './prompts.js';
3
- export interface RunLotteryAgentOptions {
4
- task: LotteryAgentTask;
5
- context?: LotteryAgentContext;
6
- gameId?: string;
7
- maxIterations?: number;
8
- }
9
- export declare function runLotteryAgentTurn(root: Plugin, options: RunLotteryAgentOptions): Promise<{
10
- ok: boolean;
11
- text: string;
12
- usedAgent: boolean;
13
- }>;
14
- //# sourceMappingURL=run-turn.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"run-turn.d.ts","sourceRoot":"","sources":["../../src/agent/run-turn.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEtC,OAAO,KAAK,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAqB1E,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAC9B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAiBD,wBAAsB,mBAAmB,CACvC,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC,CA2B5D"}
@@ -1,47 +0,0 @@
1
- import { buildDailyPipelinePrompt } from './prompts.js';
2
- import { buildLotteryAgentSystemPrompt } from './read-skills.js';
3
- const LOTTERY_TOOL_PREFIX = 'lottery_';
4
- async function resolveLotteryTools(root) {
5
- const toolService = root.inject('tool');
6
- const raw = (toolService?.getAll() ?? []).filter((t) => t.name.startsWith(LOTTERY_TOOL_PREFIX));
7
- try {
8
- const agent = await import('zhin.js/agent');
9
- const normalizeTool = agent.normalizeTool;
10
- if (typeof normalizeTool === 'function') {
11
- return raw.map((t) => normalizeTool(t));
12
- }
13
- }
14
- catch {
15
- /* agent optional */
16
- }
17
- return raw;
18
- }
19
- export async function runLotteryAgentTurn(root, options) {
20
- const ai = root.inject('ai');
21
- if (!ai?.runAgent)
22
- return { ok: false, text: '', usedAgent: false };
23
- const providers = ai.listProviders?.() ?? [];
24
- if (!providers.length && ai.isReady?.() === false) {
25
- return { ok: false, text: '', usedAgent: false };
26
- }
27
- const userPrompt = buildDailyPipelinePrompt(options.context ?? {});
28
- const lotteryTools = await resolveLotteryTools(root);
29
- try {
30
- const result = await ai.runAgent(userPrompt, {
31
- systemPrompt: buildLotteryAgentSystemPrompt(),
32
- tools: lotteryTools,
33
- useBuiltinTools: true,
34
- collectExternalTools: false,
35
- maxIterations: options.maxIterations ?? 14,
36
- });
37
- return { ok: true, text: result.content?.trim() ?? '', usedAgent: true };
38
- }
39
- catch (e) {
40
- return {
41
- ok: false,
42
- text: e instanceof Error ? e.message : String(e),
43
- usedAgent: true,
44
- };
45
- }
46
- }
47
- //# sourceMappingURL=run-turn.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"run-turn.js","sourceRoot":"","sources":["../../src/agent/run-turn.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACxD,OAAO,EAAE,6BAA6B,EAAE,MAAM,kBAAkB,CAAC;AAEjE,MAAM,mBAAmB,GAAG,UAAU,CAAC;AAwBvC,KAAK,UAAU,mBAAmB,CAAC,IAAY;IAC7C,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC,MAAM,CAAyC,CAAC;IAChF,MAAM,GAAG,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAChG,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;QAC5C,MAAM,aAAa,GAAI,KAAkD,CAAC,aAAa,CAAC;QACxF,IAAI,OAAO,aAAa,KAAK,UAAU,EAAE,CAAC;YACxC,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,oBAAoB;IACtB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,IAAY,EACZ,OAA+B;IAE/B,MAAM,EAAE,GAAG,IAAI,CAAC,MAAM,CAAC,IAAI,CAA8B,CAAC;IAC1D,IAAI,CAAC,EAAE,EAAE,QAAQ;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IACpE,MAAM,SAAS,GAAG,EAAE,CAAC,aAAa,EAAE,EAAE,IAAI,EAAE,CAAC;IAC7C,IAAI,CAAC,SAAS,CAAC,MAAM,IAAI,EAAE,CAAC,OAAO,EAAE,EAAE,KAAK,KAAK,EAAE,CAAC;QAClD,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;IACnD,CAAC;IAED,MAAM,UAAU,GAAG,wBAAwB,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IACnE,MAAM,YAAY,GAAG,MAAM,mBAAmB,CAAC,IAAI,CAAC,CAAC;IAErD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE;YAC3C,YAAY,EAAE,6BAA6B,EAAE;YAC7C,KAAK,EAAE,YAAY;YACnB,eAAe,EAAE,IAAI;YACrB,oBAAoB,EAAE,KAAK;YAC3B,aAAa,EAAE,OAAO,CAAC,aAAa,IAAI,EAAE;SAC3C,CAAC,CAAC;QACH,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC;IAC3E,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO;YACL,EAAE,EAAE,KAAK;YACT,IAAI,EAAE,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;YAChD,SAAS,EAAE,IAAI;SAChB,CAAC;IACJ,CAAC;AACH,CAAC"}