dsh-mobile-plugin 0.5.28 → 0.5.29

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 (350) hide show
  1. package/extensions/catalog.json +10 -1
  2. package/extensions/magpie/agentcompact.js +104 -0
  3. package/extensions/magpie/app.css +4902 -0
  4. package/extensions/magpie/app.js +24474 -0
  5. package/extensions/magpie/autobackup.js +185 -0
  6. package/extensions/magpie/autoresetown.js +151 -0
  7. package/extensions/magpie/balfound.js +38 -0
  8. package/extensions/magpie/boot.js +23 -0
  9. package/extensions/magpie/cfgblocked.js +39 -0
  10. package/extensions/magpie/checkinnow.js +111 -0
  11. package/extensions/magpie/claudemode.js +92 -0
  12. package/extensions/magpie/compat.js +41 -0
  13. package/extensions/magpie/context.css +433 -0
  14. package/extensions/magpie/context.js +1576 -0
  15. package/extensions/magpie/ctxtext.js +223 -0
  16. package/extensions/magpie/fonts.js +42 -0
  17. package/extensions/magpie/i18n.js +18942 -0
  18. package/extensions/magpie/icons/ai21.svg +1 -0
  19. package/extensions/magpie/icons/ai302-color.svg +1 -0
  20. package/extensions/magpie/icons/ai360-color.svg +1 -0
  21. package/extensions/magpie/icons/aihubmix-color.svg +1 -0
  22. package/extensions/magpie/icons/aionui.svg +1 -0
  23. package/extensions/magpie/icons/air.svg +4 -0
  24. package/extensions/magpie/icons/alibaba-color.svg +1 -0
  25. package/extensions/magpie/icons/alibabacloud-color.svg +1 -0
  26. package/extensions/magpie/icons/alma.png +0 -0
  27. package/extensions/magpie/icons/anthropic.svg +1 -0
  28. package/extensions/magpie/icons/antigravity-color.svg +1 -0
  29. package/extensions/magpie/icons/anyscale-color.svg +1 -0
  30. package/extensions/magpie/icons/app-alma.png +0 -0
  31. package/extensions/magpie/icons/app-cc-switch.png +0 -0
  32. package/extensions/magpie/icons/apple-touch-icon.png +0 -0
  33. package/extensions/magpie/icons/aside.svg +28 -0
  34. package/extensions/magpie/icons/astrbot.svg +1 -0
  35. package/extensions/magpie/icons/atomcode.png +0 -0
  36. package/extensions/magpie/icons/aws.svg +1 -0
  37. package/extensions/magpie/icons/azure-color.svg +1 -0
  38. package/extensions/magpie/icons/azureai-color.svg +1 -0
  39. package/extensions/magpie/icons/baichuan-color.svg +1 -0
  40. package/extensions/magpie/icons/baidu-color.svg +1 -0
  41. package/extensions/magpie/icons/baiducloud-color.svg +1 -0
  42. package/extensions/magpie/icons/bailian-color.svg +1 -0
  43. package/extensions/magpie/icons/baseten.svg +1 -0
  44. package/extensions/magpie/icons/bedrock-color.svg +1 -0
  45. package/extensions/magpie/icons/burncloud-color.svg +1 -0
  46. package/extensions/magpie/icons/bytedance-color.svg +1 -0
  47. package/extensions/magpie/icons/cerebras.svg +1 -0
  48. package/extensions/magpie/icons/chatglm-color.svg +1 -0
  49. package/extensions/magpie/icons/cherryin-color.svg +1 -0
  50. package/extensions/magpie/icons/chutes.svg +1 -0
  51. package/extensions/magpie/icons/cindy.png +0 -0
  52. package/extensions/magpie/icons/claude-color.svg +1 -0
  53. package/extensions/magpie/icons/claudecode-color.svg +1 -0
  54. package/extensions/magpie/icons/cline.svg +1 -0
  55. package/extensions/magpie/icons/cloudflare-color.svg +1 -0
  56. package/extensions/magpie/icons/codebuddy-color.svg +1 -0
  57. package/extensions/magpie/icons/codex-color.svg +1 -0
  58. package/extensions/magpie/icons/cohere-color.svg +1 -0
  59. package/extensions/magpie/icons/cometapi-color.svg +1 -0
  60. package/extensions/magpie/icons/commandcode.svg +1 -0
  61. package/extensions/magpie/icons/copilot-color.svg +1 -0
  62. package/extensions/magpie/icons/coze.svg +1 -0
  63. package/extensions/magpie/icons/crush.png +0 -0
  64. package/extensions/magpie/icons/curl.svg +1 -0
  65. package/extensions/magpie/icons/cursor.svg +1 -0
  66. package/extensions/magpie/icons/deepinfra-color.svg +1 -0
  67. package/extensions/magpie/icons/deepmind-color.svg +1 -0
  68. package/extensions/magpie/icons/deepseek-color.svg +1 -0
  69. package/extensions/magpie/icons/deveco-color.svg +12 -0
  70. package/extensions/magpie/icons/devin.svg +1 -0
  71. package/extensions/magpie/icons/doubao-color.svg +1 -0
  72. package/extensions/magpie/icons/empryo-color.svg +1 -0
  73. package/extensions/magpie/icons/factory.svg +1 -0
  74. package/extensions/magpie/icons/favicon.svg +1 -0
  75. package/extensions/magpie/icons/featherless-color.svg +1 -0
  76. package/extensions/magpie/icons/fireworks-color.svg +1 -0
  77. package/extensions/magpie/icons/friendli.svg +1 -0
  78. package/extensions/magpie/icons/fx.svg +1 -0
  79. package/extensions/magpie/icons/gemini-color.svg +1 -0
  80. package/extensions/magpie/icons/geminicli-color.svg +1 -0
  81. package/extensions/magpie/icons/gemma-color.svg +1 -0
  82. package/extensions/magpie/icons/giteeai.svg +1 -0
  83. package/extensions/magpie/icons/github.svg +1 -0
  84. package/extensions/magpie/icons/githubcopilot.svg +1 -0
  85. package/extensions/magpie/icons/glama.svg +1 -0
  86. package/extensions/magpie/icons/gmicloud.svg +1 -0
  87. package/extensions/magpie/icons/google-color.svg +1 -0
  88. package/extensions/magpie/icons/googlecloud-color.svg +1 -0
  89. package/extensions/magpie/icons/goose.svg +1 -0
  90. package/extensions/magpie/icons/grok.svg +1 -0
  91. package/extensions/magpie/icons/groq.svg +1 -0
  92. package/extensions/magpie/icons/hanako.png +0 -0
  93. package/extensions/magpie/icons/hermes.svg +1 -0
  94. package/extensions/magpie/icons/huawei-color.svg +1 -0
  95. package/extensions/magpie/icons/huaweicloud-color.svg +1 -0
  96. package/extensions/magpie/icons/huggingface-color.svg +1 -0
  97. package/extensions/magpie/icons/hunyuan-color.svg +1 -0
  98. package/extensions/magpie/icons/hyperbolic-color.svg +1 -0
  99. package/extensions/magpie/icons/icon-512.png +0 -0
  100. package/extensions/magpie/icons/iflytekcloud-color.svg +1 -0
  101. package/extensions/magpie/icons/inference.svg +1 -0
  102. package/extensions/magpie/icons/infinigence-color.svg +1 -0
  103. package/extensions/magpie/icons/internlm-color.svg +1 -0
  104. package/extensions/magpie/icons/jcode.svg +1 -0
  105. package/extensions/magpie/icons/jina.svg +1 -0
  106. package/extensions/magpie/icons/kilo.svg +1 -0
  107. package/extensions/magpie/icons/kilocode.svg +1 -0
  108. package/extensions/magpie/icons/kimi-code-desktop.png +0 -0
  109. package/extensions/magpie/icons/kimi.svg +1 -0
  110. package/extensions/magpie/icons/kiro-color.svg +1 -0
  111. package/extensions/magpie/icons/kling-color.svg +1 -0
  112. package/extensions/magpie/icons/lambda.svg +1 -0
  113. package/extensions/magpie/icons/leptonai-color.svg +1 -0
  114. package/extensions/magpie/icons/liquid.svg +1 -0
  115. package/extensions/magpie/icons/liveagent-color.svg +1 -0
  116. package/extensions/magpie/icons/llmapi.svg +1 -0
  117. package/extensions/magpie/icons/lmstudio.svg +1 -0
  118. package/extensions/magpie/icons/lody.png +0 -0
  119. package/extensions/magpie/icons/longcat.svg +1 -0
  120. package/extensions/magpie/icons/magpie.svg +1 -0
  121. package/extensions/magpie/icons/meta-color.svg +1 -0
  122. package/extensions/magpie/icons/metaai-color.svg +1 -0
  123. package/extensions/magpie/icons/microsoft-color.svg +1 -0
  124. package/extensions/magpie/icons/mimocode.svg +1 -0
  125. package/extensions/magpie/icons/minimax-color.svg +1 -0
  126. package/extensions/magpie/icons/mistermorph-color.svg +1 -0
  127. package/extensions/magpie/icons/mistral-color.svg +1 -0
  128. package/extensions/magpie/icons/mlx-serve.png +0 -0
  129. package/extensions/magpie/icons/modelscope-color.svg +1 -0
  130. package/extensions/magpie/icons/monica-color.svg +1 -0
  131. package/extensions/magpie/icons/moonshot.svg +1 -0
  132. package/extensions/magpie/icons/morph-color.svg +1 -0
  133. package/extensions/magpie/icons/mothx.png +0 -0
  134. package/extensions/magpie/icons/nebius.svg +1 -0
  135. package/extensions/magpie/icons/newapi-color.svg +1 -0
  136. package/extensions/magpie/icons/nousresearch.svg +1 -0
  137. package/extensions/magpie/icons/nova-color.svg +1 -0
  138. package/extensions/magpie/icons/novita-color.svg +1 -0
  139. package/extensions/magpie/icons/nvidia-color.svg +1 -0
  140. package/extensions/magpie/icons/ollama.svg +1 -0
  141. package/extensions/magpie/icons/omlx.svg +1 -0
  142. package/extensions/magpie/icons/omo.svg +1 -0
  143. package/extensions/magpie/icons/omp.svg +1 -0
  144. package/extensions/magpie/icons/openai.svg +1 -0
  145. package/extensions/magpie/icons/openchamber.svg +11 -0
  146. package/extensions/magpie/icons/openclaw.svg +1 -0
  147. package/extensions/magpie/icons/opencode.svg +1 -0
  148. package/extensions/magpie/icons/openmausbot.svg +1 -0
  149. package/extensions/magpie/icons/openrouter.svg +1 -0
  150. package/extensions/magpie/icons/openwebui.svg +1 -0
  151. package/extensions/magpie/icons/parasail.svg +1 -0
  152. package/extensions/magpie/icons/penguin-color.svg +1 -0
  153. package/extensions/magpie/icons/perplexity-color.svg +1 -0
  154. package/extensions/magpie/icons/phala-color.svg +1 -0
  155. package/extensions/magpie/icons/pi.svg +1 -0
  156. package/extensions/magpie/icons/pipellm-color.svg +5 -0
  157. package/extensions/magpie/icons/poe.svg +1 -0
  158. package/extensions/magpie/icons/ppio-color.svg +1 -0
  159. package/extensions/magpie/icons/prime-agent.svg +1 -0
  160. package/extensions/magpie/icons/qiniu-color.svg +1 -0
  161. package/extensions/magpie/icons/qoder.svg +1 -0
  162. package/extensions/magpie/icons/qwen-color.svg +1 -0
  163. package/extensions/magpie/icons/qwenpaw.svg +1 -0
  164. package/extensions/magpie/icons/raycast.svg +1 -0
  165. package/extensions/magpie/icons/reasonix-color.svg +48 -0
  166. package/extensions/magpie/icons/reka.svg +1 -0
  167. package/extensions/magpie/icons/replicate.svg +1 -0
  168. package/extensions/magpie/icons/roocode.svg +1 -0
  169. package/extensions/magpie/icons/rtk.png +0 -0
  170. package/extensions/magpie/icons/sambanova-color.svg +1 -0
  171. package/extensions/magpie/icons/sensenova-color.svg +1 -0
  172. package/extensions/magpie/icons/siliconcloud-color.svg +1 -0
  173. package/extensions/magpie/icons/snow.png +0 -0
  174. package/extensions/magpie/icons/snowflake-color.svg +1 -0
  175. package/extensions/magpie/icons/sophnet-color.svg +1 -0
  176. package/extensions/magpie/icons/spark-color.svg +1 -0
  177. package/extensions/magpie/icons/stepfun-color.svg +1 -0
  178. package/extensions/magpie/icons/straico-color.svg +1 -0
  179. package/extensions/magpie/icons/submodel-color.svg +1 -0
  180. package/extensions/magpie/icons/t3code.svg +4 -0
  181. package/extensions/magpie/icons/targon-color.svg +1 -0
  182. package/extensions/magpie/icons/tencent-color.svg +1 -0
  183. package/extensions/magpie/icons/tencentcloud-color.svg +1 -0
  184. package/extensions/magpie/icons/tiangong-color.svg +1 -0
  185. package/extensions/magpie/icons/together-color.svg +1 -0
  186. package/extensions/magpie/icons/trae.svg +1 -0
  187. package/extensions/magpie/icons/typesafe.png +0 -0
  188. package/extensions/magpie/icons/upstage-color.svg +1 -0
  189. package/extensions/magpie/icons/venice-color.svg +1 -0
  190. package/extensions/magpie/icons/vercel.svg +1 -0
  191. package/extensions/magpie/icons/vertexai-color.svg +1 -0
  192. package/extensions/magpie/icons/vllm-color.svg +1 -0
  193. package/extensions/magpie/icons/volcengine-color.svg +1 -0
  194. package/extensions/magpie/icons/voyage-color.svg +1 -0
  195. package/extensions/magpie/icons/vscode.svg +1 -0
  196. package/extensions/magpie/icons/wenxin-color.svg +1 -0
  197. package/extensions/magpie/icons/windsurf.svg +1 -0
  198. package/extensions/magpie/icons/workbuddy-color.svg +1 -0
  199. package/extensions/magpie/icons/workersai-color.svg +1 -0
  200. package/extensions/magpie/icons/xai.svg +1 -0
  201. package/extensions/magpie/icons/xiaomimimo.svg +1 -0
  202. package/extensions/magpie/icons/xinference-color.svg +1 -0
  203. package/extensions/magpie/icons/yi.svg +1 -0
  204. package/extensions/magpie/icons/yuanbao-color.svg +1 -0
  205. package/extensions/magpie/icons/yylx.svg +5 -0
  206. package/extensions/magpie/icons/zai.svg +1 -0
  207. package/extensions/magpie/icons/zcode.png +0 -0
  208. package/extensions/magpie/icons/zed.svg +1 -0
  209. package/extensions/magpie/icons/zenmux.svg +1 -0
  210. package/extensions/magpie/icons/zeroone.svg +1 -0
  211. package/extensions/magpie/icons/zhipu-color.svg +1 -0
  212. package/extensions/magpie/icons/zoo-code.png +0 -0
  213. package/extensions/magpie/index.html +572 -0
  214. package/extensions/magpie/kernel.js +274 -0
  215. package/extensions/magpie/keyspend.js +63 -0
  216. package/extensions/magpie/layout.js +26 -0
  217. package/extensions/magpie/manifest.json +37 -0
  218. package/extensions/magpie/navlamp.js +47 -0
  219. package/extensions/magpie/omarchy.css +72 -0
  220. package/extensions/magpie/omarchy.js +46 -0
  221. package/extensions/magpie/passerrors.js +21 -0
  222. package/extensions/magpie/pluginpages.js +405 -0
  223. package/extensions/magpie/plugins/gateway/client.js +1194 -0
  224. package/extensions/magpie/plugins/gateway/keys.js +972 -0
  225. package/extensions/magpie/plugins/gateway/settings.js +459 -0
  226. package/extensions/magpie/plugins/library/client.js +6788 -0
  227. package/extensions/magpie/plugins/library/i18n.js +3228 -0
  228. package/extensions/magpie/plugins/library/library.css +848 -0
  229. package/extensions/magpie/plugins/otel/i18n.js +48 -0
  230. package/extensions/magpie/plugins/otel/page.js +189 -0
  231. package/extensions/magpie/plugins/redact/client.js +46 -0
  232. package/extensions/magpie/plugins/redact/demo.js +461 -0
  233. package/extensions/magpie/plugins/redact/i18n.js +432 -0
  234. package/extensions/magpie/plugins/redact/page.js +985 -0
  235. package/extensions/magpie/plugins/redact/redact.css +385 -0
  236. package/extensions/magpie/plugins/redact/settings.js +248 -0
  237. package/extensions/magpie/plugins/redact/xq_dark.jpg +0 -0
  238. package/extensions/magpie/plugins/redact/xq_dark.webm +0 -0
  239. package/extensions/magpie/plugins/redact/xq_light.jpg +0 -0
  240. package/extensions/magpie/plugins/redact/xq_light.webm +0 -0
  241. package/extensions/magpie/plugins/routing/client.js +8593 -0
  242. package/extensions/magpie/plugins/routing/i18n.js +2696 -0
  243. package/extensions/magpie/plugins/routing/routing.css +1111 -0
  244. package/extensions/magpie/plugins/search/settings.js +460 -0
  245. package/extensions/magpie/plugins/sessions/client.js +1622 -0
  246. package/extensions/magpie/plugins/sessions/i18n.js +360 -0
  247. package/extensions/magpie/plugins/sessions/sessions.css +181 -0
  248. package/extensions/magpie/plugins/sessions/settings.js +100 -0
  249. package/extensions/magpie/plugins/usage/client.js +150 -0
  250. package/extensions/magpie/plugins/usage/i18n.js +984 -0
  251. package/extensions/magpie/plugins/usage/page.js +4307 -0
  252. package/extensions/magpie/plugins.css +319 -0
  253. package/extensions/magpie/plugins.js +1926 -0
  254. package/extensions/magpie/profilerename.js +27 -0
  255. package/extensions/magpie/purposes.js +2 -0
  256. package/extensions/magpie/quitask.js +79 -0
  257. package/extensions/magpie/quotaall.js +142 -0
  258. package/extensions/magpie/ratewindows.js +123 -0
  259. package/extensions/magpie/registry.js +87 -0
  260. package/extensions/magpie/resetask.js +137 -0
  261. package/extensions/magpie/ruleedit.js +53 -0
  262. package/extensions/magpie/scrollends.js +91 -0
  263. package/extensions/magpie/settingshints.js +75 -0
  264. package/extensions/magpie/signsheets.js +86 -0
  265. package/extensions/magpie/start.js +26 -0
  266. package/extensions/magpie/syncfiles.js +216 -0
  267. package/extensions/magpie/theme.js +29 -0
  268. package/extensions/magpie/traywindows.js +41 -0
  269. package/extensions/magpie/webfonts.js +130 -0
  270. package/extensions/magpie/whatsnew.js +252 -0
  271. package/extensions/magpie.zip +0 -0
  272. package/knowledge/apps/baijiahao.md +30 -0
  273. package/knowledge/apps/bilibili.md +1 -0
  274. package/knowledge/apps/dedao.md +33 -0
  275. package/knowledge/apps/feishu.md +35 -0
  276. package/knowledge/apps/gmail.md +33 -0
  277. package/knowledge/apps/jike.md +31 -0
  278. package/knowledge/apps/kuaishou.md +34 -0
  279. package/knowledge/apps/linkedin.md +33 -0
  280. package/knowledge/apps/qqmail.md +30 -0
  281. package/knowledge/apps/telegram.md +27 -0
  282. package/knowledge/apps/toutiao.md +32 -0
  283. package/knowledge/apps/uber-eats.md +26 -0
  284. package/knowledge/apps/uber.md +27 -0
  285. package/knowledge/apps/whatsapp.md +27 -0
  286. package/knowledge/apps/x.md +32 -0
  287. package/knowledge/apps/xiaohongshu.md +1 -0
  288. package/knowledge/apps/zhihu.md +1 -0
  289. package/knowledge/sites/bilibili.com/SITE.md +50 -0
  290. package/knowledge/sites/bilibili.com/references/view-fields.md +17 -0
  291. package/knowledge/sites/github.com/SITE.md +51 -0
  292. package/knowledge/sites/github.com/references/repo-fields.md +13 -0
  293. package/knowledge/sites/x.com/SITE.md +47 -0
  294. package/knowledge/sites/xiaohongshu.com/SITE.md +48 -0
  295. package/knowledge/sites/xiaohongshu.com/references/note-fields.md +18 -0
  296. package/knowledge/sites/youtube.com/SITE.md +49 -0
  297. package/knowledge/sites/youtube.com/references/innertube-fields.md +14 -0
  298. package/knowledge/sites/zhihu.com/SITE.md +47 -0
  299. package/knowledge/sites/zhihu.com/references/api-fields.md +21 -0
  300. package/lib/mobile/extension-catalog.js +41 -1
  301. package/lib/mobile/extension-data.js +224 -0
  302. package/lib/mobile/extension-dev.js +3 -1
  303. package/lib/mobile/file-ops.js +252 -0
  304. package/lib/mobile/history-derive.js +80 -4
  305. package/lib/mobile/host-bridge/endpoints.js +48 -6
  306. package/lib/mobile/host-bridge/event-synthesis.js +33 -6
  307. package/lib/mobile/jobs-control.js +118 -0
  308. package/lib/mobile/memory.js +635 -0
  309. package/lib/mobile/model-badges.js +77 -0
  310. package/lib/mobile/pet-tools.js +50 -4
  311. package/lib/mobile/pets.js +214 -18
  312. package/lib/mobile/phone/access.js +85 -0
  313. package/lib/mobile/phone/evidence.js +228 -0
  314. package/lib/mobile/phone/gate.js +290 -0
  315. package/lib/mobile/phone/grounding.js +314 -0
  316. package/lib/mobile/phone/guard.js +465 -0
  317. package/lib/mobile/phone/irreversible.js +88 -8
  318. package/lib/mobile/phone/knowledge-tools.js +665 -0
  319. package/lib/mobile/phone/learn.js +329 -0
  320. package/lib/mobile/phone/redact.js +237 -0
  321. package/lib/mobile/phone/risk.js +95 -0
  322. package/lib/mobile/phone/routes.js +28 -1
  323. package/lib/mobile/phone/service.js +23 -0
  324. package/lib/mobile/phone/site-commands.js +271 -0
  325. package/lib/mobile/phone/step-summary.js +201 -0
  326. package/lib/mobile/phone/stop-summary.js +235 -0
  327. package/lib/mobile/phone/tool-groups.js +125 -0
  328. package/lib/mobile/phone/tools.js +589 -0
  329. package/lib/mobile/phone/untrusted.js +65 -0
  330. package/lib/mobile/phone-knowledge.js +20 -4
  331. package/lib/mobile/schedule-edit.js +500 -0
  332. package/lib/mobile/schedule.js +5 -0
  333. package/lib/mobile/send-continuation.js +52 -0
  334. package/lib/mobile/session-models.js +27 -31
  335. package/lib/mobile/session-send.js +12 -12
  336. package/lib/mobile/skill-import.js +338 -0
  337. package/lib/mobile/skill-store.js +524 -0
  338. package/lib/routes/mobile-api.js +42 -0
  339. package/package.json +7 -6
  340. package/skills/skill-authoring/SKILL.md +46 -0
  341. package/skills/skill-authoring/references/examples.md +82 -0
  342. package/skills/skill-authoring/references/frontmatter-and-fields.md +46 -0
  343. package/skills/skill-authoring/scripts/check_skill.py +167 -0
  344. package/skills/skill-authoring/scripts/manifest.json +3 -0
  345. package/knowledge/sites/bilibili.com.md +0 -27
  346. package/knowledge/sites/github.com.md +0 -27
  347. package/knowledge/sites/x.com.md +0 -28
  348. package/knowledge/sites/xiaohongshu.com.md +0 -27
  349. package/knowledge/sites/youtube.com.md +0 -28
  350. package/knowledge/sites/zhihu.com.md +0 -27
@@ -0,0 +1,314 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * 与模型无关的字面核查:回答里的引文、带单位/货币的数、日期时刻,必须能在**本次读到的
5
+ * 材料原文**里找到。
6
+ *
7
+ * 只核它核得准的——「有没有这句 / 有没有这个数」;**不核**一个值是不是属于回答说的那个
8
+ * 东西(哪个页面、哪个商品、哪一行)。语义归属要看懂上下文,那交给核查模型,不由这里判。
9
+ *
10
+ * 口径照 Mika `core/verify/Grounding.kt` 收窄:引号里的原文、带单位或货币或百分号或数量级
11
+ * 的数、小数、三位以上整数、日期与时刻;两位以内不带单位的整数(计数、序号、排名)不核。
12
+ *
13
+ * `check({answer, evidence, goal})` 返回 `{ ok, unmet, claims, matched }`:
14
+ * - `claims` 是回答里可核对的具体事实,`matched` 是其中对上的条数;
15
+ * - `unmet` 是对不上的那几条(`{ kind, text }`),`ok` 为 `unmet` 为空。
16
+ *
17
+ * 不通过时用 `rewriteHint(結果)` 给一句「退回改写一次」的提示;`review(...)` 把这个
18
+ * 「改写一次、再不行标未确认」的口径也一并给定(见文件底)。
19
+ */
20
+
21
+ /** 引号:中文直角 / 双引号 / 弯引号 / 直引号。空引号直接跳过。 */
22
+ const QUOTED = /「([^」]*)」|『([^』]*)』|“([^”]*)”|"([^"]*)"|‘([^’]*)’/g;
23
+
24
+ /** 「依据[::]」之后只核引文,其余(来源、网址、时间)不是要核对的事实。 */
25
+ const EVIDENCE = /依据\**\s*[::]/;
26
+
27
+ /** 数(含千分位与小数);后面紧跟的万/亿/千是数量级(千后面不能是米/克/瓦之类单位词)。 */
28
+ const NUMBER = /(?<!\d)(?<!\d[.,])\d+(?:[.,]\d+)*(?!\d)([ \t]*(?:[亿万]|千(?![米克瓦卡帕焦])))?/g;
29
+
30
+ /** 日期与时刻:10月23日、2026-10-23、2026/10/23、14:05、14:05:30。 */
31
+ const DATE = /(?<!\d)(?:\d{4}\s*[-/年]\s*\d{1,2}(?:\s*[-/月]\s*\d{1,2}\s*[日号]?)?|\d{1,2}\s*月\s*\d{1,2}\s*[日号]?|\d{1,2}\s*:\s*\d{2}(?:\s*:\s*\d{2})?)(?!\d)/g;
32
+
33
+ /** 数后面紧跟的量/单位(不含「条」「个」这类量词——那是回答自己数出来的)。 */
34
+ const UNIT_AFTER = /^\s*(?:%|‰|元|块|角|美元|欧元|日元|港元|英镑|℃|°|度|公里|千米|米|厘米|毫米|公斤|千克|斤|克|吨|小时|分钟|秒|毫秒|岁|英寸|寸|折|星|km|cm|mm|kg|mAh|GB|MB|KB|TB|Hz|ms)(?![A-Za-z])/;
35
+
36
+ /** 数前面的货币符号。 */
37
+ const CURRENCY_BEFORE = /[¥$€£]\s*$/;
38
+
39
+ /** 引用编号(@e16 / @v2)与脚注([1] / 【3】)不是回答内容,比对前去掉。 */
40
+ const REF_CITATION = /\(?\s*@[ev]\d+(?:\s*[,、]\s*@[ev]\d+)*\s*\)?/g;
41
+ const FOOTNOTE = /\[\^?\d{1,3}\]|【\d{1,3}】/g;
42
+
43
+ /** 排版强调与行内代码只是排版,不是内容(单个 * 可能是乘号,不动)。 */
44
+ const MARKUP = /\*\*|__|~~|`/g;
45
+ const ZERO_WIDTH = /[\u200B-\u200D\uFEFF\u2060]/g;
46
+
47
+ /** 屏上「当前 App:」那一行不算屏上文字。 */
48
+ const APP_HEADER = '当前 App:';
49
+
50
+ /** 截断标记。 */
51
+ const CUT = '...';
52
+
53
+ const MAGNITUDE = { 亿: 8, 万: 4, 千: 3 };
54
+
55
+ function canon(s) {
56
+ return String(s == null ? '' : s)
57
+ .normalize('NFKC')
58
+ .replace(ZERO_WIDTH, '')
59
+ .replace(MARKUP, '')
60
+ .replace(REF_CITATION, ' ')
61
+ .replace(FOOTNOTE, ' ');
62
+ }
63
+
64
+ /** 只留字母与数字,用于「这句原文在不在这行里」。 */
65
+ function norm(s) {
66
+ return String(s == null ? '' : s).replace(/[^\p{L}\p{N}]/gu, '');
67
+ }
68
+
69
+ function quotes(s) {
70
+ const out = [];
71
+ QUOTED.lastIndex = 0;
72
+ let m;
73
+ while ((m = QUOTED.exec(s)) !== null) {
74
+ const q = m.slice(1).find((x) => typeof x === 'string' && x !== '');
75
+ if (q !== undefined) out.push(q);
76
+ }
77
+ return out;
78
+ }
79
+
80
+ /** 一个数 + 数量级。scaled 是折算到基本单位后的写法(5.3万 = 53000)。 */
81
+ function makeNum(value, magnitude) {
82
+ const clean = value.replace(/,/g, '');
83
+ let scaled = null;
84
+ if (/^\d+(?:\.\d+)?$/.test(clean)) {
85
+ const base = Number(clean);
86
+ if (Number.isFinite(base)) {
87
+ const pow = MAGNITUDE[magnitude];
88
+ scaled = pow ? String(base * 10 ** pow) : String(base);
89
+ }
90
+ }
91
+ return { value: clean, magnitude: magnitude || '', scaled };
92
+ }
93
+
94
+ function numMatches(a, b) {
95
+ if (a.value === b.value && (a.magnitude === '' || a.magnitude === b.magnitude)) return true;
96
+ return a.scaled !== null && a.scaled === b.scaled;
97
+ }
98
+
99
+ /** 一行里的全部数(不判它们是不是「值」,只做比对底料)。 */
100
+ function numbersIn(s) {
101
+ const out = [];
102
+ NUMBER.lastIndex = 0;
103
+ let m;
104
+ while ((m = NUMBER.exec(s)) !== null) {
105
+ const mag = m[1] || '';
106
+ const magnitude = mag.trim();
107
+ const raw = m[0].slice(0, m[0].length - mag.length);
108
+ out.push(makeNum(raw, magnitude));
109
+ }
110
+ return out;
111
+ }
112
+
113
+ /**
114
+ * 回答里算作事实的数:带数量级 / 单位 / 货币的,小数,三位以上整数。
115
+ * 题目里给了的数(goal 里的数)视为已知,不再核(但据它算出的结果仍要在屏上读到)。
116
+ */
117
+ function valueNumbers(line, goalValues) {
118
+ const out = [];
119
+ NUMBER.lastIndex = 0;
120
+ let m;
121
+ while ((m = NUMBER.exec(line)) !== null) {
122
+ const mag = m[1] || '';
123
+ const magnitude = mag.trim();
124
+ const raw = m[0].slice(0, m[0].length - mag.length);
125
+ const n = makeNum(raw, magnitude);
126
+ if (n.scaled !== null && goalValues.has(n.scaled)) continue;
127
+ const after = line.slice(m.index + m[0].length, m.index + m[0].length + 8);
128
+ const before = line.slice(0, m.index);
129
+ const unit = magnitude !== '' || UNIT_AFTER.test(after) || CURRENCY_BEFORE.test(before);
130
+ const decimal = n.value.includes('.');
131
+ const long = n.value.split('.')[0].length >= 3;
132
+ if (unit || decimal || long) out.push({ kind: 'number', text: `${n.value}${magnitude}`, num: n });
133
+ }
134
+ return out;
135
+ }
136
+
137
+ /** 一行里的日期 / 时刻(题目里已有的不算)。 */
138
+ function dateClaims(line, goalDigits) {
139
+ const out = [];
140
+ DATE.lastIndex = 0;
141
+ let m;
142
+ while ((m = DATE.exec(line)) !== null) {
143
+ const text = m[0].trim();
144
+ const digits = digitsOf(text);
145
+ if (digits.length > 0 && digits.every((d) => goalDigits.has(d))) continue;
146
+ out.push({ kind: 'date', text });
147
+ }
148
+ return out;
149
+ }
150
+
151
+ function digitsOf(s) {
152
+ return (String(s).match(/\d+/g) || []).map((d) => d.replace(/^0+(?=\d)/, '')).filter((d) => d !== '');
153
+ }
154
+
155
+ /** 把一处材料拆成「按行预处理好」的比对底料。 */
156
+ function prepareSources(evidence) {
157
+ const texts = Array.isArray(evidence)
158
+ ? evidence
159
+ : (evidence && typeof evidence === 'object' && typeof evidence.text === 'string' ? [evidence.text] : []);
160
+ return texts
161
+ .filter((t) => typeof t === 'string' && t !== '')
162
+ .map((text) => {
163
+ const lines = canon(text).split('\n').filter((l) => l.trim() !== '' && !l.trim().startsWith(APP_HEADER));
164
+ return {
165
+ normLines: lines.map(norm),
166
+ // 每行的数、数字串、字母数字串
167
+ nums: lines.map((l) => numbersIn(l)),
168
+ digits: lines.map((l) => digitsOf(l)),
169
+ tokens: lines.map((l) => (l.toLowerCase().match(/[a-z0-9]+/g) || [])),
170
+ };
171
+ });
172
+ }
173
+
174
+ /** 引文在某处材料里:被 ... 分开的几段各对得上,而且在同一处。 */
175
+ function quoteInSources(quote, sources) {
176
+ const parts = canon(quote).split(CUT).map(norm).filter((p) => p.length >= 2);
177
+ if (parts.length === 0) return false;
178
+ return sources.some((src) => parts.every((p) => src.normLines.some((line) => line.includes(p))));
179
+ }
180
+
181
+ /** 数在某处材料里(按整个数比,含数量级折算)。 */
182
+ function numberInSources(num, sources) {
183
+ return sources.some((src) => src.nums.some((lineNums) => lineNums.some((n) => numMatches(num, n))));
184
+ }
185
+
186
+ /** 日期在某处材料里:数字串窗口对上(含丢掉年份的「月日」)。 */
187
+ function dateInSources(text, sources) {
188
+ const comps = digitsOf(text);
189
+ if (comps.length === 0) return false;
190
+ const variants = [comps];
191
+ if (comps.length === 3 && comps[0].length === 4) variants.push(comps.slice(1));
192
+ return sources.some((src) => variants.some((v) => src.digits.some((line) => {
193
+ if (v.length > line.length) return false;
194
+ for (let i = 0; i + v.length <= line.length; i += 1) {
195
+ if (v.every((d, k) => line[i + k] === d)) return true;
196
+ }
197
+ return false;
198
+ })));
199
+ }
200
+
201
+ /**
202
+ * 核一遍。
203
+ *
204
+ * @param {{answer:string, evidence:(string|string[]|{text:string}), goal?:string}} input
205
+ * @returns {{ ok:boolean, unmet:Array<{kind:string,text:string}>, claims:Array<{kind:string,text:string}>, matched:number }}
206
+ */
207
+ function check(input) {
208
+ const answer = input && typeof input.answer === 'string' ? input.answer : '';
209
+ const goal = input && typeof input.goal === 'string' ? input.goal : '';
210
+ const sources = prepareSources(input && input.evidence);
211
+
212
+ const a = canon(answer);
213
+ const at = EVIDENCE.exec(a);
214
+ const body = at ? a.slice(0, at.index) : a;
215
+ const basis = at ? a.slice(at.index + at[0].length) : '';
216
+
217
+ const goalText = norm(goal);
218
+ const goalNumbers = numbersIn(canon(goal));
219
+ const goalValues = new Set(goalNumbers.map((n) => n.scaled).filter((v) => v !== null));
220
+ const goalDigits = new Set(digitsOf(goal));
221
+
222
+ const claims = [];
223
+
224
+ // 回答正文里的引文(题目里本来有的、空的不算)。
225
+ const plainBody = body.replace(QUOTED, ' ');
226
+ for (const q of quotes(body)) {
227
+ if (norm(q).length < 2) continue;
228
+ if (norm(q) && goalText && goalText.includes(norm(q))) continue;
229
+ claims.push({ kind: 'quote', text: q });
230
+ }
231
+ // 「依据:」里的引文同样要核。
232
+ for (const q of quotes(basis)) {
233
+ if (norm(q).length < 2) continue;
234
+ claims.push({ kind: 'quote', text: q });
235
+ }
236
+
237
+ // 逐行取数、取日期(正文里引号内容要遮掉,避免引文里的数被重复当成正文的事实)。
238
+ for (const rawLine of plainBody.split('\n')) {
239
+ const line = rawLine.replace(MARKUP, '');
240
+ for (const c of dateClaims(line, goalDigits)) claims.push(c);
241
+ for (const c of valueNumbers(line, goalValues)) claims.push(c);
242
+ }
243
+
244
+ // 去重
245
+ const seen = new Set();
246
+ const unique = claims.filter((c) => {
247
+ const key = `${c.kind}\u0000${c.text}`;
248
+ if (seen.has(key)) return false;
249
+ seen.add(key);
250
+ return true;
251
+ });
252
+
253
+ let matched = 0;
254
+ const unmet = [];
255
+ for (const c of unique) {
256
+ let ok;
257
+ if (c.kind === 'quote') ok = quoteInSources(c.text, sources);
258
+ else if (c.kind === 'number') ok = numberInSources(c.num || makeNum(c.text, ''), sources);
259
+ else ok = dateInSources(c.text, sources);
260
+ if (ok) matched += 1;
261
+ else unmet.push({ kind: c.kind, text: c.text });
262
+ }
263
+
264
+ // 去掉内部字段再返回。
265
+ const claimsOut = unique.map((c) => ({ kind: c.kind, text: c.text }));
266
+ return { ok: unmet.length === 0, unmet, claims: claimsOut, matched };
267
+ }
268
+
269
+ const KIND_LABEL = { quote: '引文', number: '数', date: '日期' };
270
+
271
+ /** 给「退回改写一次」用的一句提示:把对不上的逐条列出来,让它改写或标未确认。 */
272
+ function rewriteHint(result) {
273
+ const unmet = result && Array.isArray(result.unmet) ? result.unmet : [];
274
+ if (unmet.length === 0) return '';
275
+ const items = unmet.map((u) => `- ${KIND_LABEL[u.kind] || u.kind}「${u.text}」`).join('\n');
276
+ return [
277
+ '下面这些在本次读到的材料里找不到原文:',
278
+ items,
279
+ '请改写一次:删掉,或改成材料里确实出现过的话和数;确实没法确认的,标成「未确认」。',
280
+ ].join('\n');
281
+ }
282
+
283
+ /** 最多退回改写几次。 */
284
+ const MAX_REWRITE = 1;
285
+
286
+ /**
287
+ * 交回答前的核查口径:对不上就退回改写**一次**;改写过还是一样对不上,就标未确认交出
288
+ * (不无限重试,也不假装通过)。
289
+ *
290
+ * @param {{answer:string, evidence:*, goal?:string, alreadyRewritten?:boolean}} input
291
+ * @returns {{ action:'pass'|'rewrite'|'unconfirmed', ok:boolean, unmet:Array, claims:Array, matched:number, rewriteHint:string }}
292
+ */
293
+ function review(input) {
294
+ const result = check(input);
295
+ if (result.ok) return { ...result, action: 'pass', rewriteHint: '' };
296
+ const hint = rewriteHint(result);
297
+ if (input && input.alreadyRewritten) return { ...result, action: 'unconfirmed', rewriteHint: hint };
298
+ return { ...result, action: 'rewrite', rewriteHint: hint };
299
+ }
300
+
301
+ module.exports = {
302
+ check,
303
+ review,
304
+ rewriteHint,
305
+ // 守卫可直接用的纯函数与小常量:
306
+ canon,
307
+ norm,
308
+ quotes,
309
+ numbersIn,
310
+ valueNumbers,
311
+ dateClaims,
312
+ MAX_REWRITE,
313
+ CUT,
314
+ };