koishi-plugin-cocoyyy-console 1.1.3-alpha.5 → 1.1.3

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/lib/index.d.ts CHANGED
@@ -9,6 +9,7 @@ export interface Config {
9
9
  tag_config?: my_config.SaveConfig;
10
10
  repeat_config?: my_config.RepeatConfig;
11
11
  son_config?: my_config.ShitOrNotConfig;
12
+ wish_config?: my_config.WishConfig;
12
13
  game_config?: my_config.GameConfig;
13
14
  test?: string;
14
15
  }
package/lib/index.js CHANGED
@@ -38,7 +38,7 @@ __export(src_exports, {
38
38
  savePath: () => savePath
39
39
  });
40
40
  module.exports = __toCommonJS(src_exports);
41
- var import_koishi14 = require("koishi");
41
+ var import_koishi16 = require("koishi");
42
42
 
43
43
  // src/utils/configs/function_config.ts
44
44
  var import_koishi = require("koishi");
@@ -50,6 +50,7 @@ var FunctionConfigSchema = import_koishi.Schema.object({
50
50
  rbq_flag: import_koishi.Schema.boolean().default(true).description("*人功能是否启用"),
51
51
  son_flag: import_koishi.Schema.boolean().default(true).description("鉴别史消息功能是否启用"),
52
52
  setu_flag: import_koishi.Schema.boolean().default(true).description("随机涩图功能是否启用"),
53
+ wish_flag: import_koishi.Schema.boolean().default(true).description("许愿功能是否启用"),
53
54
  game_flag: import_koishi.Schema.boolean().default(true).description("游戏功能是否启用"),
54
55
  kuro_flag: import_koishi.Schema.boolean().default(true).description("鸣潮功能是否启用")
55
56
  });
@@ -110,6 +111,13 @@ var AiAPIConfigSchema = import_koishi8.Schema.object({
110
111
  api_key: import_koishi8.Schema.string().default("").description("API Key")
111
112
  });
112
113
 
114
+ // src/utils/configs/wish_config.ts
115
+ var import_koishi9 = require("koishi");
116
+ var WishConfigSchema = import_koishi9.Schema.object({
117
+ config_path: import_koishi9.Schema.string().default("").description("配置文件路径"),
118
+ api_model: import_koishi9.Schema.string().default("").description("AI模型")
119
+ });
120
+
113
121
  // src/infra/mysql_init.ts
114
122
  var import_sequelize = require("sequelize");
115
123
  var sequelize = null;
@@ -325,70 +333,71 @@ __name(loadYamlConfig, "loadYamlConfig");
325
333
  var menuList = [
326
334
  {
327
335
  name: "tag",
328
- description: "标签功能,用于记录黑历史",
329
- command: "maketag [标签]"
336
+ description: "标签功能,用于记录黑历史"
330
337
  },
331
338
  {
332
339
  name: "repeat",
333
- description: "复读功能,用于复读",
334
- command: "无"
340
+ description: "复读功能,用于复读"
335
341
  },
336
342
  {
337
343
  name: "rbq",
338
- description: "*人功能,用于*人",
339
- command: "无"
344
+ description: "*人功能,用于*人"
340
345
  },
341
346
  {
342
347
  name: "son",
343
- description: "shit_or_not功能,用于鉴别史消息",
344
- command: "无"
348
+ description: "shit_or_not功能,用于鉴别史消息"
345
349
  },
346
350
  {
347
351
  name: "setu",
348
- description: "随机涩图功能,用于获取涩图",
349
- command: "无"
352
+ description: "随机涩图功能,用于获取涩图"
353
+ },
354
+ {
355
+ name: "wish",
356
+ description: "许愿功能,用于许愿"
350
357
  },
351
358
  {
352
359
  name: "game",
353
- description: "游戏功能,用于游玩游戏",
354
- command: "无"
360
+ description: "游戏功能,用于游玩游戏"
355
361
  },
356
362
  {
357
363
  name: "kuro",
358
- description: "库洛相关功能,用于鸣潮相关功能",
359
- command: "无"
364
+ description: "库洛相关功能,用于鸣潮相关功能"
360
365
  }
361
366
  ];
362
367
  function getMenuList(command = null, functionConfig) {
363
368
  switch (command) {
364
- case "tag":
369
+ case menuList[0].name:
365
370
  if (!functionConfig.tag_flag)
366
371
  return "标签功能已关闭";
367
372
  return getTagFuncMenu(command);
368
- case "repeat":
373
+ case menuList[1].name:
369
374
  if (!functionConfig.repeat_flag)
370
375
  return "复读功能已关闭";
371
376
  return `[所有命令都需要@bot]
372
377
  复读功能菜单:
373
378
  群内重复一定次数的消息会进行复读
374
379
  如果遇到问题请联系开发人员。`;
375
- case "rbq":
380
+ case menuList[2].name:
376
381
  if (!functionConfig.rbq_flag)
377
382
  return "*人功能已关闭";
378
383
  return getRbqFuncMenu(command);
379
- case "son":
384
+ case menuList[3].name:
380
385
  if (!functionConfig.son_flag)
381
386
  return "son功能已关闭";
382
387
  return getSonFuncMenu(command);
383
- case "setu":
388
+ case menuList[4].name:
384
389
  if (!functionConfig.setu_flag)
385
390
  return "son功能已关闭";
386
391
  return getSetuFuncMenu(command);
387
- case "game":
392
+ case menuList[5].name:
393
+ if (!functionConfig.wish_flag)
394
+ return "许愿功能已关闭";
395
+ return getWishFuncMenu(command);
396
+ case menuList[6].name:
388
397
  if (!functionConfig.game_flag)
389
398
  return "游戏功能已关闭";
390
399
  return getGameFuncMenu(command);
391
- case "kuro":
400
+ case menuList[7].name:
392
401
  if (!functionConfig.kuro_flag)
393
402
  return "库洛相关功能已关闭";
394
403
  return getKuroFuncMenu(command);
@@ -516,6 +525,20 @@ setu功能菜单:
516
525
  输入对应指令使用setu功能,如果遇到问题请联系开发人员。`;
517
526
  }
518
527
  __name(getSetuFuncMenu, "getSetuFuncMenu");
528
+ var wishFuncMenuList = [
529
+ {
530
+ name: "wish",
531
+ description: "许愿功能",
532
+ command: "wish [愿望消息(不要超过80字)]"
533
+ }
534
+ ];
535
+ function getWishFuncMenu(command = null) {
536
+ return `[所有命令都需要@bot]
537
+ 许愿功能菜单:
538
+ ${wishFuncMenuList.map((item) => item.command + ": " + item.description).join("\n ")}
539
+ 输入对应指令使用许愿功能,如果遇到问题请联系开发人员。`;
540
+ }
541
+ __name(getWishFuncMenu, "getWishFuncMenu");
519
542
  var gameFuncMenuList = [
520
543
  {
521
544
  name: "gamelist",
@@ -572,7 +595,7 @@ function registerMenuCommands(ctx, connected, functionConfig) {
572
595
  __name(registerMenuCommands, "registerMenuCommands");
573
596
 
574
597
  // src/services/tag_func/tag_commands.ts
575
- var import_koishi10 = require("koishi");
598
+ var import_koishi11 = require("koishi");
576
599
 
577
600
  // src/services/tag_func/tag_service.ts
578
601
  var import_sequelize4 = require("sequelize");
@@ -580,7 +603,7 @@ var import_fs3 = require("fs");
580
603
  var import_path3 = require("path");
581
604
 
582
605
  // src/services/tag_func/img_service.ts
583
- var import_koishi9 = require("koishi");
606
+ var import_koishi10 = require("koishi");
584
607
  var import_path2 = require("path");
585
608
  var import_fs2 = require("fs");
586
609
  async function loadImageFromUrl(ctx, url) {
@@ -655,7 +678,7 @@ async function randomImgByTag(tag_name, guild_id) {
655
678
  if (ImgList.length <= 0) {
656
679
  throw new Error("Don't have image!");
657
680
  }
658
- const random = new import_koishi9.Random(() => Math.random());
681
+ const random = new import_koishi10.Random(() => Math.random());
659
682
  let result = ImgList[random.int(0, ImgList.length)];
660
683
  const filePath = result.get("img_url");
661
684
  return filePath;
@@ -900,7 +923,7 @@ function registerTagCommands(ctx, connected, savePath2) {
900
923
  if (!exec)
901
924
  return `获取图片失败`;
902
925
  let path2 = (0, import_url.pathToFileURL)(exec).href;
903
- return import_koishi10.h.image(path2);
926
+ return import_koishi11.h.image(path2);
904
927
  });
905
928
  ctx.command("bind <参数>", "标签绑定别名").action(async ({ session }, ...args) => {
906
929
  if (!dev_mode) {
@@ -1043,7 +1066,7 @@ function registerRepeatMiddleware(ctx, config) {
1043
1066
  __name(registerRepeatMiddleware, "registerRepeatMiddleware");
1044
1067
 
1045
1068
  // src/services/rbq_func/rbq_command.ts
1046
- var import_koishi11 = require("koishi");
1069
+ var import_koishi12 = require("koishi");
1047
1070
 
1048
1071
  // src/models/rbq_persons.ts
1049
1072
  var import_sequelize5 = require("sequelize");
@@ -1368,7 +1391,7 @@ function registerRbqCommands(ctx, connected) {
1368
1391
  if (!list || list.length === 0) {
1369
1392
  return "当前群聊还没有设置任何rbq";
1370
1393
  }
1371
- return "当前群聊rbq列表:\n" + list.map((item) => (0, import_koishi11.h)("at", { id: item })).join(",");
1394
+ return "当前群聊rbq列表:\n" + list.map((item) => (0, import_koishi12.h)("at", { id: item })).join(",");
1372
1395
  });
1373
1396
  ctx.command("rbqadd <参数>", "添加rbq").action(async ({ session }, ...args) => {
1374
1397
  if (!dev_mode) {
@@ -1386,7 +1409,7 @@ function registerRbqCommands(ctx, connected) {
1386
1409
  exec = await create_person(session.guildId, uid);
1387
1410
  if (!exec.result)
1388
1411
  return `添加rbq失败: ${exec.error}`;
1389
- return "已添加rbq:" + (0, import_koishi11.h)("at", { id: uid });
1412
+ return "已添加rbq:" + (0, import_koishi12.h)("at", { id: uid });
1390
1413
  });
1391
1414
  ctx.command("rbqinstead <参数>", "替换rbq").action(async ({ session }, ...args) => {
1392
1415
  if (!dev_mode) {
@@ -1411,12 +1434,12 @@ function registerRbqCommands(ctx, connected) {
1411
1434
  exec = await instead_person(session.guildId, source_uid, new_target);
1412
1435
  if (!exec.result)
1413
1436
  return `替换rbq失败:${exec.error}`;
1414
- return "倒反天罡!进去吧你,已替换rbq:\n" + (0, import_koishi11.h)("at", { id: source_uid }) + " -> " + (0, import_koishi11.h)("at", { id: new_target });
1437
+ return "倒反天罡!进去吧你,已替换rbq:\n" + (0, import_koishi12.h)("at", { id: source_uid }) + " -> " + (0, import_koishi12.h)("at", { id: new_target });
1415
1438
  }
1416
1439
  exec = await instead_person(session.guildId, source_uid, target_uid);
1417
1440
  if (!exec.result)
1418
1441
  return `替换rbq失败:${exec.error}`;
1419
- return (0, import_koishi11.h)("p", "已替换rbq:", (0, import_koishi11.h)("at", { id: source_uid }), " -> ", (0, import_koishi11.h)("at", { id: target_uid }));
1442
+ return (0, import_koishi12.h)("p", "已替换rbq:", (0, import_koishi12.h)("at", { id: source_uid }), " -> ", (0, import_koishi12.h)("at", { id: target_uid }));
1420
1443
  });
1421
1444
  ctx.command("rbqadd_txt <参数>", "添加自定义文本").action(async ({ session }, ...args) => {
1422
1445
  if (!dev_mode) {
@@ -1443,10 +1466,10 @@ function registerRbqCommands(ctx, connected) {
1443
1466
  const contents = await get_content_list(session.guildId, target_uid);
1444
1467
  let content2 = "*死你";
1445
1468
  if (contents && contents.length > 0) {
1446
- const random = new import_koishi11.Random(() => Math.random());
1469
+ const random = new import_koishi12.Random(() => Math.random());
1447
1470
  content2 = contents[random.int(0, contents.length)];
1448
1471
  }
1449
- return (0, import_koishi11.h)("at", { id: target_uid }) + "还想自己加文本?!\n" + content2;
1472
+ return (0, import_koishi12.h)("at", { id: target_uid }) + "还想自己加文本?!\n" + content2;
1450
1473
  } catch (error) {
1451
1474
  logger.error("[rbq rbqadd_txt] Error:", error);
1452
1475
  return "不能给自己设置文本,请输入其他qq号";
@@ -1476,10 +1499,10 @@ function registerRbqCommands(ctx, connected) {
1476
1499
  const contents = await get_content_list(guildId, matchedUid);
1477
1500
  let content = "*死你";
1478
1501
  if (contents && contents.length > 0) {
1479
- const random = new import_koishi11.Random(() => Math.random());
1502
+ const random = new import_koishi12.Random(() => Math.random());
1480
1503
  content = contents[random.int(0, contents.length)];
1481
1504
  }
1482
- return (0, import_koishi11.h)("at", { id: matchedUid }) + " " + content;
1505
+ return (0, import_koishi12.h)("at", { id: matchedUid }) + " " + content;
1483
1506
  } catch (error) {
1484
1507
  logger.error("[rbq middleware] Error:", error);
1485
1508
  return next();
@@ -1528,14 +1551,19 @@ var import_tesseract2 = require("tesseract.js");
1528
1551
 
1529
1552
  // src/utils/ai_axios.ts
1530
1553
  var import_axios = __toESM(require("axios"));
1531
- async function callOpenRouter(api_url, api_key, api_model = "gpt-4o-mini", messages) {
1554
+ async function callOpenRouter(api_url, api_key, api_model = "gpt-4o-mini", messages, tools2, tool_choice) {
1532
1555
  try {
1556
+ const requestBody = {
1557
+ model: api_model,
1558
+ messages
1559
+ };
1560
+ if (tools2 && tools2.length > 0) {
1561
+ requestBody.tools = tools2;
1562
+ requestBody.tool_choice = tool_choice ?? "auto";
1563
+ }
1533
1564
  const { data } = await import_axios.default.post(
1534
1565
  api_url,
1535
- {
1536
- model: api_model,
1537
- messages
1538
- },
1566
+ requestBody,
1539
1567
  {
1540
1568
  headers: {
1541
1569
  Authorization: `Bearer ${api_key}`,
@@ -1544,7 +1572,17 @@ async function callOpenRouter(api_url, api_key, api_model = "gpt-4o-mini", messa
1544
1572
  }
1545
1573
  );
1546
1574
  const choices = data?.choices ?? [];
1547
- const reply = choices[0]?.message?.content;
1575
+ const message = choices[0]?.message;
1576
+ const reply = message?.content;
1577
+ const tool_calls = message?.tool_calls;
1578
+ if (tool_calls && tool_calls.length > 0) {
1579
+ const firstToolCall = tool_calls[0];
1580
+ return {
1581
+ err: null,
1582
+ resp: firstToolCall.function.arguments,
1583
+ tool_calls
1584
+ };
1585
+ }
1548
1586
  let responseText;
1549
1587
  let err = null;
1550
1588
  if (typeof reply === "string") {
@@ -1557,20 +1595,46 @@ async function callOpenRouter(api_url, api_key, api_model = "gpt-4o-mini", messa
1557
1595
  if (!responseText) {
1558
1596
  err = "OpenRouter 返回空内容";
1559
1597
  }
1598
+ } else if (reply === null) {
1599
+ err = "OpenRouter 返回空内容";
1600
+ responseText = "";
1560
1601
  } else {
1561
1602
  err = "OpenRouter 返回了未知格式,请检查日志";
1603
+ responseText = "";
1562
1604
  }
1563
- return { err, resp: responseText };
1605
+ return { err, resp: responseText, tool_calls: void 0 };
1564
1606
  } catch (error) {
1565
1607
  const err = error;
1566
1608
  const status = err.response?.status;
1567
- const detail = err.response?.data?.error || err.response?.data?.message || err.message;
1609
+ const responseData = err.response?.data;
1610
+ let detail = responseData?.error || responseData?.message || err.message;
1611
+ let errorCode = responseData?.code;
1612
+ if (typeof detail === "object" && detail !== null) {
1613
+ const errorMsg = detail.message || detail.error || JSON.stringify(detail);
1614
+ errorCode = detail.code || errorCode;
1615
+ detail = errorMsg;
1616
+ }
1568
1617
  logger.error("[callOpenRouter Error]: OpenRouter 请求失败", {
1569
1618
  status,
1619
+ code: errorCode,
1570
1620
  detail,
1571
- url: err.config?.url
1621
+ url: err.config?.url,
1622
+ model: api_model,
1623
+ hasTools: tools2 && tools2.length > 0,
1624
+ requestBody: tools2 && tools2.length > 0 ? {
1625
+ model: api_model,
1626
+ hasTools: true,
1627
+ tool_choice: tool_choice ?? "auto"
1628
+ } : void 0
1572
1629
  });
1573
- const errorMessage = `test error${status ? `(${status})` : ""}: ${detail}`;
1630
+ if (status === 404 && tools2 && tools2.length > 0) {
1631
+ const toolErrorHint = `模型 "${api_model}" 可能不支持工具调用,或模型名称格式不正确(应包含 provider 前缀,如 "deepseek/deepseek-chat-v3.1")。请检查模型配置。`;
1632
+ return {
1633
+ err: `OpenRouter error(${status}): ${detail}. ${toolErrorHint}`,
1634
+ resp: null
1635
+ };
1636
+ }
1637
+ const errorMessage = `OpenRouter error${status ? `(${status})` : ""}: ${detail}`;
1574
1638
  return { err: errorMessage, resp: null };
1575
1639
  }
1576
1640
  }
@@ -1692,7 +1756,7 @@ __name(is_at_bot_quote, "is_at_bot_quote");
1692
1756
 
1693
1757
  // src/services/himg_func/himg_service.ts
1694
1758
  var import_axios2 = __toESM(require("axios"));
1695
- var import_koishi12 = require("koishi");
1759
+ var import_koishi13 = require("koishi");
1696
1760
  async function randomHImg(keywords, ...args) {
1697
1761
  try {
1698
1762
  const r18 = keywords?.[0];
@@ -1700,13 +1764,14 @@ async function randomHImg(keywords, ...args) {
1700
1764
  const params = new URLSearchParams();
1701
1765
  params.append("excludeAI", "true");
1702
1766
  params.append("size", "regular");
1703
- const random = new import_koishi12.Random(() => Math.random());
1767
+ let r18_flag = 0;
1704
1768
  if (r18) {
1705
1769
  if (r18.toLowerCase() === "r18") {
1706
- params.append("r18", "1");
1770
+ r18_flag = 1;
1707
1771
  tags = keywords?.slice(1);
1708
1772
  }
1709
1773
  }
1774
+ params.append("r18", r18_flag.toString());
1710
1775
  if (args[0]) {
1711
1776
  params.append("num", args[0].toString());
1712
1777
  }
@@ -1721,7 +1786,7 @@ async function randomHImg(keywords, ...args) {
1721
1786
  let author = item.author;
1722
1787
  let url = item.urls.regular;
1723
1788
  let tags2 = item.tags;
1724
- result_content += "作者: " + author + "\n标签: \n[" + tags2.join(",") + "]\n" + import_koishi12.h.image(url) + "\n";
1789
+ result_content += "作者: " + author + "\n标签: \n[" + tags2.join(",") + "]\n" + import_koishi13.h.image(url) + "\n";
1725
1790
  }
1726
1791
  return {
1727
1792
  result: result_content,
@@ -1777,6 +1842,171 @@ function registerHImgCommands(ctx) {
1777
1842
  }
1778
1843
  __name(registerHImgCommands, "registerHImgCommands");
1779
1844
 
1845
+ // src/services/wish_func/wish_command.ts
1846
+ var import_koishi14 = require("koishi");
1847
+
1848
+ // src/services/wish_func/wish_service.ts
1849
+ var chatHistory2 = [];
1850
+ var tools = [
1851
+ {
1852
+ type: "function",
1853
+ function: {
1854
+ name: "wish_audit_result",
1855
+ description: "对用户愿望进行合规审计并返回结构化结果",
1856
+ parameters: {
1857
+ type: "object",
1858
+ properties: {
1859
+ category: {
1860
+ type: "string",
1861
+ enum: ["block", "allow"],
1862
+ description: "是否允许该愿望"
1863
+ },
1864
+ reason: {
1865
+ type: "string",
1866
+ description: "block:说明触犯的禁忌类型;allow:说明内容合规"
1867
+ },
1868
+ wish: {
1869
+ type: "string",
1870
+ description: "allow:复述用户愿望(去除语气词);block:必须为空字符串"
1871
+ }
1872
+ },
1873
+ required: ["category", "reason", "wish"],
1874
+ additionalProperties: false
1875
+ }
1876
+ }
1877
+ },
1878
+ {
1879
+ type: "function",
1880
+ function: {
1881
+ name: "wish_generation_result",
1882
+ description: "生成愿望实现的场景",
1883
+ parameters: {
1884
+ type: "object",
1885
+ properties: {
1886
+ scenario: {
1887
+ type: "string",
1888
+ description: "愿望实现的场景"
1889
+ }
1890
+ },
1891
+ required: ["scenario"],
1892
+ additionalProperties: false
1893
+ }
1894
+ }
1895
+ }
1896
+ ];
1897
+ async function checkAudit(local_config4, wish_content, config, wish_config) {
1898
+ let prompt_msg = "";
1899
+ if (!local_config4) return { result: false, reason: "未加载配置文件,请查看日志" };
1900
+ prompt_msg = local_config4.wish_config?.prompts["audit"];
1901
+ if (!prompt_msg) return { result: false, reason: "未找到prompt,请查看日志" };
1902
+ try {
1903
+ prompt_msg = prompt_msg.replace("{{USER_TEXT}}", wish_content);
1904
+ chatHistory2 = [];
1905
+ chatHistory2.push({ role: "system", content: [{ type: "text", text: prompt_msg }] });
1906
+ const using_model = wish_config.api_model || config.api_model;
1907
+ const { err, resp } = await callOpenRouter(
1908
+ config.api_url,
1909
+ config.api_key,
1910
+ using_model,
1911
+ chatHistory2,
1912
+ tools,
1913
+ { type: "function", function: { name: "wish_audit_result" } }
1914
+ );
1915
+ if (err != null) {
1916
+ logger.error("[checkAudit Error]: " + err);
1917
+ return { result: false, reason: err };
1918
+ }
1919
+ if (!resp) {
1920
+ logger.error("[checkAudit Error]: API返回为空");
1921
+ return { result: false, reason: "API返回为空" };
1922
+ }
1923
+ const json = JSON.parse(resp);
1924
+ if (json.category == "block") {
1925
+ logger.info("[checkAudit Info]: 愿望被拒绝,原因: " + json.reason);
1926
+ return { result: false, reason: json.reason };
1927
+ }
1928
+ if (json.category == "allow" || json.category == "review") {
1929
+ return { result: true, reason: json.reason };
1930
+ }
1931
+ logger.error("[checkAudit Error]: API返回有误,未触发block或allow/review: " + resp);
1932
+ return { result: false, reason: "API返回有误,未触发block或allow/review" };
1933
+ } catch (e) {
1934
+ logger.error("[checkAudit Error]: " + e);
1935
+ return { result: false, reason: "未知错误,请查看日志" };
1936
+ }
1937
+ }
1938
+ __name(checkAudit, "checkAudit");
1939
+ async function gernerationSoluation(local_config4, wish_content, config, wish_config) {
1940
+ let prompt_msg = "";
1941
+ if (!local_config4) return "未加载配置文件,请查看日志";
1942
+ prompt_msg = local_config4.wish_config?.prompts["generation"];
1943
+ if (!prompt_msg) return "未找到prompt,请查看日志";
1944
+ try {
1945
+ prompt_msg = prompt_msg.replace("{{USER_TEXT}}", wish_content);
1946
+ chatHistory2 = [];
1947
+ chatHistory2.push({ role: "system", content: [{ type: "text", text: prompt_msg }] });
1948
+ const using_model = wish_config.api_model || config.api_model;
1949
+ const { err, resp } = await callOpenRouter(
1950
+ config.api_url,
1951
+ config.api_key,
1952
+ using_model,
1953
+ chatHistory2,
1954
+ tools,
1955
+ { type: "function", function: { name: "wish_generation_result" } }
1956
+ );
1957
+ if (err != null) {
1958
+ logger.error("[gernerationSoluation Error]: " + err);
1959
+ return null;
1960
+ }
1961
+ const json = JSON.parse(resp);
1962
+ const scenario = json.scenario;
1963
+ if (!scenario) {
1964
+ logger.info("[gernerationSoluation Info]: API返回有误: " + resp);
1965
+ return null;
1966
+ }
1967
+ return scenario;
1968
+ } catch (e) {
1969
+ logger.error("[gernerationSoluation Error]: " + e);
1970
+ return null;
1971
+ }
1972
+ }
1973
+ __name(gernerationSoluation, "gernerationSoluation");
1974
+
1975
+ // src/services/wish_func/wish_command.ts
1976
+ var local_config2 = null;
1977
+ var think_flag2 = false;
1978
+ function registerWishCommands(ctx, ai_config, wish_config) {
1979
+ if (wish_config?.config_path) {
1980
+ local_config2 = loadYamlConfig(wish_config.config_path);
1981
+ if (local_config2) {
1982
+ logger.info("[loadYamlConfig Info]: Wish 成功加载配置文件");
1983
+ } else {
1984
+ logger.error("[loadYamlConfig Error]: Wish 配置文件加载失败,将使用默认配置");
1985
+ }
1986
+ } else {
1987
+ logger.error("[loadYamlConfig Error]: 未配置 Wish 配置文件路径");
1988
+ }
1989
+ ctx.command("wish <参数>", "许愿").action(async ({ session }, ...args) => {
1990
+ if (!dev_mode) {
1991
+ if (!is_at_bot(session)) return "请提供正确格式,如: @bot wish [愿望消息(不要超过80字)]";
1992
+ }
1993
+ const wish_content = args?.[0];
1994
+ if (!wish_content) return "输入愿望消息,不要超过80字";
1995
+ await session.send("已收到,正在祈祷中...");
1996
+ think_flag2 = true;
1997
+ try {
1998
+ let exec = await checkAudit(local_config2, wish_content, ai_config, wish_config);
1999
+ if (!exec) return "愿望不合规被拒绝,请重新许愿";
2000
+ let exec_generation = await gernerationSoluation(local_config2, wish_content, ai_config, wish_config);
2001
+ if (!exec_generation) return "愿望实现失败,请重新许愿";
2002
+ return (0, import_koishi14.h)("at", { id: session.userId }) + " 祈祷成功,愿梦想成真!\n" + exec_generation;
2003
+ } finally {
2004
+ think_flag2 = false;
2005
+ }
2006
+ });
2007
+ }
2008
+ __name(registerWishCommands, "registerWishCommands");
2009
+
1780
2010
  // src/services/kuro_func/kuro_service.ts
1781
2011
  var import_axios3 = __toESM(require("axios"));
1782
2012
  var import_qs = __toESM(require("qs"));
@@ -2186,7 +2416,7 @@ function registerKuroCommands(ctx, connected) {
2186
2416
  __name(registerKuroCommands, "registerKuroCommands");
2187
2417
 
2188
2418
  // src/services/game_func/game_command.ts
2189
- var import_koishi13 = require("koishi");
2419
+ var import_koishi15 = require("koishi");
2190
2420
 
2191
2421
  // src/services/game_func/game_service.ts
2192
2422
  var gameTimeout = null;
@@ -2215,11 +2445,11 @@ __name(clearGameTimeout, "clearGameTimeout");
2215
2445
  // src/services/game_func/games/game_turtlesoup_service.ts
2216
2446
  var is_gaming = false;
2217
2447
  var chatPrompt = [];
2218
- var chatHistory2 = [];
2448
+ var chatHistory3 = [];
2219
2449
  async function startSituationPuzzle(config) {
2220
2450
  chatPrompt = [];
2221
- chatHistory2 = [];
2222
- const prompt_start = local_config2?.game?.situation_puzzle;
2451
+ chatHistory3 = [];
2452
+ const prompt_start = local_config3?.game?.situation_puzzle;
2223
2453
  chatPrompt.push({ role: "system", content: [{ type: "text", text: prompt_start }] });
2224
2454
  const { err, resp } = await callOpenRouter(config.api_url, config.api_key, config.api_model, chatPrompt);
2225
2455
  if (err != null) {
@@ -2234,7 +2464,7 @@ async function startSituationPuzzle(config) {
2234
2464
  logger.info(`[SituationPuzzle Timeout]: 游戏已超时(${GAME_TIMEOUT_MINUTES}分钟),自动结束游戏`);
2235
2465
  is_gaming = false;
2236
2466
  chatPrompt = [];
2237
- chatHistory2 = [];
2467
+ chatHistory3 = [];
2238
2468
  setGameTimeout(null);
2239
2469
  }, GAME_TIMEOUT_MINUTES * 60 * 1e3);
2240
2470
  logger.info("[startSituationPuzzle Info]: ai api send message success");
@@ -2242,9 +2472,9 @@ async function startSituationPuzzle(config) {
2242
2472
  }
2243
2473
  __name(startSituationPuzzle, "startSituationPuzzle");
2244
2474
  async function questSituationPuzzle(content, config) {
2245
- chatHistory2 = [...chatPrompt];
2246
- chatHistory2.push({ role: "user", content: [{ type: "text", text: content }] });
2247
- const { err, resp } = await callOpenRouter(config.api_url, config.api_key, config.api_model, chatHistory2);
2475
+ chatHistory3 = [...chatPrompt];
2476
+ chatHistory3.push({ role: "user", content: [{ type: "text", text: content }] });
2477
+ const { err, resp } = await callOpenRouter(config.api_url, config.api_key, config.api_model, chatHistory3);
2248
2478
  if (err != null) {
2249
2479
  logger.error("[questSituationPuzzle Error]: " + err);
2250
2480
  return null;
@@ -2253,7 +2483,7 @@ async function questSituationPuzzle(content, config) {
2253
2483
  if (resp.includes("猜中了")) {
2254
2484
  is_gaming = false;
2255
2485
  chatPrompt = [];
2256
- chatHistory2 = [];
2486
+ chatHistory3 = [];
2257
2487
  clearGameTimeout();
2258
2488
  } else {
2259
2489
  clearGameTimeout();
@@ -2261,7 +2491,7 @@ async function questSituationPuzzle(content, config) {
2261
2491
  logger.info(`[SituationPuzzle Timeout]: 游戏已超时(${GAME_TIMEOUT_MINUTES}分钟),自动结束游戏`);
2262
2492
  is_gaming = false;
2263
2493
  chatPrompt = [];
2264
- chatHistory2 = [];
2494
+ chatHistory3 = [];
2265
2495
  setGameTimeout(null);
2266
2496
  }, GAME_TIMEOUT_MINUTES * 60 * 1e3);
2267
2497
  }
@@ -2270,9 +2500,9 @@ async function questSituationPuzzle(content, config) {
2270
2500
  __name(questSituationPuzzle, "questSituationPuzzle");
2271
2501
  async function endSituationPuzzle(config) {
2272
2502
  is_gaming = false;
2273
- chatHistory2 = [...chatPrompt];
2274
- chatHistory2.push({ role: "user", content: [{ type: "text", text: "结束游戏,请给出答案" }] });
2275
- const { err, resp } = await callOpenRouter(config.api_url, config.api_key, config.api_model, chatHistory2);
2503
+ chatHistory3 = [...chatPrompt];
2504
+ chatHistory3.push({ role: "user", content: [{ type: "text", text: "结束游戏,请给出答案" }] });
2505
+ const { err, resp } = await callOpenRouter(config.api_url, config.api_key, config.api_model, chatHistory3);
2276
2506
  if (err != null) {
2277
2507
  logger.error("[endSituationPuzzle Error]: " + err);
2278
2508
  return null;
@@ -2283,16 +2513,16 @@ async function endSituationPuzzle(config) {
2283
2513
  }
2284
2514
  __name(endSituationPuzzle, "endSituationPuzzle");
2285
2515
  async function rerollSituationPuzzle(config) {
2286
- chatHistory2 = [...chatPrompt];
2287
- chatHistory2.push({ role: "user", content: [{ type: "text", text: "重新生成新谜题" }] });
2288
- const { err, resp } = await callOpenRouter(config.api_url, config.api_key, config.api_model, chatHistory2);
2516
+ chatHistory3 = [...chatPrompt];
2517
+ chatHistory3.push({ role: "user", content: [{ type: "text", text: "重新生成新谜题" }] });
2518
+ const { err, resp } = await callOpenRouter(config.api_url, config.api_key, config.api_model, chatHistory3);
2289
2519
  if (err != null) {
2290
2520
  logger.error("[rerollSituationPuzzle Error]: " + err);
2291
2521
  chatPrompt.pop();
2292
2522
  return null;
2293
2523
  }
2294
2524
  chatPrompt = [];
2295
- const prompt_start = local_config2?.game?.situation_puzzle;
2525
+ const prompt_start = local_config3?.game?.situation_puzzle;
2296
2526
  chatPrompt.push({ role: "system", content: [{ type: "text", text: prompt_start }] });
2297
2527
  chatPrompt.push({ role: "assistant", content: [{ type: "text", text: resp }] });
2298
2528
  is_gaming = true;
@@ -2301,7 +2531,7 @@ async function rerollSituationPuzzle(config) {
2301
2531
  logger.info(`[SituationPuzzle Timeout]: 游戏已超时(${GAME_TIMEOUT_MINUTES}分钟),自动结束游戏`);
2302
2532
  is_gaming = false;
2303
2533
  chatPrompt = [];
2304
- chatHistory2 = [];
2534
+ chatHistory3 = [];
2305
2535
  setGameTimeout(null);
2306
2536
  }, GAME_TIMEOUT_MINUTES * 60 * 1e3);
2307
2537
  logger.info("[rerollSituationPuzzle Info]: ai api send message success");
@@ -2411,7 +2641,7 @@ function getSolution() {
2411
2641
  __name(getSolution, "getSolution");
2412
2642
 
2413
2643
  // src/services/game_func/game_command.ts
2414
- var local_config2 = null;
2644
+ var local_config3 = null;
2415
2645
  var is_thinking = false;
2416
2646
  var now_game = null;
2417
2647
  var gameList = [
@@ -2433,8 +2663,8 @@ var commandList = [
2433
2663
  ];
2434
2664
  function registerGameCommands(ctx, game_config, ai_config) {
2435
2665
  if (game_config?.config_path) {
2436
- local_config2 = loadYamlConfig(game_config.config_path);
2437
- if (local_config2) {
2666
+ local_config3 = loadYamlConfig(game_config.config_path);
2667
+ if (local_config3) {
2438
2668
  logger.info("[loadYamlConfig Info]: Game 成功加载配置文件");
2439
2669
  } else {
2440
2670
  logger.error("[loadYamlConfig Error]: Game 配置文件加载失败,将使用默认配置");
@@ -2443,7 +2673,7 @@ function registerGameCommands(ctx, game_config, ai_config) {
2443
2673
  logger.error("[loadYamlConfig Error]: 未配置 Game 配置文件路径");
2444
2674
  }
2445
2675
  if (GAME_TIMEOUT_MINUTES <= 0) {
2446
- setGameTimeoutMinutes(local_config2?.game?.timeout_minutes || 10);
2676
+ setGameTimeoutMinutes(local_config3?.game?.timeout_minutes || 10);
2447
2677
  }
2448
2678
  ctx.command("gamelist", "查看所有游戏").action(async ({}) => {
2449
2679
  return `[所有命令都需要@bot]
@@ -2552,7 +2782,7 @@ async function situationPuzzleMiddleware(session, ai_config) {
2552
2782
  return checkResp(resp2);
2553
2783
  }
2554
2784
  const resp = await questSituationPuzzle(text, ai_config);
2555
- return (0, import_koishi13.h)("at", { id: userId }) + " " + checkResp(resp);
2785
+ return (0, import_koishi15.h)("at", { id: userId }) + " " + checkResp(resp);
2556
2786
  } finally {
2557
2787
  is_thinking = false;
2558
2788
  }
@@ -2569,17 +2799,18 @@ __name(checkResp, "checkResp");
2569
2799
  // src/index.ts
2570
2800
  var name = "cocoyyy-console";
2571
2801
  var dev_mode;
2572
- var Config = import_koishi14.Schema.object({
2802
+ var Config = import_koishi16.Schema.object({
2573
2803
  function_config: FunctionConfigSchema.description("功能开关配置"),
2574
2804
  ai_config: AiAPIConfigSchema.description("AI API配置"),
2575
2805
  mysql_config: MysqlConfigSchema.description("MySQL 数据库配置"),
2576
2806
  tag_config: SaveConfigSchema.description("tag图片保存配置"),
2577
2807
  repeat_config: RepeatConfigSchema.description("复读配置"),
2578
2808
  son_config: ShitOrNotConfigSchema.description("SON配置"),
2809
+ wish_config: WishConfigSchema.description("许愿配置"),
2579
2810
  game_config: GameConfigSchema.description("游戏配置"),
2580
- test: import_koishi14.Schema.string().description("测试")
2811
+ test: import_koishi16.Schema.string().description("测试")
2581
2812
  });
2582
- var logger = new import_koishi14.Logger(name);
2813
+ var logger = new import_koishi16.Logger(name);
2583
2814
  var savePath = null;
2584
2815
  async function apply(ctx, config) {
2585
2816
  ctx = ctx.guild();
@@ -2603,6 +2834,8 @@ async function apply(ctx, config) {
2603
2834
  registerShitOrNotCommands(ctx, config?.ai_config, config?.son_config);
2604
2835
  if (config.function_config.setu_flag)
2605
2836
  registerHImgCommands(ctx);
2837
+ if (config.function_config.wish_flag)
2838
+ registerWishCommands(ctx, config?.ai_config, config?.wish_config);
2606
2839
  if (config.function_config.game_flag) {
2607
2840
  registerGameCommands(ctx, config?.game_config, config?.ai_config);
2608
2841
  registerGameMiddleware(ctx, config?.ai_config);
@@ -0,0 +1,5 @@
1
+ import { Context } from 'koishi';
2
+ import { AiAPIConfig } from '../../utils/configs/ai_config';
3
+ import { WishConfig } from '../../utils/configs/wish_config';
4
+ declare function registerWishCommands(ctx: Context, ai_config: AiAPIConfig, wish_config: WishConfig): void;
5
+ export { registerWishCommands };
@@ -0,0 +1,8 @@
1
+ import { AiAPIConfig } from '../../utils/configs/ai_config';
2
+ import { WishConfig } from '../../utils/configs/wish_config';
3
+ declare function checkAudit(local_config: any, wish_content: string, config: AiAPIConfig, wish_config: WishConfig): Promise<{
4
+ result: boolean;
5
+ reason: string;
6
+ }>;
7
+ declare function gernerationSoluation(local_config: any, wish_content: string, config: AiAPIConfig, wish_config: WishConfig): Promise<any>;
8
+ export { checkAudit, gernerationSoluation };
@@ -8,8 +8,37 @@ export interface OpenRouterMessage {
8
8
  };
9
9
  }>;
10
10
  }
11
+ export interface OpenRouterTool {
12
+ type: 'function';
13
+ function: {
14
+ name: string;
15
+ description: string;
16
+ parameters: {
17
+ type: string;
18
+ properties?: Record<string, any>;
19
+ required?: string[];
20
+ additionalProperties?: boolean;
21
+ };
22
+ };
23
+ }
24
+ export type OpenRouterToolChoice = 'none' | 'auto' | 'required' | {
25
+ type: 'function';
26
+ function: {
27
+ name: string;
28
+ };
29
+ };
30
+ interface OpenRouterToolCall {
31
+ id: string;
32
+ type: 'function';
33
+ function: {
34
+ name: string;
35
+ arguments: string;
36
+ };
37
+ }
11
38
  export interface OpenRouterResult {
12
39
  err: string | null;
13
40
  resp: string | null;
41
+ tool_calls?: OpenRouterToolCall[];
14
42
  }
15
- export declare function callOpenRouter(api_url: string, api_key: string, api_model: string, messages: OpenRouterMessage[]): Promise<OpenRouterResult>;
43
+ export declare function callOpenRouter(api_url: string, api_key: string, api_model: string, messages: OpenRouterMessage[], tools?: OpenRouterTool[], tool_choice?: OpenRouterToolChoice): Promise<OpenRouterResult>;
44
+ export {};
@@ -6,3 +6,4 @@ export * from './configs/redis_config';
6
6
  export * from './configs/son_config';
7
7
  export * from './configs/game_config';
8
8
  export * from './configs/ai_config';
9
+ export * from './configs/wish_config';
@@ -7,6 +7,7 @@ interface FunctionConfig {
7
7
  rbq_flag: boolean;
8
8
  son_flag: boolean;
9
9
  setu_flag: boolean;
10
+ wish_flag: boolean;
10
11
  game_flag: boolean;
11
12
  kuro_flag: boolean;
12
13
  }
@@ -0,0 +1,7 @@
1
+ import { Schema } from 'koishi';
2
+ interface WishConfig {
3
+ config_path?: string;
4
+ api_model?: string;
5
+ }
6
+ declare const WishConfigSchema: Schema<WishConfig>;
7
+ export { WishConfig, WishConfigSchema, };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "koishi-plugin-cocoyyy-console",
3
3
  "description": "自用koishi插件,功能包含复读,记录黑历史,*人等",
4
- "version": "1.1.3-alpha.5",
4
+ "version": "1.1.3",
5
5
  "main": "lib/index.js",
6
6
  "typings": "lib/index.d.ts",
7
7
  "contributors": [