guanwei 1.2.7 → 1.3.0
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 +27 -0
- package/package.json +1 -1
- package/server/src/data/db.json +315 -0
- package/server/src/data/guanwei.db +0 -0
- package/server/src/routes/ai.ts +20 -1
- package/server/src/routes/divine.ts +3 -59
- package/server/src/services/orchestrator.ts +106 -0
- package/server/src/services/promptBuilder.ts +2 -2
- package/shared/core/engine/chart.ts +76 -0
package/README.md
CHANGED
|
@@ -87,6 +87,33 @@ AI 层:多 LLM 适配(OpenAI 兼容 / Google 格式,DeepSeek / Gemini / Gr
|
|
|
87
87
|
③ 历史:GET /api/divine?username= → 档案管理页列表/详情/删除
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
+
## 🤖 开放分发(v1.3.0 · 程序化调用排盘)
|
|
91
|
+
|
|
92
|
+
排盘能力已封装为可被程序调用的服务(与 Web 端共用 `shared/core` 单一算法副本):
|
|
93
|
+
|
|
94
|
+
**MCP Server**(Claude Code / Cursor 等 agent 直接调用):
|
|
95
|
+
|
|
96
|
+
```jsonc
|
|
97
|
+
// claude_desktop_config.json
|
|
98
|
+
{ "mcpServers": { "guanwei": { "command": "npx", "args": ["tsx", "packages/guanwei-api/src/mcp.ts"], "cwd": "/你的/guanwei路径" } } }
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
```text
|
|
102
|
+
agent:用观微排一个 1993-01-23 寅时的八字
|
|
103
|
+
→ 工具 guanwei_chart(art: "bazi", inputs: {...}) → 完整盘面
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**REST API**(`packages/guanwei-api`,免费无 Key):
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
cd packages/guanwei-api && npm start # http://127.0.0.1:3020/v1
|
|
110
|
+
curl -X POST http://127.0.0.1:3020/v1/chart -H "Content-Type: application/json" \
|
|
111
|
+
-d '{"art":"liuren","inputs":{"datetime":"2026-08-29T12:00:00"}}'
|
|
112
|
+
curl http://127.0.0.1:3020/v1/arts # 九术能力清单 + 参数 schema
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
> 排盘免费(纯计算零 token);协议风格与未来托管 API 一致(/v1、统一错误码),本地自部署与第三方集成同源。
|
|
116
|
+
|
|
90
117
|
## 🚀 快速开始(一行命令)
|
|
91
118
|
|
|
92
119
|
### ⚡ 方式一:npm 一行安装(推荐,国内几秒装完)
|
package/package.json
CHANGED
package/server/src/data/db.json
CHANGED
|
@@ -6486,6 +6486,321 @@
|
|
|
6486
6486
|
"records": [],
|
|
6487
6487
|
"token": "b949c6fcac9b821cc74e1afb5a50acfacebafa21c79d13c61ae892998f33bbe9",
|
|
6488
6488
|
"tokenExpires": 1791206668608
|
|
6489
|
+
},
|
|
6490
|
+
{
|
|
6491
|
+
"username": "联调5050",
|
|
6492
|
+
"passHash": "scrypt$bf40f5daa6a9a53952861bbd3273ba26$4aa265c117b3a102c07214fa27a66b6b66503c372c9ce1b96cf3eaaa54f0c78f48007a5499132ef03a04cd85033d3bbef0e919cf9aab2526fd87511aa41e22fe",
|
|
6493
|
+
"createdAt": 1788656535121,
|
|
6494
|
+
"profile": {
|
|
6495
|
+
"birthDate": "1996-09-09",
|
|
6496
|
+
"birthHourIndex": 5,
|
|
6497
|
+
"gender": "男",
|
|
6498
|
+
"location": null
|
|
6499
|
+
},
|
|
6500
|
+
"samples": [],
|
|
6501
|
+
"records": [
|
|
6502
|
+
{
|
|
6503
|
+
"artId": "bazi",
|
|
6504
|
+
"createdAt": 1,
|
|
6505
|
+
"result": {
|
|
6506
|
+
"dayGZ": "壬申"
|
|
6507
|
+
}
|
|
6508
|
+
}
|
|
6509
|
+
],
|
|
6510
|
+
"token": "c3844cd28357240447326062dc92a29b4cbf7bf05cc4f63c4f16d320fb951d32",
|
|
6511
|
+
"tokenExpires": 1791248535194
|
|
6512
|
+
},
|
|
6513
|
+
{
|
|
6514
|
+
"username": "鉴权5280",
|
|
6515
|
+
"passHash": "scrypt$dbe5830db7570713fc95920032f943b5$9ca907f2ba3dc583a46e7d3c56c5e1f71705cee897d87eacd4c391e365d301ea4f083644acdaa2b003919635d5402a3972a7718e94266428d4a7b0bc4cbeb1d2",
|
|
6516
|
+
"createdAt": 1788656535313,
|
|
6517
|
+
"profile": {
|
|
6518
|
+
"birthDate": "1999-01-01"
|
|
6519
|
+
},
|
|
6520
|
+
"samples": [],
|
|
6521
|
+
"records": [],
|
|
6522
|
+
"token": "6db524357e54767784b4d4ad932ea0f45f71ebf96af44467baa6b1e49cf15754",
|
|
6523
|
+
"tokenExpires": 1791248535313
|
|
6524
|
+
},
|
|
6525
|
+
{
|
|
6526
|
+
"username": "他人5332",
|
|
6527
|
+
"passHash": "scrypt$1e363a1711a69d5920a5ed049279b602$82b72356633397200f974327c4aef9b03b561fd6824d90190d1ef83331235bb6b6883ce718d79cd830c128f2fa08814f62f25f0a9cc67e991db9f5ae4816ec5e",
|
|
6528
|
+
"createdAt": 1788656535361,
|
|
6529
|
+
"profile": {},
|
|
6530
|
+
"samples": [],
|
|
6531
|
+
"records": [],
|
|
6532
|
+
"token": "c5355a2b7376d9e1b99411f6232631244c53bacdba76ea43b746380947a8cfaf",
|
|
6533
|
+
"tokenExpires": 1791248535361
|
|
6534
|
+
},
|
|
6535
|
+
{
|
|
6536
|
+
"username": "轮换5368",
|
|
6537
|
+
"passHash": "scrypt$4400cc24ab2b9eedaa69f40ae1449826$0a2f9b327a17522775cda6d4e53e5d18545825bc8602a468d5a977a53ac0e49eb9875c4675b1462413244637431d7658976a05f576e62db0b1ef4f276999c9d3",
|
|
6538
|
+
"createdAt": 1788656535400,
|
|
6539
|
+
"profile": {},
|
|
6540
|
+
"samples": [],
|
|
6541
|
+
"records": [],
|
|
6542
|
+
"token": "dfee2d9a2d5366361e5fe7b8eacb2cd42c784d286e344bd8150ba4fa6eeaa55d",
|
|
6543
|
+
"tokenExpires": 1791248535437
|
|
6544
|
+
},
|
|
6545
|
+
{
|
|
6546
|
+
"username": "占位5446",
|
|
6547
|
+
"passHash": "scrypt$2d3199a92acffc2830b4cc672f3eb7b2$f3423d89fefe892488a9ab5e04b77724251d7d787446b9242c88566ce70e647e2c0615d44faf300e117df1f774ed7dee6eab78ece955446ac8b7ab8c67f883fa",
|
|
6548
|
+
"createdAt": 1788656535450,
|
|
6549
|
+
"profile": {},
|
|
6550
|
+
"samples": [],
|
|
6551
|
+
"records": [],
|
|
6552
|
+
"token": "e8709cd87cde3047be5507d5b2889fa26f40ab140519436ca8d362fd50335e44",
|
|
6553
|
+
"tokenExpires": 1791248535544
|
|
6554
|
+
},
|
|
6555
|
+
{
|
|
6556
|
+
"username": "甲5546",
|
|
6557
|
+
"passHash": "scrypt$2f4f33fd5e453036459ce9cf6e995e49$8c6c0969034ec6a1003643de622f62aa335a0a3974e6e7362cda82a4b5795c0192eb714ba4e7e5917d6aa8a1c1f0d43e9286372270301ac7bed702b4ba0458a3",
|
|
6558
|
+
"createdAt": 1788656535582,
|
|
6559
|
+
"profile": {},
|
|
6560
|
+
"samples": [],
|
|
6561
|
+
"records": [],
|
|
6562
|
+
"token": "5aca19f53c1be5d88a38df04bc0e6244c58ac980691c859c123ef3cd91ec7fbb",
|
|
6563
|
+
"tokenExpires": 1791248535582
|
|
6564
|
+
},
|
|
6565
|
+
{
|
|
6566
|
+
"username": "乙5546",
|
|
6567
|
+
"passHash": "scrypt$38ca20b58b781db8c17e77ac14df4a57$35d9423d48bbad4ab75f4677ae12786f574dfa678b9f32bc1cc4c0c20db11f0e67e2608f6b0b71c5a09cf1c97f9851c48466a668431e6b373aad4c180598325d",
|
|
6568
|
+
"createdAt": 1788656535621,
|
|
6569
|
+
"profile": {},
|
|
6570
|
+
"samples": [],
|
|
6571
|
+
"records": [],
|
|
6572
|
+
"token": "17e392a444b48f658ca24356da281b2fd31dd1e7eb16fc7978becd58aa238adc",
|
|
6573
|
+
"tokenExpires": 1791248535621
|
|
6574
|
+
},
|
|
6575
|
+
{
|
|
6576
|
+
"username": "列删5668",
|
|
6577
|
+
"passHash": "scrypt$bc34567711d77c2a736756b8cb6a0c3b$1fd68b5244cde889d4351794c24de4352c7f0125ace41680bc6dfe97c743221c8651838ee6437957542b0e85413a1483e73cd0794ab34c20bc5029710c273eac",
|
|
6578
|
+
"createdAt": 1788656535700,
|
|
6579
|
+
"profile": {},
|
|
6580
|
+
"samples": [],
|
|
6581
|
+
"records": [],
|
|
6582
|
+
"token": "1d59b0ddc8e830d6521c2985050a2b1d8543983453429f8b00e4f8cdfd945631",
|
|
6583
|
+
"tokenExpires": 1791248535700
|
|
6584
|
+
},
|
|
6585
|
+
{
|
|
6586
|
+
"username": "删乙5668",
|
|
6587
|
+
"passHash": "scrypt$f887a7e8f5a9533ccd07cfd7c63bbc7e$4bb2f63af55c704fbd801b39b3d3c79b9c889076057673b18c85a343bd8350dc5e7160d566a49e031f31ba1c028b8729687325970ceef66cefe0f9e1c51464b9",
|
|
6588
|
+
"createdAt": 1788656535745,
|
|
6589
|
+
"profile": {},
|
|
6590
|
+
"samples": [],
|
|
6591
|
+
"records": [],
|
|
6592
|
+
"token": "2b1e8e6fee6b55fa6ec7b34698d5417e0ffdbc558a5dbfbbfaf6a817e089ed77",
|
|
6593
|
+
"tokenExpires": 1791248535745
|
|
6594
|
+
},
|
|
6595
|
+
{
|
|
6596
|
+
"username": "联调7905",
|
|
6597
|
+
"passHash": "scrypt$49cdc5afb9eb173d5455c48d8f31983a$b7b02ad7add1aaf4904a5f797d4a3554d48aed88228b5030d6ce712821c23e0501cfbc5edda8a8b1368294c16e41e7bd9571f74cfa5c670d97703b2e23ad4ae4",
|
|
6598
|
+
"createdAt": 1788656727972,
|
|
6599
|
+
"profile": {
|
|
6600
|
+
"birthDate": "1996-09-09",
|
|
6601
|
+
"birthHourIndex": 5,
|
|
6602
|
+
"gender": "男",
|
|
6603
|
+
"location": null
|
|
6604
|
+
},
|
|
6605
|
+
"samples": [],
|
|
6606
|
+
"records": [
|
|
6607
|
+
{
|
|
6608
|
+
"artId": "bazi",
|
|
6609
|
+
"createdAt": 1,
|
|
6610
|
+
"result": {
|
|
6611
|
+
"dayGZ": "壬申"
|
|
6612
|
+
}
|
|
6613
|
+
}
|
|
6614
|
+
],
|
|
6615
|
+
"token": "119ed7b0aa8a1e6e123578a26f36f7b931b5ada3a892ddf22eb51f89f2b35604",
|
|
6616
|
+
"tokenExpires": 1791248728039
|
|
6617
|
+
},
|
|
6618
|
+
{
|
|
6619
|
+
"username": "鉴权8122",
|
|
6620
|
+
"passHash": "scrypt$e265380493f0dedfafd8d7f4f90a8cef$9f8397ec3b242ae775fc1004cd5b1f6e98b37a61aa9cd4baf18597e41e5912e38c9b78a09b0d99b07ab671850f433c46c7132d734cc85d41e219e810f2bd050d",
|
|
6621
|
+
"createdAt": 1788656728159,
|
|
6622
|
+
"profile": {
|
|
6623
|
+
"birthDate": "1999-01-01"
|
|
6624
|
+
},
|
|
6625
|
+
"samples": [],
|
|
6626
|
+
"records": [],
|
|
6627
|
+
"token": "8ab64b73eac240b2a0b186f7b2fddc03d8a7061ccf33d6dbbee39cb5dfae1054",
|
|
6628
|
+
"tokenExpires": 1791248728159
|
|
6629
|
+
},
|
|
6630
|
+
{
|
|
6631
|
+
"username": "他人8184",
|
|
6632
|
+
"passHash": "scrypt$176de87bd3ade7866cb88e2f3ff18b4f$241cd9c463ee1c785b916972936c8b8fed9b0355cea0e319712cb05afb19b95a57a7b2d8738a1d19640e9085196a95e868bc5d66fde3675e1f33994e296bf360",
|
|
6633
|
+
"createdAt": 1788656728227,
|
|
6634
|
+
"profile": {},
|
|
6635
|
+
"samples": [],
|
|
6636
|
+
"records": [],
|
|
6637
|
+
"token": "b9d5e19626a4b1287c3b99b5b205237c9ef59c76ad5d992e77fe3e4489fe4f27",
|
|
6638
|
+
"tokenExpires": 1791248728227
|
|
6639
|
+
},
|
|
6640
|
+
{
|
|
6641
|
+
"username": "轮换8236",
|
|
6642
|
+
"passHash": "scrypt$c559ee39ef9941f21daca916c9522831$3e1a47d4bfd1e7a9f0a515dda6aa65610fa1f328894a11b6f3fa7da2c41ec037e56c1fff48f04d854351e012dadf91be8493263fceee464bddf1d2e7f791c102",
|
|
6643
|
+
"createdAt": 1788656728270,
|
|
6644
|
+
"profile": {},
|
|
6645
|
+
"samples": [],
|
|
6646
|
+
"records": [],
|
|
6647
|
+
"token": "c621eb2629313b1e6aab90a1db26970a620821639c8b2ea03ccfc13c6b047395",
|
|
6648
|
+
"tokenExpires": 1791248728314
|
|
6649
|
+
},
|
|
6650
|
+
{
|
|
6651
|
+
"username": "占位8326",
|
|
6652
|
+
"passHash": "scrypt$6890b74d8a4a8c337986d93fe785417c$eea609b0149683ffdd3734a8949fbbc6b0398cd27813f3dba938d70bd42504007f66ddda73cf591a6620544c7e1f6e9e23e5c2fd2e4f69b60d55c13ffb4276cf",
|
|
6653
|
+
"createdAt": 1788656728335,
|
|
6654
|
+
"profile": {},
|
|
6655
|
+
"samples": [],
|
|
6656
|
+
"records": [],
|
|
6657
|
+
"token": "8052720e19f2e6d8e0c1c3a58547faa976302f826dfbf36592859b904ce46595",
|
|
6658
|
+
"tokenExpires": 1791248728428
|
|
6659
|
+
},
|
|
6660
|
+
{
|
|
6661
|
+
"username": "甲8431",
|
|
6662
|
+
"passHash": "scrypt$24331e9122f4668629e7e3f47a66d4cc$96ad98c72e92f3aa20da504657005b2b53a5ce0e4097b15682d922df9d142e5970429e32af4e759220445b803f14237540bf4653c954be3cb1a80d1721a33fdc",
|
|
6663
|
+
"createdAt": 1788656728467,
|
|
6664
|
+
"profile": {},
|
|
6665
|
+
"samples": [],
|
|
6666
|
+
"records": [],
|
|
6667
|
+
"token": "f1cb56f7c7a4a5ecc5f22b0c6cf5e4cc211be4bd2757f702e698eaaacf8a4e43",
|
|
6668
|
+
"tokenExpires": 1791248728467
|
|
6669
|
+
},
|
|
6670
|
+
{
|
|
6671
|
+
"username": "乙8431",
|
|
6672
|
+
"passHash": "scrypt$77935be141f0a4f4db438e922a762304$eaed3aaf76450dc406b3edf82327a7b6de108c1162ecf91b4ae0ad136918ee7e9a517ea2c3c00262859319b6b0568bf27f217ca91178c43bfcabaea0d4b4254b",
|
|
6673
|
+
"createdAt": 1788656728511,
|
|
6674
|
+
"profile": {},
|
|
6675
|
+
"samples": [],
|
|
6676
|
+
"records": [],
|
|
6677
|
+
"token": "a42c05c0c350a70b63fa9b8ad7d06e44b48b396b1494c4be9838bcc1305907be",
|
|
6678
|
+
"tokenExpires": 1791248728511
|
|
6679
|
+
},
|
|
6680
|
+
{
|
|
6681
|
+
"username": "列删8549",
|
|
6682
|
+
"passHash": "scrypt$b59bb912b8ec3b772d6780f54e633b3c$467f6c4c7dc95d4509cab0e2c5956649b2df650f2fe2a6517bb7e6b9be3233fc649ec339785ad77054aeaec528f1c17a8f2d905c5aab337ca62ffcbbb9e3611b",
|
|
6683
|
+
"createdAt": 1788656728586,
|
|
6684
|
+
"profile": {},
|
|
6685
|
+
"samples": [],
|
|
6686
|
+
"records": [],
|
|
6687
|
+
"token": "39d7929d8ae538dc1ab2453f49a0239aa83922f9ca947023648ce25d10bef248",
|
|
6688
|
+
"tokenExpires": 1791248728586
|
|
6689
|
+
},
|
|
6690
|
+
{
|
|
6691
|
+
"username": "删乙8549",
|
|
6692
|
+
"passHash": "scrypt$9370c356aae368426704ad5f63d534c8$1596e1eab509523f1e62899c47bd135a7bc770c7583231d23128e452661a11437bfa10e8c867f174ca621a66213344fc962d4962d8acafef2f4292ee5a6f9768",
|
|
6693
|
+
"createdAt": 1788656728629,
|
|
6694
|
+
"profile": {},
|
|
6695
|
+
"samples": [],
|
|
6696
|
+
"records": [],
|
|
6697
|
+
"token": "a195fcc6854001dd3b94aad7aa386ce0a0aeda65189e48029b5e0c7e537e80ef",
|
|
6698
|
+
"tokenExpires": 1791248728629
|
|
6699
|
+
},
|
|
6700
|
+
{
|
|
6701
|
+
"username": "联调0077",
|
|
6702
|
+
"passHash": "scrypt$50edd92f69ee72f3e0a68201f1bc5d20$ffcf31876a36ea9f4b068ff1c65946446015e044d257ed94a19b7b696c0a3b8bfd71344509175632d11309869c7945e2ca2c231890aeec0af55edd5963cb4bcb",
|
|
6703
|
+
"createdAt": 1788656750131,
|
|
6704
|
+
"profile": {
|
|
6705
|
+
"birthDate": "1996-09-09",
|
|
6706
|
+
"birthHourIndex": 5,
|
|
6707
|
+
"gender": "男",
|
|
6708
|
+
"location": null
|
|
6709
|
+
},
|
|
6710
|
+
"samples": [],
|
|
6711
|
+
"records": [
|
|
6712
|
+
{
|
|
6713
|
+
"artId": "bazi",
|
|
6714
|
+
"createdAt": 1,
|
|
6715
|
+
"result": {
|
|
6716
|
+
"dayGZ": "壬申"
|
|
6717
|
+
}
|
|
6718
|
+
}
|
|
6719
|
+
],
|
|
6720
|
+
"token": "dc26a50c9d65a0f58d1a9b2fb2fd3de2b761370363db2eaa3041544b3dca5397",
|
|
6721
|
+
"tokenExpires": 1791248750189
|
|
6722
|
+
},
|
|
6723
|
+
{
|
|
6724
|
+
"username": "鉴权0281",
|
|
6725
|
+
"passHash": "scrypt$65d1e113491e9f536756c140f8379375$08ac8f2710e866b22b6061062085ef23a0ee8b8898f69f20b59503339481f4374ced21eed1271a187b5c6f084993431ce12c5ff958ad8434aa5d1ccf8655071d",
|
|
6726
|
+
"createdAt": 1788656750313,
|
|
6727
|
+
"profile": {
|
|
6728
|
+
"birthDate": "1999-01-01"
|
|
6729
|
+
},
|
|
6730
|
+
"samples": [],
|
|
6731
|
+
"records": [],
|
|
6732
|
+
"token": "1e068fb703b577ab8bfb6ce010112d39490958c1f0de002ce917e938bb266ba4",
|
|
6733
|
+
"tokenExpires": 1791248750313
|
|
6734
|
+
},
|
|
6735
|
+
{
|
|
6736
|
+
"username": "他人0335",
|
|
6737
|
+
"passHash": "scrypt$2e4bd91e7c5e7eb5ed1624f4ad37f14c$7348e352613dab4da05a5a20ddcf8aa315588c1c3f1a883f9854fc15fe3d59a755b6b9beb48f0d3a464396460bbd7ddc07e8f5d90f8d5fbf2a1c88934e06fc65",
|
|
6738
|
+
"createdAt": 1788656750378,
|
|
6739
|
+
"profile": {},
|
|
6740
|
+
"samples": [],
|
|
6741
|
+
"records": [],
|
|
6742
|
+
"token": "cf0c100819459c4f6bcb2b2213cdf55ca478ff7de2610dc3fe297fcde0115d94",
|
|
6743
|
+
"tokenExpires": 1791248750378
|
|
6744
|
+
},
|
|
6745
|
+
{
|
|
6746
|
+
"username": "轮换0384",
|
|
6747
|
+
"passHash": "scrypt$3e6b39a19490d89c279575a1487f7ef6$f9116d02e9c83b349138ca308eb621f7c8206a68adef459c325537ec1ff76497cbc20d83e530313ae69f4ddd0de2aa4c7f97a30341b013173776c5e83b2cad57",
|
|
6748
|
+
"createdAt": 1788656750427,
|
|
6749
|
+
"profile": {},
|
|
6750
|
+
"samples": [],
|
|
6751
|
+
"records": [],
|
|
6752
|
+
"token": "d2e0fa44d0787c3dadae450bcfdcc2da8c21828e6cc20431b6781c61fb98a114",
|
|
6753
|
+
"tokenExpires": 1791248750470
|
|
6754
|
+
},
|
|
6755
|
+
{
|
|
6756
|
+
"username": "占位0481",
|
|
6757
|
+
"passHash": "scrypt$70e48545fcf9b358db4ea5d62c5c5e02$23678b8e4e3dc36e6da8600478c681e2f9b10c90abfbbd9fdd45326e223edf038cf0b475947ddafe9d2740498f3db104c08b78d6cc188e5e5c60ffb46c971872",
|
|
6758
|
+
"createdAt": 1788656750485,
|
|
6759
|
+
"profile": {},
|
|
6760
|
+
"samples": [],
|
|
6761
|
+
"records": [],
|
|
6762
|
+
"token": "32a48906aba1a838f03d1d53e5e1423212b39f275d8566d1b80c9f05ed6ad561",
|
|
6763
|
+
"tokenExpires": 1791248750571
|
|
6764
|
+
},
|
|
6765
|
+
{
|
|
6766
|
+
"username": "甲0573",
|
|
6767
|
+
"passHash": "scrypt$e7d97388393be7ff74627db02c86ab85$c00f3fbbc7ba849664db2887ee250dd69e34d234588f4c6ae0ff4bdceb256f24fa9b5f0789f81744b7fdde2c346365c5ad4d8bb5ea4c4f655afe2faff99231db",
|
|
6768
|
+
"createdAt": 1788656750606,
|
|
6769
|
+
"profile": {},
|
|
6770
|
+
"samples": [],
|
|
6771
|
+
"records": [],
|
|
6772
|
+
"token": "244f43af5d6ac85187ceb43fab5ee96b4e9e4fc6be1dd757e05728f5396b103c",
|
|
6773
|
+
"tokenExpires": 1791248750606
|
|
6774
|
+
},
|
|
6775
|
+
{
|
|
6776
|
+
"username": "乙0573",
|
|
6777
|
+
"passHash": "scrypt$ba780cc69712a61fc6298cc5f66cf4cd$621a99751fee71c830135212bd0a5dadb57dccc0bcc24de321324ae5856bc1f51035ec7efeb4679367e5a5438c0d9b93c982f6173bd62081cd55b6c74ff81a61",
|
|
6778
|
+
"createdAt": 1788656750646,
|
|
6779
|
+
"profile": {},
|
|
6780
|
+
"samples": [],
|
|
6781
|
+
"records": [],
|
|
6782
|
+
"token": "6ba780a775f3d206f96edf69bd146d5c3531c52ef3e08d87b56c5230b60accf9",
|
|
6783
|
+
"tokenExpires": 1791248750646
|
|
6784
|
+
},
|
|
6785
|
+
{
|
|
6786
|
+
"username": "列删0677",
|
|
6787
|
+
"passHash": "scrypt$60eebf3efab799e0966cf94d92017e14$340cb6dbe30f22d46e45b82b981849a957f17e35c6fbb0cf6a1cc00261456f6cf4968b49efe43ebbb1c18b043199f56c63591b39990c4afe6135f4748a8606df",
|
|
6788
|
+
"createdAt": 1788656750717,
|
|
6789
|
+
"profile": {},
|
|
6790
|
+
"samples": [],
|
|
6791
|
+
"records": [],
|
|
6792
|
+
"token": "403ad44e3d82f0cffb45efb7b32033e548f4cd4ab3d3f6296f48233d5ca4b9be",
|
|
6793
|
+
"tokenExpires": 1791248750717
|
|
6794
|
+
},
|
|
6795
|
+
{
|
|
6796
|
+
"username": "删乙0677",
|
|
6797
|
+
"passHash": "scrypt$a387cfd0aed6e0639c1a77371231856e$ae510248082fdc35243c8d64b71c424f9f98c410574a6eba1ff8de4d55765014740ca3895f0d06bea7b3c0b2ef39cc403622a62379a7be6ec5921f3e735446d7",
|
|
6798
|
+
"createdAt": 1788656750766,
|
|
6799
|
+
"profile": {},
|
|
6800
|
+
"samples": [],
|
|
6801
|
+
"records": [],
|
|
6802
|
+
"token": "c9f8abdca63dd948b07289e84586b6d73f47ed0bab242426a380dbc0a699ba28",
|
|
6803
|
+
"tokenExpires": 1791248750766
|
|
6489
6804
|
}
|
|
6490
6805
|
]
|
|
6491
6806
|
}
|
|
Binary file
|
package/server/src/routes/ai.ts
CHANGED
|
@@ -8,6 +8,8 @@ import { buildMessages, buildReportMessages, buildStep1Messages, buildStep2Messa
|
|
|
8
8
|
import { chatOnce, chatStream, activeProvider, providerStatus, lastFinishReason } from '../services/llmProvider.js';
|
|
9
9
|
import { getDivination, attachReport, markAiFailed } from '../services/divineStore.js';
|
|
10
10
|
import { verifyRelatives, fixFamilyRelatives } from '../services/relativesCheck.js';
|
|
11
|
+
import { orchestrateZiweiDeep } from '../services/orchestrator.js';
|
|
12
|
+
import { MINGPAN_TEMPLATE } from '../services/promptBuilder.js';
|
|
11
13
|
|
|
12
14
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
13
15
|
|
|
@@ -46,7 +48,7 @@ router.get('/providers', (_req, res) => {
|
|
|
46
48
|
|
|
47
49
|
// 非流式解读(保底通道)
|
|
48
50
|
router.post('/interpret', async (req, res) => {
|
|
49
|
-
const { artId, question, divineId, semantic, profile, report, fit, username } = req.body;
|
|
51
|
+
const { artId, question, divineId, semantic, profile, report, fit, username, orchestrate } = req.body;
|
|
50
52
|
if (!artId) return res.status(400).json({ error: '缺少必要参数' });
|
|
51
53
|
try {
|
|
52
54
|
// 从 SQLite 读排盘数据(v6:不再信任前端直传 resultRaw)
|
|
@@ -61,6 +63,23 @@ router.post('/interpret', async (req, res) => {
|
|
|
61
63
|
} else {
|
|
62
64
|
return res.status(400).json({ error: 'DIVINE_REQUIRED', message: '请先起占(divineId 缺失)' });
|
|
63
65
|
}
|
|
66
|
+
// 真·多 Agent 编排模式(v1:紫微深度三步链式)
|
|
67
|
+
if (orchestrate === 'ziwei-deep' && artId === 'ziwei') {
|
|
68
|
+
const { full } = await orchestrateZiweiDeep(resultRaw, question, MINGPAN_TEMPLATE, (recProfile as any)?.gender || (profile as any)?.gender);
|
|
69
|
+
const parsed2 = parseReport(full, 'mingpan');
|
|
70
|
+
const relErrs2 = verifyRelatives('ziwei', resultRaw, parsed2);
|
|
71
|
+
if (relErrs2.length && relErrs2.length <= 6) {
|
|
72
|
+
console.warn('[ai] 六亲表述矛盾,定向修正:', relErrs2.join(';'));
|
|
73
|
+
const fixed2 = await fixFamilyRelatives('ziwei', resultRaw, parsed2, relErrs2);
|
|
74
|
+
if (fixed2) parsed2.family = fixed2 as any;
|
|
75
|
+
}
|
|
76
|
+
if (parsed2.quality === 'ok') {
|
|
77
|
+
attachReport(divineId, parsed2, 'ok');
|
|
78
|
+
return res.json({ provider: activeProvider()?.id, report: parsed2, sections: parseSections(full), orchestrated: true });
|
|
79
|
+
}
|
|
80
|
+
markAiFailed(divineId, 'ziwei', 'mingpan', '编排质量未达标', full.slice(0, 4000));
|
|
81
|
+
return res.status(502).json({ error: 'AI_REPORT_INVALID', message: 'AI 输出不符合报告结构,请重试' });
|
|
82
|
+
}
|
|
64
83
|
// 统一报告模式:两步管线(Step1 盘面解析 → Step2 深度报告),Step1 失败降级单步
|
|
65
84
|
const kind = ['bazi', 'ziwei', 'astrology'].includes(artId) ? 'mingpan' : 'zhanwen';
|
|
66
85
|
let step1Text = '';
|
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
// 排盘路由:登录用户起占 → 后端引擎计算 → SQLite 入库 → 返回 resultRaw + display
|
|
2
2
|
import { Router } from 'express';
|
|
3
|
-
import {
|
|
4
|
-
import { ziweiCalc } from '../../../shared/core/engine/ziwei.js';
|
|
5
|
-
import { astrologyCalc } from '../../../shared/core/engine/astrology.js';
|
|
6
|
-
import { qimenCalc } from '../../../shared/core/engine/qimen.js';
|
|
7
|
-
import { meihuaCalc } from '../../../shared/core/engine/meihua.js';
|
|
8
|
-
import { liuyaoCalc } from '../../../shared/core/engine/liuyao.js';
|
|
9
|
-
import { liurenCalc } from '../../../shared/core/engine/liuren.js';
|
|
10
|
-
import { xiaoliurenCalc } from '../../../shared/core/engine/xiaoliuren.js';
|
|
11
|
-
import { tarotDraw } from '../../../shared/core/engine/tarot.js';
|
|
12
|
-
import { allTarotSpreads } from '../../../shared/core/data/tarotSpreads.js';
|
|
3
|
+
import { chartCalc } from '../../../shared/core/engine/chart.js';
|
|
13
4
|
import { createDivination, listDivinations, getDivination, deleteDivination } from '../services/divineStore.js';
|
|
14
5
|
import fs from 'fs';
|
|
15
6
|
import path from 'path';
|
|
@@ -91,56 +82,9 @@ router.post('/', (req, res) => {
|
|
|
91
82
|
|
|
92
83
|
let resultRaw: unknown;
|
|
93
84
|
try {
|
|
94
|
-
|
|
95
|
-
case 'bazi': {
|
|
96
|
-
const i = inputs as any;
|
|
97
|
-
resultRaw = baziCalc({ y: i.y, m: i.m, d: i.d, hourIndex: i.hourIndex, time: i.time, gender: i.gender, location: i.location });
|
|
98
|
-
break;
|
|
99
|
-
}
|
|
100
|
-
case 'ziwei': {
|
|
101
|
-
const i = inputs as any;
|
|
102
|
-
resultRaw = ziweiCalc({ ganzhi: i.ganzhi, month: i.month, day: i.day, hour: i.hour, time: i.time, location: i.location, gender: i.gender, birthYear: i.birthYear });
|
|
103
|
-
break;
|
|
104
|
-
}
|
|
105
|
-
case 'astrology': {
|
|
106
|
-
const i = inputs as any;
|
|
107
|
-
resultRaw = astrologyCalc(i.y, i.m, i.d, i.hour || 0, i.min || 0, i.lng, i.lat);
|
|
108
|
-
break;
|
|
109
|
-
}
|
|
110
|
-
case 'qimen': {
|
|
111
|
-
resultRaw = qimenCalc({ datetime: (inputs as any).datetime || new Date() });
|
|
112
|
-
break;
|
|
113
|
-
}
|
|
114
|
-
case 'meihua': {
|
|
115
|
-
const i = inputs as any;
|
|
116
|
-
resultRaw = meihuaCalc({ mode: i.mode || 'time', n1: i.n1, n2: i.n2, n3: i.n3, now: i.now ? new Date(i.now) : undefined });
|
|
117
|
-
break;
|
|
118
|
-
}
|
|
119
|
-
case 'liuyao': {
|
|
120
|
-
const now = new Date();
|
|
121
|
-
resultRaw = liuyaoCalc(undefined, { y: now.getFullYear(), m: now.getMonth() + 1, d: now.getDate() });
|
|
122
|
-
break;
|
|
123
|
-
}
|
|
124
|
-
case 'liuren': {
|
|
125
|
-
resultRaw = liurenCalc((inputs as any).datetime || new Date());
|
|
126
|
-
break;
|
|
127
|
-
}
|
|
128
|
-
case 'xiaoliuren': {
|
|
129
|
-
const i = inputs as any;
|
|
130
|
-
resultRaw = xiaoliurenCalc(i.mode || 'time', i.m, i.d, i.h, i.n1, i.n2, i.n3);
|
|
131
|
-
break;
|
|
132
|
-
}
|
|
133
|
-
case 'tarot': {
|
|
134
|
-
const i = inputs as any;
|
|
135
|
-
const cards = tarotDraw(Math.max(1, i.n || 3));
|
|
136
|
-
const spread = allTarotSpreads().find((s: any) => s.id === i.spread) || allTarotSpreads()[0];
|
|
137
|
-
resultRaw = { spread: spread || { id: 'three', name: '圣三角', description: '', positions: [] }, cards };
|
|
138
|
-
break;
|
|
139
|
-
}
|
|
140
|
-
default:
|
|
141
|
-
return res.status(400).json({ error: '术无此名' });
|
|
142
|
-
}
|
|
85
|
+
resultRaw = chartCalc(artId, inputs);
|
|
143
86
|
} catch (e: any) {
|
|
87
|
+
if (e?.message?.includes('术无此名')) return res.status(400).json({ error: '术无此名' });
|
|
144
88
|
console.error('[divine] 推演异常:', e);
|
|
145
89
|
return res.status(500).json({ error: 'DIVINE_FAILED', message: '推演未应机' });
|
|
146
90
|
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
// 真·多 Agent 编排 v1(guanwei-pro 雏形):
|
|
2
|
+
// 命盘类分步链式推理——Step A 结构解构 → Step B 宫位/星曜专题 → Step C 汇总成报告
|
|
3
|
+
// 与单轮/两步管线区别:每一步独立 LLM 调用、上一步输出作为下一步唯一事实源,步间事实约束
|
|
4
|
+
// 设计:每步 prompt 短而聚焦(降低单次输出幻觉面),关键事实链(chartBrief 十二宫清单)全程逐字引用
|
|
5
|
+
import { chartBrief } from './chartBrief.js';
|
|
6
|
+
import { duanyuPromptBlock } from './duanyu.js';
|
|
7
|
+
import { chatOnce } from './llmProvider.js';
|
|
8
|
+
import { nowFact } from './promptBuilder.js';
|
|
9
|
+
|
|
10
|
+
export type OrchestrateMode = 'off' | 'ziwei-deep';
|
|
11
|
+
|
|
12
|
+
// 每步输出 ≤ 400 字的事实性专题,不做人生论断(论断集中在最后汇总步)
|
|
13
|
+
function stepMessages(agentName: string, step: string, brief: string, prior: string[], question?: string): { role: string; content: string }[] {
|
|
14
|
+
const priorBlock = prior.length
|
|
15
|
+
? prior.map((p, i) => `【上一步结论 ${i + 1}】${p}`).join('\n')
|
|
16
|
+
: '(本步为首步)';
|
|
17
|
+
const system = [
|
|
18
|
+
'你是一位' + agentName + ',负责紫微斗数分步推理中的一个环节。',
|
|
19
|
+
'【最高约束】所有盘面事实(宫位/主星/辅星/四化/亮度)必须逐字引用下方【盘面事实】,不得推算、不得编造。',
|
|
20
|
+
'【本步任务】' + step,
|
|
21
|
+
'【输出】只输出一个 JSON 对象 {"points": ["要点1", "要点2", ...]}(3-6 条,每条 ≤80 字,只陈述盘面结构与通义,不做人生论断)。',
|
|
22
|
+
].join('\n');
|
|
23
|
+
const user = [
|
|
24
|
+
question ? '【所问】' + question + '(仅作背景,本步不回答)' : '',
|
|
25
|
+
'【盘面事实(不可更改)】',
|
|
26
|
+
brief,
|
|
27
|
+
'',
|
|
28
|
+
nowFact(),
|
|
29
|
+
'',
|
|
30
|
+
priorBlock,
|
|
31
|
+
'',
|
|
32
|
+
'请输出本步 JSON。',
|
|
33
|
+
].filter(Boolean).join('\n');
|
|
34
|
+
return [
|
|
35
|
+
{ role: 'system', content: system },
|
|
36
|
+
{ role: 'user', content: user },
|
|
37
|
+
];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function parsePoints(text: string): string[] {
|
|
41
|
+
try {
|
|
42
|
+
const obj = JSON.parse(text);
|
|
43
|
+
if (Array.isArray(obj.points)) return obj.points.map(String);
|
|
44
|
+
} catch { /* 非 JSON 时按行切 */ }
|
|
45
|
+
return text.split('\n').map(l => l.trim()).filter(l => l && !l.startsWith('{') && !l.startsWith('}')).slice(0, 8);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// 汇总步:把前面各步要点 + 盘面事实汇总成完整解读
|
|
49
|
+
function finalMessages(agentName: string, artName: string, schemaTemplate: string, brief: string, steps: string[], question?: string, gender?: string): { role: string; content: string }[] {
|
|
50
|
+
const stepBlock = steps.map((s, i) => `【分步推演 ${i + 1}】${s}`).join('\n\n');
|
|
51
|
+
const system = [
|
|
52
|
+
'你是一位' + agentName + '。',
|
|
53
|
+
'【任务】基于下面给出的【盘面事实】与【分步推演结论】,生成完整解读报告(JSON)。',
|
|
54
|
+
'【盘面事实一致性 · 最高约束】所有盘面事实必须与【盘面事实】逐字一致,不得编造或自行推算;六亲/宫位论断须注明盘面依据。',
|
|
55
|
+
'【质量】内容充实、具体到场景与行为;不作绝对化断言;结尾附免责声明。',
|
|
56
|
+
'【输出 Schema(字段名不可更改)】' + schemaTemplate,
|
|
57
|
+
].join('\n');
|
|
58
|
+
const user = [
|
|
59
|
+
'【性别语境】' + (gender || '未录'),
|
|
60
|
+
question ? '【所问之事】' + question : '',
|
|
61
|
+
'【盘面事实(不可更改)】',
|
|
62
|
+
brief,
|
|
63
|
+
'',
|
|
64
|
+
stepBlock,
|
|
65
|
+
'',
|
|
66
|
+
'请输出完整解读报告 JSON。',
|
|
67
|
+
].filter(Boolean).join('\n');
|
|
68
|
+
return [
|
|
69
|
+
{ role: 'system', content: system },
|
|
70
|
+
{ role: 'user', content: user },
|
|
71
|
+
];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* 紫微深度编排:三步独立推理后汇总。
|
|
76
|
+
* 返回 { full, steps }(full 为最终报告文本;steps 为各步要点便于调试/审计)
|
|
77
|
+
*/
|
|
78
|
+
export async function orchestrateZiweiDeep(
|
|
79
|
+
resultRaw: unknown,
|
|
80
|
+
question: string | undefined,
|
|
81
|
+
schemaTemplate: string,
|
|
82
|
+
gender?: string,
|
|
83
|
+
): Promise<{ full: string; steps: string[] }> {
|
|
84
|
+
const brief = chartBrief('ziwei', resultRaw);
|
|
85
|
+
const duanyu = duanyuPromptBlock('ziwei', resultRaw);
|
|
86
|
+
const steps: string[] = [];
|
|
87
|
+
|
|
88
|
+
const STEPS = [
|
|
89
|
+
'解构命盘骨架:命宫地支/五行局/紫微落宫/身宫/生年四化/主星布局格局,提炼盘的总体气质。',
|
|
90
|
+
'专题拆解:依十二宫主题(命/兄弟/夫妻/子女/财帛/疾厄/迁移/交友/官禄/田宅/福德/父母)逐宫提炼其星曜组合的侧重,命宫重点。',
|
|
91
|
+
'行运推演:结合当前大限(年龄段/宫位/主星)与流年宫位,提炼行运主题与关键节点。',
|
|
92
|
+
];
|
|
93
|
+
const prior: string[] = [];
|
|
94
|
+
for (const [i, step] of STEPS.entries()) {
|
|
95
|
+
const msgs = stepMessages('紫微斗数专家', step, brief, prior, question);
|
|
96
|
+
const text = await chatOnce(msgs as any);
|
|
97
|
+
const pts = parsePoints(text);
|
|
98
|
+
prior.push(pts.join(';'));
|
|
99
|
+
steps.push(pts.join(';'));
|
|
100
|
+
console.log(`[orchestrator] Step ${i + 1} 完成(${pts.length} 要点)`);
|
|
101
|
+
}
|
|
102
|
+
// 汇总步:含断语引证
|
|
103
|
+
const finalSys = finalMessages('紫微斗数专家', '紫微斗数', schemaTemplate, brief + (duanyu ? '\n' + duanyu : ''), prior, question, gender);
|
|
104
|
+
const full = await chatOnce(finalSys as any);
|
|
105
|
+
return { full, steps };
|
|
106
|
+
}
|
|
@@ -53,7 +53,7 @@ const ZHANWEN_SAMPLE = {
|
|
|
53
53
|
disclaimer: '免责声明',
|
|
54
54
|
suitability: { suitable: true, note: '适问性说明 2-3 句', suggestion: '换问建议或无' },
|
|
55
55
|
};
|
|
56
|
-
const MINGPAN_TEMPLATE = JSON.stringify(MINGPAN_SAMPLE, null, 2);
|
|
56
|
+
export const MINGPAN_TEMPLATE = JSON.stringify(MINGPAN_SAMPLE, null, 2);
|
|
57
57
|
const ZHANWEN_TEMPLATE = JSON.stringify(ZHANWEN_SAMPLE, null, 2);
|
|
58
58
|
const MINGPAN_ARTS = ['bazi', 'ziwei', 'astrology'];
|
|
59
59
|
|
|
@@ -80,7 +80,7 @@ function hourUnknownNote(profile?: unknown): string {
|
|
|
80
80
|
|
|
81
81
|
// 命主已知人生经历 → 解读校准注入(报告须呼应该年份事件、不得与其矛盾)
|
|
82
82
|
// 当前公历时间事实:注入给 AI,防止其自行推算年份(占问类无出生档案,AI 不知道"现在是哪年")
|
|
83
|
-
function nowFact(): string {
|
|
83
|
+
export function nowFact(): string {
|
|
84
84
|
const d = new Date();
|
|
85
85
|
const p = (n: number) => String(n).padStart(2, '0');
|
|
86
86
|
const week = '日一二三四五六'[d.getDay()];
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
// 九术排盘统一调度:artId + inputs → resultRaw
|
|
2
|
+
// 唯一算法副本(divine 路由 / packages/guanwei-api / MCP / 未来托管共用,禁止各层另写 switch)
|
|
3
|
+
import { baziCalc } from './bazi.js';
|
|
4
|
+
import { ziweiCalc } from './ziwei.js';
|
|
5
|
+
import { astrologyCalc } from './astrology.js';
|
|
6
|
+
import { qimenCalc } from './qimen.js';
|
|
7
|
+
import { meihuaCalc } from './meihua.js';
|
|
8
|
+
import { liuyaoCalc } from './liuyao.js';
|
|
9
|
+
import { liurenCalc } from './liuren.js';
|
|
10
|
+
import { xiaoliurenCalc } from './xiaoliuren.js';
|
|
11
|
+
import { tarotDraw } from './tarot.js';
|
|
12
|
+
import { allTarotSpreads } from '../data/tarotSpreads.js';
|
|
13
|
+
|
|
14
|
+
export const CHART_ARTS = ['bazi', 'ziwei', 'astrology', 'qimen', 'meihua', 'liuyao', 'liuren', 'xiaoliuren', 'tarot'] as const;
|
|
15
|
+
export type ChartArtId = typeof CHART_ARTS[number];
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* 九术排盘(纯函数):artId + inputs → resultRaw
|
|
19
|
+
* 抛错:未知术名 / 输入不合法 → Error(调用方转 400)
|
|
20
|
+
*/
|
|
21
|
+
export function chartCalc(artId: string, inputs: any): unknown {
|
|
22
|
+
switch (artId) {
|
|
23
|
+
case 'bazi': {
|
|
24
|
+
const i = inputs || {};
|
|
25
|
+
if (i.y == null || i.m == null || i.d == null) throw new Error('BaziInput 需 y/m/d');
|
|
26
|
+
return baziCalc({ y: i.y, m: i.m, d: i.d, hourIndex: i.hourIndex, time: i.time, gender: i.gender, location: i.location });
|
|
27
|
+
}
|
|
28
|
+
case 'ziwei': {
|
|
29
|
+
const i = inputs || {};
|
|
30
|
+
return ziweiCalc({ ganzhi: i.ganzhi, month: i.month, day: i.day, hour: i.hour, time: i.time, location: i.location, gender: i.gender, birthYear: i.birthYear });
|
|
31
|
+
}
|
|
32
|
+
case 'astrology': {
|
|
33
|
+
const i = inputs || {};
|
|
34
|
+
return astrologyCalc(i.y, i.m, i.d, i.hour || 0, i.min || 0, i.lng, i.lat);
|
|
35
|
+
}
|
|
36
|
+
case 'qimen': {
|
|
37
|
+
return qimenCalc({ datetime: inputs?.datetime ? new Date(inputs.datetime) : new Date() });
|
|
38
|
+
}
|
|
39
|
+
case 'meihua': {
|
|
40
|
+
const i = inputs || {};
|
|
41
|
+
return meihuaCalc({ mode: i.mode || 'time', n1: i.n1, n2: i.n2, n3: i.n3, now: i.now ? new Date(i.now) : undefined });
|
|
42
|
+
}
|
|
43
|
+
case 'liuyao': {
|
|
44
|
+
const now = new Date();
|
|
45
|
+
return liuyaoCalc(undefined, { y: now.getFullYear(), m: now.getMonth() + 1, d: now.getDate() });
|
|
46
|
+
}
|
|
47
|
+
case 'liuren': {
|
|
48
|
+
return liurenCalc(inputs?.datetime ? new Date(inputs.datetime) : new Date());
|
|
49
|
+
}
|
|
50
|
+
case 'xiaoliuren': {
|
|
51
|
+
const i = inputs || {};
|
|
52
|
+
return xiaoliurenCalc(i.mode || 'time', i.m, i.d, i.h, i.n1, i.n2, i.n3);
|
|
53
|
+
}
|
|
54
|
+
case 'tarot': {
|
|
55
|
+
const i = inputs || {};
|
|
56
|
+
const cards = tarotDraw(Math.max(1, i.n || 3));
|
|
57
|
+
const spread = allTarotSpreads().find((s: any) => s.id === i.spread) || allTarotSpreads()[0];
|
|
58
|
+
return { spread: spread || { id: 'three', name: '圣三角', description: '', positions: [] }, cards };
|
|
59
|
+
}
|
|
60
|
+
default:
|
|
61
|
+
throw new Error('术无此名: ' + artId);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** 每术输入参数说明(/v1/arts 能力清单用) */
|
|
66
|
+
export const CHART_INPUT_SCHEMA: Record<string, Record<string, string>> = {
|
|
67
|
+
bazi: { y: '公历年', m: '公历月', d: '公历日', hourIndex: '时辰 0-11(0=子)', gender: '男/女', location: '{lng,lat,province,city,district}' },
|
|
68
|
+
ziwei: { ganzhi: '年干支', month: '农历月', day: '农历日', hour: '时辰 0-11', gender: '男/女', location: '{lng,lat}' },
|
|
69
|
+
astrology: { y: '公历年', m: '月', d: '日', hour: '时 0-23', min: '分', lng: '经度', lat: '纬度' },
|
|
70
|
+
qimen: { datetime: '起局时刻 ISO 字符串' },
|
|
71
|
+
meihua: { mode: 'time|number', n1: '报数1', n2: '报数2', n3: '报数3' },
|
|
72
|
+
liuyao: {},
|
|
73
|
+
liuren: { datetime: '起课时刻 ISO 字符串' },
|
|
74
|
+
xiaoliuren: { mode: 'time', m: '农历月', d: '农历日', h: '时辰 0-11' },
|
|
75
|
+
tarot: { n: '抽牌数(默认3)', spread: '牌阵 id' },
|
|
76
|
+
};
|