@pi-harness/pi-harness 0.1.13 → 0.1.14

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 (1333) hide show
  1. package/README.md +678 -2
  2. package/apps/web/dist/assets/index-BVI_IS-R.css +2 -0
  3. package/apps/web/dist/assets/index-C98SJjJd.js +22 -0
  4. package/apps/web/dist/index.html +2 -2
  5. package/apps/web/package.json +6 -6
  6. package/node_modules/@pi-harness/api-gateway/dist/index.d.ts.map +1 -1
  7. package/node_modules/@pi-harness/api-gateway/dist/index.js +97 -9
  8. package/node_modules/@pi-harness/api-gateway/dist/index.js.map +1 -1
  9. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/agent-teams.json +6 -6
  10. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/anchored-standard.json +1 -1
  11. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/annotation.json +1 -2
  12. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/archify.json +1 -1
  13. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/at-file.json +11 -5
  14. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/auto-mode.json +1 -1
  15. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/better-sidebar.json +1 -1
  16. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/browser-fetch.json +12 -5
  17. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/browser-session.json +14 -8
  18. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/canvas-draw.json +3 -4
  19. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/change-verifier.json +1 -1
  20. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cleaner.json +11 -6
  21. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cli-notifier.json +5 -5
  22. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/code2skill.json +5 -5
  23. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/colleague-skill.json +1 -2
  24. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/context-doctor.json +12 -7
  25. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/context.json +10 -5
  26. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cordis-group.json +2 -2
  27. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cordis-logger-console.json +4 -4
  28. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cordis-timer.json +3 -3
  29. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/cost-meter.json +9 -6
  30. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/dependency-checker.json +13 -10
  31. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/docker-sandbox.json +10 -5
  32. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/fail-logger.json +11 -6
  33. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/genui.json +7 -5
  34. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/git-time-capsule.json +13 -8
  35. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/graph-memory.json +13 -7
  36. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/history-compressor.json +1 -1
  37. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/hol-guard.json +1 -1
  38. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/i18n-pair.json +9 -6
  39. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/image-compressor.json +1 -1
  40. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/llm-verifier.json +1 -1
  41. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mcp-client.json +12 -7
  42. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mcp-panel.json +1 -1
  43. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/memory.json +1 -1
  44. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mirage-bridge.json +1 -1
  45. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/mock-server.json +1 -1
  46. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/modlens.json +4 -4
  47. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/module-search.json +1 -1
  48. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/obsidian-sync.json +1 -1
  49. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/openpets.json +9 -5
  50. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plan-execute.json +1 -1
  51. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-check.json +1 -1
  52. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-dev.json +8 -6
  53. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-finder.json +1 -1
  54. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-radar.json +1 -1
  55. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/plugin-stars.json +15 -7
  56. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/prompt-guard.json +1 -1
  57. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/prompt-library.json +1 -1
  58. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/readme-gen.json +12 -8
  59. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/recall-unread.json +11 -6
  60. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/reverse-skill.json +1 -1
  61. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/reviewer-bot.json +1 -1
  62. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/runtime-doctor.json +1 -1
  63. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/secure-audit.json +1 -1
  64. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-bookmarks.json +1 -1
  65. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-bridge.json +13 -8
  66. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-compare.json +1 -1
  67. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-export.json +1 -1
  68. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-insights.json +12 -6
  69. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/session-search.json +1 -1
  70. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/skill-catalog.json +1 -1
  71. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/skill-guard.json +9 -5
  72. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/sql-lens.json +13 -7
  73. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/synapse.json +1 -1
  74. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/tab-manager.json +1 -1
  75. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/taskboard.json +1 -1
  76. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/telemetry-blocker.json +1 -1
  77. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/test-harness.json +14 -7
  78. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/theme-studio.json +1 -1
  79. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/token-guard.json +12 -6
  80. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/turn-rewind.json +11 -6
  81. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/undo-savepoint.json +1 -1
  82. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/vision-toolkit.json +8 -5
  83. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/web-research.json +1 -1
  84. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/workspace-navigator.json +1 -1
  85. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/workspace-search.json +1 -1
  86. package/node_modules/@pi-harness/api-gateway/dist/marketplace-entries/official/yaml-validator.json +8 -5
  87. package/node_modules/@pi-harness/api-gateway/package.json +1 -1
  88. package/node_modules/@pi-harness/cli/dist/node-stdio.d.ts.map +1 -1
  89. package/node_modules/@pi-harness/cli/dist/node-stdio.js +83 -20
  90. package/node_modules/@pi-harness/cli/dist/node-stdio.js.map +1 -1
  91. package/node_modules/@pi-harness/cli/package.json +1 -1
  92. package/node_modules/@pi-harness/core/dist/atomic-write.d.ts +8 -0
  93. package/node_modules/@pi-harness/core/dist/atomic-write.d.ts.map +1 -0
  94. package/node_modules/@pi-harness/core/dist/atomic-write.js +40 -0
  95. package/node_modules/@pi-harness/core/dist/atomic-write.js.map +1 -0
  96. package/node_modules/@pi-harness/core/dist/boot.d.ts.map +1 -1
  97. package/node_modules/@pi-harness/core/dist/boot.js +132 -10
  98. package/node_modules/@pi-harness/core/dist/boot.js.map +1 -1
  99. package/node_modules/@pi-harness/core/dist/bounded-file.d.ts +7 -0
  100. package/node_modules/@pi-harness/core/dist/bounded-file.d.ts.map +1 -0
  101. package/node_modules/@pi-harness/core/dist/bounded-file.js +50 -0
  102. package/node_modules/@pi-harness/core/dist/bounded-file.js.map +1 -0
  103. package/node_modules/@pi-harness/core/dist/config.d.ts +2 -0
  104. package/node_modules/@pi-harness/core/dist/config.d.ts.map +1 -1
  105. package/node_modules/@pi-harness/core/dist/config.js +21 -0
  106. package/node_modules/@pi-harness/core/dist/config.js.map +1 -1
  107. package/node_modules/@pi-harness/core/dist/cordis-timer.d.ts +15 -0
  108. package/node_modules/@pi-harness/core/dist/cordis-timer.d.ts.map +1 -0
  109. package/node_modules/@pi-harness/core/dist/cordis-timer.js +99 -0
  110. package/node_modules/@pi-harness/core/dist/cordis-timer.js.map +1 -0
  111. package/node_modules/@pi-harness/core/dist/plugins/agent-teams.d.ts +5 -1
  112. package/node_modules/@pi-harness/core/dist/plugins/agent-teams.d.ts.map +1 -1
  113. package/node_modules/@pi-harness/core/dist/plugins/agent-teams.js +986 -105
  114. package/node_modules/@pi-harness/core/dist/plugins/agent-teams.js.map +1 -1
  115. package/node_modules/@pi-harness/core/dist/plugins/anchored-standard.d.ts +1 -0
  116. package/node_modules/@pi-harness/core/dist/plugins/anchored-standard.d.ts.map +1 -1
  117. package/node_modules/@pi-harness/core/dist/plugins/anchored-standard.js +39 -11
  118. package/node_modules/@pi-harness/core/dist/plugins/anchored-standard.js.map +1 -1
  119. package/node_modules/@pi-harness/core/dist/plugins/annotation.d.ts +1 -0
  120. package/node_modules/@pi-harness/core/dist/plugins/annotation.d.ts.map +1 -1
  121. package/node_modules/@pi-harness/core/dist/plugins/annotation.js +35 -17
  122. package/node_modules/@pi-harness/core/dist/plugins/annotation.js.map +1 -1
  123. package/node_modules/@pi-harness/core/dist/plugins/archify.d.ts +1 -0
  124. package/node_modules/@pi-harness/core/dist/plugins/archify.d.ts.map +1 -1
  125. package/node_modules/@pi-harness/core/dist/plugins/archify.js +69 -22
  126. package/node_modules/@pi-harness/core/dist/plugins/archify.js.map +1 -1
  127. package/node_modules/@pi-harness/core/dist/plugins/at-file.d.ts +5 -1
  128. package/node_modules/@pi-harness/core/dist/plugins/at-file.d.ts.map +1 -1
  129. package/node_modules/@pi-harness/core/dist/plugins/at-file.js +120 -29
  130. package/node_modules/@pi-harness/core/dist/plugins/at-file.js.map +1 -1
  131. package/node_modules/@pi-harness/core/dist/plugins/auto-mode.d.ts.map +1 -1
  132. package/node_modules/@pi-harness/core/dist/plugins/auto-mode.js +89 -20
  133. package/node_modules/@pi-harness/core/dist/plugins/auto-mode.js.map +1 -1
  134. package/node_modules/@pi-harness/core/dist/plugins/better-sidebar.d.ts +1 -0
  135. package/node_modules/@pi-harness/core/dist/plugins/better-sidebar.d.ts.map +1 -1
  136. package/node_modules/@pi-harness/core/dist/plugins/better-sidebar.js +14 -4
  137. package/node_modules/@pi-harness/core/dist/plugins/better-sidebar.js.map +1 -1
  138. package/node_modules/@pi-harness/core/dist/plugins/browser-fetch.d.ts +1 -0
  139. package/node_modules/@pi-harness/core/dist/plugins/browser-fetch.d.ts.map +1 -1
  140. package/node_modules/@pi-harness/core/dist/plugins/browser-fetch.js +288 -96
  141. package/node_modules/@pi-harness/core/dist/plugins/browser-fetch.js.map +1 -1
  142. package/node_modules/@pi-harness/core/dist/plugins/browser-session.d.ts.map +1 -1
  143. package/node_modules/@pi-harness/core/dist/plugins/browser-session.js +445 -106
  144. package/node_modules/@pi-harness/core/dist/plugins/browser-session.js.map +1 -1
  145. package/node_modules/@pi-harness/core/dist/plugins/canvas-draw.d.ts +1 -0
  146. package/node_modules/@pi-harness/core/dist/plugins/canvas-draw.d.ts.map +1 -1
  147. package/node_modules/@pi-harness/core/dist/plugins/canvas-draw.js +71 -19
  148. package/node_modules/@pi-harness/core/dist/plugins/canvas-draw.js.map +1 -1
  149. package/node_modules/@pi-harness/core/dist/plugins/change-verifier.d.ts +1 -0
  150. package/node_modules/@pi-harness/core/dist/plugins/change-verifier.d.ts.map +1 -1
  151. package/node_modules/@pi-harness/core/dist/plugins/change-verifier.js +30 -9
  152. package/node_modules/@pi-harness/core/dist/plugins/change-verifier.js.map +1 -1
  153. package/node_modules/@pi-harness/core/dist/plugins/cleaner.d.ts +5 -1
  154. package/node_modules/@pi-harness/core/dist/plugins/cleaner.d.ts.map +1 -1
  155. package/node_modules/@pi-harness/core/dist/plugins/cleaner.js +337 -40
  156. package/node_modules/@pi-harness/core/dist/plugins/cleaner.js.map +1 -1
  157. package/node_modules/@pi-harness/core/dist/plugins/cli-notifier.d.ts +2 -1
  158. package/node_modules/@pi-harness/core/dist/plugins/cli-notifier.d.ts.map +1 -1
  159. package/node_modules/@pi-harness/core/dist/plugins/cli-notifier.js +99 -42
  160. package/node_modules/@pi-harness/core/dist/plugins/cli-notifier.js.map +1 -1
  161. package/node_modules/@pi-harness/core/dist/plugins/code2skill.d.ts +1 -0
  162. package/node_modules/@pi-harness/core/dist/plugins/code2skill.d.ts.map +1 -1
  163. package/node_modules/@pi-harness/core/dist/plugins/code2skill.js +178 -38
  164. package/node_modules/@pi-harness/core/dist/plugins/code2skill.js.map +1 -1
  165. package/node_modules/@pi-harness/core/dist/plugins/colleague-skill.d.ts +2 -1
  166. package/node_modules/@pi-harness/core/dist/plugins/colleague-skill.d.ts.map +1 -1
  167. package/node_modules/@pi-harness/core/dist/plugins/colleague-skill.js +79 -49
  168. package/node_modules/@pi-harness/core/dist/plugins/colleague-skill.js.map +1 -1
  169. package/node_modules/@pi-harness/core/dist/plugins/context-doctor.d.ts +6 -1
  170. package/node_modules/@pi-harness/core/dist/plugins/context-doctor.d.ts.map +1 -1
  171. package/node_modules/@pi-harness/core/dist/plugins/context-doctor.js +403 -39
  172. package/node_modules/@pi-harness/core/dist/plugins/context-doctor.js.map +1 -1
  173. package/node_modules/@pi-harness/core/dist/plugins/context.d.ts +1 -0
  174. package/node_modules/@pi-harness/core/dist/plugins/context.d.ts.map +1 -1
  175. package/node_modules/@pi-harness/core/dist/plugins/context.js +169 -42
  176. package/node_modules/@pi-harness/core/dist/plugins/context.js.map +1 -1
  177. package/node_modules/@pi-harness/core/dist/plugins/cost-meter.d.ts +4 -0
  178. package/node_modules/@pi-harness/core/dist/plugins/cost-meter.d.ts.map +1 -1
  179. package/node_modules/@pi-harness/core/dist/plugins/cost-meter.js +319 -93
  180. package/node_modules/@pi-harness/core/dist/plugins/cost-meter.js.map +1 -1
  181. package/node_modules/@pi-harness/core/dist/plugins/dependency-checker.d.ts +11 -2
  182. package/node_modules/@pi-harness/core/dist/plugins/dependency-checker.d.ts.map +1 -1
  183. package/node_modules/@pi-harness/core/dist/plugins/dependency-checker.js +463 -114
  184. package/node_modules/@pi-harness/core/dist/plugins/dependency-checker.js.map +1 -1
  185. package/node_modules/@pi-harness/core/dist/plugins/docker-sandbox.d.ts +1 -0
  186. package/node_modules/@pi-harness/core/dist/plugins/docker-sandbox.d.ts.map +1 -1
  187. package/node_modules/@pi-harness/core/dist/plugins/docker-sandbox.js +322 -80
  188. package/node_modules/@pi-harness/core/dist/plugins/docker-sandbox.js.map +1 -1
  189. package/node_modules/@pi-harness/core/dist/plugins/fail-logger.d.ts +1 -0
  190. package/node_modules/@pi-harness/core/dist/plugins/fail-logger.d.ts.map +1 -1
  191. package/node_modules/@pi-harness/core/dist/plugins/fail-logger.js +187 -20
  192. package/node_modules/@pi-harness/core/dist/plugins/fail-logger.js.map +1 -1
  193. package/node_modules/@pi-harness/core/dist/plugins/genui.d.ts +1 -0
  194. package/node_modules/@pi-harness/core/dist/plugins/genui.d.ts.map +1 -1
  195. package/node_modules/@pi-harness/core/dist/plugins/genui.js +103 -38
  196. package/node_modules/@pi-harness/core/dist/plugins/genui.js.map +1 -1
  197. package/node_modules/@pi-harness/core/dist/plugins/git-time-capsule.d.ts +8 -2
  198. package/node_modules/@pi-harness/core/dist/plugins/git-time-capsule.d.ts.map +1 -1
  199. package/node_modules/@pi-harness/core/dist/plugins/git-time-capsule.js +400 -54
  200. package/node_modules/@pi-harness/core/dist/plugins/git-time-capsule.js.map +1 -1
  201. package/node_modules/@pi-harness/core/dist/plugins/graph-memory.d.ts.map +1 -1
  202. package/node_modules/@pi-harness/core/dist/plugins/graph-memory.js +329 -42
  203. package/node_modules/@pi-harness/core/dist/plugins/graph-memory.js.map +1 -1
  204. package/node_modules/@pi-harness/core/dist/plugins/history-compressor.d.ts.map +1 -1
  205. package/node_modules/@pi-harness/core/dist/plugins/history-compressor.js +31 -12
  206. package/node_modules/@pi-harness/core/dist/plugins/history-compressor.js.map +1 -1
  207. package/node_modules/@pi-harness/core/dist/plugins/hol-guard.d.ts.map +1 -1
  208. package/node_modules/@pi-harness/core/dist/plugins/hol-guard.js +33 -13
  209. package/node_modules/@pi-harness/core/dist/plugins/hol-guard.js.map +1 -1
  210. package/node_modules/@pi-harness/core/dist/plugins/i18n-pair.d.ts +5 -1
  211. package/node_modules/@pi-harness/core/dist/plugins/i18n-pair.d.ts.map +1 -1
  212. package/node_modules/@pi-harness/core/dist/plugins/i18n-pair.js +308 -52
  213. package/node_modules/@pi-harness/core/dist/plugins/i18n-pair.js.map +1 -1
  214. package/node_modules/@pi-harness/core/dist/plugins/image-compressor.d.ts +7 -0
  215. package/node_modules/@pi-harness/core/dist/plugins/image-compressor.d.ts.map +1 -1
  216. package/node_modules/@pi-harness/core/dist/plugins/image-compressor.js +98 -25
  217. package/node_modules/@pi-harness/core/dist/plugins/image-compressor.js.map +1 -1
  218. package/node_modules/@pi-harness/core/dist/plugins/llm-verifier.d.ts.map +1 -1
  219. package/node_modules/@pi-harness/core/dist/plugins/llm-verifier.js +21 -11
  220. package/node_modules/@pi-harness/core/dist/plugins/llm-verifier.js.map +1 -1
  221. package/node_modules/@pi-harness/core/dist/plugins/mcp-client.d.ts.map +1 -1
  222. package/node_modules/@pi-harness/core/dist/plugins/mcp-client.js +986 -232
  223. package/node_modules/@pi-harness/core/dist/plugins/mcp-client.js.map +1 -1
  224. package/node_modules/@pi-harness/core/dist/plugins/mcp-panel.d.ts.map +1 -1
  225. package/node_modules/@pi-harness/core/dist/plugins/mcp-panel.js +30 -16
  226. package/node_modules/@pi-harness/core/dist/plugins/mcp-panel.js.map +1 -1
  227. package/node_modules/@pi-harness/core/dist/plugins/memory.d.ts.map +1 -1
  228. package/node_modules/@pi-harness/core/dist/plugins/memory.js +292 -59
  229. package/node_modules/@pi-harness/core/dist/plugins/memory.js.map +1 -1
  230. package/node_modules/@pi-harness/core/dist/plugins/mirage-bridge.d.ts.map +1 -1
  231. package/node_modules/@pi-harness/core/dist/plugins/mirage-bridge.js +20 -10
  232. package/node_modules/@pi-harness/core/dist/plugins/mirage-bridge.js.map +1 -1
  233. package/node_modules/@pi-harness/core/dist/plugins/mock-server.d.ts.map +1 -1
  234. package/node_modules/@pi-harness/core/dist/plugins/mock-server.js +85 -54
  235. package/node_modules/@pi-harness/core/dist/plugins/mock-server.js.map +1 -1
  236. package/node_modules/@pi-harness/core/dist/plugins/model.d.ts +3 -0
  237. package/node_modules/@pi-harness/core/dist/plugins/model.d.ts.map +1 -1
  238. package/node_modules/@pi-harness/core/dist/plugins/model.js +3 -0
  239. package/node_modules/@pi-harness/core/dist/plugins/model.js.map +1 -1
  240. package/node_modules/@pi-harness/core/dist/plugins/models.d.ts.map +1 -1
  241. package/node_modules/@pi-harness/core/dist/plugins/models.js +10 -2
  242. package/node_modules/@pi-harness/core/dist/plugins/models.js.map +1 -1
  243. package/node_modules/@pi-harness/core/dist/plugins/modlens.d.ts +8 -1
  244. package/node_modules/@pi-harness/core/dist/plugins/modlens.d.ts.map +1 -1
  245. package/node_modules/@pi-harness/core/dist/plugins/modlens.js +438 -31
  246. package/node_modules/@pi-harness/core/dist/plugins/modlens.js.map +1 -1
  247. package/node_modules/@pi-harness/core/dist/plugins/module-search.d.ts +1 -0
  248. package/node_modules/@pi-harness/core/dist/plugins/module-search.d.ts.map +1 -1
  249. package/node_modules/@pi-harness/core/dist/plugins/module-search.js +35 -16
  250. package/node_modules/@pi-harness/core/dist/plugins/module-search.js.map +1 -1
  251. package/node_modules/@pi-harness/core/dist/plugins/obsidian-sync.d.ts.map +1 -1
  252. package/node_modules/@pi-harness/core/dist/plugins/obsidian-sync.js +20 -11
  253. package/node_modules/@pi-harness/core/dist/plugins/obsidian-sync.js.map +1 -1
  254. package/node_modules/@pi-harness/core/dist/plugins/openpets.d.ts.map +1 -1
  255. package/node_modules/@pi-harness/core/dist/plugins/openpets.js +203 -44
  256. package/node_modules/@pi-harness/core/dist/plugins/openpets.js.map +1 -1
  257. package/node_modules/@pi-harness/core/dist/plugins/plan-execute.d.ts +4 -1
  258. package/node_modules/@pi-harness/core/dist/plugins/plan-execute.d.ts.map +1 -1
  259. package/node_modules/@pi-harness/core/dist/plugins/plan-execute.js +42 -21
  260. package/node_modules/@pi-harness/core/dist/plugins/plan-execute.js.map +1 -1
  261. package/node_modules/@pi-harness/core/dist/plugins/plugin-check.d.ts +12 -3
  262. package/node_modules/@pi-harness/core/dist/plugins/plugin-check.d.ts.map +1 -1
  263. package/node_modules/@pi-harness/core/dist/plugins/plugin-check.js +83 -12
  264. package/node_modules/@pi-harness/core/dist/plugins/plugin-check.js.map +1 -1
  265. package/node_modules/@pi-harness/core/dist/plugins/plugin-dev.d.ts +1 -0
  266. package/node_modules/@pi-harness/core/dist/plugins/plugin-dev.d.ts.map +1 -1
  267. package/node_modules/@pi-harness/core/dist/plugins/plugin-dev.js +156 -23
  268. package/node_modules/@pi-harness/core/dist/plugins/plugin-dev.js.map +1 -1
  269. package/node_modules/@pi-harness/core/dist/plugins/plugin-finder.d.ts +1 -0
  270. package/node_modules/@pi-harness/core/dist/plugins/plugin-finder.d.ts.map +1 -1
  271. package/node_modules/@pi-harness/core/dist/plugins/plugin-finder.js +131 -13
  272. package/node_modules/@pi-harness/core/dist/plugins/plugin-finder.js.map +1 -1
  273. package/node_modules/@pi-harness/core/dist/plugins/plugin-radar.d.ts +4 -0
  274. package/node_modules/@pi-harness/core/dist/plugins/plugin-radar.d.ts.map +1 -1
  275. package/node_modules/@pi-harness/core/dist/plugins/plugin-radar.js +137 -36
  276. package/node_modules/@pi-harness/core/dist/plugins/plugin-radar.js.map +1 -1
  277. package/node_modules/@pi-harness/core/dist/plugins/plugin-stars.d.ts.map +1 -1
  278. package/node_modules/@pi-harness/core/dist/plugins/plugin-stars.js +282 -81
  279. package/node_modules/@pi-harness/core/dist/plugins/plugin-stars.js.map +1 -1
  280. package/node_modules/@pi-harness/core/dist/plugins/prompt-guard.d.ts +1 -0
  281. package/node_modules/@pi-harness/core/dist/plugins/prompt-guard.d.ts.map +1 -1
  282. package/node_modules/@pi-harness/core/dist/plugins/prompt-guard.js +60 -9
  283. package/node_modules/@pi-harness/core/dist/plugins/prompt-guard.js.map +1 -1
  284. package/node_modules/@pi-harness/core/dist/plugins/prompt-library.d.ts +1 -0
  285. package/node_modules/@pi-harness/core/dist/plugins/prompt-library.d.ts.map +1 -1
  286. package/node_modules/@pi-harness/core/dist/plugins/prompt-library.js +4 -1
  287. package/node_modules/@pi-harness/core/dist/plugins/prompt-library.js.map +1 -1
  288. package/node_modules/@pi-harness/core/dist/plugins/readme-gen.d.ts +6 -2
  289. package/node_modules/@pi-harness/core/dist/plugins/readme-gen.d.ts.map +1 -1
  290. package/node_modules/@pi-harness/core/dist/plugins/readme-gen.js +514 -73
  291. package/node_modules/@pi-harness/core/dist/plugins/readme-gen.js.map +1 -1
  292. package/node_modules/@pi-harness/core/dist/plugins/recall-unread.d.ts +1 -1
  293. package/node_modules/@pi-harness/core/dist/plugins/recall-unread.d.ts.map +1 -1
  294. package/node_modules/@pi-harness/core/dist/plugins/recall-unread.js +411 -68
  295. package/node_modules/@pi-harness/core/dist/plugins/recall-unread.js.map +1 -1
  296. package/node_modules/@pi-harness/core/dist/plugins/resources.d.ts.map +1 -1
  297. package/node_modules/@pi-harness/core/dist/plugins/resources.js +66 -3
  298. package/node_modules/@pi-harness/core/dist/plugins/resources.js.map +1 -1
  299. package/node_modules/@pi-harness/core/dist/plugins/reverse-skill.d.ts.map +1 -1
  300. package/node_modules/@pi-harness/core/dist/plugins/reverse-skill.js +2 -1
  301. package/node_modules/@pi-harness/core/dist/plugins/reverse-skill.js.map +1 -1
  302. package/node_modules/@pi-harness/core/dist/plugins/reviewer-bot.d.ts +1 -0
  303. package/node_modules/@pi-harness/core/dist/plugins/reviewer-bot.d.ts.map +1 -1
  304. package/node_modules/@pi-harness/core/dist/plugins/reviewer-bot.js +35 -16
  305. package/node_modules/@pi-harness/core/dist/plugins/reviewer-bot.js.map +1 -1
  306. package/node_modules/@pi-harness/core/dist/plugins/runtime-doctor.d.ts +1 -0
  307. package/node_modules/@pi-harness/core/dist/plugins/runtime-doctor.d.ts.map +1 -1
  308. package/node_modules/@pi-harness/core/dist/plugins/runtime-doctor.js +4 -1
  309. package/node_modules/@pi-harness/core/dist/plugins/runtime-doctor.js.map +1 -1
  310. package/node_modules/@pi-harness/core/dist/plugins/runtime.d.ts.map +1 -1
  311. package/node_modules/@pi-harness/core/dist/plugins/runtime.js +104 -70
  312. package/node_modules/@pi-harness/core/dist/plugins/runtime.js.map +1 -1
  313. package/node_modules/@pi-harness/core/dist/plugins/secure-audit.d.ts +1 -0
  314. package/node_modules/@pi-harness/core/dist/plugins/secure-audit.d.ts.map +1 -1
  315. package/node_modules/@pi-harness/core/dist/plugins/secure-audit.js +30 -12
  316. package/node_modules/@pi-harness/core/dist/plugins/secure-audit.js.map +1 -1
  317. package/node_modules/@pi-harness/core/dist/plugins/session-bookmarks.d.ts +1 -0
  318. package/node_modules/@pi-harness/core/dist/plugins/session-bookmarks.d.ts.map +1 -1
  319. package/node_modules/@pi-harness/core/dist/plugins/session-bookmarks.js +4 -1
  320. package/node_modules/@pi-harness/core/dist/plugins/session-bookmarks.js.map +1 -1
  321. package/node_modules/@pi-harness/core/dist/plugins/session-bridge.d.ts +1 -0
  322. package/node_modules/@pi-harness/core/dist/plugins/session-bridge.d.ts.map +1 -1
  323. package/node_modules/@pi-harness/core/dist/plugins/session-bridge.js +401 -88
  324. package/node_modules/@pi-harness/core/dist/plugins/session-bridge.js.map +1 -1
  325. package/node_modules/@pi-harness/core/dist/plugins/session-compare.d.ts +1 -0
  326. package/node_modules/@pi-harness/core/dist/plugins/session-compare.d.ts.map +1 -1
  327. package/node_modules/@pi-harness/core/dist/plugins/session-compare.js +4 -1
  328. package/node_modules/@pi-harness/core/dist/plugins/session-compare.js.map +1 -1
  329. package/node_modules/@pi-harness/core/dist/plugins/session-export.d.ts +1 -0
  330. package/node_modules/@pi-harness/core/dist/plugins/session-export.d.ts.map +1 -1
  331. package/node_modules/@pi-harness/core/dist/plugins/session-export.js +6 -6
  332. package/node_modules/@pi-harness/core/dist/plugins/session-export.js.map +1 -1
  333. package/node_modules/@pi-harness/core/dist/plugins/session-insights.d.ts +37 -1
  334. package/node_modules/@pi-harness/core/dist/plugins/session-insights.d.ts.map +1 -1
  335. package/node_modules/@pi-harness/core/dist/plugins/session-insights.js +406 -21
  336. package/node_modules/@pi-harness/core/dist/plugins/session-insights.js.map +1 -1
  337. package/node_modules/@pi-harness/core/dist/plugins/session-search.d.ts +1 -0
  338. package/node_modules/@pi-harness/core/dist/plugins/session-search.d.ts.map +1 -1
  339. package/node_modules/@pi-harness/core/dist/plugins/session-search.js +4 -1
  340. package/node_modules/@pi-harness/core/dist/plugins/session-search.js.map +1 -1
  341. package/node_modules/@pi-harness/core/dist/plugins/session.d.ts.map +1 -1
  342. package/node_modules/@pi-harness/core/dist/plugins/session.js +8 -1
  343. package/node_modules/@pi-harness/core/dist/plugins/session.js.map +1 -1
  344. package/node_modules/@pi-harness/core/dist/plugins/skill-catalog.d.ts +1 -0
  345. package/node_modules/@pi-harness/core/dist/plugins/skill-catalog.d.ts.map +1 -1
  346. package/node_modules/@pi-harness/core/dist/plugins/skill-catalog.js +6 -5
  347. package/node_modules/@pi-harness/core/dist/plugins/skill-catalog.js.map +1 -1
  348. package/node_modules/@pi-harness/core/dist/plugins/skill-guard.d.ts +2 -1
  349. package/node_modules/@pi-harness/core/dist/plugins/skill-guard.d.ts.map +1 -1
  350. package/node_modules/@pi-harness/core/dist/plugins/skill-guard.js +241 -61
  351. package/node_modules/@pi-harness/core/dist/plugins/skill-guard.js.map +1 -1
  352. package/node_modules/@pi-harness/core/dist/plugins/sql-lens-worker.d.ts +2 -0
  353. package/node_modules/@pi-harness/core/dist/plugins/sql-lens-worker.d.ts.map +1 -0
  354. package/node_modules/@pi-harness/core/dist/plugins/sql-lens-worker.js +206 -0
  355. package/node_modules/@pi-harness/core/dist/plugins/sql-lens-worker.js.map +1 -0
  356. package/node_modules/@pi-harness/core/dist/plugins/sql-lens.d.ts +7 -1
  357. package/node_modules/@pi-harness/core/dist/plugins/sql-lens.d.ts.map +1 -1
  358. package/node_modules/@pi-harness/core/dist/plugins/sql-lens.js +301 -68
  359. package/node_modules/@pi-harness/core/dist/plugins/sql-lens.js.map +1 -1
  360. package/node_modules/@pi-harness/core/dist/plugins/stdio.d.ts +3 -0
  361. package/node_modules/@pi-harness/core/dist/plugins/stdio.d.ts.map +1 -1
  362. package/node_modules/@pi-harness/core/dist/plugins/stdio.js +62 -4
  363. package/node_modules/@pi-harness/core/dist/plugins/stdio.js.map +1 -1
  364. package/node_modules/@pi-harness/core/dist/plugins/synapse.d.ts.map +1 -1
  365. package/node_modules/@pi-harness/core/dist/plugins/synapse.js +17 -9
  366. package/node_modules/@pi-harness/core/dist/plugins/synapse.js.map +1 -1
  367. package/node_modules/@pi-harness/core/dist/plugins/tab-manager.d.ts +1 -0
  368. package/node_modules/@pi-harness/core/dist/plugins/tab-manager.d.ts.map +1 -1
  369. package/node_modules/@pi-harness/core/dist/plugins/tab-manager.js +167 -62
  370. package/node_modules/@pi-harness/core/dist/plugins/tab-manager.js.map +1 -1
  371. package/node_modules/@pi-harness/core/dist/plugins/taskboard.d.ts.map +1 -1
  372. package/node_modules/@pi-harness/core/dist/plugins/taskboard.js +50 -22
  373. package/node_modules/@pi-harness/core/dist/plugins/taskboard.js.map +1 -1
  374. package/node_modules/@pi-harness/core/dist/plugins/telemetry-blocker.d.ts +4 -1
  375. package/node_modules/@pi-harness/core/dist/plugins/telemetry-blocker.d.ts.map +1 -1
  376. package/node_modules/@pi-harness/core/dist/plugins/telemetry-blocker.js +30 -11
  377. package/node_modules/@pi-harness/core/dist/plugins/telemetry-blocker.js.map +1 -1
  378. package/node_modules/@pi-harness/core/dist/plugins/test-harness.d.ts +7 -1
  379. package/node_modules/@pi-harness/core/dist/plugins/test-harness.d.ts.map +1 -1
  380. package/node_modules/@pi-harness/core/dist/plugins/test-harness.js +255 -43
  381. package/node_modules/@pi-harness/core/dist/plugins/test-harness.js.map +1 -1
  382. package/node_modules/@pi-harness/core/dist/plugins/theme-studio.d.ts.map +1 -1
  383. package/node_modules/@pi-harness/core/dist/plugins/theme-studio.js +4 -2
  384. package/node_modules/@pi-harness/core/dist/plugins/theme-studio.js.map +1 -1
  385. package/node_modules/@pi-harness/core/dist/plugins/token-guard.d.ts.map +1 -1
  386. package/node_modules/@pi-harness/core/dist/plugins/token-guard.js +164 -32
  387. package/node_modules/@pi-harness/core/dist/plugins/token-guard.js.map +1 -1
  388. package/node_modules/@pi-harness/core/dist/plugins/tools.d.ts.map +1 -1
  389. package/node_modules/@pi-harness/core/dist/plugins/tools.js +4 -1
  390. package/node_modules/@pi-harness/core/dist/plugins/tools.js.map +1 -1
  391. package/node_modules/@pi-harness/core/dist/plugins/turn-rewind.d.ts +17 -0
  392. package/node_modules/@pi-harness/core/dist/plugins/turn-rewind.d.ts.map +1 -1
  393. package/node_modules/@pi-harness/core/dist/plugins/turn-rewind.js +340 -36
  394. package/node_modules/@pi-harness/core/dist/plugins/turn-rewind.js.map +1 -1
  395. package/node_modules/@pi-harness/core/dist/plugins/undo-savepoint.d.ts.map +1 -1
  396. package/node_modules/@pi-harness/core/dist/plugins/undo-savepoint.js +157 -51
  397. package/node_modules/@pi-harness/core/dist/plugins/undo-savepoint.js.map +1 -1
  398. package/node_modules/@pi-harness/core/dist/plugins/vision-toolkit.d.ts +22 -3
  399. package/node_modules/@pi-harness/core/dist/plugins/vision-toolkit.d.ts.map +1 -1
  400. package/node_modules/@pi-harness/core/dist/plugins/vision-toolkit.js +389 -66
  401. package/node_modules/@pi-harness/core/dist/plugins/vision-toolkit.js.map +1 -1
  402. package/node_modules/@pi-harness/core/dist/plugins/web-research.d.ts.map +1 -1
  403. package/node_modules/@pi-harness/core/dist/plugins/web-research.js +13 -4
  404. package/node_modules/@pi-harness/core/dist/plugins/web-research.js.map +1 -1
  405. package/node_modules/@pi-harness/core/dist/plugins/workspace-navigator.d.ts +8 -2
  406. package/node_modules/@pi-harness/core/dist/plugins/workspace-navigator.d.ts.map +1 -1
  407. package/node_modules/@pi-harness/core/dist/plugins/workspace-navigator.js +28 -10
  408. package/node_modules/@pi-harness/core/dist/plugins/workspace-navigator.js.map +1 -1
  409. package/node_modules/@pi-harness/core/dist/plugins/workspace-search.d.ts +7 -0
  410. package/node_modules/@pi-harness/core/dist/plugins/workspace-search.d.ts.map +1 -1
  411. package/node_modules/@pi-harness/core/dist/plugins/workspace-search.js +67 -34
  412. package/node_modules/@pi-harness/core/dist/plugins/workspace-search.js.map +1 -1
  413. package/node_modules/@pi-harness/core/dist/plugins/yaml-validator.d.ts +1 -0
  414. package/node_modules/@pi-harness/core/dist/plugins/yaml-validator.d.ts.map +1 -1
  415. package/node_modules/@pi-harness/core/dist/plugins/yaml-validator.js +156 -47
  416. package/node_modules/@pi-harness/core/dist/plugins/yaml-validator.js.map +1 -1
  417. package/node_modules/@pi-harness/core/dist/runtime.d.ts.map +1 -1
  418. package/node_modules/@pi-harness/core/dist/runtime.js +8 -3
  419. package/node_modules/@pi-harness/core/dist/runtime.js.map +1 -1
  420. package/node_modules/@pi-harness/core/dist/services.d.ts.map +1 -1
  421. package/node_modules/@pi-harness/core/dist/services.js +22 -2
  422. package/node_modules/@pi-harness/core/dist/services.js.map +1 -1
  423. package/node_modules/@pi-harness/core/dist/stdio.d.ts +1 -0
  424. package/node_modules/@pi-harness/core/dist/stdio.d.ts.map +1 -1
  425. package/node_modules/@pi-harness/core/dist/stdio.js +241 -25
  426. package/node_modules/@pi-harness/core/dist/stdio.js.map +1 -1
  427. package/node_modules/@pi-harness/core/dist/workspace-path.d.ts +1 -0
  428. package/node_modules/@pi-harness/core/dist/workspace-path.d.ts.map +1 -1
  429. package/node_modules/@pi-harness/core/dist/workspace-path.js +9 -0
  430. package/node_modules/@pi-harness/core/dist/workspace-path.js.map +1 -1
  431. package/node_modules/@pi-harness/core/package.json +1 -1
  432. package/node_modules/@pi-harness/core/profiles/default/cordis.yml +4 -2
  433. package/node_modules/@pi-harness/host-webserver/package.json +1 -1
  434. package/node_modules/@pi-harness/web-app/package.json +1 -1
  435. package/package.json +12 -7
  436. package/packages/api-gateway/dist/index.d.ts.map +1 -1
  437. package/packages/api-gateway/dist/index.js +97 -9
  438. package/packages/api-gateway/dist/index.js.map +1 -1
  439. package/packages/api-gateway/dist/marketplace-entries/official/agent-teams.json +6 -6
  440. package/packages/api-gateway/dist/marketplace-entries/official/anchored-standard.json +1 -1
  441. package/packages/api-gateway/dist/marketplace-entries/official/annotation.json +1 -2
  442. package/packages/api-gateway/dist/marketplace-entries/official/archify.json +1 -1
  443. package/packages/api-gateway/dist/marketplace-entries/official/at-file.json +11 -5
  444. package/packages/api-gateway/dist/marketplace-entries/official/auto-mode.json +1 -1
  445. package/packages/api-gateway/dist/marketplace-entries/official/better-sidebar.json +1 -1
  446. package/packages/api-gateway/dist/marketplace-entries/official/browser-fetch.json +12 -5
  447. package/packages/api-gateway/dist/marketplace-entries/official/browser-session.json +14 -8
  448. package/packages/api-gateway/dist/marketplace-entries/official/canvas-draw.json +3 -4
  449. package/packages/api-gateway/dist/marketplace-entries/official/change-verifier.json +1 -1
  450. package/packages/api-gateway/dist/marketplace-entries/official/cleaner.json +11 -6
  451. package/packages/api-gateway/dist/marketplace-entries/official/cli-notifier.json +5 -5
  452. package/packages/api-gateway/dist/marketplace-entries/official/code2skill.json +5 -5
  453. package/packages/api-gateway/dist/marketplace-entries/official/colleague-skill.json +1 -2
  454. package/packages/api-gateway/dist/marketplace-entries/official/context-doctor.json +12 -7
  455. package/packages/api-gateway/dist/marketplace-entries/official/context.json +10 -5
  456. package/packages/api-gateway/dist/marketplace-entries/official/cordis-group.json +2 -2
  457. package/packages/api-gateway/dist/marketplace-entries/official/cordis-logger-console.json +4 -4
  458. package/packages/api-gateway/dist/marketplace-entries/official/cordis-timer.json +3 -3
  459. package/packages/api-gateway/dist/marketplace-entries/official/cost-meter.json +9 -6
  460. package/packages/api-gateway/dist/marketplace-entries/official/dependency-checker.json +13 -10
  461. package/packages/api-gateway/dist/marketplace-entries/official/docker-sandbox.json +10 -5
  462. package/packages/api-gateway/dist/marketplace-entries/official/fail-logger.json +11 -6
  463. package/packages/api-gateway/dist/marketplace-entries/official/genui.json +7 -5
  464. package/packages/api-gateway/dist/marketplace-entries/official/git-time-capsule.json +13 -8
  465. package/packages/api-gateway/dist/marketplace-entries/official/graph-memory.json +13 -7
  466. package/packages/api-gateway/dist/marketplace-entries/official/history-compressor.json +1 -1
  467. package/packages/api-gateway/dist/marketplace-entries/official/hol-guard.json +1 -1
  468. package/packages/api-gateway/dist/marketplace-entries/official/i18n-pair.json +9 -6
  469. package/packages/api-gateway/dist/marketplace-entries/official/image-compressor.json +1 -1
  470. package/packages/api-gateway/dist/marketplace-entries/official/llm-verifier.json +1 -1
  471. package/packages/api-gateway/dist/marketplace-entries/official/mcp-client.json +12 -7
  472. package/packages/api-gateway/dist/marketplace-entries/official/mcp-panel.json +1 -1
  473. package/packages/api-gateway/dist/marketplace-entries/official/memory.json +1 -1
  474. package/packages/api-gateway/dist/marketplace-entries/official/mirage-bridge.json +1 -1
  475. package/packages/api-gateway/dist/marketplace-entries/official/mock-server.json +1 -1
  476. package/packages/api-gateway/dist/marketplace-entries/official/modlens.json +4 -4
  477. package/packages/api-gateway/dist/marketplace-entries/official/module-search.json +1 -1
  478. package/packages/api-gateway/dist/marketplace-entries/official/obsidian-sync.json +1 -1
  479. package/packages/api-gateway/dist/marketplace-entries/official/openpets.json +9 -5
  480. package/packages/api-gateway/dist/marketplace-entries/official/plan-execute.json +1 -1
  481. package/packages/api-gateway/dist/marketplace-entries/official/plugin-check.json +1 -1
  482. package/packages/api-gateway/dist/marketplace-entries/official/plugin-dev.json +8 -6
  483. package/packages/api-gateway/dist/marketplace-entries/official/plugin-finder.json +1 -1
  484. package/packages/api-gateway/dist/marketplace-entries/official/plugin-radar.json +1 -1
  485. package/packages/api-gateway/dist/marketplace-entries/official/plugin-stars.json +15 -7
  486. package/packages/api-gateway/dist/marketplace-entries/official/prompt-guard.json +1 -1
  487. package/packages/api-gateway/dist/marketplace-entries/official/prompt-library.json +1 -1
  488. package/packages/api-gateway/dist/marketplace-entries/official/readme-gen.json +12 -8
  489. package/packages/api-gateway/dist/marketplace-entries/official/recall-unread.json +11 -6
  490. package/packages/api-gateway/dist/marketplace-entries/official/reverse-skill.json +1 -1
  491. package/packages/api-gateway/dist/marketplace-entries/official/reviewer-bot.json +1 -1
  492. package/packages/api-gateway/dist/marketplace-entries/official/runtime-doctor.json +1 -1
  493. package/packages/api-gateway/dist/marketplace-entries/official/secure-audit.json +1 -1
  494. package/packages/api-gateway/dist/marketplace-entries/official/session-bookmarks.json +1 -1
  495. package/packages/api-gateway/dist/marketplace-entries/official/session-bridge.json +13 -8
  496. package/packages/api-gateway/dist/marketplace-entries/official/session-compare.json +1 -1
  497. package/packages/api-gateway/dist/marketplace-entries/official/session-export.json +1 -1
  498. package/packages/api-gateway/dist/marketplace-entries/official/session-insights.json +12 -6
  499. package/packages/api-gateway/dist/marketplace-entries/official/session-search.json +1 -1
  500. package/packages/api-gateway/dist/marketplace-entries/official/skill-catalog.json +1 -1
  501. package/packages/api-gateway/dist/marketplace-entries/official/skill-guard.json +9 -5
  502. package/packages/api-gateway/dist/marketplace-entries/official/sql-lens.json +13 -7
  503. package/packages/api-gateway/dist/marketplace-entries/official/synapse.json +1 -1
  504. package/packages/api-gateway/dist/marketplace-entries/official/tab-manager.json +1 -1
  505. package/packages/api-gateway/dist/marketplace-entries/official/taskboard.json +1 -1
  506. package/packages/api-gateway/dist/marketplace-entries/official/telemetry-blocker.json +1 -1
  507. package/packages/api-gateway/dist/marketplace-entries/official/test-harness.json +14 -7
  508. package/packages/api-gateway/dist/marketplace-entries/official/theme-studio.json +1 -1
  509. package/packages/api-gateway/dist/marketplace-entries/official/token-guard.json +12 -6
  510. package/packages/api-gateway/dist/marketplace-entries/official/turn-rewind.json +11 -6
  511. package/packages/api-gateway/dist/marketplace-entries/official/undo-savepoint.json +1 -1
  512. package/packages/api-gateway/dist/marketplace-entries/official/vision-toolkit.json +8 -5
  513. package/packages/api-gateway/dist/marketplace-entries/official/web-research.json +1 -1
  514. package/packages/api-gateway/dist/marketplace-entries/official/workspace-navigator.json +1 -1
  515. package/packages/api-gateway/dist/marketplace-entries/official/workspace-search.json +1 -1
  516. package/packages/api-gateway/dist/marketplace-entries/official/yaml-validator.json +8 -5
  517. package/packages/api-gateway/package.json +1 -1
  518. package/packages/api-gateway/src/index.ts +90 -9
  519. package/packages/api-gateway/src/marketplace-entries/official/agent-teams.json +6 -6
  520. package/packages/api-gateway/src/marketplace-entries/official/anchored-standard.json +1 -1
  521. package/packages/api-gateway/src/marketplace-entries/official/annotation.json +1 -2
  522. package/packages/api-gateway/src/marketplace-entries/official/archify.json +1 -1
  523. package/packages/api-gateway/src/marketplace-entries/official/at-file.json +11 -5
  524. package/packages/api-gateway/src/marketplace-entries/official/auto-mode.json +1 -1
  525. package/packages/api-gateway/src/marketplace-entries/official/better-sidebar.json +1 -1
  526. package/packages/api-gateway/src/marketplace-entries/official/browser-fetch.json +12 -5
  527. package/packages/api-gateway/src/marketplace-entries/official/browser-session.json +14 -8
  528. package/packages/api-gateway/src/marketplace-entries/official/canvas-draw.json +3 -4
  529. package/packages/api-gateway/src/marketplace-entries/official/change-verifier.json +1 -1
  530. package/packages/api-gateway/src/marketplace-entries/official/cleaner.json +11 -6
  531. package/packages/api-gateway/src/marketplace-entries/official/cli-notifier.json +5 -5
  532. package/packages/api-gateway/src/marketplace-entries/official/code2skill.json +5 -5
  533. package/packages/api-gateway/src/marketplace-entries/official/colleague-skill.json +1 -2
  534. package/packages/api-gateway/src/marketplace-entries/official/context-doctor.json +12 -7
  535. package/packages/api-gateway/src/marketplace-entries/official/context.json +10 -5
  536. package/packages/api-gateway/src/marketplace-entries/official/cordis-group.json +2 -2
  537. package/packages/api-gateway/src/marketplace-entries/official/cordis-logger-console.json +4 -4
  538. package/packages/api-gateway/src/marketplace-entries/official/cordis-timer.json +3 -3
  539. package/packages/api-gateway/src/marketplace-entries/official/cost-meter.json +9 -6
  540. package/packages/api-gateway/src/marketplace-entries/official/dependency-checker.json +13 -10
  541. package/packages/api-gateway/src/marketplace-entries/official/docker-sandbox.json +10 -5
  542. package/packages/api-gateway/src/marketplace-entries/official/fail-logger.json +11 -6
  543. package/packages/api-gateway/src/marketplace-entries/official/genui.json +7 -5
  544. package/packages/api-gateway/src/marketplace-entries/official/git-time-capsule.json +13 -8
  545. package/packages/api-gateway/src/marketplace-entries/official/graph-memory.json +13 -7
  546. package/packages/api-gateway/src/marketplace-entries/official/history-compressor.json +1 -1
  547. package/packages/api-gateway/src/marketplace-entries/official/hol-guard.json +1 -1
  548. package/packages/api-gateway/src/marketplace-entries/official/i18n-pair.json +9 -6
  549. package/packages/api-gateway/src/marketplace-entries/official/image-compressor.json +1 -1
  550. package/packages/api-gateway/src/marketplace-entries/official/llm-verifier.json +1 -1
  551. package/packages/api-gateway/src/marketplace-entries/official/mcp-client.json +12 -7
  552. package/packages/api-gateway/src/marketplace-entries/official/mcp-panel.json +1 -1
  553. package/packages/api-gateway/src/marketplace-entries/official/memory.json +1 -1
  554. package/packages/api-gateway/src/marketplace-entries/official/mirage-bridge.json +1 -1
  555. package/packages/api-gateway/src/marketplace-entries/official/mock-server.json +1 -1
  556. package/packages/api-gateway/src/marketplace-entries/official/modlens.json +4 -4
  557. package/packages/api-gateway/src/marketplace-entries/official/module-search.json +1 -1
  558. package/packages/api-gateway/src/marketplace-entries/official/obsidian-sync.json +1 -1
  559. package/packages/api-gateway/src/marketplace-entries/official/openpets.json +9 -5
  560. package/packages/api-gateway/src/marketplace-entries/official/plan-execute.json +1 -1
  561. package/packages/api-gateway/src/marketplace-entries/official/plugin-check.json +1 -1
  562. package/packages/api-gateway/src/marketplace-entries/official/plugin-dev.json +8 -6
  563. package/packages/api-gateway/src/marketplace-entries/official/plugin-finder.json +1 -1
  564. package/packages/api-gateway/src/marketplace-entries/official/plugin-radar.json +1 -1
  565. package/packages/api-gateway/src/marketplace-entries/official/plugin-stars.json +15 -7
  566. package/packages/api-gateway/src/marketplace-entries/official/prompt-guard.json +1 -1
  567. package/packages/api-gateway/src/marketplace-entries/official/prompt-library.json +1 -1
  568. package/packages/api-gateway/src/marketplace-entries/official/readme-gen.json +12 -8
  569. package/packages/api-gateway/src/marketplace-entries/official/recall-unread.json +11 -6
  570. package/packages/api-gateway/src/marketplace-entries/official/reverse-skill.json +1 -1
  571. package/packages/api-gateway/src/marketplace-entries/official/reviewer-bot.json +1 -1
  572. package/packages/api-gateway/src/marketplace-entries/official/runtime-doctor.json +1 -1
  573. package/packages/api-gateway/src/marketplace-entries/official/secure-audit.json +1 -1
  574. package/packages/api-gateway/src/marketplace-entries/official/session-bookmarks.json +1 -1
  575. package/packages/api-gateway/src/marketplace-entries/official/session-bridge.json +13 -8
  576. package/packages/api-gateway/src/marketplace-entries/official/session-compare.json +1 -1
  577. package/packages/api-gateway/src/marketplace-entries/official/session-export.json +1 -1
  578. package/packages/api-gateway/src/marketplace-entries/official/session-insights.json +12 -6
  579. package/packages/api-gateway/src/marketplace-entries/official/session-search.json +1 -1
  580. package/packages/api-gateway/src/marketplace-entries/official/skill-catalog.json +1 -1
  581. package/packages/api-gateway/src/marketplace-entries/official/skill-guard.json +9 -5
  582. package/packages/api-gateway/src/marketplace-entries/official/sql-lens.json +13 -7
  583. package/packages/api-gateway/src/marketplace-entries/official/synapse.json +1 -1
  584. package/packages/api-gateway/src/marketplace-entries/official/tab-manager.json +1 -1
  585. package/packages/api-gateway/src/marketplace-entries/official/taskboard.json +1 -1
  586. package/packages/api-gateway/src/marketplace-entries/official/telemetry-blocker.json +1 -1
  587. package/packages/api-gateway/src/marketplace-entries/official/test-harness.json +14 -7
  588. package/packages/api-gateway/src/marketplace-entries/official/theme-studio.json +1 -1
  589. package/packages/api-gateway/src/marketplace-entries/official/token-guard.json +12 -6
  590. package/packages/api-gateway/src/marketplace-entries/official/turn-rewind.json +11 -6
  591. package/packages/api-gateway/src/marketplace-entries/official/undo-savepoint.json +1 -1
  592. package/packages/api-gateway/src/marketplace-entries/official/vision-toolkit.json +8 -5
  593. package/packages/api-gateway/src/marketplace-entries/official/web-research.json +1 -1
  594. package/packages/api-gateway/src/marketplace-entries/official/workspace-navigator.json +1 -1
  595. package/packages/api-gateway/src/marketplace-entries/official/workspace-search.json +1 -1
  596. package/packages/api-gateway/src/marketplace-entries/official/yaml-validator.json +8 -5
  597. package/packages/api-gateway/test/index.test.ts +1594 -2
  598. package/packages/api-gateway/test/marketplace.test.ts +389 -2
  599. package/packages/api-gateway/test/release-package.test.ts +1 -0
  600. package/packages/bundle-web-app/package.json +1 -1
  601. package/packages/cli/dist/node-stdio.d.ts.map +1 -1
  602. package/packages/cli/dist/node-stdio.js +83 -20
  603. package/packages/cli/dist/node-stdio.js.map +1 -1
  604. package/packages/cli/package.json +1 -1
  605. package/packages/cli/src/node-stdio.ts +77 -20
  606. package/packages/cli/test/node-stdio.test.ts +118 -2
  607. package/packages/client-web/dist/agent-teams-view.d.ts +70 -0
  608. package/packages/client-web/dist/agent-teams-view.d.ts.map +1 -0
  609. package/packages/client-web/dist/agent-teams-view.js +159 -0
  610. package/packages/client-web/dist/agent-teams-view.js.map +1 -0
  611. package/packages/client-web/dist/at-file-view.d.ts +10 -0
  612. package/packages/client-web/dist/at-file-view.d.ts.map +1 -0
  613. package/packages/client-web/dist/at-file-view.js +65 -0
  614. package/packages/client-web/dist/at-file-view.js.map +1 -0
  615. package/packages/client-web/dist/browser-fetch-view.d.ts +22 -0
  616. package/packages/client-web/dist/browser-fetch-view.d.ts.map +1 -0
  617. package/packages/client-web/dist/browser-fetch-view.js +101 -0
  618. package/packages/client-web/dist/browser-fetch-view.js.map +1 -0
  619. package/packages/client-web/dist/browser-session-view.d.ts +32 -0
  620. package/packages/client-web/dist/browser-session-view.d.ts.map +1 -1
  621. package/packages/client-web/dist/browser-session-view.js +206 -3
  622. package/packages/client-web/dist/browser-session-view.js.map +1 -1
  623. package/packages/client-web/dist/cleaner-view.d.ts +29 -0
  624. package/packages/client-web/dist/cleaner-view.d.ts.map +1 -0
  625. package/packages/client-web/dist/cleaner-view.js +191 -0
  626. package/packages/client-web/dist/cleaner-view.js.map +1 -0
  627. package/packages/client-web/dist/context-doctor-view.d.ts +35 -0
  628. package/packages/client-web/dist/context-doctor-view.d.ts.map +1 -0
  629. package/packages/client-web/dist/context-doctor-view.js +129 -0
  630. package/packages/client-web/dist/context-doctor-view.js.map +1 -0
  631. package/packages/client-web/dist/context-insights-view.d.ts +31 -0
  632. package/packages/client-web/dist/context-insights-view.d.ts.map +1 -0
  633. package/packages/client-web/dist/context-insights-view.js +90 -0
  634. package/packages/client-web/dist/context-insights-view.js.map +1 -0
  635. package/packages/client-web/dist/cost-meter-view.d.ts +16 -0
  636. package/packages/client-web/dist/cost-meter-view.d.ts.map +1 -0
  637. package/packages/client-web/dist/cost-meter-view.js +43 -0
  638. package/packages/client-web/dist/cost-meter-view.js.map +1 -0
  639. package/packages/client-web/dist/dependency-checker-view.d.ts +24 -0
  640. package/packages/client-web/dist/dependency-checker-view.d.ts.map +1 -0
  641. package/packages/client-web/dist/dependency-checker-view.js +195 -0
  642. package/packages/client-web/dist/dependency-checker-view.js.map +1 -0
  643. package/packages/client-web/dist/docker-sandbox-view.d.ts +28 -0
  644. package/packages/client-web/dist/docker-sandbox-view.d.ts.map +1 -0
  645. package/packages/client-web/dist/docker-sandbox-view.js +152 -0
  646. package/packages/client-web/dist/docker-sandbox-view.js.map +1 -0
  647. package/packages/client-web/dist/fail-logger-view.d.ts +16 -0
  648. package/packages/client-web/dist/fail-logger-view.d.ts.map +1 -0
  649. package/packages/client-web/dist/fail-logger-view.js +97 -0
  650. package/packages/client-web/dist/fail-logger-view.js.map +1 -0
  651. package/packages/client-web/dist/genui-view.d.ts +28 -0
  652. package/packages/client-web/dist/genui-view.d.ts.map +1 -0
  653. package/packages/client-web/dist/genui-view.js +62 -0
  654. package/packages/client-web/dist/genui-view.js.map +1 -0
  655. package/packages/client-web/dist/git-time-capsule-view.d.ts +31 -0
  656. package/packages/client-web/dist/git-time-capsule-view.d.ts.map +1 -0
  657. package/packages/client-web/dist/git-time-capsule-view.js +203 -0
  658. package/packages/client-web/dist/git-time-capsule-view.js.map +1 -0
  659. package/packages/client-web/dist/graph-memory-view.d.ts +39 -0
  660. package/packages/client-web/dist/graph-memory-view.d.ts.map +1 -0
  661. package/packages/client-web/dist/graph-memory-view.js +82 -0
  662. package/packages/client-web/dist/graph-memory-view.js.map +1 -0
  663. package/packages/client-web/dist/i18n-pair-view.d.ts +32 -0
  664. package/packages/client-web/dist/i18n-pair-view.d.ts.map +1 -0
  665. package/packages/client-web/dist/i18n-pair-view.js +182 -0
  666. package/packages/client-web/dist/i18n-pair-view.js.map +1 -0
  667. package/packages/client-web/dist/mcp-client-view.d.ts +58 -0
  668. package/packages/client-web/dist/mcp-client-view.d.ts.map +1 -0
  669. package/packages/client-web/dist/mcp-client-view.js +121 -0
  670. package/packages/client-web/dist/mcp-client-view.js.map +1 -0
  671. package/packages/client-web/dist/modlens-view.d.ts +43 -0
  672. package/packages/client-web/dist/modlens-view.d.ts.map +1 -0
  673. package/packages/client-web/dist/modlens-view.js +176 -0
  674. package/packages/client-web/dist/modlens-view.js.map +1 -0
  675. package/packages/client-web/dist/openpets-view.d.ts +26 -0
  676. package/packages/client-web/dist/openpets-view.d.ts.map +1 -0
  677. package/packages/client-web/dist/openpets-view.js +62 -0
  678. package/packages/client-web/dist/openpets-view.js.map +1 -0
  679. package/packages/client-web/dist/panel-safe.d.ts +5 -0
  680. package/packages/client-web/dist/panel-safe.d.ts.map +1 -0
  681. package/packages/client-web/dist/panel-safe.js +58 -0
  682. package/packages/client-web/dist/panel-safe.js.map +1 -0
  683. package/packages/client-web/dist/plugin-dev-view.d.ts +15 -0
  684. package/packages/client-web/dist/plugin-dev-view.d.ts.map +1 -0
  685. package/packages/client-web/dist/plugin-dev-view.js +33 -0
  686. package/packages/client-web/dist/plugin-dev-view.js.map +1 -0
  687. package/packages/client-web/dist/plugin-stars-view.d.ts +28 -0
  688. package/packages/client-web/dist/plugin-stars-view.d.ts.map +1 -1
  689. package/packages/client-web/dist/plugin-stars-view.js +209 -1
  690. package/packages/client-web/dist/plugin-stars-view.js.map +1 -1
  691. package/packages/client-web/dist/react-room.d.ts +5 -1
  692. package/packages/client-web/dist/react-room.d.ts.map +1 -1
  693. package/packages/client-web/dist/react-room.js +463 -219
  694. package/packages/client-web/dist/react-room.js.map +1 -1
  695. package/packages/client-web/dist/readme-gen-view.d.ts +30 -0
  696. package/packages/client-web/dist/readme-gen-view.d.ts.map +1 -0
  697. package/packages/client-web/dist/readme-gen-view.js +134 -0
  698. package/packages/client-web/dist/readme-gen-view.js.map +1 -0
  699. package/packages/client-web/dist/recall-unread-view.d.ts +46 -0
  700. package/packages/client-web/dist/recall-unread-view.d.ts.map +1 -0
  701. package/packages/client-web/dist/recall-unread-view.js +104 -0
  702. package/packages/client-web/dist/recall-unread-view.js.map +1 -0
  703. package/packages/client-web/dist/session-bridge-view.d.ts +50 -0
  704. package/packages/client-web/dist/session-bridge-view.d.ts.map +1 -0
  705. package/packages/client-web/dist/session-bridge-view.js +113 -0
  706. package/packages/client-web/dist/session-bridge-view.js.map +1 -0
  707. package/packages/client-web/dist/session-insights-view.d.ts +40 -0
  708. package/packages/client-web/dist/session-insights-view.d.ts.map +1 -0
  709. package/packages/client-web/dist/session-insights-view.js +157 -0
  710. package/packages/client-web/dist/session-insights-view.js.map +1 -0
  711. package/packages/client-web/dist/skill-guard-view.d.ts +47 -0
  712. package/packages/client-web/dist/skill-guard-view.d.ts.map +1 -0
  713. package/packages/client-web/dist/skill-guard-view.js +93 -0
  714. package/packages/client-web/dist/skill-guard-view.js.map +1 -0
  715. package/packages/client-web/dist/sql-lens-view.d.ts +37 -0
  716. package/packages/client-web/dist/sql-lens-view.d.ts.map +1 -0
  717. package/packages/client-web/dist/sql-lens-view.js +235 -0
  718. package/packages/client-web/dist/sql-lens-view.js.map +1 -0
  719. package/packages/client-web/dist/test-harness-view.d.ts +24 -0
  720. package/packages/client-web/dist/test-harness-view.d.ts.map +1 -0
  721. package/packages/client-web/dist/test-harness-view.js +149 -0
  722. package/packages/client-web/dist/test-harness-view.js.map +1 -0
  723. package/packages/client-web/dist/token-guard-view.d.ts +19 -0
  724. package/packages/client-web/dist/token-guard-view.d.ts.map +1 -0
  725. package/packages/client-web/dist/token-guard-view.js +56 -0
  726. package/packages/client-web/dist/token-guard-view.js.map +1 -0
  727. package/packages/client-web/dist/turn-rewind-view.d.ts +41 -0
  728. package/packages/client-web/dist/turn-rewind-view.d.ts.map +1 -0
  729. package/packages/client-web/dist/turn-rewind-view.js +117 -0
  730. package/packages/client-web/dist/turn-rewind-view.js.map +1 -0
  731. package/packages/client-web/dist/vision-toolkit-view.d.ts +66 -0
  732. package/packages/client-web/dist/vision-toolkit-view.d.ts.map +1 -0
  733. package/packages/client-web/dist/vision-toolkit-view.js +238 -0
  734. package/packages/client-web/dist/vision-toolkit-view.js.map +1 -0
  735. package/packages/client-web/dist/yaml-validator-view.d.ts +52 -0
  736. package/packages/client-web/dist/yaml-validator-view.d.ts.map +1 -0
  737. package/packages/client-web/dist/yaml-validator-view.js +96 -0
  738. package/packages/client-web/dist/yaml-validator-view.js.map +1 -0
  739. package/packages/client-web/package.json +1 -1
  740. package/packages/client-web/src/agent-teams-view.ts +189 -0
  741. package/packages/client-web/src/at-file-view.ts +69 -0
  742. package/packages/client-web/src/browser-fetch-view.ts +114 -0
  743. package/packages/client-web/src/browser-session-view.ts +222 -3
  744. package/packages/client-web/src/cleaner-view.ts +207 -0
  745. package/packages/client-web/src/context-doctor-view.ts +140 -0
  746. package/packages/client-web/src/context-insights-view.ts +125 -0
  747. package/packages/client-web/src/cost-meter-view.ts +63 -0
  748. package/packages/client-web/src/dependency-checker-view.ts +215 -0
  749. package/packages/client-web/src/docker-sandbox-view.ts +177 -0
  750. package/packages/client-web/src/fail-logger-view.ts +112 -0
  751. package/packages/client-web/src/genui-view.ts +88 -0
  752. package/packages/client-web/src/git-time-capsule-view.ts +215 -0
  753. package/packages/client-web/src/graph-memory-view.ts +91 -0
  754. package/packages/client-web/src/i18n-pair-view.ts +194 -0
  755. package/packages/client-web/src/mcp-client-view.ts +122 -0
  756. package/packages/client-web/src/modlens-view.ts +210 -0
  757. package/packages/client-web/src/openpets-view.ts +67 -0
  758. package/packages/client-web/src/panel-safe.ts +47 -0
  759. package/packages/client-web/src/plugin-dev-view.ts +39 -0
  760. package/packages/client-web/src/plugin-stars-view.ts +239 -1
  761. package/packages/client-web/src/react-room.tsx +1770 -900
  762. package/packages/client-web/src/readme-gen-view.ts +145 -0
  763. package/packages/client-web/src/recall-unread-view.ts +105 -0
  764. package/packages/client-web/src/session-bridge-view.ts +118 -0
  765. package/packages/client-web/src/session-insights-view.ts +205 -0
  766. package/packages/client-web/src/skill-guard-view.ts +94 -0
  767. package/packages/client-web/src/sql-lens-view.ts +247 -0
  768. package/packages/client-web/src/test-harness-view.ts +170 -0
  769. package/packages/client-web/src/token-guard-view.ts +75 -0
  770. package/packages/client-web/src/turn-rewind-view.ts +120 -0
  771. package/packages/client-web/src/vision-toolkit-view.ts +280 -0
  772. package/packages/client-web/src/yaml-validator-view.ts +102 -0
  773. package/packages/client-web/test/agent-teams-view.test.ts +198 -0
  774. package/packages/client-web/test/at-file-panel.test.ts +76 -0
  775. package/packages/client-web/test/browser-fetch-panel.test.ts +44 -0
  776. package/packages/client-web/test/browser-fetch-view.test.ts +89 -0
  777. package/packages/client-web/test/browser-session-panel.test.ts +55 -0
  778. package/packages/client-web/test/browser-session-view.test.ts +99 -1
  779. package/packages/client-web/test/cleaner-panel.test.ts +66 -0
  780. package/packages/client-web/test/cleaner-view.test.ts +143 -0
  781. package/packages/client-web/test/context-doctor-view.test.ts +169 -0
  782. package/packages/client-web/test/context-insights-view.test.ts +120 -0
  783. package/packages/client-web/test/cost-meter-view.test.ts +53 -0
  784. package/packages/client-web/test/dependency-checker-panel.test.ts +51 -0
  785. package/packages/client-web/test/dependency-checker-view.test.ts +266 -0
  786. package/packages/client-web/test/docker-sandbox-panel.test.ts +44 -0
  787. package/packages/client-web/test/docker-sandbox-view.test.ts +127 -0
  788. package/packages/client-web/test/fail-logger-view.test.ts +155 -0
  789. package/packages/client-web/test/genui-view.test.ts +55 -0
  790. package/packages/client-web/test/git-time-capsule-view.test.ts +252 -0
  791. package/packages/client-web/test/graph-memory-view.test.ts +67 -0
  792. package/packages/client-web/test/i18n-pair-panel.test.ts +72 -0
  793. package/packages/client-web/test/i18n-pair-view.test.ts +164 -0
  794. package/packages/client-web/test/mcp-client-view.test.ts +106 -0
  795. package/packages/client-web/test/modlens-view.test.ts +198 -0
  796. package/packages/client-web/test/openpets-view.test.ts +57 -0
  797. package/packages/client-web/test/plugin-dev-view.test.ts +63 -0
  798. package/packages/client-web/test/plugin-stars-panel.test.ts +44 -0
  799. package/packages/client-web/test/plugin-stars-view.test.ts +88 -1
  800. package/packages/client-web/test/readme-gen-panel.test.ts +81 -0
  801. package/packages/client-web/test/readme-gen-view.test.ts +91 -0
  802. package/packages/client-web/test/recall-unread-view.test.ts +153 -0
  803. package/packages/client-web/test/session-bridge-view.test.ts +102 -0
  804. package/packages/client-web/test/session-insights-panel.test.ts +85 -0
  805. package/packages/client-web/test/session-insights-view.test.ts +152 -0
  806. package/packages/client-web/test/skill-guard-view.test.ts +138 -0
  807. package/packages/client-web/test/sql-lens-panel.test.ts +52 -0
  808. package/packages/client-web/test/sql-lens-view.test.ts +134 -0
  809. package/packages/client-web/test/test-harness-panel.test.ts +228 -0
  810. package/packages/client-web/test/token-guard-view.test.ts +93 -0
  811. package/packages/client-web/test/turn-rewind-view.test.ts +159 -0
  812. package/packages/client-web/test/vision-toolkit-view.test.ts +152 -0
  813. package/packages/client-web/test/yaml-validator-view.test.ts +100 -0
  814. package/packages/core/dist/atomic-write.d.ts +8 -0
  815. package/packages/core/dist/atomic-write.d.ts.map +1 -0
  816. package/packages/core/dist/atomic-write.js +40 -0
  817. package/packages/core/dist/atomic-write.js.map +1 -0
  818. package/packages/core/dist/boot.d.ts.map +1 -1
  819. package/packages/core/dist/boot.js +132 -10
  820. package/packages/core/dist/boot.js.map +1 -1
  821. package/packages/core/dist/bounded-file.d.ts +7 -0
  822. package/packages/core/dist/bounded-file.d.ts.map +1 -0
  823. package/packages/core/dist/bounded-file.js +50 -0
  824. package/packages/core/dist/bounded-file.js.map +1 -0
  825. package/packages/core/dist/config.d.ts +2 -0
  826. package/packages/core/dist/config.d.ts.map +1 -1
  827. package/packages/core/dist/config.js +21 -0
  828. package/packages/core/dist/config.js.map +1 -1
  829. package/packages/core/dist/cordis-timer.d.ts +15 -0
  830. package/packages/core/dist/cordis-timer.d.ts.map +1 -0
  831. package/packages/core/dist/cordis-timer.js +99 -0
  832. package/packages/core/dist/cordis-timer.js.map +1 -0
  833. package/packages/core/dist/plugins/agent-teams.d.ts +5 -1
  834. package/packages/core/dist/plugins/agent-teams.d.ts.map +1 -1
  835. package/packages/core/dist/plugins/agent-teams.js +986 -105
  836. package/packages/core/dist/plugins/agent-teams.js.map +1 -1
  837. package/packages/core/dist/plugins/anchored-standard.d.ts +1 -0
  838. package/packages/core/dist/plugins/anchored-standard.d.ts.map +1 -1
  839. package/packages/core/dist/plugins/anchored-standard.js +39 -11
  840. package/packages/core/dist/plugins/anchored-standard.js.map +1 -1
  841. package/packages/core/dist/plugins/annotation.d.ts +1 -0
  842. package/packages/core/dist/plugins/annotation.d.ts.map +1 -1
  843. package/packages/core/dist/plugins/annotation.js +35 -17
  844. package/packages/core/dist/plugins/annotation.js.map +1 -1
  845. package/packages/core/dist/plugins/archify.d.ts +1 -0
  846. package/packages/core/dist/plugins/archify.d.ts.map +1 -1
  847. package/packages/core/dist/plugins/archify.js +69 -22
  848. package/packages/core/dist/plugins/archify.js.map +1 -1
  849. package/packages/core/dist/plugins/at-file.d.ts +5 -1
  850. package/packages/core/dist/plugins/at-file.d.ts.map +1 -1
  851. package/packages/core/dist/plugins/at-file.js +120 -29
  852. package/packages/core/dist/plugins/at-file.js.map +1 -1
  853. package/packages/core/dist/plugins/auto-mode.d.ts.map +1 -1
  854. package/packages/core/dist/plugins/auto-mode.js +89 -20
  855. package/packages/core/dist/plugins/auto-mode.js.map +1 -1
  856. package/packages/core/dist/plugins/better-sidebar.d.ts +1 -0
  857. package/packages/core/dist/plugins/better-sidebar.d.ts.map +1 -1
  858. package/packages/core/dist/plugins/better-sidebar.js +14 -4
  859. package/packages/core/dist/plugins/better-sidebar.js.map +1 -1
  860. package/packages/core/dist/plugins/browser-fetch.d.ts +1 -0
  861. package/packages/core/dist/plugins/browser-fetch.d.ts.map +1 -1
  862. package/packages/core/dist/plugins/browser-fetch.js +288 -96
  863. package/packages/core/dist/plugins/browser-fetch.js.map +1 -1
  864. package/packages/core/dist/plugins/browser-session.d.ts.map +1 -1
  865. package/packages/core/dist/plugins/browser-session.js +445 -106
  866. package/packages/core/dist/plugins/browser-session.js.map +1 -1
  867. package/packages/core/dist/plugins/canvas-draw.d.ts +1 -0
  868. package/packages/core/dist/plugins/canvas-draw.d.ts.map +1 -1
  869. package/packages/core/dist/plugins/canvas-draw.js +71 -19
  870. package/packages/core/dist/plugins/canvas-draw.js.map +1 -1
  871. package/packages/core/dist/plugins/change-verifier.d.ts +1 -0
  872. package/packages/core/dist/plugins/change-verifier.d.ts.map +1 -1
  873. package/packages/core/dist/plugins/change-verifier.js +30 -9
  874. package/packages/core/dist/plugins/change-verifier.js.map +1 -1
  875. package/packages/core/dist/plugins/cleaner.d.ts +5 -1
  876. package/packages/core/dist/plugins/cleaner.d.ts.map +1 -1
  877. package/packages/core/dist/plugins/cleaner.js +337 -40
  878. package/packages/core/dist/plugins/cleaner.js.map +1 -1
  879. package/packages/core/dist/plugins/cli-notifier.d.ts +2 -1
  880. package/packages/core/dist/plugins/cli-notifier.d.ts.map +1 -1
  881. package/packages/core/dist/plugins/cli-notifier.js +99 -42
  882. package/packages/core/dist/plugins/cli-notifier.js.map +1 -1
  883. package/packages/core/dist/plugins/code2skill.d.ts +1 -0
  884. package/packages/core/dist/plugins/code2skill.d.ts.map +1 -1
  885. package/packages/core/dist/plugins/code2skill.js +178 -38
  886. package/packages/core/dist/plugins/code2skill.js.map +1 -1
  887. package/packages/core/dist/plugins/colleague-skill.d.ts +2 -1
  888. package/packages/core/dist/plugins/colleague-skill.d.ts.map +1 -1
  889. package/packages/core/dist/plugins/colleague-skill.js +79 -49
  890. package/packages/core/dist/plugins/colleague-skill.js.map +1 -1
  891. package/packages/core/dist/plugins/context-doctor.d.ts +6 -1
  892. package/packages/core/dist/plugins/context-doctor.d.ts.map +1 -1
  893. package/packages/core/dist/plugins/context-doctor.js +403 -39
  894. package/packages/core/dist/plugins/context-doctor.js.map +1 -1
  895. package/packages/core/dist/plugins/context.d.ts +1 -0
  896. package/packages/core/dist/plugins/context.d.ts.map +1 -1
  897. package/packages/core/dist/plugins/context.js +169 -42
  898. package/packages/core/dist/plugins/context.js.map +1 -1
  899. package/packages/core/dist/plugins/cost-meter.d.ts +4 -0
  900. package/packages/core/dist/plugins/cost-meter.d.ts.map +1 -1
  901. package/packages/core/dist/plugins/cost-meter.js +319 -93
  902. package/packages/core/dist/plugins/cost-meter.js.map +1 -1
  903. package/packages/core/dist/plugins/dependency-checker.d.ts +11 -2
  904. package/packages/core/dist/plugins/dependency-checker.d.ts.map +1 -1
  905. package/packages/core/dist/plugins/dependency-checker.js +463 -114
  906. package/packages/core/dist/plugins/dependency-checker.js.map +1 -1
  907. package/packages/core/dist/plugins/docker-sandbox.d.ts +1 -0
  908. package/packages/core/dist/plugins/docker-sandbox.d.ts.map +1 -1
  909. package/packages/core/dist/plugins/docker-sandbox.js +322 -80
  910. package/packages/core/dist/plugins/docker-sandbox.js.map +1 -1
  911. package/packages/core/dist/plugins/fail-logger.d.ts +1 -0
  912. package/packages/core/dist/plugins/fail-logger.d.ts.map +1 -1
  913. package/packages/core/dist/plugins/fail-logger.js +187 -20
  914. package/packages/core/dist/plugins/fail-logger.js.map +1 -1
  915. package/packages/core/dist/plugins/genui.d.ts +1 -0
  916. package/packages/core/dist/plugins/genui.d.ts.map +1 -1
  917. package/packages/core/dist/plugins/genui.js +103 -38
  918. package/packages/core/dist/plugins/genui.js.map +1 -1
  919. package/packages/core/dist/plugins/git-time-capsule.d.ts +8 -2
  920. package/packages/core/dist/plugins/git-time-capsule.d.ts.map +1 -1
  921. package/packages/core/dist/plugins/git-time-capsule.js +400 -54
  922. package/packages/core/dist/plugins/git-time-capsule.js.map +1 -1
  923. package/packages/core/dist/plugins/graph-memory.d.ts.map +1 -1
  924. package/packages/core/dist/plugins/graph-memory.js +329 -42
  925. package/packages/core/dist/plugins/graph-memory.js.map +1 -1
  926. package/packages/core/dist/plugins/history-compressor.d.ts.map +1 -1
  927. package/packages/core/dist/plugins/history-compressor.js +31 -12
  928. package/packages/core/dist/plugins/history-compressor.js.map +1 -1
  929. package/packages/core/dist/plugins/hol-guard.d.ts.map +1 -1
  930. package/packages/core/dist/plugins/hol-guard.js +33 -13
  931. package/packages/core/dist/plugins/hol-guard.js.map +1 -1
  932. package/packages/core/dist/plugins/i18n-pair.d.ts +5 -1
  933. package/packages/core/dist/plugins/i18n-pair.d.ts.map +1 -1
  934. package/packages/core/dist/plugins/i18n-pair.js +308 -52
  935. package/packages/core/dist/plugins/i18n-pair.js.map +1 -1
  936. package/packages/core/dist/plugins/image-compressor.d.ts +7 -0
  937. package/packages/core/dist/plugins/image-compressor.d.ts.map +1 -1
  938. package/packages/core/dist/plugins/image-compressor.js +98 -25
  939. package/packages/core/dist/plugins/image-compressor.js.map +1 -1
  940. package/packages/core/dist/plugins/llm-verifier.d.ts.map +1 -1
  941. package/packages/core/dist/plugins/llm-verifier.js +21 -11
  942. package/packages/core/dist/plugins/llm-verifier.js.map +1 -1
  943. package/packages/core/dist/plugins/mcp-client.d.ts.map +1 -1
  944. package/packages/core/dist/plugins/mcp-client.js +986 -232
  945. package/packages/core/dist/plugins/mcp-client.js.map +1 -1
  946. package/packages/core/dist/plugins/mcp-panel.d.ts.map +1 -1
  947. package/packages/core/dist/plugins/mcp-panel.js +30 -16
  948. package/packages/core/dist/plugins/mcp-panel.js.map +1 -1
  949. package/packages/core/dist/plugins/memory.d.ts.map +1 -1
  950. package/packages/core/dist/plugins/memory.js +292 -59
  951. package/packages/core/dist/plugins/memory.js.map +1 -1
  952. package/packages/core/dist/plugins/mirage-bridge.d.ts.map +1 -1
  953. package/packages/core/dist/plugins/mirage-bridge.js +20 -10
  954. package/packages/core/dist/plugins/mirage-bridge.js.map +1 -1
  955. package/packages/core/dist/plugins/mock-server.d.ts.map +1 -1
  956. package/packages/core/dist/plugins/mock-server.js +85 -54
  957. package/packages/core/dist/plugins/mock-server.js.map +1 -1
  958. package/packages/core/dist/plugins/model.d.ts +3 -0
  959. package/packages/core/dist/plugins/model.d.ts.map +1 -1
  960. package/packages/core/dist/plugins/model.js +3 -0
  961. package/packages/core/dist/plugins/model.js.map +1 -1
  962. package/packages/core/dist/plugins/models.d.ts.map +1 -1
  963. package/packages/core/dist/plugins/models.js +10 -2
  964. package/packages/core/dist/plugins/models.js.map +1 -1
  965. package/packages/core/dist/plugins/modlens.d.ts +8 -1
  966. package/packages/core/dist/plugins/modlens.d.ts.map +1 -1
  967. package/packages/core/dist/plugins/modlens.js +438 -31
  968. package/packages/core/dist/plugins/modlens.js.map +1 -1
  969. package/packages/core/dist/plugins/module-search.d.ts +1 -0
  970. package/packages/core/dist/plugins/module-search.d.ts.map +1 -1
  971. package/packages/core/dist/plugins/module-search.js +35 -16
  972. package/packages/core/dist/plugins/module-search.js.map +1 -1
  973. package/packages/core/dist/plugins/obsidian-sync.d.ts.map +1 -1
  974. package/packages/core/dist/plugins/obsidian-sync.js +20 -11
  975. package/packages/core/dist/plugins/obsidian-sync.js.map +1 -1
  976. package/packages/core/dist/plugins/openpets.d.ts.map +1 -1
  977. package/packages/core/dist/plugins/openpets.js +203 -44
  978. package/packages/core/dist/plugins/openpets.js.map +1 -1
  979. package/packages/core/dist/plugins/plan-execute.d.ts +4 -1
  980. package/packages/core/dist/plugins/plan-execute.d.ts.map +1 -1
  981. package/packages/core/dist/plugins/plan-execute.js +42 -21
  982. package/packages/core/dist/plugins/plan-execute.js.map +1 -1
  983. package/packages/core/dist/plugins/plugin-check.d.ts +12 -3
  984. package/packages/core/dist/plugins/plugin-check.d.ts.map +1 -1
  985. package/packages/core/dist/plugins/plugin-check.js +83 -12
  986. package/packages/core/dist/plugins/plugin-check.js.map +1 -1
  987. package/packages/core/dist/plugins/plugin-dev.d.ts +1 -0
  988. package/packages/core/dist/plugins/plugin-dev.d.ts.map +1 -1
  989. package/packages/core/dist/plugins/plugin-dev.js +156 -23
  990. package/packages/core/dist/plugins/plugin-dev.js.map +1 -1
  991. package/packages/core/dist/plugins/plugin-finder.d.ts +1 -0
  992. package/packages/core/dist/plugins/plugin-finder.d.ts.map +1 -1
  993. package/packages/core/dist/plugins/plugin-finder.js +131 -13
  994. package/packages/core/dist/plugins/plugin-finder.js.map +1 -1
  995. package/packages/core/dist/plugins/plugin-radar.d.ts +4 -0
  996. package/packages/core/dist/plugins/plugin-radar.d.ts.map +1 -1
  997. package/packages/core/dist/plugins/plugin-radar.js +137 -36
  998. package/packages/core/dist/plugins/plugin-radar.js.map +1 -1
  999. package/packages/core/dist/plugins/plugin-stars.d.ts.map +1 -1
  1000. package/packages/core/dist/plugins/plugin-stars.js +282 -81
  1001. package/packages/core/dist/plugins/plugin-stars.js.map +1 -1
  1002. package/packages/core/dist/plugins/prompt-guard.d.ts +1 -0
  1003. package/packages/core/dist/plugins/prompt-guard.d.ts.map +1 -1
  1004. package/packages/core/dist/plugins/prompt-guard.js +60 -9
  1005. package/packages/core/dist/plugins/prompt-guard.js.map +1 -1
  1006. package/packages/core/dist/plugins/prompt-library.d.ts +1 -0
  1007. package/packages/core/dist/plugins/prompt-library.d.ts.map +1 -1
  1008. package/packages/core/dist/plugins/prompt-library.js +4 -1
  1009. package/packages/core/dist/plugins/prompt-library.js.map +1 -1
  1010. package/packages/core/dist/plugins/readme-gen.d.ts +6 -2
  1011. package/packages/core/dist/plugins/readme-gen.d.ts.map +1 -1
  1012. package/packages/core/dist/plugins/readme-gen.js +514 -73
  1013. package/packages/core/dist/plugins/readme-gen.js.map +1 -1
  1014. package/packages/core/dist/plugins/recall-unread.d.ts +1 -1
  1015. package/packages/core/dist/plugins/recall-unread.d.ts.map +1 -1
  1016. package/packages/core/dist/plugins/recall-unread.js +411 -68
  1017. package/packages/core/dist/plugins/recall-unread.js.map +1 -1
  1018. package/packages/core/dist/plugins/resources.d.ts.map +1 -1
  1019. package/packages/core/dist/plugins/resources.js +66 -3
  1020. package/packages/core/dist/plugins/resources.js.map +1 -1
  1021. package/packages/core/dist/plugins/reverse-skill.d.ts.map +1 -1
  1022. package/packages/core/dist/plugins/reverse-skill.js +2 -1
  1023. package/packages/core/dist/plugins/reverse-skill.js.map +1 -1
  1024. package/packages/core/dist/plugins/reviewer-bot.d.ts +1 -0
  1025. package/packages/core/dist/plugins/reviewer-bot.d.ts.map +1 -1
  1026. package/packages/core/dist/plugins/reviewer-bot.js +35 -16
  1027. package/packages/core/dist/plugins/reviewer-bot.js.map +1 -1
  1028. package/packages/core/dist/plugins/runtime-doctor.d.ts +1 -0
  1029. package/packages/core/dist/plugins/runtime-doctor.d.ts.map +1 -1
  1030. package/packages/core/dist/plugins/runtime-doctor.js +4 -1
  1031. package/packages/core/dist/plugins/runtime-doctor.js.map +1 -1
  1032. package/packages/core/dist/plugins/runtime.d.ts.map +1 -1
  1033. package/packages/core/dist/plugins/runtime.js +104 -70
  1034. package/packages/core/dist/plugins/runtime.js.map +1 -1
  1035. package/packages/core/dist/plugins/secure-audit.d.ts +1 -0
  1036. package/packages/core/dist/plugins/secure-audit.d.ts.map +1 -1
  1037. package/packages/core/dist/plugins/secure-audit.js +30 -12
  1038. package/packages/core/dist/plugins/secure-audit.js.map +1 -1
  1039. package/packages/core/dist/plugins/session-bookmarks.d.ts +1 -0
  1040. package/packages/core/dist/plugins/session-bookmarks.d.ts.map +1 -1
  1041. package/packages/core/dist/plugins/session-bookmarks.js +4 -1
  1042. package/packages/core/dist/plugins/session-bookmarks.js.map +1 -1
  1043. package/packages/core/dist/plugins/session-bridge.d.ts +1 -0
  1044. package/packages/core/dist/plugins/session-bridge.d.ts.map +1 -1
  1045. package/packages/core/dist/plugins/session-bridge.js +401 -88
  1046. package/packages/core/dist/plugins/session-bridge.js.map +1 -1
  1047. package/packages/core/dist/plugins/session-compare.d.ts +1 -0
  1048. package/packages/core/dist/plugins/session-compare.d.ts.map +1 -1
  1049. package/packages/core/dist/plugins/session-compare.js +4 -1
  1050. package/packages/core/dist/plugins/session-compare.js.map +1 -1
  1051. package/packages/core/dist/plugins/session-export.d.ts +1 -0
  1052. package/packages/core/dist/plugins/session-export.d.ts.map +1 -1
  1053. package/packages/core/dist/plugins/session-export.js +6 -6
  1054. package/packages/core/dist/plugins/session-export.js.map +1 -1
  1055. package/packages/core/dist/plugins/session-insights.d.ts +37 -1
  1056. package/packages/core/dist/plugins/session-insights.d.ts.map +1 -1
  1057. package/packages/core/dist/plugins/session-insights.js +406 -21
  1058. package/packages/core/dist/plugins/session-insights.js.map +1 -1
  1059. package/packages/core/dist/plugins/session-search.d.ts +1 -0
  1060. package/packages/core/dist/plugins/session-search.d.ts.map +1 -1
  1061. package/packages/core/dist/plugins/session-search.js +4 -1
  1062. package/packages/core/dist/plugins/session-search.js.map +1 -1
  1063. package/packages/core/dist/plugins/session.d.ts.map +1 -1
  1064. package/packages/core/dist/plugins/session.js +8 -1
  1065. package/packages/core/dist/plugins/session.js.map +1 -1
  1066. package/packages/core/dist/plugins/skill-catalog.d.ts +1 -0
  1067. package/packages/core/dist/plugins/skill-catalog.d.ts.map +1 -1
  1068. package/packages/core/dist/plugins/skill-catalog.js +6 -5
  1069. package/packages/core/dist/plugins/skill-catalog.js.map +1 -1
  1070. package/packages/core/dist/plugins/skill-guard.d.ts +2 -1
  1071. package/packages/core/dist/plugins/skill-guard.d.ts.map +1 -1
  1072. package/packages/core/dist/plugins/skill-guard.js +241 -61
  1073. package/packages/core/dist/plugins/skill-guard.js.map +1 -1
  1074. package/packages/core/dist/plugins/sql-lens-worker.d.ts +2 -0
  1075. package/packages/core/dist/plugins/sql-lens-worker.d.ts.map +1 -0
  1076. package/packages/core/dist/plugins/sql-lens-worker.js +206 -0
  1077. package/packages/core/dist/plugins/sql-lens-worker.js.map +1 -0
  1078. package/packages/core/dist/plugins/sql-lens.d.ts +7 -1
  1079. package/packages/core/dist/plugins/sql-lens.d.ts.map +1 -1
  1080. package/packages/core/dist/plugins/sql-lens.js +301 -68
  1081. package/packages/core/dist/plugins/sql-lens.js.map +1 -1
  1082. package/packages/core/dist/plugins/stdio.d.ts +3 -0
  1083. package/packages/core/dist/plugins/stdio.d.ts.map +1 -1
  1084. package/packages/core/dist/plugins/stdio.js +62 -4
  1085. package/packages/core/dist/plugins/stdio.js.map +1 -1
  1086. package/packages/core/dist/plugins/synapse.d.ts.map +1 -1
  1087. package/packages/core/dist/plugins/synapse.js +17 -9
  1088. package/packages/core/dist/plugins/synapse.js.map +1 -1
  1089. package/packages/core/dist/plugins/tab-manager.d.ts +1 -0
  1090. package/packages/core/dist/plugins/tab-manager.d.ts.map +1 -1
  1091. package/packages/core/dist/plugins/tab-manager.js +167 -62
  1092. package/packages/core/dist/plugins/tab-manager.js.map +1 -1
  1093. package/packages/core/dist/plugins/taskboard.d.ts.map +1 -1
  1094. package/packages/core/dist/plugins/taskboard.js +50 -22
  1095. package/packages/core/dist/plugins/taskboard.js.map +1 -1
  1096. package/packages/core/dist/plugins/telemetry-blocker.d.ts +4 -1
  1097. package/packages/core/dist/plugins/telemetry-blocker.d.ts.map +1 -1
  1098. package/packages/core/dist/plugins/telemetry-blocker.js +30 -11
  1099. package/packages/core/dist/plugins/telemetry-blocker.js.map +1 -1
  1100. package/packages/core/dist/plugins/test-harness.d.ts +7 -1
  1101. package/packages/core/dist/plugins/test-harness.d.ts.map +1 -1
  1102. package/packages/core/dist/plugins/test-harness.js +255 -43
  1103. package/packages/core/dist/plugins/test-harness.js.map +1 -1
  1104. package/packages/core/dist/plugins/theme-studio.d.ts.map +1 -1
  1105. package/packages/core/dist/plugins/theme-studio.js +4 -2
  1106. package/packages/core/dist/plugins/theme-studio.js.map +1 -1
  1107. package/packages/core/dist/plugins/token-guard.d.ts.map +1 -1
  1108. package/packages/core/dist/plugins/token-guard.js +164 -32
  1109. package/packages/core/dist/plugins/token-guard.js.map +1 -1
  1110. package/packages/core/dist/plugins/tools.d.ts.map +1 -1
  1111. package/packages/core/dist/plugins/tools.js +4 -1
  1112. package/packages/core/dist/plugins/tools.js.map +1 -1
  1113. package/packages/core/dist/plugins/turn-rewind.d.ts +17 -0
  1114. package/packages/core/dist/plugins/turn-rewind.d.ts.map +1 -1
  1115. package/packages/core/dist/plugins/turn-rewind.js +340 -36
  1116. package/packages/core/dist/plugins/turn-rewind.js.map +1 -1
  1117. package/packages/core/dist/plugins/undo-savepoint.d.ts.map +1 -1
  1118. package/packages/core/dist/plugins/undo-savepoint.js +157 -51
  1119. package/packages/core/dist/plugins/undo-savepoint.js.map +1 -1
  1120. package/packages/core/dist/plugins/vision-toolkit.d.ts +22 -3
  1121. package/packages/core/dist/plugins/vision-toolkit.d.ts.map +1 -1
  1122. package/packages/core/dist/plugins/vision-toolkit.js +389 -66
  1123. package/packages/core/dist/plugins/vision-toolkit.js.map +1 -1
  1124. package/packages/core/dist/plugins/web-research.d.ts.map +1 -1
  1125. package/packages/core/dist/plugins/web-research.js +13 -4
  1126. package/packages/core/dist/plugins/web-research.js.map +1 -1
  1127. package/packages/core/dist/plugins/workspace-navigator.d.ts +8 -2
  1128. package/packages/core/dist/plugins/workspace-navigator.d.ts.map +1 -1
  1129. package/packages/core/dist/plugins/workspace-navigator.js +28 -10
  1130. package/packages/core/dist/plugins/workspace-navigator.js.map +1 -1
  1131. package/packages/core/dist/plugins/workspace-search.d.ts +7 -0
  1132. package/packages/core/dist/plugins/workspace-search.d.ts.map +1 -1
  1133. package/packages/core/dist/plugins/workspace-search.js +67 -34
  1134. package/packages/core/dist/plugins/workspace-search.js.map +1 -1
  1135. package/packages/core/dist/plugins/yaml-validator.d.ts +1 -0
  1136. package/packages/core/dist/plugins/yaml-validator.d.ts.map +1 -1
  1137. package/packages/core/dist/plugins/yaml-validator.js +156 -47
  1138. package/packages/core/dist/plugins/yaml-validator.js.map +1 -1
  1139. package/packages/core/dist/runtime.d.ts.map +1 -1
  1140. package/packages/core/dist/runtime.js +8 -3
  1141. package/packages/core/dist/runtime.js.map +1 -1
  1142. package/packages/core/dist/services.d.ts.map +1 -1
  1143. package/packages/core/dist/services.js +22 -2
  1144. package/packages/core/dist/services.js.map +1 -1
  1145. package/packages/core/dist/stdio.d.ts +1 -0
  1146. package/packages/core/dist/stdio.d.ts.map +1 -1
  1147. package/packages/core/dist/stdio.js +241 -25
  1148. package/packages/core/dist/stdio.js.map +1 -1
  1149. package/packages/core/dist/workspace-path.d.ts +1 -0
  1150. package/packages/core/dist/workspace-path.d.ts.map +1 -1
  1151. package/packages/core/dist/workspace-path.js +9 -0
  1152. package/packages/core/dist/workspace-path.js.map +1 -1
  1153. package/packages/core/package.json +1 -1
  1154. package/packages/core/profiles/default/cordis.yml +4 -2
  1155. package/packages/core/src/atomic-write.ts +45 -0
  1156. package/packages/core/src/boot.ts +123 -11
  1157. package/packages/core/src/bounded-file.ts +41 -0
  1158. package/packages/core/src/config.ts +18 -0
  1159. package/packages/core/src/cordis-timer.ts +107 -0
  1160. package/packages/core/src/plugins/agent-teams.ts +1003 -103
  1161. package/packages/core/src/plugins/anchored-standard.ts +41 -14
  1162. package/packages/core/src/plugins/annotation.ts +36 -19
  1163. package/packages/core/src/plugins/archify.ts +80 -33
  1164. package/packages/core/src/plugins/at-file.ts +110 -26
  1165. package/packages/core/src/plugins/auto-mode.ts +91 -24
  1166. package/packages/core/src/plugins/better-sidebar.ts +15 -4
  1167. package/packages/core/src/plugins/browser-fetch.ts +286 -95
  1168. package/packages/core/src/plugins/browser-session.ts +421 -102
  1169. package/packages/core/src/plugins/canvas-draw.ts +74 -21
  1170. package/packages/core/src/plugins/change-verifier.ts +33 -9
  1171. package/packages/core/src/plugins/cleaner.ts +339 -37
  1172. package/packages/core/src/plugins/cli-notifier.ts +110 -41
  1173. package/packages/core/src/plugins/code2skill.ts +175 -34
  1174. package/packages/core/src/plugins/colleague-skill.ts +72 -47
  1175. package/packages/core/src/plugins/context-doctor.ts +410 -40
  1176. package/packages/core/src/plugins/context.ts +164 -39
  1177. package/packages/core/src/plugins/cost-meter.ts +360 -113
  1178. package/packages/core/src/plugins/dependency-checker.ts +456 -119
  1179. package/packages/core/src/plugins/docker-sandbox.ts +312 -76
  1180. package/packages/core/src/plugins/fail-logger.ts +169 -18
  1181. package/packages/core/src/plugins/genui.ts +104 -42
  1182. package/packages/core/src/plugins/git-time-capsule.ts +424 -55
  1183. package/packages/core/src/plugins/graph-memory.ts +333 -60
  1184. package/packages/core/src/plugins/history-compressor.ts +29 -12
  1185. package/packages/core/src/plugins/hol-guard.ts +31 -13
  1186. package/packages/core/src/plugins/i18n-pair.ts +296 -52
  1187. package/packages/core/src/plugins/image-compressor.ts +98 -25
  1188. package/packages/core/src/plugins/llm-verifier.ts +39 -21
  1189. package/packages/core/src/plugins/mcp-client.ts +1069 -249
  1190. package/packages/core/src/plugins/mcp-panel.ts +37 -21
  1191. package/packages/core/src/plugins/memory.ts +262 -57
  1192. package/packages/core/src/plugins/mirage-bridge.ts +22 -10
  1193. package/packages/core/src/plugins/mock-server.ts +91 -60
  1194. package/packages/core/src/plugins/model.ts +4 -0
  1195. package/packages/core/src/plugins/models.ts +10 -2
  1196. package/packages/core/src/plugins/modlens.ts +463 -29
  1197. package/packages/core/src/plugins/module-search.ts +40 -19
  1198. package/packages/core/src/plugins/obsidian-sync.ts +26 -15
  1199. package/packages/core/src/plugins/openpets.ts +193 -42
  1200. package/packages/core/src/plugins/plan-execute.ts +49 -21
  1201. package/packages/core/src/plugins/plugin-check.ts +100 -16
  1202. package/packages/core/src/plugins/plugin-dev.ts +167 -23
  1203. package/packages/core/src/plugins/plugin-finder.ts +119 -12
  1204. package/packages/core/src/plugins/plugin-radar.ts +130 -39
  1205. package/packages/core/src/plugins/plugin-stars.ts +252 -80
  1206. package/packages/core/src/plugins/prompt-guard.ts +51 -12
  1207. package/packages/core/src/plugins/prompt-library.ts +14 -8
  1208. package/packages/core/src/plugins/readme-gen.ts +476 -79
  1209. package/packages/core/src/plugins/recall-unread.ts +412 -68
  1210. package/packages/core/src/plugins/resources.ts +70 -2
  1211. package/packages/core/src/plugins/reverse-skill.ts +9 -5
  1212. package/packages/core/src/plugins/reviewer-bot.ts +34 -16
  1213. package/packages/core/src/plugins/runtime-doctor.ts +4 -1
  1214. package/packages/core/src/plugins/runtime.ts +98 -68
  1215. package/packages/core/src/plugins/secure-audit.ts +33 -12
  1216. package/packages/core/src/plugins/session-bookmarks.ts +12 -6
  1217. package/packages/core/src/plugins/session-bridge.ts +404 -89
  1218. package/packages/core/src/plugins/session-compare.ts +10 -4
  1219. package/packages/core/src/plugins/session-export.ts +12 -9
  1220. package/packages/core/src/plugins/session-insights.ts +454 -31
  1221. package/packages/core/src/plugins/session-search.ts +4 -1
  1222. package/packages/core/src/plugins/session.ts +8 -1
  1223. package/packages/core/src/plugins/skill-catalog.ts +13 -8
  1224. package/packages/core/src/plugins/skill-guard.ts +254 -61
  1225. package/packages/core/src/plugins/sql-lens-worker.ts +202 -0
  1226. package/packages/core/src/plugins/sql-lens.ts +323 -71
  1227. package/packages/core/src/plugins/stdio.ts +58 -3
  1228. package/packages/core/src/plugins/synapse.ts +16 -9
  1229. package/packages/core/src/plugins/tab-manager.ts +163 -65
  1230. package/packages/core/src/plugins/taskboard.ts +81 -47
  1231. package/packages/core/src/plugins/telemetry-blocker.ts +27 -11
  1232. package/packages/core/src/plugins/test-harness.ts +275 -42
  1233. package/packages/core/src/plugins/theme-studio.ts +7 -2
  1234. package/packages/core/src/plugins/token-guard.ts +171 -31
  1235. package/packages/core/src/plugins/tools.ts +4 -1
  1236. package/packages/core/src/plugins/turn-rewind.ts +351 -37
  1237. package/packages/core/src/plugins/undo-savepoint.ts +160 -59
  1238. package/packages/core/src/plugins/vision-toolkit.ts +420 -63
  1239. package/packages/core/src/plugins/web-research.ts +19 -7
  1240. package/packages/core/src/plugins/workspace-navigator.ts +39 -14
  1241. package/packages/core/src/plugins/workspace-search.ts +75 -37
  1242. package/packages/core/src/plugins/yaml-validator.ts +165 -46
  1243. package/packages/core/src/runtime.ts +8 -2
  1244. package/packages/core/src/services.ts +22 -2
  1245. package/packages/core/src/stdio.ts +220 -25
  1246. package/packages/core/src/workspace-path.ts +10 -0
  1247. package/packages/core/test/agent-teams.test.ts +495 -2
  1248. package/packages/core/test/anchored-standard.test.ts +60 -0
  1249. package/packages/core/test/annotation.test.ts +69 -0
  1250. package/packages/core/test/archify.test.ts +212 -1
  1251. package/packages/core/test/at-file.test.ts +666 -0
  1252. package/packages/core/test/atomic-write.test.ts +52 -0
  1253. package/packages/core/test/auto-mode.test.ts +629 -0
  1254. package/packages/core/test/better-sidebar.test.ts +108 -1
  1255. package/packages/core/test/boot.test.ts +129 -1
  1256. package/packages/core/test/bounded-file.test.ts +55 -0
  1257. package/packages/core/test/browser-fetch-rebinding.test.ts +93 -0
  1258. package/packages/core/test/browser-fetch.test.ts +844 -0
  1259. package/packages/core/test/browser-session.test.ts +1236 -0
  1260. package/packages/core/test/canvas-draw.test.ts +164 -0
  1261. package/packages/core/test/change-verifier.test.ts +200 -0
  1262. package/packages/core/test/cleaner.test.ts +316 -0
  1263. package/packages/core/test/cli-notifier.test.ts +235 -0
  1264. package/packages/core/test/code2skill.test.ts +264 -0
  1265. package/packages/core/test/colleague-skill.test.ts +167 -0
  1266. package/packages/core/test/config.test.ts +8 -0
  1267. package/packages/core/test/context-doctor.test.ts +597 -2
  1268. package/packages/core/test/context-insights.test.ts +396 -0
  1269. package/packages/core/test/cordis-timer.test.ts +147 -0
  1270. package/packages/core/test/cost-meter.test.ts +362 -0
  1271. package/packages/core/test/dependency-checker.test.ts +576 -3
  1272. package/packages/core/test/docker-sandbox.test.ts +170 -0
  1273. package/packages/core/test/fail-logger.test.ts +363 -0
  1274. package/packages/core/test/genui.test.ts +162 -0
  1275. package/packages/core/test/git-time-capsule.test.ts +1364 -3
  1276. package/packages/core/test/graph-memory.test.ts +508 -0
  1277. package/packages/core/test/history-compressor.test.ts +47 -0
  1278. package/packages/core/test/hol-guard.test.ts +61 -0
  1279. package/packages/core/test/i18n-pair.test.ts +367 -0
  1280. package/packages/core/test/image-compressor.test.ts +59 -0
  1281. package/packages/core/test/llm-verifier.test.ts +4 -0
  1282. package/packages/core/test/mcp-client.test.ts +1037 -0
  1283. package/packages/core/test/mcp-panel.test.ts +91 -0
  1284. package/packages/core/test/memory.test.ts +125 -0
  1285. package/packages/core/test/mirage-bridge.test.ts +4 -0
  1286. package/packages/core/test/mock-server.test.ts +63 -0
  1287. package/packages/core/test/model.test.ts +62 -0
  1288. package/packages/core/test/models.test.ts +85 -0
  1289. package/packages/core/test/modlens.test.ts +615 -0
  1290. package/packages/core/test/module-search.test.ts +20 -0
  1291. package/packages/core/test/obsidian-sync.test.ts +57 -0
  1292. package/packages/core/test/openpets.test.ts +273 -0
  1293. package/packages/core/test/plan-execute.test.ts +86 -0
  1294. package/packages/core/test/plugin-dev.test.ts +246 -0
  1295. package/packages/core/test/plugin-finder.test.ts +105 -0
  1296. package/packages/core/test/plugin-radar.test.ts +87 -0
  1297. package/packages/core/test/plugin-stars.test.ts +429 -4
  1298. package/packages/core/test/profiles.integration.test.ts +451 -2
  1299. package/packages/core/test/prompt-guard.test.ts +78 -0
  1300. package/packages/core/test/readme-gen.test.ts +403 -3
  1301. package/packages/core/test/recall-unread.test.ts +559 -2
  1302. package/packages/core/test/registry.test.ts +16 -0
  1303. package/packages/core/test/resources.test.ts +310 -0
  1304. package/packages/core/test/reviewer-bot.test.ts +55 -0
  1305. package/packages/core/test/runtime-fixture.ts +10 -1
  1306. package/packages/core/test/runtime.test.ts +155 -2
  1307. package/packages/core/test/secure-audit.test.ts +14 -1
  1308. package/packages/core/test/services.test.ts +2772 -117
  1309. package/packages/core/test/session-bridge.test.ts +309 -1
  1310. package/packages/core/test/session-insights.test.ts +486 -0
  1311. package/packages/core/test/session.test.ts +153 -0
  1312. package/packages/core/test/skill-guard.test.ts +261 -2
  1313. package/packages/core/test/sql-lens.test.ts +244 -0
  1314. package/packages/core/test/stdio-args.test.ts +484 -1
  1315. package/packages/core/test/stdio.test.ts +159 -0
  1316. package/packages/core/test/synapse.test.ts +67 -0
  1317. package/packages/core/test/tab-manager.test.ts +58 -0
  1318. package/packages/core/test/taskboard.test.ts +73 -0
  1319. package/packages/core/test/telemetry-blocker.test.ts +61 -0
  1320. package/packages/core/test/test-harness.test.ts +297 -0
  1321. package/packages/core/test/token-guard.test.ts +362 -1
  1322. package/packages/core/test/tools.test.ts +118 -0
  1323. package/packages/core/test/turn-rewind.test.ts +532 -2
  1324. package/packages/core/test/undo-savepoint.test.ts +222 -0
  1325. package/packages/core/test/vision-toolkit.test.ts +480 -7
  1326. package/packages/core/test/web-research.test.ts +63 -0
  1327. package/packages/core/test/workspace-git-status.test.ts +19 -2
  1328. package/packages/core/test/workspace-navigator.test.ts +11 -1
  1329. package/packages/core/test/workspace-search.test.ts +88 -0
  1330. package/packages/core/test/yaml-validator.test.ts +195 -0
  1331. package/packages/host-webserver/package.json +1 -1
  1332. package/apps/web/dist/assets/index-C_AdODuM.js +0 -20
  1333. package/apps/web/dist/assets/index-De8Rm01Z.css +0 -2
@@ -24,11 +24,40 @@ import { messageText, projectChatTurns } from "./message-content.js";
24
24
  import { formatAnnotationPrompt, parseAnnotationPrompt, type ClientAnnotation } from "./annotation-ui.js";
25
25
  import { marketplaceCategoryTabs, marketplaceDetailPath, marketplaceStatisticItems, readMarketplaceDetailId } from "./marketplace-navigation.js";
26
26
  import { loadMarketplaceCatalog } from "./marketplace-catalog.js";
27
- import { pluginStarsRows } from "./plugin-stars-view.js";
28
- import { browserSessionTabs } from "./browser-session-view.js";
27
+ import { pluginStarsPanelView } from "./plugin-stars-view.js";
28
+ import { pluginDevPanelView } from "./plugin-dev-view.js";
29
+ import { atFilePanelView } from "./at-file-view.js";
30
+ import { testHarnessPanelView } from "./test-harness-view.js";
31
+ import { sessionInsightsPanelView } from "./session-insights-view.js";
32
+ import { yamlValidatorPanelView } from "./yaml-validator-view.js";
33
+ import { browserFetchPanelView } from "./browser-fetch-view.js";
34
+ import { browserSessionPanelView } from "./browser-session-view.js";
35
+ import { cleanerPanelView } from "./cleaner-view.js";
29
36
  import { matchesPluginQuery } from "./plugin-search.js";
30
37
  import { readInstalledPluginDetailId } from "./plugin-navigation.js";
31
38
  import { installedPluginCardContent } from "./plugin-card.js";
39
+ import { costMeterPanelView } from "./cost-meter-view.js";
40
+ import { dependencyCheckerPanelView } from "./dependency-checker-view.js";
41
+ import { dockerSandboxPanelView } from "./docker-sandbox-view.js";
42
+ import { failLoggerPanelView } from "./fail-logger-view.js";
43
+ import { genUiPanelView } from "./genui-view.js";
44
+ import { gitTimeCapsulePanelView } from "./git-time-capsule-view.js";
45
+ import { graphMemoryPanelView } from "./graph-memory-view.js";
46
+ import { i18nPairPanelView } from "./i18n-pair-view.js";
47
+ import { mcpClientPanelView } from "./mcp-client-view.js";
48
+ import { openPetsPanelView } from "./openpets-view.js";
49
+ import { recallUnreadPanelView } from "./recall-unread-view.js";
50
+ import { turnRewindPanelView } from "./turn-rewind-view.js";
51
+ import { contextDoctorPanelView } from "./context-doctor-view.js";
52
+ import { contextInsightsPanelView } from "./context-insights-view.js";
53
+ import { tokenGuardPanelView } from "./token-guard-view.js";
54
+ import { sessionBridgePanelView } from "./session-bridge-view.js";
55
+ import { skillGuardPanelView } from "./skill-guard-view.js";
56
+ import { sqlLensPanelView } from "./sql-lens-view.js";
57
+ import { agentTeamsPanelView } from "./agent-teams-view.js";
58
+ import { modlensPanelView } from "./modlens-view.js";
59
+ import { visionToolkitPanelView } from "./vision-toolkit-view.js";
60
+ import { readmeGenPanelView } from "./readme-gen-view.js";
32
61
 
33
62
  export type { ClientApi } from "./control-room.js";
34
63
 
@@ -987,8 +1016,26 @@ function pluginPanelValue(input: unknown): string {
987
1016
  }
988
1017
  }
989
1018
 
990
- function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel; inline?: boolean }) {
991
- const data = panel.data !== null && typeof panel.data === "object" && !Array.isArray(panel.data) ? (panel.data as Record<string, unknown>) : undefined;
1019
+ function pluginPanelData(value: unknown): Record<string, unknown> | undefined {
1020
+ try {
1021
+ if (value === null || typeof value !== "object" || Array.isArray(value)) return undefined;
1022
+ const prototype = Object.getPrototypeOf(value) as unknown;
1023
+ if (prototype !== Object.prototype && prototype !== null) return undefined;
1024
+ const descriptors = Object.getOwnPropertyDescriptors(value);
1025
+ if (Reflect.ownKeys(descriptors).some((key) => typeof key !== "string")) return undefined;
1026
+ const output = Object.create(null) as Record<string, unknown>;
1027
+ for (const [key, descriptor] of Object.entries(descriptors)) {
1028
+ if (!("value" in descriptor)) return undefined;
1029
+ output[key] = descriptor.value;
1030
+ }
1031
+ return output;
1032
+ } catch {
1033
+ return undefined;
1034
+ }
1035
+ }
1036
+
1037
+ export function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel; inline?: boolean }) {
1038
+ const data = pluginPanelData(panel.data);
992
1039
  const entries = data ? Object.entries(data) : [["内容", panel.data] as const];
993
1040
  const items = data && Array.isArray(data.items) ? data.items : [];
994
1041
  const pluginEntries = data && Array.isArray(data.entries) ? data.entries : [];
@@ -1073,208 +1120,394 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
1073
1120
  </div>
1074
1121
  </div>
1075
1122
  ) : panel.id === "agent-teams-panel" ? (
1076
- <div className="mt-3 grid gap-3">
1077
- <div className="grid gap-2 sm:grid-cols-3">
1078
- {capabilities.length > 0
1079
- ? capabilities.map((capability, index) => (
1080
- <span
1081
- className="rounded-md border border-[#dce5f5] bg-white px-2 py-1 text-center text-[10px] text-[#3565c5]"
1082
- key={`${value(capability)}-${index}`}
1083
- >
1084
- {value(capability)}
1085
- </span>
1086
- ))
1087
- : null}
1088
- <div className="rounded-lg bg-[#f6f8fa] px-3 py-2">
1089
- <span className="block text-[10px] text-[#687381]">成员</span>
1090
- <strong className="mt-1 block text-[17px] font-semibold text-[#30343b]">{value(Array.isArray(data?.members) ? data.members.length : 0)}</strong>
1091
- </div>
1092
- <div className="rounded-lg bg-[#f6f8fa] px-3 py-2">
1093
- <span className="block text-[10px] text-[#687381]">任务</span>
1094
- <strong className="mt-1 block text-[17px] font-semibold text-[#30343b]">{value(Array.isArray(data?.tasks) ? data.tasks.length : 0)}</strong>
1095
- </div>
1096
- <div className="rounded-lg bg-[#f6f8fa] px-3 py-2">
1097
- <span className="block text-[10px] text-[#687381]">未读消息</span>
1098
- <strong className="mt-1 block text-[17px] font-semibold text-[#30343b]">
1099
- {value(
1100
- Array.isArray(data?.messages)
1101
- ? data.messages.filter((message) => message !== null && typeof message === "object" && (message as Record<string, unknown>).read !== true)
1102
- .length
1103
- : 0,
1104
- )}
1105
- </strong>
1106
- </div>
1107
- <div className="rounded-lg bg-[#f6f8fa] px-3 py-2">
1108
- <span className="block text-[10px] text-[#687381]">可执行任务</span>
1109
- <strong className="mt-1 block text-[17px] font-semibold text-[#30343b]">
1110
- {value(Array.isArray(data?.readyTasks) ? data.readyTasks.length : 0)}
1111
- </strong>
1112
- </div>
1113
- </div>
1114
- {Array.isArray(data?.dependencyCycle) && data.dependencyCycle.length > 1 ? (
1115
- <div className="rounded-lg border border-[#f4caca] bg-[#fff5f5] px-3 py-2 text-[11px] text-[#b42318]">
1116
- 依赖循环:{data.dependencyCycle.map((item) => value(item)).join(" → ")}
1117
- </div>
1118
- ) : null}
1119
- <div className="grid gap-2">
1120
- {Array.isArray(data?.members) && data.members.length > 0 ? (
1121
- data.members.map((item, index) => {
1122
- const member = item !== null && typeof item === "object" ? (item as Record<string, unknown>) : {};
1123
- return (
1124
- <div className="flex items-center gap-3 rounded-lg border border-[#edf0f3] px-3 py-2" key={`${value(member.id ?? "member")}-${index}`}>
1125
- <span className="h-2 w-2 rounded-full bg-[#22c55e]"></span>
1126
- <span className="min-w-0 flex-1 truncate text-[11px] font-semibold text-[#30343b]">{value(member.name ?? "成员")}</span>
1127
- <span className="text-[10px] text-[#687381]">{value(member.role ?? "协作成员")}</span>
1128
- <span className="font-mono text-[10px] text-[#3565c5]">{value(member.status ?? "idle")}</span>
1123
+ (() => {
1124
+ const view = agentTeamsPanelView(data);
1125
+ return (
1126
+ <div className="mt-3 grid gap-3">
1127
+ <div className="grid gap-2 sm:grid-cols-4">
1128
+ {[
1129
+ ["成员", view.inventory.members.total],
1130
+ ["任务", view.inventory.tasks.total],
1131
+ ["未读消息", view.inventory.messages.unread],
1132
+ ["可执行任务", view.inventory.tasks.ready],
1133
+ ].map(([label, item]) => (
1134
+ <div className="rounded-lg bg-[#f6f8fa] px-3 py-2" key={value(label)}>
1135
+ <span className="block text-[10px] text-[#687381]">{value(label)}</span>
1136
+ <strong className="mt-1 block text-[17px] font-semibold text-[#30343b]">{value(item)}</strong>
1129
1137
  </div>
1130
- );
1131
- })
1132
- ) : (
1133
- <div className="rounded-lg bg-[#f6f8fa] px-3 py-3 text-[12px] text-[#687381]">暂无协作成员。</div>
1134
- )}
1135
- </div>
1136
- <div className="grid gap-2">
1137
- {Array.isArray(data?.tasks) && data.tasks.length > 0 ? (
1138
- data.tasks.map((item, index) => {
1139
- const task = item !== null && typeof item === "object" ? (item as Record<string, unknown>) : {};
1140
- return (
1141
- <div className="flex items-center gap-3 rounded-lg border border-[#edf0f3] px-3 py-2" key={`${value(task.id ?? "task")}-${index}`}>
1142
- <div className="min-w-0 flex-1">
1143
- <span className="block truncate text-[11px] text-[#30343b]">{value(task.title ?? "未命名任务")}</span>
1144
- {Array.isArray(task.dependsOn) && task.dependsOn.length > 0 ? (
1145
- <span className="mt-0.5 block truncate font-mono text-[9px] text-[#687381]">依赖:{task.dependsOn.join(", ")}</span>
1146
- ) : null}
1138
+ ))}
1139
+ </div>
1140
+ {view.dependencyCycle !== null && view.dependencyCycle.length > 1 ? (
1141
+ <div className="rounded-lg border border-[#f4caca] bg-[#fff5f5] px-3 py-2 text-[11px] text-[#b42318]">
1142
+ 依赖循环:{view.dependencyCycle.join(" → ")}
1143
+ </div>
1144
+ ) : null}
1145
+ <div className="grid gap-2">
1146
+ {view.members.length > 0 ? (
1147
+ view.members.map((member) => (
1148
+ <div className="flex items-center gap-3 rounded-lg border border-[#edf0f3] px-3 py-2" key={member.id}>
1149
+ <span className={`h-2 w-2 rounded-full ${member.status === "working" ? "bg-[#22c55e]" : "bg-[#a0a8b2]"}`}></span>
1150
+ <span className="min-w-0 flex-1 truncate text-[11px] font-semibold text-[#30343b]">{member.name}</span>
1151
+ <span className="truncate text-[10px] text-[#687381]">{member.role}</span>
1152
+ <span className="font-mono text-[10px] text-[#3565c5]">{member.status}</span>
1147
1153
  </div>
1148
- <span className="text-[10px] text-[#687381]">{value(task.assignee ?? "unassigned")}</span>
1149
- <span
1150
- className={`rounded-full px-2 py-1 text-[10px] ${task.status === "blocked" ? "bg-[#fff4e5] text-[#8a5a00]" : task.status === "done" ? "bg-[#e8f8ee] text-[#14733f]" : "bg-[#edf3fe] text-[#3565c5]"}`}
1151
- >
1152
- {value(task.status ?? "todo")}
1153
- </span>
1154
- </div>
1155
- );
1156
- })
1157
- ) : (
1158
- <div className="rounded-lg bg-[#f6f8fa] px-3 py-3 text-[12px] text-[#687381]">还没有任务。可让 Agent 使用 team_task 创建。</div>
1159
- )}
1160
- </div>
1161
- <div className="grid gap-2">
1162
- <div className="flex items-center justify-between">
1163
- <span className="text-[11px] font-semibold text-[#30343b]">团队消息</span>
1164
- <span className="font-mono text-[10px] text-[#687381]">durable mailbox</span>
1165
- </div>
1166
- {Array.isArray(data?.messages) && data.messages.length > 0 ? (
1167
- Array.from(data.messages as readonly unknown[])
1168
- .reverse()
1169
- .slice(0, 5)
1170
- .map((item, index) => {
1171
- const message = item !== null && typeof item === "object" ? (item as Record<string, unknown>) : {};
1172
- return (
1154
+ ))
1155
+ ) : (
1156
+ <div className="rounded-lg bg-[#f6f8fa] px-3 py-3 text-[12px] text-[#687381]">暂无协作角色。</div>
1157
+ )}
1158
+ </div>
1159
+ <div className="grid gap-2">
1160
+ {view.tasks.length > 0 ? (
1161
+ view.tasks.map((task) => (
1162
+ <div className="flex items-center gap-3 rounded-lg border border-[#edf0f3] px-3 py-2" key={task.id}>
1163
+ <div className="min-w-0 flex-1">
1164
+ <span className="block truncate text-[11px] text-[#30343b]">{task.title}</span>
1165
+ {task.dependsOn.length > 0 ? (
1166
+ <span className="mt-0.5 block truncate font-mono text-[9px] text-[#687381]">依赖:{task.dependsOn.join(", ")}</span>
1167
+ ) : null}
1168
+ </div>
1169
+ <span className="text-[10px] text-[#687381]">{task.assignee}</span>
1170
+ <span
1171
+ className={`rounded-full px-2 py-1 text-[10px] ${task.status === "blocked" ? "bg-[#fff4e5] text-[#8a5a00]" : task.status === "done" ? "bg-[#e8f8ee] text-[#14733f]" : "bg-[#edf3fe] text-[#3565c5]"}`}
1172
+ >
1173
+ {task.status}
1174
+ </span>
1175
+ </div>
1176
+ ))
1177
+ ) : (
1178
+ <div className="rounded-lg bg-[#f6f8fa] px-3 py-3 text-[12px] text-[#687381]">还没有任务。可让 Agent 使用 team_task 创建。</div>
1179
+ )}
1180
+ </div>
1181
+ <div className="grid gap-2">
1182
+ <div className="flex items-center justify-between">
1183
+ <span className="text-[11px] font-semibold text-[#30343b]">会话内邮箱备注</span>
1184
+ <span className="font-mono text-[10px] text-[#687381]">
1185
+ {view.inventory.messages.shown} / {view.inventory.messages.total}
1186
+ </span>
1187
+ </div>
1188
+ {view.messages.length > 0 ? (
1189
+ [...view.messages].reverse().map((message) => (
1173
1190
  <div
1174
- className={`rounded-lg border px-3 py-2 ${message.read === true ? "border-[#edf0f3] bg-white" : "border-[#cfe0ff] bg-[#f4f8ff]"}`}
1175
- key={`${value(message.id ?? "message")}-${index}`}
1191
+ className={`rounded-lg border px-3 py-2 ${message.read ? "border-[#edf0f3] bg-white" : "border-[#cfe0ff] bg-[#f4f8ff]"}`}
1192
+ key={message.id}
1176
1193
  >
1177
1194
  <div className="flex items-center gap-2 text-[10px] text-[#687381]">
1178
1195
  <span className="font-mono text-[#3565c5]">
1179
- {value(message.from ?? "unknown")} → {value(message.to ?? "unknown")}
1196
+ {message.from} → {message.to}
1180
1197
  </span>
1181
- <span className="ml-auto">{message.read === true ? "已读" : "未读"}</span>
1198
+ <span className="ml-auto">{message.read ? "已读" : "未读"}</span>
1182
1199
  </div>
1183
- <p className="mt-1 whitespace-pre-wrap break-words text-[11px] text-[#30343b]">{value(message.body ?? "")}</p>
1200
+ <p className="mt-1 whitespace-pre-wrap break-words text-[11px] text-[#30343b]">{message.body}</p>
1184
1201
  </div>
1185
- );
1186
- })
1187
- ) : (
1188
- <div className="rounded-lg bg-[#f6f8fa] px-3 py-3 text-[12px] text-[#687381]">暂无团队消息。</div>
1189
- )}
1190
- </div>
1191
- </div>
1202
+ ))
1203
+ ) : (
1204
+ <div className="rounded-lg bg-[#f6f8fa] px-3 py-3 text-[12px] text-[#687381]">暂无邮箱备注。</div>
1205
+ )}
1206
+ </div>
1207
+ {view.truncated || view.inventory.members.truncated || view.inventory.tasks.truncated || view.inventory.messages.truncated ? (
1208
+ <p className="text-[10px] leading-4 text-[#8a6200]">面板按固定安全上限展示;完整计数保留在上方。</p>
1209
+ ) : null}
1210
+ <p className="text-[10px] leading-4 text-[#687381]">这是当前 Pi 会话的协作账本,不会启动其他 Agent、创建进程或向外部发送消息。</p>
1211
+ </div>
1212
+ );
1213
+ })()
1192
1214
  ) : panel.id === "modlens-panel" ? (
1193
- <div className="mt-3 grid gap-3">
1194
- <div className={`rounded-lg border px-3 py-3 ${data?.attached === true ? "border-[#b9e6c9] bg-[#f0fbf4]" : "border-[#e3e7ee] bg-[#f6f8fa]"}`}>
1195
- <div className="flex items-center justify-between gap-3">
1196
- <span className="text-[11px] font-semibold text-[#30343b]">{data?.attached === true ? "图片已附加" : "等待图片"}</span>
1197
- <span className="font-mono text-[10px] text-[#687381]">vision_inspect</span>
1215
+ (() => {
1216
+ const view = modlensPanelView(panel.data);
1217
+ const stateLabel =
1218
+ view.status.state === "running"
1219
+ ? "正在读取视觉内容"
1220
+ : view.status.state === "failed"
1221
+ ? "视觉检查失败"
1222
+ : view.status.state === "cancelled"
1223
+ ? "视觉检查已取消"
1224
+ : view.status.state === "completed"
1225
+ ? "视觉检查完成"
1226
+ : "等待图片";
1227
+ const mode = view.status.state === "idle" ? view.image?.mode : view.status.mode;
1228
+ const path = view.status.state === "idle" ? view.image?.path : view.status.path;
1229
+ const stateStyle =
1230
+ view.status.state === "failed"
1231
+ ? "border-[#f4caca] bg-[#fff5f5]"
1232
+ : view.status.state === "cancelled"
1233
+ ? "border-[#f1d7a8] bg-[#fff9ed]"
1234
+ : view.status.state === "running"
1235
+ ? "border-[#c9d9f7] bg-[#f4f8ff]"
1236
+ : view.attached
1237
+ ? "border-[#b9e6c9] bg-[#f0fbf4]"
1238
+ : "border-[#e3e7ee] bg-[#f6f8fa]";
1239
+ return (
1240
+ <div className="mt-3 grid gap-3">
1241
+ <div className={`rounded-lg border px-3 py-3 ${stateStyle}`}>
1242
+ <div className="flex items-center justify-between gap-3">
1243
+ <span className="text-[11px] font-semibold text-[#30343b]">{stateLabel}</span>
1244
+ <span className="rounded-full border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[9px] text-[#3565c5]">
1245
+ {mode === "native" ? "原生直传" : mode === "evidence" ? "ModLens 证据" : "vision_inspect"}
1246
+ </span>
1247
+ </div>
1248
+ {path !== undefined ? <p className="mt-2 truncate font-mono text-[10px] text-[#65707b]">{path}</p> : null}
1249
+ {view.image !== null ? (
1250
+ <div className="mt-2 flex flex-wrap gap-x-3 gap-y-1 text-[10px] text-[#687381]">
1251
+ <span>{view.image.mimeType}</span>
1252
+ <span>{view.image.bytes.toLocaleString()} bytes</span>
1253
+ {view.image.cached ? <span className="font-semibold text-[#14733f]">缓存命中</span> : null}
1254
+ </div>
1255
+ ) : view.status.state === "idle" ? (
1256
+ <p className="mt-2 text-[11px] text-[#687381]">让 Agent 调用 vision_inspect,并提供工作区内的图片路径。</p>
1257
+ ) : null}
1258
+ {view.status.state === "failed" || view.status.state === "cancelled" ? (
1259
+ <p className="mt-2 break-words text-[10px] leading-4 text-[#9b2c24]">{view.status.error}</p>
1260
+ ) : null}
1261
+ </div>
1262
+ <div className="flex flex-wrap gap-2">
1263
+ {view.supportedTypes.map((type) => (
1264
+ <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[10px] text-[#3565c5]" key={type}>
1265
+ {type}
1266
+ </span>
1267
+ ))}
1268
+ </div>
1269
+ <div className="flex flex-wrap gap-2 font-mono text-[9px] text-[#687381]">
1270
+ <span>image:{Math.round(view.limits.imageBytes / 1_048_576)}MiB</span>
1271
+ <span>evidence:{Math.round(view.limits.evidenceBytes / 1_024)}KiB</span>
1272
+ <span>timeout:{Math.round(view.limits.timeoutMs / 1_000)}s</span>
1273
+ <span>cache:{view.limits.cacheEntries}</span>
1274
+ </div>
1275
+ {view.truncated ? <p className="text-[10px] leading-4 text-[#8a6200]">异常面板数据已按固定安全边界丢弃或截断。</p> : null}
1276
+ <p className="rounded-lg border border-[#dce5f5] bg-[#f7f9fd] px-3 py-2 text-[10px] leading-4 text-[#566273]">
1277
+ 纯文本模型会启动外部 ModLens 引擎,可能使用网络和 provider 配额并产生费用。视觉证据是不可信数据,不构成指令或用户授权。
1278
+ </p>
1198
1279
  </div>
1199
- {data?.image !== null && data?.image !== undefined && typeof data.image === "object" ? (
1200
- <p className="mt-2 truncate text-[11px] text-[#65707b]">
1201
- {value((data.image as Record<string, unknown>).path ?? "图片")} · {value((data.image as Record<string, unknown>).bytes ?? 0)} bytes
1280
+ );
1281
+ })()
1282
+ ) : panel.id === "vision-toolkit-panel" ? (
1283
+ (() => {
1284
+ const view = visionToolkitPanelView(panel.data);
1285
+ const report = view.report;
1286
+ const stateLabel =
1287
+ view.status.state === "running"
1288
+ ? view.status.operation === "catalog"
1289
+ ? "正在盘点视觉素材"
1290
+ : "正在读取图片元数据"
1291
+ : view.status.state === "failed"
1292
+ ? "视觉素材检查失败"
1293
+ : view.status.state === "cancelled"
1294
+ ? "视觉素材检查已取消"
1295
+ : view.status.state === "completed"
1296
+ ? "视觉素材检查完成"
1297
+ : "等待检查";
1298
+ const stateStyle =
1299
+ view.status.state === "failed"
1300
+ ? "border-[#f4caca] bg-[#fff5f5]"
1301
+ : view.status.state === "cancelled"
1302
+ ? "border-[#f1d7a8] bg-[#fff9ed]"
1303
+ : view.status.state === "running"
1304
+ ? "border-[#c9d9f7] bg-[#f4f8ff]"
1305
+ : view.status.state === "completed"
1306
+ ? "border-[#b9e6c9] bg-[#f0fbf4]"
1307
+ : "border-[#e3e7ee] bg-[#f6f8fa]";
1308
+ const shownAssets = report?.assets.slice(0, 20) ?? [];
1309
+ const shownIssues = report?.issues.slice(0, 10) ?? [];
1310
+ return (
1311
+ <div className="mt-3 grid gap-3">
1312
+ <div className={`rounded-lg border px-3 py-3 ${stateStyle}`}>
1313
+ <div className="flex items-center justify-between gap-3">
1314
+ <span className="text-[11px] font-semibold text-[#30343b]">{stateLabel}</span>
1315
+ <span className="rounded-full border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[9px] text-[#3565c5]">
1316
+ {view.status.state === "idle" ? "vision_catalog" : view.status.operation === "catalog" ? "catalog" : "image info"}
1317
+ </span>
1318
+ </div>
1319
+ {view.status.state !== "idle" && view.status.path !== undefined ? (
1320
+ <p className="mt-2 truncate font-mono text-[10px] text-[#65707b]">{view.status.path}</p>
1321
+ ) : null}
1322
+ {view.status.state === "failed" || view.status.state === "cancelled" ? (
1323
+ <p className="mt-2 break-words text-[10px] leading-4 text-[#9b2c24]">{view.status.error}</p>
1324
+ ) : null}
1325
+ </div>
1326
+ <div className="grid grid-cols-2 gap-2 sm:grid-cols-4">
1327
+ {[
1328
+ ["已扫描", report?.scannedEntries ?? 0],
1329
+ ["候选图片", report?.inspectedCandidates ?? 0],
1330
+ ["有效素材", report?.assets.length ?? 0],
1331
+ ["问题", report?.issues.length ?? 0],
1332
+ ].map(([label, count]) => (
1333
+ <div className="rounded-lg bg-[#f6f8fa] px-3 py-2" key={label}>
1334
+ <span className="block text-[10px] text-[#687381]">{label}</span>
1335
+ <strong className="mt-1 block font-mono text-[16px] text-[#30343b]">{count}</strong>
1336
+ </div>
1337
+ ))}
1338
+ </div>
1339
+ {shownAssets.length > 0 ? (
1340
+ <div className="max-h-52 overflow-auto rounded-lg border border-[#edf0f3] bg-[#fbfcfd]">
1341
+ {shownAssets.map((asset, index) => (
1342
+ <div className="border-b border-[#edf0f3] px-3 py-2 last:border-b-0" key={`${asset.path}-${index}`}>
1343
+ <div className="flex items-center justify-between gap-3">
1344
+ <span className="min-w-0 truncate font-mono text-[10px] text-[#30343b]" title={asset.path}>
1345
+ {asset.path}
1346
+ </span>
1347
+ <span className="shrink-0 font-mono text-[9px] text-[#3565c5]">{asset.width === null ? "?×?" : `${asset.width}×${asset.height}`}</span>
1348
+ </div>
1349
+ <div className="mt-1 flex flex-wrap gap-x-3 text-[9px] text-[#687381]">
1350
+ <span>{asset.mimeType}</span>
1351
+ <span>{asset.bytes.toLocaleString()} B</span>
1352
+ {asset.headerTruncated ? <span className="text-[#8a6200]">仅扫描前 256 KiB</span> : null}
1353
+ </div>
1354
+ </div>
1355
+ ))}
1356
+ </div>
1357
+ ) : (
1358
+ <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">
1359
+ {report === null ? "让 Agent 调用 vision_catalog 盘点工作区图片,或调用 vision_image_info 检查单张图片。" : "未发现有效的受支持图片。"}
1360
+ </div>
1361
+ )}
1362
+ {shownIssues.length > 0 ? (
1363
+ <div className="rounded-lg border border-[#f1d7a8] bg-[#fff9ed] px-3 py-3">
1364
+ <p className="text-[10px] font-semibold text-[#8a6200]">图片问题(显示 {shownIssues.length} 条)</p>
1365
+ <div className="mt-2 grid gap-1.5">
1366
+ {shownIssues.map((issue, index) => (
1367
+ <p className="break-words font-mono text-[9px] leading-4 text-[#6f5730]" key={`${issue.path}-${index}`}>
1368
+ {issue.path}: {issue.reason}
1369
+ </p>
1370
+ ))}
1371
+ </div>
1372
+ </div>
1373
+ ) : null}
1374
+ <div className="flex flex-wrap gap-2">
1375
+ {view.supportedTypes.map((type) => (
1376
+ <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[9px] text-[#3565c5]" key={type}>
1377
+ {type}
1378
+ </span>
1379
+ ))}
1380
+ <span className="rounded-md border border-[#e3e7ee] bg-[#f6f8fa] px-2 py-1 font-mono text-[9px] text-[#687381]">
1381
+ file≤{Math.round(view.limits.imageBytes / 1_048_576)}MiB
1382
+ </span>
1383
+ <span className="rounded-md border border-[#e3e7ee] bg-[#f6f8fa] px-2 py-1 font-mono text-[9px] text-[#687381]">
1384
+ assets≤{view.limits.assets}
1385
+ </span>
1386
+ </div>
1387
+ {view.truncated ||
1388
+ report?.truncated === true ||
1389
+ report?.issuesTruncated === true ||
1390
+ (report !== null && (report.assets.length > shownAssets.length || report.issues.length > shownIssues.length)) ? (
1391
+ <p className="text-[10px] leading-4 text-[#8a6200]">面板或扫描结果已按固定安全上限截断;计数与警告会保留可见。</p>
1392
+ ) : null}
1393
+ <p className="rounded-lg border border-[#dce5f5] bg-[#f7f9fd] px-3 py-2 text-[10px] leading-4 text-[#566273]">
1394
+ 仅在当前 workspace 内本地读取图片头部,不上传图片、不调用外部视觉服务;这里展示的是元数据,不是完整图像解码结果。
1202
1395
  </p>
1203
- ) : (
1204
- <p className="mt-2 text-[11px] text-[#687381]">调用 vision_inspect 并提供工作区内图片路径。</p>
1205
- )}
1206
- </div>
1207
- <div className="flex flex-wrap gap-2">
1208
- {capabilities.map((capability, index) => (
1209
- <span
1210
- className="rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[10px] text-[#3565c5]"
1211
- key={`${value(capability)}-${index}`}
1212
- >
1213
- {value(capability)}
1214
- </span>
1215
- ))}
1216
- </div>
1217
- </div>
1396
+ </div>
1397
+ );
1398
+ })()
1218
1399
  ) : panel.id === "at-file-panel" ? (
1219
- <div className="mt-3 grid gap-3">
1220
- <div className="rounded-lg border border-[#e3eaf8] bg-[#f6f8ff] px-3 py-3">
1221
- <div className="flex items-center justify-between gap-3">
1222
- <span className="text-[11px] font-semibold text-[#30343b]">最近附加</span>
1223
- <span className="font-mono text-[10px] text-[#687381]">file_context</span>
1400
+ (() => {
1401
+ const view = atFilePanelView(panel.data);
1402
+ return (
1403
+ <div className="mt-3 grid gap-3">
1404
+ <div className="rounded-lg border border-[#e3eaf8] bg-[#f6f8ff] px-3 py-3">
1405
+ <div className="flex items-center justify-between gap-3">
1406
+ <span className="text-[11px] font-semibold text-[#30343b]">最近附加</span>
1407
+ <span className="font-mono text-[10px] text-[#687381]">file_context</span>
1408
+ </div>
1409
+ {view.lastFile !== null ? (
1410
+ <p className="mt-2 min-w-0 whitespace-normal break-all text-[11px] leading-4 text-[#65707b]">
1411
+ {view.lastFile.path} · {view.lastFile.bytes} bytes
1412
+ </p>
1413
+ ) : (
1414
+ <p className="mt-2 text-[11px] text-[#687381]">还没有附加文件。可使用 @file 或让 Agent 调用 file_context。</p>
1415
+ )}
1416
+ </div>
1417
+ <div className="flex items-center justify-between text-[11px] text-[#687381]">
1418
+ <span>单文件上限</span>
1419
+ <strong className="font-mono text-[#3565c5]">{view.maxBytes} bytes</strong>
1420
+ </div>
1421
+ {view.truncated ? <p className="text-[10px] leading-4 text-[#8a6200]">面板数据不完整或已按固定安全上限调整。</p> : null}
1224
1422
  </div>
1225
- {data?.lastFile !== null && data?.lastFile !== undefined && typeof data.lastFile === "object" ? (
1226
- <p className="mt-2 truncate text-[11px] text-[#65707b]">
1227
- {value((data.lastFile as Record<string, unknown>).path ?? "文件")} · {value((data.lastFile as Record<string, unknown>).bytes ?? 0)} bytes
1228
- </p>
1229
- ) : (
1230
- <p className="mt-2 text-[11px] text-[#687381]">还没有附加文件。可使用 @file 或让 Agent 调用 file_context。</p>
1231
- )}
1232
- </div>
1233
- <div className="flex items-center justify-between text-[11px] text-[#687381]">
1234
- <span>单文件上限</span>
1235
- <strong className="font-mono text-[#3565c5]">{value(data?.maxBytes ?? 0)} bytes</strong>
1236
- </div>
1237
- </div>
1423
+ );
1424
+ })()
1238
1425
  ) : panel.id === "git-time-capsule-panel" ? (
1239
- <div className="mt-3 grid gap-3">
1240
- <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3">
1241
- <div className="flex items-center justify-between gap-3">
1242
- <span className="text-[11px] font-semibold text-[#30343b]">最近快照</span>
1243
- <span className="font-mono text-[10px] text-[#687381]">git_snapshot</span>
1244
- </div>
1245
- {data?.latest !== null && data?.latest !== undefined && typeof data.latest === "object" ? (
1246
- <p className="mt-2 truncate text-[11px] text-[#65707b]">
1247
- {value((data.latest as Record<string, unknown>).name ?? "snapshot")} · {value((data.latest as Record<string, unknown>).files ?? 0)} 个文件
1248
- {(data.latest as Record<string, unknown>).restored === true ? " · 已恢复" : ""}
1426
+ (() => {
1427
+ const report = gitTimeCapsulePanelView(data);
1428
+ const latest = report.latest;
1429
+ const statusLabel = latest?.status === "completed" ? "已完成" : latest?.status === "cancelled" ? "已取消" : "失败";
1430
+ const statusStyle =
1431
+ latest?.status === "completed"
1432
+ ? "border-[#b9e6c9] bg-[#f0fbf4] text-[#147a43]"
1433
+ : latest?.status === "cancelled"
1434
+ ? "border-[#f1ddb1] bg-[#fff9eb] text-[#996515]"
1435
+ : "border-[#f4caca] bg-[#fff5f5] text-[#b42318]";
1436
+ return (
1437
+ <div className="mt-3 grid gap-3">
1438
+ <div className={`rounded-lg border px-3 py-3 ${latest === null ? "border-[#e3e7ee] bg-[#f6f8fa]" : statusStyle}`}>
1439
+ <div className="flex items-center justify-between gap-3">
1440
+ <span className="text-[11px] font-semibold text-[#30343b]">{latest?.action === "restore" ? "最近撤销" : "最近捕获"}</span>
1441
+ {latest === null ? (
1442
+ <span className="font-mono text-[10px] text-[#687381]">git_snapshot</span>
1443
+ ) : (
1444
+ <span className="rounded-full border border-current px-2 py-0.5 text-[9px] font-semibold">{statusLabel}</span>
1445
+ )}
1446
+ </div>
1447
+ {latest === null ? (
1448
+ <p className="mt-2 text-[11px] leading-4 text-[#687381]">当前没有撤销胶囊。先产生 unstaged tracked 改动,再让 Agent 调用 git_snapshot。</p>
1449
+ ) : (
1450
+ <div className="mt-2 grid gap-1 text-[11px] text-[#65707b]">
1451
+ {latest.name !== null ? <p className="truncate font-mono text-[10px] text-[#30343b]">{latest.name}</p> : null}
1452
+ <p>
1453
+ {latest.files} 个文件 · {latest.bytes} bytes · <time dateTime={latest.at}>{latest.at.replace("T", " ")}</time>
1454
+ </p>
1455
+ {latest.error !== null ? <p className="break-words text-[#b42318]">{latest.error}</p> : null}
1456
+ </div>
1457
+ )}
1458
+ </div>
1459
+ <div className="rounded-lg border border-[#e3e7ee] bg-white px-3 py-3">
1460
+ <div className="flex items-center justify-between gap-3">
1461
+ <span className="text-[11px] font-semibold text-[#30343b]">最近胶囊</span>
1462
+ <span className="font-mono text-[10px] text-[#3565c5]">
1463
+ {report.inventory.shown} / {report.inventory.total}
1464
+ </span>
1465
+ </div>
1466
+ {report.capsules.length > 0 ? (
1467
+ <div className="mt-2 max-h-44 overflow-y-auto border-l-2 border-[#cbd8ef] pl-3">
1468
+ {report.capsules.map((capsule) => (
1469
+ <div className="flex min-w-0 items-center gap-2 border-b border-[#eef1f5] py-1.5 last:border-b-0" key={capsule.name}>
1470
+ <span className="min-w-0 flex-1 truncate font-mono text-[10px] text-[#30343b]">{capsule.name}</span>
1471
+ <span className="shrink-0 font-mono text-[9px] text-[#687381]">{capsule.bytes} B</span>
1472
+ </div>
1473
+ ))}
1474
+ </div>
1475
+ ) : (
1476
+ <p className="mt-2 text-[11px] text-[#687381]">尚未保存 tracked diff。</p>
1477
+ )}
1478
+ {report.inventory.truncated || report.truncated ? (
1479
+ <p className="mt-2 text-[10px] text-[#996515]">列表已按安全上限截断,仅展示最近 {report.inventory.displayLimit} 条有效记录。</p>
1480
+ ) : null}
1481
+ </div>
1482
+ <div className="grid grid-cols-2 gap-2 text-[10px] text-[#687381]">
1483
+ <span className="rounded-md bg-[#f6f8fa] px-2 py-1.5">Git 超时:{report.timeoutMs} ms</span>
1484
+ <span className="rounded-md bg-[#f6f8fa] px-2 py-1.5">单胶囊:{report.limits.capsuleBytes} B</span>
1485
+ </div>
1486
+ <p className="text-[10px] leading-4 text-[#687381]">
1487
+ git_snapshot 捕获当前 unstaged tracked 改动;git_restore 会反向应用该 patch。staged 与未跟踪文件不包含在内,恢复必须传入 confirm=true。
1249
1488
  </p>
1250
- ) : (
1251
- <p className="mt-2 text-[11px] text-[#687381]">还没有快照。修改代码前让 Agent 调用 git_snapshot。</p>
1252
- )}
1253
- </div>
1254
- <div className="flex items-center justify-between text-[11px] text-[#687381]">
1255
- <span>保留快照</span>
1256
- <strong className="font-mono text-[#3565c5]">{value(Array.isArray(data?.capsules) ? data.capsules.length : 0)} / 20</strong>
1257
- </div>
1258
- <p className="text-[10px] leading-4 text-[#687381]">恢复会反向应用选中的 patch,必须显式传入 confirm=true。</p>
1259
- </div>
1489
+ </div>
1490
+ );
1491
+ })()
1260
1492
  ) : panel.id === "dependency-checker-panel" ? (
1261
1493
  <div className="mt-3 grid gap-3">
1262
1494
  {(() => {
1263
- const report = data?.report !== null && typeof data?.report === "object" ? (data.report as Record<string, unknown>) : {};
1264
- const missing: unknown[] = Array.isArray(report.missing) ? report.missing : [];
1265
- const invalid: unknown[] = Array.isArray(report.invalid) ? report.invalid : [];
1266
- const conflicts: unknown[] = Array.isArray(report.conflicts) ? report.conflicts : [];
1495
+ const report = dependencyCheckerPanelView(data);
1496
+ const hasProblems = report.missingCount > 0 || report.invalidCount > 0 || report.conflictCount > 0;
1497
+ const isIndeterminate = report.unresolvedCount > 0 || report.truncated;
1267
1498
  return (
1268
1499
  <>
1269
1500
  <div className="flex items-center justify-between rounded-lg border border-[#dce5f5] bg-[#f6f8ff] px-3 py-2 text-[10px]">
1270
- <span className="text-[#65707b]">清单类型</span>
1271
- <strong className="font-mono uppercase text-[#315fb8]">{value(report.ecosystem ?? "npm")}</strong>
1501
+ <span className="min-w-0 truncate font-mono text-[#65707b]">{report.manifest}</span>
1502
+ <strong className="shrink-0 font-mono uppercase text-[#315fb8]">{report.ecosystem}</strong>
1272
1503
  </div>
1273
- <div className="grid grid-cols-3 gap-2">
1504
+ <div className="grid grid-cols-2 gap-2 sm:grid-cols-5">
1274
1505
  {[
1275
- ["声明", report.declared ?? 0],
1276
- ["已安装", report.installed ?? 0],
1277
- ["缺失", missing.length + invalid.length],
1506
+ ["声明", report.declared],
1507
+ ["已安装", report.installed],
1508
+ ["问题", report.missingCount + report.invalidCount],
1509
+ ["可选缺席", report.optionalMissingCount],
1510
+ ["未决", report.unresolvedCount],
1278
1511
  ].map(([label, item]) => (
1279
1512
  <div className="rounded-lg bg-[#f6f8fa] px-3 py-2" key={value(label)}>
1280
1513
  <span className="block text-[10px] text-[#687381]">{value(label)}</span>
@@ -1283,165 +1516,310 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
1283
1516
  ))}
1284
1517
  </div>
1285
1518
  <div
1286
- className={`rounded-lg border px-3 py-3 text-[11px] ${missing.length || invalid.length || conflicts.length ? "border-[#f4caca] bg-[#fff5f5] text-[#b42318]" : "border-[#b9e6c9] bg-[#f0fbf4] text-[#14733f]"}`}
1519
+ className={`min-w-0 break-words rounded-lg border px-3 py-3 text-[11px] [overflow-wrap:anywhere] ${hasProblems ? "border-[#f4caca] bg-[#fff5f5] text-[#b42318]" : isIndeterminate ? "border-[#f3dfab] bg-[#fffaf0] text-[#8a6200]" : "border-[#b9e6c9] bg-[#f0fbf4] text-[#14733f]"}`}
1287
1520
  >
1288
- {missing.length || invalid.length
1289
- ? `缺失或无效:${[...missing, ...invalid].map((item) => value(item)).join(", ")}`
1290
- : "依赖声明与本地安装一致。"}
1521
+ {report.missingCount || report.invalidCount
1522
+ ? `缺失 ${report.missingCount}、无效 ${report.invalidCount}:${[...report.missing, ...report.invalid].join(", ")}`
1523
+ : report.conflictCount
1524
+ ? `本地安装存在 ${report.conflictCount} 组声明约束冲突。`
1525
+ : report.unresolvedCount
1526
+ ? `${report.unresolvedCount} 组声明约束无法离线判定。`
1527
+ : report.truncated
1528
+ ? "报告不完整,无法确认依赖状态。"
1529
+ : "依赖声明与本地安装一致。"}
1291
1530
  </div>
1292
- {conflicts.length > 0 ? (
1531
+ {report.optionalMissingCount > 0 ? (
1532
+ <div className="min-w-0 break-words rounded-lg border border-[#f3dfab] bg-[#fffaf0] px-3 py-2 text-[10px] text-[#8a6200] [overflow-wrap:anywhere]">
1533
+ 可选依赖未安装({report.optionalMissingCount}):{report.optionalMissing.join(", ")}
1534
+ </div>
1535
+ ) : null}
1536
+ {report.conflicts.length > 0 ? (
1293
1537
  <div className="rounded-lg border border-[#f3dfab] bg-[#fffaf0] px-3 py-3 text-[11px] text-[#8a6200]">
1294
1538
  <strong>版本冲突</strong>
1295
1539
  <ul className="mt-1 grid gap-1 pl-4">
1296
- {conflicts.slice(0, 6).map((item, index) => {
1297
- const conflict = item !== null && typeof item === "object" ? (item as Record<string, unknown>) : {};
1298
- const constraints = Array.isArray(conflict.constraints) ? conflict.constraints.map((constraint) => value(constraint)).join(" · ") : "—";
1299
- return (
1300
- <li key={`${value(conflict.name ?? "dependency")}-${index}`}>
1301
- <code>{value(conflict.name ?? "dependency")}</code>:{constraints}
1302
- </li>
1303
- );
1304
- })}
1540
+ {report.conflicts.map((conflict, index) => (
1541
+ <li className="min-w-0 break-words [overflow-wrap:anywhere]" key={`${conflict.name}-${index}`}>
1542
+ <code>{conflict.name}</code>:{conflict.constraints.join(" · ") || "—"}
1543
+ </li>
1544
+ ))}
1305
1545
  </ul>
1306
1546
  </div>
1307
1547
  ) : null}
1548
+ {report.unresolved.length > 0 ? (
1549
+ <div className="rounded-lg border border-[#f3dfab] bg-[#fffaf0] px-3 py-3 text-[11px] text-[#8a6200]">
1550
+ <strong>未决约束</strong>
1551
+ <ul className="mt-1 grid gap-1 pl-4">
1552
+ {report.unresolved.map((constraint, index) => (
1553
+ <li className="min-w-0 break-words [overflow-wrap:anywhere]" key={`${constraint.name}-${index}`}>
1554
+ <code>{constraint.name}</code>:{constraint.constraints.join(" · ") || "—"}
1555
+ </li>
1556
+ ))}
1557
+ </ul>
1558
+ </div>
1559
+ ) : null}
1560
+ <div className="flex items-center justify-between text-[10px] text-[#687381]">
1561
+ <span>本地只读扫描 · 上限 {report.scanLimit} 项</span>
1562
+ {report.truncated ? <span>面板明细已截断</span> : null}
1563
+ </div>
1308
1564
  </>
1309
1565
  );
1310
1566
  })()}
1311
1567
  </div>
1312
1568
  ) : panel.id === "token-guard-panel" ? (
1313
- <div className="mt-3 grid gap-3">
1314
- <div className="grid gap-2 sm:grid-cols-2">
1315
- <div className={`rounded-lg border px-3 py-3 ${data?.exceeded === true ? "border-[#f4caca] bg-[#fff5f5]" : "border-[#e3eaf8] bg-[#f6f8ff]"}`}>
1316
- <div className="flex items-center justify-between gap-3">
1317
- <span className="text-[11px] font-semibold text-[#30343b]">上下文预算</span>
1318
- <strong className="font-mono text-[12px] text-[#315fb8]">
1319
- {value(data?.percent ?? "—")}% / {value(data?.maxPercent ?? "—")}%
1320
- </strong>
1321
- </div>
1322
- <div className="mt-2 h-2 overflow-hidden rounded-full bg-[#dfe8fb]">
1323
- <div
1324
- className={`h-full rounded-full ${data?.exceeded === true ? "bg-[#d64545]" : "bg-[#5d8bea]"}`}
1325
- style={{ width: `${Math.max(0, Math.min(100, typeof data?.percent === "number" ? data.percent : 0))}%` }}
1326
- />
1327
- </div>
1328
- <p className="mt-2 text-[11px] text-[#5d6d82]">
1329
- {data?.exceeded === true ? "已达到阈值,运行会被自动停止。" : `自动停止次数:${value(data?.aborts ?? 0)}`}
1330
- </p>
1331
- </div>
1332
- <div className={`rounded-lg border px-3 py-3 ${data?.runExceeded === true ? "border-[#f4caca] bg-[#fff5f5]" : "border-[#e3eaf8] bg-[#f6f8ff]"}`}>
1333
- <div className="flex items-center justify-between gap-3">
1334
- <span className="text-[11px] font-semibold text-[#30343b]">单次任务</span>
1335
- <strong className="font-mono text-[12px] text-[#315fb8]">
1336
- {value(data?.runTokens ?? "—")} / {value(data?.maxRunTokens || "")}
1337
- </strong>
1569
+ (() => {
1570
+ const view = tokenGuardPanelView(data);
1571
+ return (
1572
+ <div className="mt-3 grid gap-3">
1573
+ <div className="grid gap-2 sm:grid-cols-2">
1574
+ <div className={`rounded-lg border px-3 py-3 ${view.exceeded ? "border-[#f4caca] bg-[#fff5f5]" : "border-[#e3eaf8] bg-[#f6f8ff]"}`}>
1575
+ <div className="flex items-center justify-between gap-3">
1576
+ <span className="text-[11px] font-semibold text-[#30343b]">上下文预算</span>
1577
+ <strong className="font-mono text-[12px] text-[#315fb8]">
1578
+ {view.percent === null ? "—" : view.percent}% / {view.maxPercent}%
1579
+ </strong>
1580
+ </div>
1581
+ <div className="mt-2 h-2 overflow-hidden rounded-full bg-[#dfe8fb]">
1582
+ <div
1583
+ className={`h-full rounded-full ${view.exceeded ? "bg-[#d64545]" : "bg-[#5d8bea]"}`}
1584
+ style={{ width: `${Math.min(100, view.percent ?? 0)}%` }}
1585
+ />
1586
+ </div>
1587
+ <p className="mt-2 text-[11px] text-[#5d6d82]">
1588
+ {view.tokens === null ? "上下文 token 未知" : `${view.tokens.toLocaleString()} / ${view.contextWindow?.toLocaleString() ?? "—"} tokens`}
1589
+ {` · 已请求停止 ${view.aborts} 次`}
1590
+ </p>
1591
+ </div>
1592
+ <div className={`rounded-lg border px-3 py-3 ${view.runExceeded ? "border-[#f4caca] bg-[#fff5f5]" : "border-[#e3eaf8] bg-[#f6f8ff]"}`}>
1593
+ <div className="flex items-center justify-between gap-3">
1594
+ <span className="text-[11px] font-semibold text-[#30343b]">单次任务</span>
1595
+ <strong className="font-mono text-[12px] text-[#315fb8]">
1596
+ {view.runTokens === null ? "—" : view.runTokens.toLocaleString()} / {view.maxRunTokens === 0 ? "—" : view.maxRunTokens.toLocaleString()}
1597
+ </strong>
1598
+ </div>
1599
+ <p className="mt-2 text-[11px] text-[#5d6d82]">
1600
+ {view.maxRunTokens > 0 ? "按 agent_start 后新增的已结算 token 熔断。" : "未启用绝对 Token 上限。"}
1601
+ </p>
1602
+ </div>
1338
1603
  </div>
1339
- <p className="mt-2 text-[11px] text-[#5d6d82]">{data?.maxRunTokens ? "按 agent_start 后累计 token 熔断。" : "未启用绝对 Token 上限。"}</p>
1604
+ {view.lastError === null ? null : (
1605
+ <div className="rounded-lg border border-[#f4caca] bg-[#fff5f5] px-3 py-2 text-[10px] leading-4 text-[#b42318]">
1606
+ 保护器错误:{view.lastError}
1607
+ </div>
1608
+ )}
1340
1609
  </div>
1341
- </div>
1342
- </div>
1610
+ );
1611
+ })()
1343
1612
  ) : panel.id === "test-harness-panel" ? (
1344
- <div className="mt-3 grid gap-3">
1345
- {data?.latest !== null && data?.latest !== undefined && typeof data.latest === "object" ? (
1346
- (() => {
1347
- const run = data.latest as Record<string, unknown>;
1348
- return (
1349
- <div className={`rounded-lg border px-3 py-3 ${run.exitCode === 0 ? "border-[#b9e6c9] bg-[#f0fbf4]" : "border-[#f4caca] bg-[#fff5f5]"}`}>
1350
- <div className="flex items-center justify-between gap-3">
1351
- <span className="font-mono text-[11px] font-semibold text-[#30343b]">{value(run.command ?? "npm run test")}</span>
1352
- <strong className={`text-[12px] ${run.exitCode === 0 ? "text-[#14733f]" : "text-[#b42318]"}`}>exit {value(run.exitCode ?? "—")}</strong>
1613
+ (() => {
1614
+ const view = testHarnessPanelView(panel.data);
1615
+ const run = view.latest;
1616
+ const statusLabel =
1617
+ run?.status === "passed"
1618
+ ? "验证通过"
1619
+ : run?.status === "failed"
1620
+ ? "验证失败"
1621
+ : run?.status === "timed-out"
1622
+ ? "验证超时"
1623
+ : run?.status === "cancelled"
1624
+ ? "验证已取消"
1625
+ : "等待验证";
1626
+ const statusStyle =
1627
+ run?.status === "passed"
1628
+ ? "border-[#b9e6c9] bg-[#f0fbf4] text-[#14733f]"
1629
+ : run?.status === "failed"
1630
+ ? "border-[#f4caca] bg-[#fff5f5] text-[#b42318]"
1631
+ : run?.status === "timed-out" || run?.status === "cancelled"
1632
+ ? "border-[#f1d7a8] bg-[#fff9ed] text-[#8a6200]"
1633
+ : "border-[#e3e7ee] bg-[#f6f8fa] text-[#687381]";
1634
+ return (
1635
+ <div className="mt-3 grid min-w-0 gap-3">
1636
+ <div className={`min-w-0 rounded-lg border px-3 py-3 ${statusStyle}`}>
1637
+ <div className="flex min-w-0 flex-wrap items-center justify-between gap-2">
1638
+ <span className="break-all font-mono text-[11px] font-semibold text-[#30343b]">{run?.command ?? "npm run test"}</span>
1639
+ <span className="rounded-full border border-current px-2 py-0.5 text-[9px] font-semibold">{statusLabel}</span>
1640
+ </div>
1641
+ {run === null ? (
1642
+ <p className="mt-2 text-[11px] leading-4 text-[#687381]">还没有执行验证脚本。可让 Agent 调用 run_project_tests。</p>
1643
+ ) : (
1644
+ <div className="mt-2 flex flex-wrap gap-x-3 gap-y-1 text-[10px] text-[#65707b]">
1645
+ <span>exit {run.exitCode ?? "—"}</span>
1646
+ {run.signal === null ? null : <span>{run.signal}</span>}
1647
+ <span>{run.durationMs} ms</span>
1648
+ <span>{run.outputBytes.toLocaleString()} output bytes</span>
1649
+ </div>
1650
+ )}
1651
+ </div>
1652
+ {run !== null && run.output !== "" ? (
1653
+ <div className="min-w-0 rounded-lg border border-[#e3e7ee] bg-[#111318] p-3">
1654
+ <div className="mb-2 flex flex-wrap items-center justify-between gap-2 text-[9px] text-[#9ba6b2]">
1655
+ <span className="font-semibold uppercase tracking-[0.08em]">输出末尾</span>
1656
+ <span>最多 {view.limits.outputBytes} bytes</span>
1353
1657
  </div>
1354
- <p className="mt-2 text-[11px] text-[#65707b]">耗时 {value(run.durationMs ?? 0)} ms</p>
1658
+ <pre className="max-h-52 min-w-0 overflow-auto whitespace-pre-wrap break-all font-mono text-[10px] leading-4 text-[#e6edf3]">
1659
+ {run.output}
1660
+ </pre>
1355
1661
  </div>
1356
- );
1357
- })()
1358
- ) : (
1359
- <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">
1360
- 还没有执行验证脚本。可让 Agent 调用 run_project_tests。
1361
- </div>
1362
- )}
1363
- <div className="flex flex-wrap gap-2">
1364
- {Array.isArray(data?.allowedScripts)
1365
- ? data.allowedScripts.map((script, index) => (
1366
- <span
1367
- className="rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[10px] text-[#3565c5]"
1368
- key={`${value(script)}-${index}`}
1369
- >
1370
- {value(script)}
1662
+ ) : null}
1663
+ {run?.outputTruncated || run?.outputSanitized ? (
1664
+ <p className="text-[10px] leading-4 text-[#8a6200]">
1665
+ {run.outputTruncated ? "输出只保留最后 12 KiB。" : ""}
1666
+ {run.outputSanitized ? "终端控制字符已清理。" : ""}
1667
+ </p>
1668
+ ) : null}
1669
+ <div className="flex flex-wrap gap-2">
1670
+ {view.allowedScripts.map((script) => (
1671
+ <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[10px] text-[#3565c5]" key={script}>
1672
+ {script}
1371
1673
  </span>
1372
- ))
1373
- : null}
1374
- </div>
1375
- </div>
1674
+ ))}
1675
+ </div>
1676
+ <div className="flex flex-wrap gap-x-3 gap-y-1 font-mono text-[9px] text-[#687381]">
1677
+ <span>timeout {view.limits.timeoutMs} ms</span>
1678
+ <span>output {view.limits.outputBytes} bytes</span>
1679
+ </div>
1680
+ {view.truncated ? <p className="text-[10px] leading-4 text-[#8a6200]">面板数据不完整或已按固定安全上限调整。</p> : null}
1681
+ <p className="rounded-lg border border-[#f1d7a8] bg-[#fff9ed] px-3 py-2 text-[10px] leading-4 text-[#6f5730]">
1682
+ npm scripts 会执行当前项目定义的代码;仅在可信 workspace 中使用。Test Harness 不是沙箱,也不会把脚本输出当作用户授权。
1683
+ </p>
1684
+ </div>
1685
+ );
1686
+ })()
1376
1687
  ) : panel.id === "session-insights-panel" ? (
1377
- <div className="mt-3 grid gap-3">
1378
- {(() => {
1379
- const tokens = data?.tokens !== null && typeof data?.tokens === "object" ? (data.tokens as Record<string, unknown>) : {};
1380
- const usage = data?.contextUsage !== null && typeof data?.contextUsage === "object" ? (data.contextUsage as Record<string, unknown>) : {};
1688
+ (() => {
1689
+ const view = sessionInsightsPanelView(panel.data);
1690
+ const report = view.report;
1691
+ if (report === null)
1381
1692
  return (
1382
- <>
1383
- <div className="grid grid-cols-3 gap-2">
1384
- {[
1385
- ["消息", data?.totalMessages ?? 0],
1386
- ["工具调用", data?.toolCalls ?? 0],
1387
- ["成本", `$${Number(data?.cost ?? 0).toFixed(4)}`],
1388
- ].map(([label, item]) => (
1389
- <div className="rounded-lg bg-[#f6f8fa] px-3 py-2" key={value(label)}>
1390
- <span className="block text-[10px] text-[#687381]">{value(label)}</span>
1391
- <strong className="mt-1 block text-[17px] font-semibold text-[#30343b]">{value(item)}</strong>
1392
- </div>
1393
- ))}
1394
- </div>
1395
- <div className="rounded-lg border border-[#e3eaf8] bg-[#f6f8ff] px-3 py-3">
1396
- <div className="flex items-center justify-between">
1397
- <span className="text-[11px] font-semibold text-[#30343b]">上下文</span>
1398
- <strong className="font-mono text-[12px] text-[#315fb8]">{value(usage.percent ?? "—")}%</strong>
1693
+ <div className="mt-3 rounded-lg border border-[#f3c4c4] bg-[#fff4f4] px-3 py-3 text-[11px] leading-5 text-[#a23b3b]">
1694
+ 会话统计数据无效,已停止展示指标,避免把损坏数据误报为健康状态。
1695
+ </div>
1696
+ );
1697
+ const contextUsage = report.contextUsage;
1698
+ const compactionLabels = {
1699
+ idle: "尚未请求压缩",
1700
+ queued: "等待 Agent 空闲",
1701
+ running: "正在压缩",
1702
+ completed: "压缩已完成",
1703
+ failed: "压缩失败",
1704
+ cancelled: "压缩已取消",
1705
+ unknown: "压缩状态数据无效",
1706
+ } as const;
1707
+ const compactionStyles = {
1708
+ idle: "border-[#e3e7ee] bg-[#f6f8fa] text-[#687381]",
1709
+ queued: "border-[#f1d7a8] bg-[#fff9ed] text-[#8a6200]",
1710
+ running: "border-[#cbdaf6] bg-[#f3f7ff] text-[#315fb8]",
1711
+ completed: "border-[#bfe4cb] bg-[#f1fbf4] text-[#287a43]",
1712
+ failed: "border-[#f3c4c4] bg-[#fff4f4] text-[#a23b3b]",
1713
+ cancelled: "border-[#f1d7a8] bg-[#fff9ed] text-[#8a6200]",
1714
+ unknown: "border-[#f3c4c4] bg-[#fff4f4] text-[#a23b3b]",
1715
+ } as const;
1716
+ return (
1717
+ <div className="mt-3 grid min-w-0 gap-3">
1718
+ <div className="min-w-0 rounded-lg border border-[#e3e7ee] bg-white px-3 py-2">
1719
+ <span className="block text-[9px] font-semibold uppercase tracking-[0.08em] text-[#7a8490]">Session</span>
1720
+ <p className="mt-1 min-w-0 break-all font-mono text-[10px] leading-4 text-[#3d4650]">{report.sessionId}</p>
1721
+ </div>
1722
+ <div className="grid min-w-0 grid-cols-1 gap-2 min-[360px]:grid-cols-3">
1723
+ {[
1724
+ ["消息", report.totalMessages.toLocaleString("en-US")],
1725
+ ["工具调用 / 结果", `${report.toolCalls.toLocaleString("en-US")} / ${report.toolResults.toLocaleString("en-US")}`],
1726
+ ["成本", `$${report.cost.toFixed(4)}`],
1727
+ ].map(([label, item]) => (
1728
+ <div className="min-w-0 rounded-lg bg-[#f6f8fa] px-3 py-2" key={label}>
1729
+ <span className="block text-[10px] text-[#687381]">{label}</span>
1730
+ <strong className="mt-1 block break-all text-[16px] font-semibold text-[#30343b]">{item}</strong>
1399
1731
  </div>
1400
- <p className="mt-2 text-[11px] text-[#5d6d82]">
1401
- {value(tokens.total ?? 0)} tracked tokens · 输入 {value(tokens.input ?? 0)} · 输出 {value(tokens.output ?? 0)}
1732
+ ))}
1733
+ </div>
1734
+ <div className="min-w-0 rounded-lg border border-[#e3eaf8] bg-[#f6f8ff] px-3 py-3">
1735
+ <div className="flex min-w-0 flex-wrap items-center justify-between gap-2">
1736
+ <span className="text-[11px] font-semibold text-[#30343b]">累计 token</span>
1737
+ <strong className="break-all font-mono text-[14px] text-[#315fb8]">{report.tokens.total.toLocaleString("en-US")}</strong>
1738
+ </div>
1739
+ <div className="mt-2 flex min-w-0 flex-wrap gap-x-3 gap-y-1 text-[10px] leading-4 text-[#5d6d82]">
1740
+ <span>输入 {report.tokens.input.toLocaleString("en-US")}</span>
1741
+ <span>输出 {report.tokens.output.toLocaleString("en-US")}</span>
1742
+ <span>缓存读取 {report.tokens.cacheRead.toLocaleString("en-US")}</span>
1743
+ <span>缓存写入 {report.tokens.cacheWrite.toLocaleString("en-US")}</span>
1744
+ </div>
1745
+ </div>
1746
+ <div className="min-w-0 rounded-lg border border-[#e3e7ee] bg-white px-3 py-3">
1747
+ <div className="flex min-w-0 flex-wrap items-center justify-between gap-2">
1748
+ <span className="text-[11px] font-semibold text-[#30343b]">当前上下文</span>
1749
+ {contextUsage === null ? null : contextUsage.percent === null ? (
1750
+ <strong className="text-[11px] font-semibold text-[#8a6200]">待下一次模型响应</strong>
1751
+ ) : (
1752
+ <strong className="font-mono text-[12px] text-[#315fb8]">{contextUsage.percent.toFixed(1)}%</strong>
1753
+ )}
1754
+ </div>
1755
+ {contextUsage === null ? (
1756
+ <p className="mt-2 text-[10px] leading-4 text-[#687381]">当前模型未提供上下文窗口。</p>
1757
+ ) : contextUsage.tokens === null ? (
1758
+ <p className="mt-2 text-[10px] leading-4 text-[#687381]">
1759
+ 压缩后 token 暂不可估算 · 上下文窗口 {contextUsage.contextWindow.toLocaleString("en-US")}
1402
1760
  </p>
1761
+ ) : (
1762
+ <p className="mt-2 text-[10px] leading-4 text-[#687381]">
1763
+ {contextUsage.tokens.toLocaleString("en-US")} / {contextUsage.contextWindow.toLocaleString("en-US")} tokens
1764
+ </p>
1765
+ )}
1766
+ </div>
1767
+ <div className={`min-w-0 rounded-lg border px-3 py-3 ${compactionStyles[view.compaction.status]}`}>
1768
+ <div className="flex min-w-0 flex-wrap items-center justify-between gap-2">
1769
+ <span className="text-[10px] font-semibold uppercase tracking-[0.08em]">会话压缩</span>
1770
+ <strong className="text-[11px] font-semibold">{compactionLabels[view.compaction.status]}</strong>
1403
1771
  </div>
1404
- </>
1405
- );
1406
- })()}
1407
- </div>
1772
+ {view.compaction.error === null ? null : <p className="mt-2 break-words text-[10px] leading-4">{view.compaction.error}</p>}
1773
+ </div>
1774
+ {view.malformed && view.compaction.status !== "unknown" ? <p className="text-[10px] leading-4 text-[#a23b3b]">面板数据不完整或不一致。</p> : null}
1775
+ </div>
1776
+ );
1777
+ })()
1408
1778
  ) : panel.id === "session-bridge-panel" ? (
1409
1779
  <div className="mt-3 grid gap-3">
1410
1780
  {(() => {
1411
- const latestPreview =
1412
- data?.latestPreview !== null && typeof data?.latestPreview === "object"
1413
- ? ((data.latestPreview as Record<string, unknown>).preview as Record<string, unknown> | undefined)
1414
- : undefined;
1415
- const preview =
1416
- latestPreview ??
1417
- (data?.currentPreview !== null && typeof data?.currentPreview === "object" ? (data.currentPreview as Record<string, unknown>) : {});
1418
- const sections: readonly [string, unknown][] = [
1419
- ["目标", preview.goal],
1420
- ["当前状态", preview.currentState],
1421
- ["下一步", preview.nextStep],
1781
+ const view = sessionBridgePanelView(data);
1782
+ const sections: readonly [string, string][] = [
1783
+ ["目标", view.preview.goal],
1784
+ ["当前状态", view.preview.currentState],
1785
+ ["下一步", view.preview.nextStep],
1786
+ ];
1787
+ const lists: readonly (readonly [string, readonly string[]])[] = [
1788
+ ["关键决策", view.preview.decisions],
1789
+ ["关键文件", view.preview.keyFiles],
1422
1790
  ];
1423
1791
  return (
1424
1792
  <>
1425
1793
  <div className="rounded-lg border border-[#dce5f5] bg-[#f6f8ff] px-3 py-3 text-[11px] leading-5 text-[#315fb8]">
1426
1794
  预览不会创建目标会话,也不会修改源会话。
1427
1795
  </div>
1796
+ {view.status.state === "failed" || view.status.state === "cancelled" ? (
1797
+ <div
1798
+ className={`rounded-lg border px-3 py-3 text-[11px] leading-5 ${
1799
+ view.status.state === "failed" ? "border-[#f3c4c4] bg-[#fff4f4] text-[#a23b3b]" : "border-[#f4d8a8] bg-[#fff9ed] text-[#9a6700]"
1800
+ }`}
1801
+ >
1802
+ {view.status.operation === "import" ? "导入" : view.status.operation === "export" ? "导出" : "预览"}
1803
+ {view.status.state === "failed" ? "失败" : "已取消"}
1804
+ {view.status.error === null ? "" : `:${view.status.error}`}
1805
+ </div>
1806
+ ) : null}
1428
1807
  {sections.map(([label, item]) => (
1429
1808
  <div className="rounded-lg border border-[#e3e7ee] bg-white px-3 py-3" key={label}>
1430
1809
  <span className="block text-[10px] font-semibold uppercase tracking-[0.08em] text-[#687381]">{label}</span>
1431
- <p className="mt-2 whitespace-pre-wrap text-[11px] leading-5 text-[#30343b]">{value(item)}</p>
1810
+ <p className="mt-2 whitespace-pre-wrap break-words text-[11px] leading-5 text-[#30343b]">{item || "暂无"}</p>
1432
1811
  </div>
1433
1812
  ))}
1434
1813
  <div className="grid gap-2 sm:grid-cols-2">
1435
- {[
1436
- ["关键决策", preview.decisions],
1437
- ["关键文件", preview.keyFiles],
1438
- ].map(([label, items]) => (
1814
+ {lists.map(([label, items]) => (
1439
1815
  <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3" key={value(label)}>
1440
1816
  <span className="block text-[10px] font-semibold uppercase tracking-[0.08em] text-[#687381]">{value(label)}</span>
1441
- {Array.isArray(items) && items.length > 0 ? (
1817
+ {items.length > 0 ? (
1442
1818
  <ul className="mt-2 grid gap-1 text-[10px] leading-4 text-[#65707b]">
1443
- {items.slice(0, 8).map((item, index) => (
1444
- <li key={`${value(item)}-${index}`}>{value(item)}</li>
1819
+ {items.map((item, index) => (
1820
+ <li className="break-words" key={`${item}-${index}`}>
1821
+ {item}
1822
+ </li>
1445
1823
  ))}
1446
1824
  </ul>
1447
1825
  ) : (
@@ -1450,6 +1828,14 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
1450
1828
  </div>
1451
1829
  ))}
1452
1830
  </div>
1831
+ <div className="flex flex-wrap gap-2 text-[10px] text-[#687381]">
1832
+ <span>格式 v{view.formatVersion}</span>
1833
+ <span>最多 {view.limits.messages} 条消息</span>
1834
+ <span>正文 {view.limits.totalMessageCharacters} 字符</span>
1835
+ <span>附件标记 {view.limits.attachments} 个</span>
1836
+ {view.source !== null ? <span className="max-w-full truncate">来源 {view.source.sessionId}</span> : null}
1837
+ {view.latest !== null ? <span>{view.latest.direction === "import" ? "最近导入" : "最近导出"}</span> : null}
1838
+ </div>
1453
1839
  </>
1454
1840
  );
1455
1841
  })()}
@@ -1562,32 +1948,81 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
1562
1948
  )}
1563
1949
  </div>
1564
1950
  ) : panel.id === "context-doctor-panel" ? (
1565
- <div className="mt-3 grid gap-3">
1566
- <div
1567
- className={`rounded-lg border px-3 py-3 text-[11px] ${data?.status === "warning" ? "border-[#f4caca] bg-[#fff5f5] text-[#b42318]" : "border-[#b9e6c9] bg-[#f0fbf4] text-[#14733f]"}`}
1568
- >
1569
- {data?.status === "warning" ? "需要关注上下文风险。" : "上下文状态正常。"}
1570
- </div>
1571
- <div className="grid grid-cols-3 gap-2">
1572
- {[
1573
- ["占用", `${value(data?.usagePercent ?? "")}%`],
1574
- ["超大消息", data?.oversizedMessages ?? 0],
1575
- ["工具错误", data?.toolErrors ?? 0],
1576
- ].map(([label, item]) => (
1577
- <div className="rounded-lg bg-[#f6f8fa] px-3 py-2" key={value(label)}>
1578
- <span className="block text-[10px] text-[#687381]">{value(label)}</span>
1579
- <strong className="mt-1 block text-[17px] text-[#30343b]">{value(item)}</strong>
1951
+ (() => {
1952
+ const view = contextDoctorPanelView(data);
1953
+ const compactionLabel = {
1954
+ idle: "尚未请求",
1955
+ queued: "已排队",
1956
+ running: "压缩中",
1957
+ completed: "已完成",
1958
+ failed: "失败",
1959
+ cancelled: "已取消",
1960
+ unknown: "未知",
1961
+ } as const;
1962
+ const compactionTone =
1963
+ view.compaction.status === "completed"
1964
+ ? "border-[#b9e6c9] bg-[#f0fbf4] text-[#14733f]"
1965
+ : view.compaction.status === "failed"
1966
+ ? "border-[#f3c4c4] bg-[#fff4f4] text-[#a23b3b]"
1967
+ : view.compaction.status === "cancelled"
1968
+ ? "border-[#f4d8a8] bg-[#fff9ed] text-[#9a6700]"
1969
+ : "border-[#dce5f5] bg-[#f6f8ff] text-[#3565c5]";
1970
+ return (
1971
+ <div className="mt-3 grid gap-3">
1972
+ <div
1973
+ className={`rounded-lg border px-3 py-3 text-[11px] ${
1974
+ view.status === "warning"
1975
+ ? "border-[#f4caca] bg-[#fff5f5] text-[#b42318]"
1976
+ : view.status === "ok"
1977
+ ? "border-[#b9e6c9] bg-[#f0fbf4] text-[#14733f]"
1978
+ : "border-[#e3e7ee] bg-[#f6f8fa] text-[#687381]"
1979
+ }`}
1980
+ >
1981
+ {view.status === "warning" ? "需要关注上下文风险。" : view.status === "ok" ? "上下文状态正常。" : "上下文状态不可用。"}
1580
1982
  </div>
1581
- ))}
1582
- </div>
1583
- {Array.isArray(data?.recommendations) && data.recommendations.length > 0 ? (
1584
- <ul className="grid gap-1 rounded-lg border border-[#e3e7ee] bg-white px-4 py-3 text-[10px] text-[#65707b]">
1585
- {data.recommendations.slice(0, 4).map((item, index) => (
1586
- <li key={`${value(item)}-${index}`}>{value(item)}</li>
1587
- ))}
1588
- </ul>
1589
- ) : null}
1590
- </div>
1983
+ <div className="grid grid-cols-2 gap-2 sm:grid-cols-4">
1984
+ {[
1985
+ ["占用", view.usagePercent === null ? "—" : `${view.usagePercent}%`],
1986
+ ["超限/不可测", view.oversizedMessages],
1987
+ ["无法安全检查", view.uninspectableMessages],
1988
+ ["工具错误", view.toolErrors],
1989
+ ].map(([label, item]) => (
1990
+ <div className="rounded-lg bg-[#f6f8fa] px-3 py-2" key={String(label)}>
1991
+ <span className="block text-[10px] text-[#687381]">{label}</span>
1992
+ <strong className="mt-1 block text-[17px] text-[#30343b]">{item}</strong>
1993
+ </div>
1994
+ ))}
1995
+ </div>
1996
+ {view.compaction.status === "idle" || view.compaction.status === "unknown" ? null : (
1997
+ <div className={`rounded-lg border px-3 py-3 text-[11px] ${compactionTone}`}>
1998
+ <div className="flex items-center justify-between gap-2">
1999
+ <span>最近压缩</span>
2000
+ <strong>{compactionLabel[view.compaction.status]}</strong>
2001
+ </div>
2002
+ {view.compaction.error === null ? null : <p className="mt-2 break-words text-[10px] leading-4">{view.compaction.error}</p>}
2003
+ </div>
2004
+ )}
2005
+ {view.recommendations.length > 0 ? (
2006
+ <ul className="grid gap-1 rounded-lg border border-[#e3e7ee] bg-white px-4 py-3 text-[10px] text-[#65707b]">
2007
+ {view.recommendations.map((item, index) => (
2008
+ <li key={`${item}-${index}`}>{item}</li>
2009
+ ))}
2010
+ {view.recommendationsTruncated ? <li>部分建议因浏览器显示上限被省略。</li> : null}
2011
+ </ul>
2012
+ ) : null}
2013
+ <div className="flex flex-wrap gap-2 text-[10px] text-[#687381]">
2014
+ <span className="rounded bg-[#f6f8fa] px-2 py-1">
2015
+ 扫描 {view.scannedMessages} / {view.messageCount} 条消息{view.messagesTruncated ? "(已截断)" : ""}
2016
+ </span>
2017
+ <span className="rounded bg-[#f6f8fa] px-2 py-1">告警阈值 {view.warnPercent}%</span>
2018
+ <span className="rounded bg-[#f6f8fa] px-2 py-1">大消息阈值 {view.maxMessageBytes}B</span>
2019
+ <span className="rounded bg-[#f6f8fa] px-2 py-1">
2020
+ 结构预算 {view.limits.jsonNodesPerAudit} 节点 / 深度 {view.limits.jsonDepth}
2021
+ </span>
2022
+ </div>
2023
+ </div>
2024
+ );
2025
+ })()
1591
2026
  ) : panel.id === "history-compressor-panel" ? (
1592
2027
  <div className="mt-3 grid gap-3">
1593
2028
  <div className="flex items-center justify-between rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3">
@@ -1947,6 +2382,26 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
1947
2382
  ))}
1948
2383
  </div>
1949
2384
  ) : null}
2385
+ {constraints.length > 0 ? (
2386
+ <div className="rounded-lg border border-[#edf0f3] bg-[#fffaf0] px-3 py-2">
2387
+ <strong className="text-[10px] text-[#9a6700]">约束</strong>
2388
+ <ul className="mt-1 grid gap-1 text-[10px] text-[#65707b]">
2389
+ {constraints.slice(0, 8).map((constraint, index) => (
2390
+ <li key={`${constraint}-${index}`}>• {constraint}</li>
2391
+ ))}
2392
+ </ul>
2393
+ </div>
2394
+ ) : null}
2395
+ {acceptance.length > 0 ? (
2396
+ <div className="rounded-lg border border-[#edf0f3] bg-[#f0fbf4] px-3 py-2">
2397
+ <strong className="text-[10px] text-[#14733f]">验收条件</strong>
2398
+ <ul className="mt-1 grid gap-1 text-[10px] text-[#65707b]">
2399
+ {acceptance.slice(0, 8).map((criterion, index) => (
2400
+ <li key={`${criterion}-${index}`}>• {criterion}</li>
2401
+ ))}
2402
+ </ul>
2403
+ </div>
2404
+ ) : null}
1950
2405
  <div className="grid grid-cols-2 gap-2 text-[10px] text-[#65707b]">
1951
2406
  <span>约束 {constraints.length} 条</span>
1952
2407
  <span>验收 {acceptance.length} 条</span>
@@ -2100,35 +2555,31 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
2100
2555
  )}
2101
2556
  </div>
2102
2557
  ) : panel.id === "plugin-stars-panel" ? (
2103
- <div className="mt-3 grid gap-3">
2104
- <div className="flex items-center justify-between rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px]">
2105
- <span className="font-medium text-[#30343b]">社区排行榜</span>
2106
- <span className="font-mono text-[#65707b]">上限 {value(data?.limit ?? "—")}</span>
2107
- </div>
2108
- {data?.latest && typeof data.latest === "object" ? (
2109
- (() => {
2110
- const latest = data.latest as Record<string, unknown>;
2111
- const entries = Array.isArray(latest.results)
2112
- ? latest.results.flatMap((entry): Array<{ fullName: string; name: string; stars: number; htmlUrl: string; updatedAt: string }> => {
2113
- if (entry === null || typeof entry !== "object") return [];
2114
- const item = entry as Record<string, unknown>;
2115
- if (
2116
- typeof item.fullName !== "string" ||
2117
- typeof item.name !== "string" ||
2118
- typeof item.stars !== "number" ||
2119
- typeof item.htmlUrl !== "string" ||
2120
- typeof item.updatedAt !== "string"
2121
- )
2122
- return [];
2123
- return [{ fullName: item.fullName, name: item.name, stars: item.stars, htmlUrl: item.htmlUrl, updatedAt: item.updatedAt }];
2124
- })
2125
- : [];
2126
- const rows = pluginStarsRows(entries, 8);
2127
- return (
2558
+ (() => {
2559
+ const view = pluginStarsPanelView(data);
2560
+ if (view.malformed) {
2561
+ return (
2562
+ <div className="rounded-lg border border-[#f4caca] bg-[#fff5f5] px-3 py-3 text-[11px] text-[#b42318]">
2563
+ <strong className="block text-[12px]">Plugin Stars 面板数据异常</strong>
2564
+ <span className="mt-1 block">面板数据不完整或不可信,请重新加载排行榜。</span>
2565
+ </div>
2566
+ );
2567
+ }
2568
+ const latest = view.latest;
2569
+ const rows = latest?.results ?? [];
2570
+ return (
2571
+ <div className="mt-3 grid gap-3">
2572
+ <div className="flex items-center justify-between rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px]">
2573
+ <span className="font-medium text-[#30343b]">社区排行榜</span>
2574
+ <span className="font-mono text-[#65707b]">结果上限 {view.limit}</span>
2575
+ </div>
2576
+ {latest !== null ? (
2128
2577
  <>
2129
2578
  <div className="flex items-center justify-between text-[11px] text-[#65707b]">
2130
- <span>查询:{value(latest.query, "全部")}</span>
2131
- <strong className="font-mono text-[#3565c5]">{value(latest.total ?? rows.length)} 个结果</strong>
2579
+ <span>查询:{latest.query || "全部"}</span>
2580
+ <strong className="font-mono text-[#3565c5]">
2581
+ 显示 {view.inventory.shown}/{view.inventory.total}
2582
+ </strong>
2132
2583
  </div>
2133
2584
  {rows.length > 0 ? (
2134
2585
  <ol className="grid gap-1.5">
@@ -2153,16 +2604,16 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
2153
2604
  ) : (
2154
2605
  <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">没有找到匹配的社区插件。</div>
2155
2606
  )}
2156
- <p className="text-[10px] leading-4 text-[#687381]">来源:{value(latest.source, "dsh-plugin-stars")} · 仅展示公开仓库信息,不会自动安装。</p>
2607
+ <p className="text-[10px] leading-4 text-[#687381]">来源:{latest.source || "dsh-plugin-stars"} · 仅展示公开仓库信息,不会自动安装。</p>
2157
2608
  </>
2158
- );
2159
- })()
2160
- ) : (
2161
- <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">
2162
- Agent 可调用 plugin_stars_search 拉取并筛选社区排行榜。
2609
+ ) : (
2610
+ <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">
2611
+ Agent 可调用 plugin_stars_search 拉取并筛选社区排行榜。
2612
+ </div>
2613
+ )}
2163
2614
  </div>
2164
- )}
2165
- </div>
2615
+ );
2616
+ })()
2166
2617
  ) : panel.id === "plugin-finder-panel" ? (
2167
2618
  <div className="mt-3 grid gap-3">
2168
2619
  <div className="flex items-center justify-between rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px]">
@@ -2228,9 +2679,10 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
2228
2679
  </div>
2229
2680
  ) : panel.id === "graph-memory-panel" ? (
2230
2681
  (() => {
2231
- const kinds = data?.kinds !== null && typeof data?.kinds === "object" ? (data.kinds as Record<string, unknown>) : {};
2232
- const recent = Array.isArray(data?.recent) ? data.recent : [];
2233
- const recentRelations = Array.isArray(data?.recentRelations) ? data.recentRelations : [];
2682
+ const report = graphMemoryPanelView(data);
2683
+ const kinds = report.kinds;
2684
+ const recent = report.recent;
2685
+ const recentRelations = report.recentRelations;
2234
2686
  return (
2235
2687
  <div className="mt-3 grid gap-3">
2236
2688
  <div className="grid grid-cols-3 gap-2">
@@ -2251,13 +2703,13 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
2251
2703
  <div className="flex items-center justify-between rounded-lg border border-[#e3eaf8] bg-[#f6f8ff] px-3 py-2 text-[10px]">
2252
2704
  <span className="text-[#65707b]">本地关系图</span>
2253
2705
  <span className="font-mono text-[#3565c5]">
2254
- {value(data?.nodes ?? 0)} 节点 · {value(data?.relations ?? 0)} 关系
2706
+ {report.nodes} 节点 · {report.relations} 关系
2255
2707
  </span>
2256
2708
  </div>
2257
2709
  {recent.length > 0 ? (
2258
2710
  <ul className="grid gap-1.5">
2259
2711
  <li className="text-[9px] uppercase tracking-[0.08em] text-[#687381]">
2260
- 最近节点 {Math.min(recent.length, 5)} / {value(data?.nodes ?? recent.length)}
2712
+ 最近节点 {Math.min(recent.length, 5)} / {report.nodes}
2261
2713
  </li>
2262
2714
  {recent.slice(0, 5).map((entry, index) => {
2263
2715
  const item = entry !== null && typeof entry === "object" ? (entry as Record<string, unknown>) : {};
@@ -2291,7 +2743,7 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
2291
2743
  {recentRelations.length > 0 ? (
2292
2744
  <div className="grid gap-1 rounded-lg border border-[#edf0f3] bg-[#fbfcfd] px-3 py-2">
2293
2745
  <span className="text-[9px] uppercase tracking-[0.08em] text-[#687381]">
2294
- 最近关系 {Math.min(recentRelations.length, 3)} / {value(data?.relations ?? recentRelations.length)}
2746
+ 最近关系 {Math.min(recentRelations.length, 3)} / {report.relations}
2295
2747
  </span>
2296
2748
  {recentRelations.slice(0, 3).map((entry, index) => {
2297
2749
  const relation = entry !== null && typeof entry === "object" ? (entry as Record<string, unknown>) : {};
@@ -2308,6 +2760,20 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
2308
2760
  })}
2309
2761
  </div>
2310
2762
  ) : null}
2763
+ {report.lastSearch !== null ? (
2764
+ <div className="flex items-center justify-between rounded-lg border border-[#e3eaf8] bg-[#f6f8ff] px-3 py-2 text-[10px]">
2765
+ <span className="min-w-0 truncate text-[#65707b]">最近搜索:{report.lastSearch.query}</span>
2766
+ <span className="shrink-0 font-mono text-[#3565c5]">
2767
+ {report.lastSearch.shown} / {report.lastSearch.total}
2768
+ </span>
2769
+ </div>
2770
+ ) : null}
2771
+ <div className="flex flex-wrap gap-2 font-mono text-[9px] text-[#687381]">
2772
+ <span className="rounded bg-[#f6f8fa] px-2 py-1">节点 ≤ {report.limits.nodes}</span>
2773
+ <span className="rounded bg-[#f6f8fa] px-2 py-1">关系 ≤ {report.limits.relations}</span>
2774
+ <span className="rounded bg-[#f6f8fa] px-2 py-1">文件 ≤ {report.limits.fileBytes} B</span>
2775
+ </div>
2776
+ {report.truncated ? <p className="text-[10px] text-[#996515]">面板内容已按安全显示上限截断。</p> : null}
2311
2777
  </div>
2312
2778
  );
2313
2779
  })()
@@ -2463,7 +2929,7 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
2463
2929
  (() => {
2464
2930
  const budget = typeof data?.budget === "number" ? data.budget : null;
2465
2931
  const budgetPercent = typeof data?.budgetPercent === "number" ? data.budgetPercent : null;
2466
- const entries = Array.isArray(data?.entries) ? data.entries : [];
2932
+ const meterView = costMeterPanelView(data);
2467
2933
  const budgetClass =
2468
2934
  budgetPercent !== null && budgetPercent >= 100
2469
2935
  ? "text-[#b42318]"
@@ -2474,7 +2940,7 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
2474
2940
  <div className="mt-3 grid gap-3">
2475
2941
  <div className="grid grid-cols-3 gap-2">
2476
2942
  {[
2477
- ["今日", `$${Number(data?.todayCost ?? 0).toFixed(4)}`],
2943
+ ["今日(UTC)", `$${Number(data?.todayCost ?? 0).toFixed(4)}`],
2478
2944
  ["当前会话", `$${Number(data?.sessionCost ?? 0).toFixed(4)}`],
2479
2945
  ["累计", `$${Number(data?.lifetimeCost ?? 0).toFixed(4)}`],
2480
2946
  ].map(([label, item]) => (
@@ -2486,7 +2952,7 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
2486
2952
  </div>
2487
2953
  <div className="rounded-lg border border-[#e3eaf8] bg-[#f6f8ff] px-3 py-3">
2488
2954
  <div className="flex items-center justify-between text-[11px]">
2489
- <span className="text-[#65707b]">每日预算</span>
2955
+ <span className="text-[#65707b]">每日预算(UTC)</span>
2490
2956
  <strong className={budgetClass}>{budget === null ? "未设置" : `$${budget.toFixed(4)} · ${budgetPercent?.toFixed(2) ?? "0.00"}%`}</strong>
2491
2957
  </div>
2492
2958
  {budget !== null ? (
@@ -2498,20 +2964,29 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
2498
2964
  </div>
2499
2965
  ) : null}
2500
2966
  </div>
2501
- {entries.length > 0 ? (
2967
+ <div className="flex flex-wrap gap-2 text-[10px] text-[#687381]">
2968
+ <span className="rounded bg-[#f6f8fa] px-2 py-1">{meterView.dayBasis} 日账本</span>
2969
+ <span className="rounded bg-[#f6f8fa] px-2 py-1">账本上限 {meterView.entryLimit ?? "—"} 条</span>
2970
+ </div>
2971
+ {meterView.lastError !== null ? (
2972
+ <div className="rounded-lg border border-[#f0c8c4] bg-[#fff5f4] px-3 py-2 text-[10px] text-[#b42318]">最近写入错误:{meterView.lastError}</div>
2973
+ ) : null}
2974
+ {meterView.entries.length > 0 ? (
2502
2975
  <ul className="grid gap-1.5">
2503
- {entries.slice(0, 5).map((entry, index) => {
2504
- const item = entry !== null && typeof entry === "object" ? (entry as Record<string, unknown>) : {};
2505
- return (
2506
- <li
2507
- className="flex items-center justify-between rounded-lg border border-[#edf0f3] bg-white px-3 py-2 text-[10px]"
2508
- key={`${value(item.sessionId ?? "session")}-${index}`}
2509
- >
2510
- <span className="truncate font-mono text-[#65707b]">{value(item.sessionId ?? "未知会话")}</span>
2511
- <strong className="font-mono text-[#30343b]">${Number(item.cost ?? 0).toFixed(4)}</strong>
2512
- </li>
2513
- );
2514
- })}
2976
+ {meterView.entries.map((entry, index) => (
2977
+ <li className="rounded-lg border border-[#edf0f3] bg-white px-3 py-2 text-[10px]" key={`${entry.sessionId}-${entry.utcDate}-${index}`}>
2978
+ <div className="flex items-center justify-between gap-3">
2979
+ <span className="min-w-0 truncate font-mono text-[#65707b]">{entry.sessionId}</span>
2980
+ <strong className="shrink-0 font-mono text-[#30343b]">${entry.dailyCost.toFixed(4)} 当日增量</strong>
2981
+ </div>
2982
+ <div className="mt-1 flex flex-wrap gap-x-3 gap-y-1 text-[#7a8490]">
2983
+ <span>UTC {entry.utcDate}</span>
2984
+ <span>会话累计 ${entry.sessionCost.toFixed(4)}</span>
2985
+ <span>{entry.tokens} tokens</span>
2986
+ <span>{entry.messages} 消息</span>
2987
+ </div>
2988
+ </li>
2989
+ ))}
2515
2990
  </ul>
2516
2991
  ) : (
2517
2992
  <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">
@@ -3059,122 +3534,164 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
3059
3534
  )}
3060
3535
  </div>
3061
3536
  ) : panel.id === "recall-unread-panel" ? (
3062
- <div className="mt-3 grid gap-3">
3063
- <div className="flex items-center justify-between rounded-lg border border-[#dce5f5] bg-[#f6f8ff] px-3 py-3 text-[11px]">
3064
- <span className="font-medium text-[#30343b]">未回答会话</span>
3065
- <strong className="font-mono text-[#3565c5]">{value(data?.total ?? 0)} 个</strong>
3066
- </div>
3067
- {Array.isArray(data?.items) && data.items.length > 0 ? (
3068
- <div className="grid gap-2">
3069
- {data.items.slice(0, 8).map((item, index) => {
3070
- const session = item !== null && typeof item === "object" ? (item as Record<string, unknown>) : {};
3071
- return (
3072
- <div className="rounded-lg border border-[#edf0f3] bg-white px-3 py-2" key={`${value(session.id ?? "session")}-${index}`}>
3073
- <strong className="block truncate text-[11px] text-[#30343b]">{value(session.name ?? session.id ?? "未命名会话")}</strong>
3074
- <p className="mt-1 line-clamp-2 text-[10px] leading-4 text-[#65707b]">{value(session.message ?? "")}</p>
3537
+ (() => {
3538
+ const view = recallUnreadPanelView(data);
3539
+ const visible = view.items.slice(0, 8);
3540
+ return (
3541
+ <div className="mt-3 grid gap-3">
3542
+ {view.status.state === "failed" || view.status.state === "cancelled" ? (
3543
+ <div
3544
+ className={`rounded-lg border px-3 py-3 text-[11px] leading-5 ${
3545
+ view.status.state === "failed" ? "border-[#f3c4c4] bg-[#fff4f4] text-[#a23b3b]" : "border-[#f4d8a8] bg-[#fff9ed] text-[#9a6700]"
3546
+ }`}
3547
+ >
3548
+ 扫描{view.status.state === "failed" ? "失败" : "已取消"}
3549
+ {view.status.error === null ? "" : `:${view.status.error}`}
3550
+ </div>
3551
+ ) : null}
3552
+ <div className="grid grid-cols-3 gap-2">
3553
+ {[
3554
+ ["候选", view.inventory.candidates],
3555
+ ["已扫描", view.inventory.scanned],
3556
+ ["未回答", view.total],
3557
+ ].map(([label, item]) => (
3558
+ <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-2" key={value(label)}>
3559
+ <span className="block text-[10px] text-[#687381]">{value(label)}</span>
3560
+ <strong className="mt-1 block font-mono text-[17px] text-[#30343b]">{value(item)}</strong>
3075
3561
  </div>
3076
- );
3077
- })}
3562
+ ))}
3563
+ </div>
3564
+ {visible.length > 0 ? (
3565
+ <div className="grid gap-2">
3566
+ {visible.map((session, index) => (
3567
+ <div className="rounded-lg border border-[#edf0f3] bg-white px-3 py-2" key={`${session.id}-${index}`}>
3568
+ <div className="flex items-center justify-between gap-2">
3569
+ <strong className="min-w-0 flex-1 truncate text-[11px] text-[#30343b]">{session.name}</strong>
3570
+ <span className="shrink-0 font-mono text-[9px] text-[#687381]">{session.messageCount} 条消息</span>
3571
+ </div>
3572
+ <p className="mt-1 line-clamp-2 whitespace-pre-wrap break-words text-[10px] leading-4 text-[#65707b]">{session.message}</p>
3573
+ </div>
3574
+ ))}
3575
+ </div>
3576
+ ) : (
3577
+ <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">没有以未回答用户消息结束的会话。</div>
3578
+ )}
3579
+ <p className="text-[10px] leading-4 text-[#687381]">
3580
+ 已扫描 {view.inventory.scanned}/{view.inventory.available} 个会话文件,界面显示 {visible.length}/{view.inventory.unread}{" "}
3581
+ 个;只读扫描,不会修改会话。
3582
+ {view.inventory.truncated ? " 部分结果因发现、扫描或展示上限被截断。" : ""}
3583
+ </p>
3078
3584
  </div>
3079
- ) : (
3080
- <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">没有以未回答用户消息结束的会话。</div>
3081
- )}
3082
- </div>
3585
+ );
3586
+ })()
3083
3587
  ) : panel.id === "turn-rewind-panel" ? (
3084
- <div className="mt-3 grid gap-3">
3085
- {data?.latest && typeof data.latest === "object" ? (
3086
- (() => {
3087
- const latest = data.latest as Record<string, unknown>;
3088
- const target = latest.target !== null && typeof latest.target === "object" ? (latest.target as Record<string, unknown>) : {};
3089
- const cancelled = latest.cancelled === true;
3090
- return (
3091
- <div className={`rounded-lg border px-3 py-3 ${cancelled ? "border-[#f4dfb0] bg-[#fffaf0]" : "border-[#dce5f5] bg-[#f6f8ff]"}`}>
3588
+ (() => {
3589
+ const view = turnRewindPanelView(data);
3590
+ const statusLabel = {
3591
+ queued: "已排队",
3592
+ running: "执行中",
3593
+ completed: "已回退",
3594
+ failed: "失败",
3595
+ cancelled: "已取消",
3596
+ } as const;
3597
+ const statusTone = {
3598
+ queued: "border-[#dce5f5] bg-[#f6f8ff] text-[#3565c5]",
3599
+ running: "border-[#dce5f5] bg-[#f6f8ff] text-[#3565c5]",
3600
+ completed: "border-[#b9e6c9] bg-[#f0fbf4] text-[#14733f]",
3601
+ failed: "border-[#f3c4c4] bg-[#fff4f4] text-[#a23b3b]",
3602
+ cancelled: "border-[#f4d8a8] bg-[#fff9ed] text-[#9a6700]",
3603
+ } as const;
3604
+ return (
3605
+ <div className="mt-3 grid gap-3">
3606
+ {view.latest === null ? (
3607
+ <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">还没有执行回退操作。</div>
3608
+ ) : (
3609
+ <div className={`rounded-lg border px-3 py-3 ${statusTone[view.latest.status]}`}>
3092
3610
  <div className="flex items-center justify-between gap-2">
3093
- <span className="text-[10px] font-semibold uppercase tracking-[0.08em] text-[#687381]">最近操作</span>
3094
- <span
3095
- className={`rounded-full px-2 py-1 text-[10px] font-semibold ${cancelled ? "bg-[#fff0c7] text-[#9a6700]" : "bg-[#e8f8ee] text-[#14733f]"}`}
3096
- >
3097
- {cancelled ? "已取消" : "已回退"}
3098
- </span>
3611
+ <span className="text-[10px] font-semibold uppercase tracking-[0.08em]">最近操作</span>
3612
+ <span className="rounded-full bg-white/70 px-2 py-1 text-[10px] font-semibold">{statusLabel[view.latest.status]}</span>
3099
3613
  </div>
3100
- <p className="mt-2 line-clamp-2 text-[11px] leading-4 text-[#30343b]">{value(target.text ?? "未命名轮次")}</p>
3614
+ <p className="mt-2 line-clamp-2 text-[11px] leading-4 text-[#30343b]">{view.latest.target.text}</p>
3615
+ {view.latest.error === null ? null : <p className="mt-2 break-words text-[10px] leading-4">{view.latest.error}</p>}
3616
+ {view.latest.summarized ? <p className="mt-2 text-[10px] leading-4">已请求分支摘要;该选项可能调用模型并产生费用。</p> : null}
3101
3617
  </div>
3102
- );
3103
- })()
3104
- ) : (
3105
- <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">还没有执行回退操作。</div>
3106
- )}
3107
- <div className="grid gap-2">
3108
- <span className="text-[10px] font-semibold uppercase tracking-[0.08em] text-[#687381]">可回退轮次</span>
3109
- {(() => {
3110
- const candidates = Array.isArray(data?.candidates) ? data.candidates : [];
3111
- return candidates.length > 0 ? (
3112
- candidates.slice(-8).map((item, index) => {
3113
- const candidate = item !== null && typeof item === "object" ? (item as Record<string, unknown>) : {};
3114
- return (
3115
- <div
3116
- className="flex items-start gap-2 rounded-lg border border-[#edf0f3] bg-white px-3 py-2"
3117
- key={`${value(candidate.entryId ?? "turn")}-${index}`}
3118
- >
3119
- <span className="mt-0.5 font-mono text-[10px] text-[#3565c5]">{candidates.length - index}</span>
3120
- <span className="line-clamp-2 min-w-0 flex-1 text-[11px] leading-4 text-[#65707b]">{value(candidate.text ?? "未命名轮次")}</span>
3618
+ )}
3619
+ <div className="grid gap-2">
3620
+ <span className="text-[10px] font-semibold uppercase tracking-[0.08em] text-[#687381]">可回退轮次</span>
3621
+ {view.candidates.length > 0 ? (
3622
+ view.candidates.map((candidate, index) => (
3623
+ <div className="flex items-start gap-2 rounded-lg border border-[#edf0f3] bg-white px-3 py-2" key={`${candidate.entryId}-${index}`}>
3624
+ <span className="mt-0.5 font-mono text-[10px] text-[#3565c5]">{view.candidates.length - index}</span>
3625
+ <span className="line-clamp-2 min-w-0 flex-1 text-[11px] leading-4 text-[#65707b]">{candidate.text}</span>
3121
3626
  </div>
3122
- );
3123
- })
3124
- ) : (
3125
- <div className="rounded-lg border border-[#edf0f3] bg-white px-3 py-3 text-[11px] text-[#687381]">当前会话还没有可回退的用户轮次。</div>
3126
- );
3127
- })()}
3128
- </div>
3129
- </div>
3627
+ ))
3628
+ ) : (
3629
+ <div className="rounded-lg border border-[#edf0f3] bg-white px-3 py-3 text-[11px] text-[#687381]">当前会话还没有可回退的用户轮次。</div>
3630
+ )}
3631
+ </div>
3632
+ <p className="text-[10px] leading-4 text-[#687381]">
3633
+ 已检查当前分支 {view.inventory.scannedEntries} 个条目;后端保留 {view.inventory.shown} 个候选,界面显示 {view.candidates.length} 个。
3634
+ {view.inventory.truncated ? " 部分结果因扫描、候选或显示上限被截断。" : ""}
3635
+ </p>
3636
+ </div>
3637
+ );
3638
+ })()
3130
3639
  ) : panel.id === "skill-guard-panel" ? (
3131
- <div className="mt-3 grid gap-3">
3132
- <div className="grid grid-cols-3 gap-2">
3133
- {[
3134
- ["已扫描", data?.total ?? 0],
3135
- ["高风险", data?.blocked ?? 0],
3136
- ["待复核", data?.review ?? 0],
3137
- ].map(([label, item]) => (
3138
- <div className="rounded-lg bg-[#f6f8fa] px-3 py-2" key={value(label)}>
3139
- <span className="block text-[10px] text-[#687381]">{value(label)}</span>
3140
- <strong className="mt-1 block text-[17px] font-semibold text-[#30343b]">{value(item)}</strong>
3640
+ (() => {
3641
+ const view = skillGuardPanelView(data);
3642
+ return (
3643
+ <div className="mt-3 grid gap-3">
3644
+ {view.status.state === "failed" || view.status.state === "cancelled" ? (
3645
+ <div
3646
+ className={`rounded-lg border px-3 py-3 text-[11px] leading-5 ${
3647
+ view.status.state === "failed" ? "border-[#f3c4c4] bg-[#fff4f4] text-[#a23b3b]" : "border-[#f4d8a8] bg-[#fff9ed] text-[#9a6700]"
3648
+ }`}
3649
+ >
3650
+ 扫描{view.status.state === "failed" ? "失败" : "已取消"}
3651
+ {view.status.error === null ? "" : `:${view.status.error}`}
3652
+ </div>
3653
+ ) : null}
3654
+ <div className="grid grid-cols-3 gap-2">
3655
+ {[
3656
+ ["已扫描", view.total],
3657
+ ["高风险", view.blocked],
3658
+ ["待复核", view.review],
3659
+ ].map(([label, item]) => (
3660
+ <div className="rounded-lg bg-[#f6f8fa] px-3 py-2" key={value(label)}>
3661
+ <span className="block text-[10px] text-[#687381]">{value(label)}</span>
3662
+ <strong className="mt-1 block text-[17px] font-semibold text-[#30343b]">{value(item)}</strong>
3663
+ </div>
3664
+ ))}
3141
3665
  </div>
3142
- ))}
3143
- </div>
3144
- <div className="grid gap-2">
3145
- {Array.isArray(data?.reports) && data.reports.length > 0 ? (
3146
- data.reports.slice(0, 8).map((item, index) => {
3147
- const report = item !== null && typeof item === "object" ? (item as Record<string, unknown>) : {};
3148
- const risk = report.risk;
3149
- const findings = Array.isArray(report.findings) ? report.findings : [];
3150
- return (
3151
- <div className="rounded-lg border border-[#edf0f3] bg-white px-3 py-2" key={`${value(report.name ?? "skill")}-${index}`}>
3152
- <div className="flex items-center gap-2">
3153
- <span
3154
- className={`h-2 w-2 rounded-full ${risk === "blocked" ? "bg-[#d64545]" : risk === "review" ? "bg-[#e0a11a]" : "bg-[#22a06b]"}`}
3155
- ></span>
3156
- <strong className="min-w-0 flex-1 truncate text-[11px] text-[#30343b]">{value(report.name ?? "unknown")}</strong>
3157
- <span className="text-[10px] text-[#687381]">{risk === "blocked" ? "阻断" : risk === "review" ? "复核" : "安全"}</span>
3666
+ <div className="grid gap-2">
3667
+ {view.reports.length > 0 ? (
3668
+ view.reports.slice(0, 8).map((report, index) => (
3669
+ <div className="rounded-lg border border-[#edf0f3] bg-white px-3 py-2" key={`${report.name}-${index}`}>
3670
+ <div className="flex items-center gap-2">
3671
+ <span
3672
+ className={`h-2 w-2 rounded-full ${report.risk === "blocked" ? "bg-[#d64545]" : report.risk === "review" ? "bg-[#e0a11a]" : "bg-[#22a06b]"}`}
3673
+ ></span>
3674
+ <strong className="min-w-0 flex-1 truncate text-[11px] text-[#30343b]">{report.name}</strong>
3675
+ <span className="text-[10px] text-[#687381]">{report.risk === "blocked" ? "高风险" : report.risk === "review" ? "复核" : "安全"}</span>
3676
+ </div>
3677
+ {report.findings.length > 0 ? (
3678
+ <p className="mt-1 truncate text-[10px] text-[#65707b]">{report.findings.map((finding) => finding.code).join(" · ")}</p>
3679
+ ) : null}
3158
3680
  </div>
3159
- {findings.length > 0 ? (
3160
- <p className="mt-1 truncate text-[10px] text-[#65707b]">
3161
- {findings
3162
- .map((finding) =>
3163
- finding !== null && typeof finding === "object" ? value((finding as Record<string, unknown>).code ?? "finding") : value(finding),
3164
- )
3165
- .join(" · ")}
3166
- </p>
3167
- ) : null}
3681
+ ))
3682
+ ) : (
3683
+ <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">
3684
+ 暂无 Skill 扫描结果,可让 Agent 调用 skill_guard_scan。
3168
3685
  </div>
3169
- );
3170
- })
3171
- ) : (
3172
- <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">
3173
- 暂无 Skill 扫描结果,可让 Agent 调用 skill_guard_scan。
3686
+ )}
3174
3687
  </div>
3175
- )}
3176
- </div>
3177
- </div>
3688
+ <p className="text-[10px] text-[#687381]">
3689
+ 已扫描 {view.inventory.scanned}/{view.inventory.available} 个入口,面板显示 {Math.min(view.reports.length, 8)} 个;风险等级仅供审计,不会禁用
3690
+ Skill。
3691
+ </p>
3692
+ </div>
3693
+ );
3694
+ })()
3178
3695
  ) : panel.id === "prompt-guard-panel" ? (
3179
3696
  <div className="mt-3 grid gap-3">
3180
3697
  <div
@@ -3231,56 +3748,61 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
3231
3748
  </div>
3232
3749
  ) : panel.id === "genui-panel" ? (
3233
3750
  <div className="mt-3 grid gap-3">
3234
- {data?.latest !== null && data?.latest !== undefined && typeof data.latest === "object" ? (
3235
- (() => {
3236
- const report = data.latest as Record<string, unknown>;
3237
- const blocks = Array.isArray(report.blocks) ? report.blocks : [];
3238
- const toneClass: Record<string, string> = {
3239
- neutral: "border-[#e3e7ee] bg-[#f6f8fa] text-[#65707b]",
3240
- info: "border-[#d9e4f7] bg-[#f6f8ff] text-[#315fb8]",
3241
- success: "border-[#b9e6c9] bg-[#f0fbf4] text-[#14733f]",
3242
- warning: "border-[#f3dfab] bg-[#fffaf0] text-[#9a6700]",
3243
- danger: "border-[#f4caca] bg-[#fff5f5] text-[#b42318]",
3244
- };
3245
- return (
3246
- <div className="grid gap-2">
3247
- <div className="flex items-center justify-between text-[11px]">
3248
- <strong className="text-[#30343b]">{value(report.title ?? "结构化卡片")}</strong>
3249
- <span className="font-mono text-[#687381]">{value(data.rendered ?? 0)} 次</span>
3250
- </div>
3251
- {blocks.map((block, index) => {
3252
- const item = block && typeof block === "object" ? (block as Record<string, unknown>) : {};
3253
- const tone = value(item.tone ?? "neutral");
3254
- const blockValue = item.value;
3255
- return item.type === "progress" ? (
3256
- <div className={`rounded-lg border px-3 py-2 ${toneClass[tone] ?? toneClass.neutral}`} key={`${value(item.label)}-${index}`}>
3257
- <div className="flex items-center justify-between text-[10px]">
3258
- <span>{value(item.label ?? "进度")}</span>
3259
- <strong>{value(blockValue ?? 0)}%</strong>
3260
- </div>
3261
- <div className="mt-1 h-1.5 overflow-hidden rounded-full bg-white/70">
3262
- <div className="h-full rounded-full bg-current" style={{ width: `${Math.max(0, Math.min(100, Number(blockValue) || 0))}%` }} />
3263
- </div>
3751
+ {(() => {
3752
+ const view = genUiPanelView(data);
3753
+ const toneClass: Record<string, string> = {
3754
+ neutral: "border-[#e3e7ee] bg-[#f6f8fa] text-[#65707b]",
3755
+ info: "border-[#d9e4f7] bg-[#f6f8ff] text-[#315fb8]",
3756
+ success: "border-[#b9e6c9] bg-[#f0fbf4] text-[#14733f]",
3757
+ warning: "border-[#f3dfab] bg-[#fffaf0] text-[#9a6700]",
3758
+ danger: "border-[#f4caca] bg-[#fff5f5] text-[#b42318]",
3759
+ };
3760
+ return view.latest !== null ? (
3761
+ <div className="grid gap-2">
3762
+ <div className="flex items-start justify-between gap-3 text-[11px]">
3763
+ <strong className="min-w-0 break-words text-[#30343b]">{view.latest.title}</strong>
3764
+ <span className="shrink-0 font-mono text-[10px] text-[#687381]">{view.rendered} 次</span>
3765
+ </div>
3766
+ {view.latest.blocks.map((block, index) =>
3767
+ block.type === "progress" ? (
3768
+ <div className={`rounded-lg border px-3 py-2 ${toneClass[block.tone]}`} key={`${block.label}-${index}`}>
3769
+ <div className="flex items-center justify-between gap-2 text-[10px]">
3770
+ <span className="min-w-0 break-words">{block.label}</span>
3771
+ <strong className="shrink-0">{block.value}%</strong>
3264
3772
  </div>
3265
- ) : (
3266
- <div
3267
- className={`flex items-center justify-between rounded-lg border px-3 py-2 text-[11px] ${toneClass[tone] ?? toneClass.neutral}`}
3268
- key={`${value(item.label)}-${index}`}
3269
- >
3270
- <span className="text-[#65707b]">{value(item.label, "")}</span>
3271
- <strong>{value(blockValue, "")}</strong>
3773
+ <div className="mt-1 h-1.5 overflow-hidden rounded-full bg-white/70">
3774
+ <div className="h-full rounded-full bg-current" style={{ width: `${block.value}%` }} />
3272
3775
  </div>
3273
- );
3274
- })}
3776
+ </div>
3777
+ ) : block.type === "text" ? (
3778
+ <div className={`rounded-lg border px-3 py-2 text-[11px] ${toneClass[block.tone]}`} key={`${block.label}-${index}`}>
3779
+ <strong className="block text-[10px]">{block.label}</strong>
3780
+ <p className="mt-1 whitespace-pre-wrap break-words leading-4">{block.value}</p>
3781
+ </div>
3782
+ ) : (
3783
+ <div
3784
+ className={`flex items-center justify-between gap-3 rounded-lg border px-3 py-2 text-[11px] ${toneClass[block.tone]}`}
3785
+ key={`${block.label}-${index}`}
3786
+ >
3787
+ <span className="min-w-0 break-words">{block.label}</span>
3788
+ <strong className="min-w-0 break-words text-right">{block.value}</strong>
3789
+ </div>
3790
+ ),
3791
+ )}
3792
+ <div className="flex flex-wrap gap-2 text-[10px] text-[#687381]">
3793
+ <span>最多 {view.limits.blocks} 块</span>
3794
+ <span>总文本上限 {view.limits.totalText} 字符</span>
3795
+ {view.latest.renderedAt !== null ? <span>{view.latest.renderedAt.slice(11, 19)} UTC</span> : null}
3796
+ {view.latest.truncated ? <span>面板明细已截断</span> : null}
3275
3797
  </div>
3276
- );
3277
- })()
3278
- ) : (
3279
- <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">
3280
- 还没有结构化卡片。可让 Agent 调用 genui_render。
3281
- </div>
3282
- )}
3283
- <p className="text-[10px] text-[#687381]">仅渲染结构化文本、徽标和进度块;HTML 与脚本按普通文本处理。</p>
3798
+ </div>
3799
+ ) : (
3800
+ <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">
3801
+ 还没有结构化卡片。可让 Agent 调用 genui_render。
3802
+ </div>
3803
+ );
3804
+ })()}
3805
+ <p className="text-[10px] text-[#687381]">仅渲染结构化文本、徽标和进度块;HTML 与脚本按普通文本显示。</p>
3284
3806
  </div>
3285
3807
  ) : panel.id === "anchored-standard-panel" ? (
3286
3808
  <div className="mt-3 grid gap-3">
@@ -3330,34 +3852,73 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
3330
3852
  </div>
3331
3853
  ) : panel.id === "plugin-dev-panel" ? (
3332
3854
  <div className="mt-3 grid gap-3">
3333
- <div
3334
- className={`flex items-center justify-between rounded-lg border px-3 py-3 text-[11px] ${data?.status === "reloaded" ? "border-[#b9e6c9] bg-[#f0fbf4] text-[#14733f]" : data?.status === "failed" ? "border-[#f4caca] bg-[#fff5f5] text-[#b42318]" : "border-[#e3e7ee] bg-[#f6f8fa] text-[#65707b]"}`}
3335
- >
3336
- <span>{data?.status === "reloaded" ? "插件已重载" : data?.status === "failed" ? "插件重载失败" : "等待重载"}</span>
3337
- <strong className="font-mono">{value(data?.status ?? "idle")}</strong>
3338
- </div>
3339
- <p className="text-[10px] text-[#687381]">{value(data?.reason ?? "修改本地扩展后调用 plugin_dev_reload")}</p>
3340
- {data?.error ? <p className="rounded-lg bg-[#fff5f5] px-3 py-2 text-[10px] text-[#b42318]">{value(data.error)}</p> : null}
3855
+ {(() => {
3856
+ const view = pluginDevPanelView(data);
3857
+ const presentation = {
3858
+ idle: { label: "等待重载", style: "border-[#e3e7ee] bg-[#f6f8fa] text-[#65707b]" },
3859
+ queued: { label: "等待当前运行结束", style: "border-[#d9e4f7] bg-[#f6f8ff] text-[#315fb8]" },
3860
+ running: { label: "正在重载会话资源", style: "border-[#d9e4f7] bg-[#f6f8ff] text-[#315fb8]" },
3861
+ reloaded: { label: "会话资源已重载", style: "border-[#b9e6c9] bg-[#f0fbf4] text-[#14733f]" },
3862
+ failed: { label: "会话资源重载失败", style: "border-[#f4caca] bg-[#fff5f5] text-[#b42318]" },
3863
+ cancelled: { label: "会话资源重载已取消", style: "border-[#f3dfab] bg-[#fffaf0] text-[#9a6700]" },
3864
+ }[view.status];
3865
+ return (
3866
+ <>
3867
+ <div className={`flex items-center justify-between rounded-lg border px-3 py-3 text-[11px] ${presentation.style}`}>
3868
+ <span>{presentation.label}</span>
3869
+ <strong className="font-mono">{view.status}</strong>
3870
+ </div>
3871
+ <p className="break-words text-[10px] text-[#687381]">{view.reason || "修改本地扩展后调用 plugin_dev_reload"}</p>
3872
+ {view.error !== null ? <p className="break-words rounded-lg bg-[#fff5f5] px-3 py-2 text-[10px] text-[#b42318]">{view.error}</p> : null}
3873
+ <div className="flex flex-wrap gap-2 text-[10px] text-[#687381]">
3874
+ <span>原因上限 {view.limits.reasonCharacters} 字符</span>
3875
+ <span>错误上限 {view.limits.errorCharacters} 字符</span>
3876
+ {view.reloadedAt !== null ? <span>{view.reloadedAt.slice(11, 19)} UTC</span> : null}
3877
+ </div>
3878
+ </>
3879
+ );
3880
+ })()}
3341
3881
  </div>
3342
3882
  ) : panel.id === "openpets-panel" ? (
3343
3883
  <div className="mt-3 grid gap-3">
3344
- <div className="flex items-center gap-3 rounded-lg border border-[#e3e7ee] bg-[#f8fafc] px-3 py-3">
3345
- <span className="flex h-10 w-10 items-center justify-center rounded-full bg-[#dceaff] text-[20px] text-[#3565c5]">◉</span>
3346
- <div className="min-w-0 flex-1">
3347
- <strong className="block truncate text-[13px] text-[#30343b]">{value(data?.name ?? "Pi")}</strong>
3348
- <span className="text-[10px] text-[#687381]">{value(data?.lastEvent ?? "session_start")}</span>
3349
- </div>
3350
- <span className="rounded-full bg-[#edf3fe] px-2 py-1 text-[10px] text-[#3565c5]">{value(data?.mood ?? "idle")}</span>
3351
- </div>
3352
- <div className="grid grid-cols-2 gap-2 text-[10px] text-[#65707b]">
3353
- <div className="rounded-lg bg-[#f6f8fa] px-3 py-2">
3354
- 能量 <strong className="ml-1 text-[#30343b]">{value(data?.energy ?? 0)}%</strong>
3355
- </div>
3356
- <div className="rounded-lg bg-[#f6f8fa] px-3 py-2">
3357
- 互动 <strong className="ml-1 text-[#30343b]">{value(data?.interactions ?? 0)}</strong>
3358
- </div>
3359
- </div>
3360
- <p className="text-[10px] text-[#687381]">根据真实 Pi 会话事件自动反应,也可让 Agent 调用 pet_react 进行互动。</p>
3884
+ {(() => {
3885
+ const view = openPetsPanelView(data);
3886
+ const moodLabel = { idle: "休息", focused: "专注", happy: "开心", concerned: "担心" }[view.mood];
3887
+ return (
3888
+ <>
3889
+ <div className="flex items-center gap-3 rounded-lg border border-[#e3e7ee] bg-[#f8fafc] px-3 py-3">
3890
+ <span className="flex h-10 w-10 items-center justify-center rounded-full bg-[#dceaff] text-[20px] text-[#3565c5]">◉</span>
3891
+ <div className="min-w-0 flex-1">
3892
+ <strong className="block truncate text-[13px] text-[#30343b]">{view.name}</strong>
3893
+ <span className="text-[10px] text-[#687381]">{view.lastEvent}</span>
3894
+ </div>
3895
+ <span className="rounded-full bg-[#edf3fe] px-2 py-1 text-[10px] text-[#3565c5]">{moodLabel}</span>
3896
+ </div>
3897
+ <div className="grid grid-cols-2 gap-2 text-[10px] text-[#65707b]">
3898
+ <div className="rounded-lg bg-[#f6f8fa] px-3 py-2">
3899
+ 能量 <strong className="ml-1 text-[#30343b]">{view.energy}%</strong>
3900
+ </div>
3901
+ <div className="rounded-lg bg-[#f6f8fa] px-3 py-2">
3902
+ 互动 <strong className="ml-1 text-[#30343b]">{view.interactions}</strong>
3903
+ </div>
3904
+ </div>
3905
+ <div className="flex flex-wrap gap-2 text-[10px] text-[#687381]">
3906
+ <span>
3907
+ 恢复扫描 {view.recovery.scanned} / {view.recovery.sessionEntries}
3908
+ </span>
3909
+ <span>{view.recovery.restored ? "已恢复状态" : "使用初始状态"}</span>
3910
+ <span>
3911
+ 持久化 {view.persistence.attempts - view.persistence.failures} / {view.persistence.attempts}
3912
+ </span>
3913
+ {view.updatedAt !== null ? <span>{view.updatedAt.slice(11, 19)} UTC</span> : null}
3914
+ </div>
3915
+ {view.persistence.lastError !== null ? (
3916
+ <p className="break-words rounded-lg bg-[#fff5f5] px-3 py-2 text-[10px] text-[#b42318]">{view.persistence.lastError}</p>
3917
+ ) : null}
3918
+ <p className="text-[10px] text-[#687381]">根据真实 Pi 会话事件自动反应,也可让 Agent 调用 pet_react 进行互动。</p>
3919
+ </>
3920
+ );
3921
+ })()}
3361
3922
  </div>
3362
3923
  ) : panel.id === "change-verifier-panel" ? (
3363
3924
  <div className="mt-3 grid gap-3">
@@ -3394,51 +3955,140 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
3394
3955
  <p className="text-[10px] text-[#687381]">复用 run_project_tests 和 review_changes,不重复实现测试或审查逻辑。</p>
3395
3956
  </div>
3396
3957
  ) : panel.id === "readme-gen-panel" ? (
3397
- <div className="mt-3 grid gap-3">
3398
- {data?.generated === true ? (
3399
- <>
3400
- <div className="rounded-lg border border-[#b9e6c9] bg-[#f0fbf4] px-3 py-3 text-[11px] text-[#14733f]">
3401
- 已生成 {value(data.name ?? "项目")} README 概览:{value(data.scripts ?? 0)} 个脚本,{value(data.plugins ?? 0)} 个运行时插件。
3958
+ (() => {
3959
+ const view = readmeGenPanelView(data);
3960
+ if (view.malformed)
3961
+ return (
3962
+ <div className="mt-3 rounded-lg border border-[#f4caca] bg-[#fff5f5] px-3 py-3 text-[11px] leading-5 text-[#b42318]">
3963
+ README 面板数据无效,暂不展示生成或写入结果。
3964
+ </div>
3965
+ );
3966
+ const statusLabel =
3967
+ view.status.state === "idle"
3968
+ ? "等待生成"
3969
+ : view.status.state === "running"
3970
+ ? view.status.operation === "write"
3971
+ ? "正在写入"
3972
+ : "正在生成"
3973
+ : view.status.state === "completed"
3974
+ ? view.status.operation === "write"
3975
+ ? "写入已完成"
3976
+ : "草稿已生成"
3977
+ : view.status.state === "failed"
3978
+ ? view.status.operation === "write"
3979
+ ? "写入失败"
3980
+ : "生成失败"
3981
+ : view.status.operation === "write"
3982
+ ? "写入已取消"
3983
+ : "生成已取消";
3984
+ const statusTone =
3985
+ view.status.state === "failed" || view.status.state === "cancelled"
3986
+ ? "border-[#f4caca] bg-[#fff5f5] text-[#b42318]"
3987
+ : view.status.state === "completed"
3988
+ ? "border-[#b9e6c9] bg-[#f0fbf4] text-[#14733f]"
3989
+ : "border-[#dce5f5] bg-[#f6f8ff] text-[#315fb8]";
3990
+ return (
3991
+ <div className="mt-3 grid min-w-0 gap-3">
3992
+ <div className={`flex min-w-0 items-center justify-between gap-3 rounded-lg border px-3 py-2 text-[10px] ${statusTone}`}>
3993
+ <strong className="font-semibold">{statusLabel}</strong>
3994
+ {view.status.at !== null ? <time className="shrink-0 font-mono">{view.status.at.slice(11, 19)} UTC</time> : null}
3402
3995
  </div>
3403
- {data.lastWrite && typeof data.lastWrite === "object" ? (
3404
- <div className="rounded-lg border border-[#dce5f5] bg-[#f6f8ff] px-3 py-2 text-[11px] text-[#315fb8]">
3405
- 已写入 {value((data.lastWrite as Record<string, unknown>).path ?? "README.generated.md")} ·{" "}
3406
- {value((data.lastWrite as Record<string, unknown>).bytes ?? 0)} bytes
3407
- {(data.lastWrite as Record<string, unknown>).overwritten === true ? " · 已覆盖" : " · 新文件"}
3996
+ {view.generated === null ? (
3997
+ <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] leading-5 text-[#687381]">
3998
+ 还没有生成 README 草稿。让 Agent 调用 <code className="font-mono text-[#3565c5]">readme_report</code> 先检查内容。
3999
+ </div>
4000
+ ) : (
4001
+ <div className="min-w-0 border-l-2 border-[#7aa2e8] bg-[#f8faff] px-3 py-3">
4002
+ <p className="break-all text-[12px] font-semibold leading-5 text-[#20252b]">{view.generated.name}</p>
4003
+ <p className="mt-1 text-[10px] text-[#687381]">
4004
+ {view.generated.scripts} 个脚本 · {view.generated.plugins} 个运行时插件
4005
+ </p>
4006
+ </div>
4007
+ )}
4008
+ {view.lastWrite !== null ? (
4009
+ <div className="min-w-0 rounded-lg border border-[#dce5f5] bg-white px-3 py-2 text-[#315fb8]">
4010
+ <p className="break-all font-mono text-[10px] leading-4">{view.lastWrite.path}</p>
4011
+ <p className="mt-1 text-[10px] text-[#687381]">
4012
+ {new Intl.NumberFormat("en-US").format(view.lastWrite.bytes)} bytes · {view.lastWrite.overwritten ? "已覆盖" : "新文件"}
4013
+ </p>
3408
4014
  </div>
3409
4015
  ) : null}
3410
- <p className="text-[10px] leading-4 text-[#687381]">需要落盘时调用 readme_write,并显式传入 confirm=true;默认写入 README.generated.md。</p>
3411
- </>
3412
- ) : (
3413
- <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">
3414
- 还没有生成文档。让 Agent 调用 readme_report 获取 Markdown 草稿,或调用 readme_write 写入确认后的文件。
4016
+ {view.status.error !== null ? (
4017
+ <p className="break-words rounded-lg bg-[#fff5f5] px-3 py-2 text-[10px] leading-4 text-[#b42318]">{view.status.error}</p>
4018
+ ) : null}
4019
+ <p className="text-[10px] leading-4 text-[#687381]">
4020
+ 写入需要 <code className="font-mono">confirm=true</code>;覆盖已有 README 还需要 <code className="font-mono">overwrite=true</code>。
4021
+ </p>
3415
4022
  </div>
3416
- )}
3417
- </div>
4023
+ );
4024
+ })()
3418
4025
  ) : panel.id === "sql-lens-panel" ? (
3419
- <div className="mt-3 grid gap-3">
3420
- {data?.latest !== null && data?.latest !== undefined && typeof data.latest === "object" ? (
3421
- (() => {
3422
- const report = data.latest as Record<string, unknown>;
3423
- const rows = Array.isArray(report.rows) ? report.rows : [];
3424
- return (
4026
+ (() => {
4027
+ const view = sqlLensPanelView(data);
4028
+ if (view.malformed) {
4029
+ return (
4030
+ <div className="mt-3 rounded-lg border border-[#f4caca] bg-[#fff5f5] px-3 py-3 text-[11px] text-[#b42318]">
4031
+ <strong className="block text-[12px]">SQL Lens 面板数据异常</strong>
4032
+ <span className="mt-1 block">面板数据不完整或不可信,请重新加载后再查询。</span>
4033
+ </div>
4034
+ );
4035
+ }
4036
+ const report = view.latest;
4037
+ const statusLabel =
4038
+ view.status.state === "running"
4039
+ ? "查询中"
4040
+ : view.status.state === "completed"
4041
+ ? "已完成"
4042
+ : view.status.state === "failed"
4043
+ ? "查询失败"
4044
+ : view.status.state === "cancelled"
4045
+ ? "已取消"
4046
+ : "等待查询";
4047
+ return (
4048
+ <div className="mt-3 grid gap-3">
4049
+ <div className="flex items-center justify-between gap-3 text-[10px] text-[#687381]">
4050
+ <span className="rounded-full border border-[#dce5f5] bg-[#f6f8fa] px-2 py-1 font-semibold text-[#3565c5]">{statusLabel}</span>
4051
+ {view.status.at !== null ? <time className="font-mono">{new Date(view.status.at).toLocaleString()}</time> : null}
4052
+ </div>
4053
+ {view.status.error !== null ? (
4054
+ <div className="rounded-lg border border-[#f4caca] bg-[#fff5f5] px-3 py-2 text-[10px] leading-4 text-[#b42318]">{view.status.error}</div>
4055
+ ) : null}
4056
+ {report !== null ? (
3425
4057
  <>
3426
- <div className="flex items-center justify-between rounded-lg bg-[#f6f8fa] px-3 py-3">
3427
- <span className="truncate font-mono text-[11px] text-[#30343b]">{value(report.database ?? "database")}</span>
3428
- <strong className="font-mono text-[12px] text-[#3565c5]">{value(rows.length)} rows</strong>
4058
+ <div className="rounded-lg bg-[#f6f8fa] px-3 py-3">
4059
+ <div className="flex items-center justify-between gap-3">
4060
+ <span className="truncate font-mono text-[11px] text-[#30343b]" title={report.database}>
4061
+ {report.database}
4062
+ </span>
4063
+ <strong className="shrink-0 font-mono text-[12px] text-[#3565c5]">{report.rowInventory.returned} rows</strong>
4064
+ </div>
4065
+ <code className="mt-2 block max-h-16 overflow-auto whitespace-pre-wrap break-words text-[10px] leading-4 text-[#687381]">
4066
+ {report.query}
4067
+ </code>
3429
4068
  </div>
3430
- <pre className="max-h-48 overflow-auto rounded-lg border border-[#edf0f3] bg-[#fbfcfd] p-3 text-[10px] leading-4 text-[#65707b]">
3431
- {JSON.stringify(rows, null, 2)}
4069
+ <pre className="max-h-56 overflow-auto rounded-lg border border-[#edf0f3] bg-[#fbfcfd] p-3 text-[10px] leading-4 text-[#65707b]">
4070
+ {JSON.stringify(report.rows, null, 2)}
3432
4071
  </pre>
4072
+ {report.rowInventory.truncated ? (
4073
+ <p className="text-[10px] text-[#9a6700]">
4074
+ 面板显示 {report.rowInventory.shown} / {report.rowInventory.returned} 行;查询共扫描 {report.rowInventory.scanned}{" "}
4075
+ 行,结果已按安全边界截断。
4076
+ </p>
4077
+ ) : null}
3433
4078
  </>
3434
- );
3435
- })()
3436
- ) : (
3437
- <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">
3438
- 还没有查询数据库。可让 Agent 调用 sql_readonly。
4079
+ ) : (
4080
+ <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">
4081
+ 还没有查询数据库。可让 Agent 调用 sql_readonly。
4082
+ </div>
4083
+ )}
4084
+ <div className="flex flex-wrap gap-2 font-mono text-[10px] text-[#3565c5]">
4085
+ <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1">timeout:{view.timeoutMs}ms</span>
4086
+ <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1">rows:{view.limits.rows}</span>
4087
+ <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1">result:{Math.round(view.limits.resultBytes / 1_024)}KiB</span>
4088
+ </div>
3439
4089
  </div>
3440
- )}
3441
- </div>
4090
+ );
4091
+ })()
3442
4092
  ) : panel.id === "theme-studio-panel" ? (
3443
4093
  <div className="mt-3 grid gap-3">
3444
4094
  <div className="flex items-center justify-between rounded-lg border border-[#dce5f5] bg-[#f6f8ff] px-3 py-3">
@@ -3507,103 +4157,134 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
3507
4157
  </div>
3508
4158
  ) : panel.id === "docker-sandbox-panel" ? (
3509
4159
  <div className="mt-3 grid gap-3">
3510
- {data?.latest !== null && data?.latest !== undefined && typeof data.latest === "object" ? (
3511
- (() => {
3512
- const run = data.latest as Record<string, unknown>;
4160
+ {(() => {
4161
+ const view = dockerSandboxPanelView(data);
4162
+ if (view.malformed) {
3513
4163
  return (
3514
- <div className="rounded-lg border border-[#b9e6c9] bg-[#f0fbf4] px-3 py-3">
3515
- <div className="flex items-center justify-between gap-3">
3516
- <span className="truncate font-mono text-[11px] text-[#30343b]">{value(run.image ?? "image")}</span>
3517
- <strong className="font-mono text-[12px] text-[#14733f]">exit {value(run.exitCode ?? "—")}</strong>
3518
- </div>
3519
- <p className="mt-2 text-[11px] text-[#65707b]">
3520
- {Array.isArray(run.command) ? run.command.map((argument) => value(argument)).join(" ") : "argv"}
3521
- </p>
4164
+ <div className="rounded-lg border border-[#f4caca] bg-[#fff5f5] px-3 py-3 text-[11px] text-[#b42318]">
4165
+ <strong className="block text-[12px]">Docker Sandbox 面板数据异常</strong>
4166
+ <span className="mt-1 block">面板数据不完整或不可信,请重新加载后再运行。</span>
3522
4167
  </div>
3523
4168
  );
3524
- })()
3525
- ) : (
3526
- <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">还没有沙箱运行。默认无网络、工作区只读。</div>
3527
- )}
3528
- <div className="flex flex-wrap gap-2">
3529
- {data?.defaults !== null && typeof data?.defaults === "object"
3530
- ? Object.entries(data.defaults as Record<string, unknown>).map(([key, entryValue]) => (
3531
- <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[10px] text-[#3565c5]" key={key}>
3532
- {key}:{value(entryValue)}
3533
- </span>
3534
- ))
3535
- : null}
3536
- </div>
4169
+ }
4170
+ const run = view.latest;
4171
+ const successful = run?.status === "completed" && run.exitCode === 0;
4172
+ return (
4173
+ <>
4174
+ {run !== null ? (
4175
+ <div className={`rounded-lg border px-3 py-3 ${successful ? "border-[#b9e6c9] bg-[#f0fbf4]" : "border-[#f4caca] bg-[#fff5f5]"}`}>
4176
+ <div className="flex items-center justify-between gap-3">
4177
+ <span className="truncate font-mono text-[11px] text-[#30343b]">{run.image}</span>
4178
+ <strong className={`shrink-0 font-mono text-[12px] ${successful ? "text-[#14733f]" : "text-[#b42318]"}`}>
4179
+ {run.status === "timed_out" ? "超时" : `exit ${run.exitCode}`}
4180
+ </strong>
4181
+ </div>
4182
+ <p className="mt-2 break-all font-mono text-[10px] leading-4 text-[#65707b]">
4183
+ {run.command.map((argument) => JSON.stringify(argument)).join(" ")}
4184
+ </p>
4185
+ <div className="mt-2 flex flex-wrap gap-2 text-[10px] text-[#687381]">
4186
+ <span>{run.write ? "工作区可写(已确认)" : "工作区只读"}</span>
4187
+ <span>{run.commandCount} 个 argv 参数</span>
4188
+ {run.truncated ? <span>面板明细已截断</span> : null}
4189
+ </div>
4190
+ {run.output ? (
4191
+ <pre className="mt-2 max-h-40 overflow-auto whitespace-pre-wrap break-all rounded-md bg-white/70 px-2 py-2 text-[10px] leading-4 text-[#4c5663]">
4192
+ {run.output}
4193
+ </pre>
4194
+ ) : null}
4195
+ </div>
4196
+ ) : (
4197
+ <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">
4198
+ 还没有沙箱运行。仅使用本地镜像,默认无网络、工作区只读。
4199
+ </div>
4200
+ )}
4201
+ <div className="flex flex-wrap gap-2">
4202
+ {[
4203
+ [`image:${view.defaults.image}`, "image"],
4204
+ [`pull:${view.defaults.pull}`, "pull"],
4205
+ [`network:${view.defaults.network}`, "network"],
4206
+ [`rootfs:${view.defaults.rootFilesystem}`, "rootfs"],
4207
+ [`workspace:${view.defaults.workspace}`, "workspace"],
4208
+ [`memory:${view.defaults.memory}`, "memory"],
4209
+ [`cpus:${view.defaults.cpus}`, "cpus"],
4210
+ [`pids:${view.defaults.pids}`, "pids"],
4211
+ [`timeout:${view.defaults.timeoutMs}ms`, "timeout"],
4212
+ ].map(([label, key]) => (
4213
+ <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[10px] text-[#3565c5]" key={key}>
4214
+ {label}
4215
+ </span>
4216
+ ))}
4217
+ </div>
4218
+ </>
4219
+ );
4220
+ })()}
3537
4221
  </div>
3538
4222
  ) : panel.id === "yaml-validator-panel" ? (
3539
- <div className="mt-3 grid gap-3">
3540
- {data?.latest !== null && data?.latest !== undefined && typeof data.latest === "object" ? (
3541
- (() => {
3542
- const report = data.latest as Record<string, unknown>;
3543
- const errors = Array.isArray(report.errors) ? report.errors : [];
3544
- const warnings = Array.isArray(report.warnings) ? report.warnings : [];
3545
- const valid = report.valid === true;
3546
- return (
4223
+ (() => {
4224
+ const view = yamlValidatorPanelView(data);
4225
+ const report = view.latest;
4226
+ return (
4227
+ <div className="mt-3 grid gap-3">
4228
+ {view.status.state === "failed" || view.status.state === "cancelled" ? (
4229
+ <div className="rounded-lg border border-[#f4caca] bg-[#fff5f5] px-3 py-2 text-[11px] text-[#b42318]">
4230
+ 最近一次校验{view.status.state === "cancelled" ? "已取消" : "失败"}。{view.status.error ?? ""}
4231
+ </div>
4232
+ ) : null}
4233
+ {report !== null ? (
3547
4234
  <>
3548
4235
  <div
3549
- className={`rounded-lg border px-3 py-3 text-[11px] ${valid ? "border-[#b9e6c9] bg-[#f0fbf4] text-[#14733f]" : "border-[#f4caca] bg-[#fff5f5] text-[#b42318]"}`}
4236
+ className={`rounded-lg border px-3 py-3 text-[11px] ${report.valid ? "border-[#b9e6c9] bg-[#f0fbf4] text-[#14733f]" : "border-[#f4caca] bg-[#fff5f5] text-[#b42318]"}`}
3550
4237
  >
3551
- {valid ? "YAML 语法有效。" : `发现 ${errors.length} 个语法错误。`}
4238
+ {report.valid ? "YAML 语法有效。" : `发现 ${report.errorCount} 个语法错误。`}
3552
4239
  </div>
3553
4240
  <div className="grid grid-cols-3 gap-2">
3554
4241
  {[
3555
- ["文档", report.documents ?? 0],
3556
- ["错误", errors.length],
3557
- ["警告", warnings.length],
4242
+ ["文档", report.documents],
4243
+ ["错误", report.errorCount],
4244
+ ["警告", report.warningCount],
3558
4245
  ].map(([label, entryValue]) => (
3559
- <div className="rounded-lg bg-[#f6f8fa] px-3 py-2" key={value(label)}>
3560
- <span className="block text-[10px] text-[#687381]">{value(label)}</span>
3561
- <strong className="mt-1 block text-[17px] text-[#30343b]">{value(entryValue)}</strong>
4246
+ <div className="rounded-lg bg-[#f6f8fa] px-3 py-2" key={label}>
4247
+ <span className="block text-[10px] text-[#687381]">{label}</span>
4248
+ <strong className="mt-1 block text-[17px] text-[#30343b]">{entryValue}</strong>
3562
4249
  </div>
3563
4250
  ))}
3564
4251
  </div>
3565
- {!valid && errors.length > 0 ? (
3566
- <pre className="max-h-32 overflow-auto rounded-lg border border-[#f4caca] bg-[#fffafa] p-3 text-[10px] leading-4 text-[#b42318]">
3567
- {errors
3568
- .map((error) =>
3569
- typeof error === "object" && error !== null
3570
- ? `${value((error as Record<string, unknown>).line ?? "?")}:${value((error as Record<string, unknown>).column ?? "?")} ${value((error as Record<string, unknown>).message, "")}`
3571
- : value(error),
3572
- )
3573
- .join("\n")}
4252
+ {!report.valid && report.errors.length > 0 ? (
4253
+ <pre className="max-h-32 overflow-auto whitespace-pre-wrap break-words rounded-lg border border-[#f4caca] bg-[#fffafa] p-3 text-[10px] leading-4 text-[#b42318]">
4254
+ {report.errors.map((error) => `${error.line ?? "?"}:${error.column ?? "?"} ${error.message}`).join("\n")}
3574
4255
  </pre>
3575
4256
  ) : null}
4257
+ {report.diagnosticsTruncated ? <p className="text-[10px] text-[#8a5a00]">诊断预览已截断,完整计数保留在摘要中。</p> : null}
3576
4258
  </>
3577
- );
3578
- })()
3579
- ) : (
3580
- <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">
3581
- 还没有校验 YAML。可让 Agent 调用 yaml_validate。
4259
+ ) : (
4260
+ <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">
4261
+ 还没有校验 YAML。可让 Agent 调用 yaml_validate。
4262
+ </div>
4263
+ )}
4264
+ <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[10px] text-[#3565c5]">
4265
+ max:{Math.round(view.limits.fileBytes / 1024)}KiB · read-only
4266
+ </span>
3582
4267
  </div>
3583
- )}
3584
- <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[10px] text-[#3565c5]">max:512KiB · read-only</span>
3585
- </div>
4268
+ );
4269
+ })()
3586
4270
  ) : panel.id === "browser-session-panel" ? (
3587
4271
  (() => {
3588
- const tabs = Array.isArray(data?.tabs)
3589
- ? browserSessionTabs(
3590
- data.tabs.flatMap((tab): Array<{ targetId: string; title: string; url: string }> => {
3591
- if (tab === null || typeof tab !== "object") return [];
3592
- const item = tab as Record<string, unknown>;
3593
- return typeof item.targetId === "string" && typeof item.url === "string"
3594
- ? [{ targetId: item.targetId, title: typeof item.title === "string" ? item.title : "", url: item.url }]
3595
- : [];
3596
- }),
3597
- 8,
3598
- )
3599
- : [];
3600
- const latest =
3601
- data?.latest !== null && data?.latest !== undefined && typeof data.latest === "object" ? (data.latest as Record<string, unknown>) : undefined;
4272
+ const view = browserSessionPanelView(data);
4273
+ if (view.malformed) {
4274
+ return (
4275
+ <div className="rounded-lg border border-[#f4caca] bg-[#fff5f5] px-3 py-3 text-[11px] text-[#b42318]">
4276
+ <strong className="block text-[12px]">Browser Session 面板数据异常</strong>
4277
+ <span className="mt-1 block">面板数据不完整或不可信,请重新连接后再试。</span>
4278
+ </div>
4279
+ );
4280
+ }
4281
+ const tabs = view.tabs;
4282
+ const latest = view.latest;
3602
4283
  const latestAction = latest?.screenshot
3603
4284
  ? "已截图"
3604
4285
  : latest?.clicked === true
3605
4286
  ? "已点击"
3606
- : latest?.text
4287
+ : latest?.status === "read" || typeof latest?.text === "string"
3607
4288
  ? "已读取"
3608
4289
  : latest?.status === "navigated"
3609
4290
  ? "已导航"
@@ -3612,17 +4293,17 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
3612
4293
  <div className="mt-3 grid gap-3">
3613
4294
  <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3">
3614
4295
  <div className="flex items-center justify-between gap-3">
3615
- <span className="truncate font-mono text-[11px] text-[#30343b]">{value(data?.endpoint ?? "本地浏览器未连接")}</span>
4296
+ <span className="truncate font-mono text-[11px] text-[#30343b]">{view.endpoint || "本地浏览器未连接"}</span>
3616
4297
  <span
3617
- className={`rounded-full px-2 py-1 text-[10px] font-semibold ${data?.connected === true ? "bg-[#e8f8ee] text-[#14733f]" : "bg-[#fff4e5] text-[#8a5a00]"}`}
4298
+ className={`rounded-full px-2 py-1 text-[10px] font-semibold ${view.connected ? "bg-[#e8f8ee] text-[#14733f]" : "bg-[#fff4e5] text-[#8a5a00]"}`}
3618
4299
  >
3619
- {data?.connected === true ? "已连接" : "未连接"}
4300
+ {view.connected ? "已连接" : "未连接"}
3620
4301
  </span>
3621
4302
  </div>
3622
- <p className="mt-2 text-[11px] text-[#687381]">Chrome DevTools Protocol · {tabs.length} 个可调试页面</p>
3623
- {data?.connected === false ? (
3624
- <p className="mt-2 text-[11px] text-[#b42318]">请使用 remote-debugging-port 启动 Chrome。{value(data.error, "")}</p>
3625
- ) : null}
4303
+ <p className="mt-2 text-[11px] text-[#687381]">
4304
+ Chrome DevTools Protocol · 显示 {view.inventory.shown}/{view.inventory.total} 个可调试页面
4305
+ </p>
4306
+ {!view.connected ? <p className="mt-2 text-[11px] text-[#b42318]">请使用 remote-debugging-port 启动 Chrome。{view.error ?? ""}</p> : null}
3626
4307
  </div>
3627
4308
  {latestAction ? (
3628
4309
  <div className="flex items-center justify-between rounded-lg border border-[#dce5f5] bg-[#f6f8ff] px-3 py-2 text-[11px]">
@@ -3630,6 +4311,17 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
3630
4311
  <strong className="font-mono text-[#315fb8]">{latestAction}</strong>
3631
4312
  </div>
3632
4313
  ) : null}
4314
+ {latest?.text !== undefined ? (
4315
+ <div className="rounded-lg border border-[#e3e7ee] bg-white px-3 py-3">
4316
+ <pre className="max-h-48 overflow-auto whitespace-pre-wrap break-words text-[10px] leading-4 text-[#4c5663]">{latest.text}</pre>
4317
+ {latest.previewTruncated ? <p className="mt-2 text-[10px] text-[#8a5a00]">面板正文预览已截断。</p> : null}
4318
+ </div>
4319
+ ) : null}
4320
+ {latest?.screenshot !== undefined ? (
4321
+ <div className="rounded-lg border border-[#dce5f5] bg-[#f6f8ff] px-3 py-2 text-[10px] text-[#315fb8]">
4322
+ 截图元数据:{latest.screenshot.mimeType} · {latest.screenshot.bytes.toLocaleString()} bytes
4323
+ </div>
4324
+ ) : null}
3633
4325
  {tabs.length > 0 ? (
3634
4326
  <div className="grid gap-2">
3635
4327
  {tabs.map((tab) => (
@@ -3651,91 +4343,93 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
3651
4343
  </div>
3652
4344
  );
3653
4345
  })()
3654
- ) : panel.id === "mcp-client-panel" ? (
3655
- <div className="mt-3 grid gap-3">
3656
- <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3">
3657
- <div className="flex items-center justify-between gap-3">
3658
- <span className="truncate font-mono text-[11px] text-[#30343b]">{value(data?.server ?? "尚未连接 MCP 服务器")}</span>
3659
- <div className="flex shrink-0 items-center gap-2 font-mono text-[10px] text-[#3565c5]">
3660
- <span>{value(Array.isArray(data?.tools) ? data.tools.length : 0)} 工具</span>
3661
- <span className="text-[#687381]">·</span>
3662
- <span>{value(Array.isArray(data?.resources) ? data.resources.length : 0)} 资源</span>
3663
- <span className="text-[#687381]">·</span>
3664
- <span>{value(Array.isArray(data?.prompts) ? data.prompts.length : 0)} 提示</span>
3665
- </div>
3666
- </div>
3667
- <p className="mt-2 text-[11px] text-[#687381]">
3668
- {data?.lastCall === null || data?.lastCall === undefined ? "使用 mcp_list_tools 发现 stdio 工具。" : `最近调用:${value(data.lastCall)}`}
3669
- </p>
3670
- </div>
3671
- {Array.isArray(data?.tools) && data.tools.length > 0 ? (
3672
- <div className="flex flex-wrap gap-2">
3673
- {data.tools.slice(0, 12).map((tool, index) => {
3674
- const item = typeof tool === "object" && tool !== null ? (tool as Record<string, unknown>) : {};
3675
- return (
3676
- <span
3677
- className="rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[10px] text-[#3565c5]"
3678
- key={`${value(item.name ?? "tool")}-${index}`}
3679
- >
3680
- {value(item.name ?? "tool")}
3681
- </span>
3682
- );
3683
- })}
3684
- </div>
3685
- ) : null}
3686
- {Array.isArray(data?.resources) && data.resources.length > 0 ? (
3687
- <div className="grid gap-2">
3688
- <span className="text-[10px] font-semibold uppercase tracking-[0.12em] text-[#687381]">资源</span>
3689
- <div className="flex flex-wrap gap-2">
3690
- {data.resources.slice(0, 8).map((resource, index) => {
3691
- const item = typeof resource === "object" && resource !== null ? (resource as Record<string, unknown>) : {};
3692
- return (
3693
- <span
3694
- className="rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[10px] text-[#65707b]"
3695
- key={`${value(item.uri ?? "resource")}-${index}`}
3696
- >
3697
- {value(item.name ?? item.uri ?? "resource")}
3698
- </span>
3699
- );
3700
- })}
4346
+ ) : panel.id === "mcp-client-panel" ? (
4347
+ (() => {
4348
+ const view = mcpClientPanelView(data);
4349
+ return (
4350
+ <div className="mt-3 grid gap-3">
4351
+ <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3">
4352
+ <div className="flex items-center justify-between gap-3">
4353
+ <span className="truncate font-mono text-[11px] text-[#30343b]">{value(view.server ?? "尚未连接 MCP 服务器")}</span>
4354
+ <div className="flex shrink-0 items-center gap-2 font-mono text-[10px] text-[#3565c5]">
4355
+ <span>{view.inventory.tools.total} 工具</span>
4356
+ <span className="text-[#687381]">·</span>
4357
+ <span>{view.inventory.resources.total} 资源</span>
4358
+ <span className="text-[#687381]">·</span>
4359
+ <span>{view.inventory.prompts.total} 提示</span>
4360
+ </div>
4361
+ </div>
4362
+ <p className="mt-2 text-[11px] text-[#687381]">
4363
+ {view.lastCall === null ? "使用 mcp_list_tools 发现 stdio 工具。" : `最近调用:${view.lastCall}`}
4364
+ </p>
3701
4365
  </div>
3702
- </div>
3703
- ) : null}
3704
- {Array.isArray(data?.prompts) && data.prompts.length > 0 ? (
3705
- <div className="grid gap-2">
3706
- <span className="text-[10px] font-semibold uppercase tracking-[0.12em] text-[#687381]">提示模板</span>
3707
- <div className="flex flex-wrap gap-2">
3708
- {data.prompts.slice(0, 8).map((prompt, index) => {
3709
- const item = typeof prompt === "object" && prompt !== null ? (prompt as Record<string, unknown>) : {};
3710
- return (
4366
+ {view.tools.length > 0 ? (
4367
+ <div className="flex flex-wrap gap-2">
4368
+ {view.tools.map((tool, index) => (
3711
4369
  <span
3712
- className="rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[10px] text-[#65707b]"
3713
- key={`${value(item.name ?? "prompt")}-${index}`}
4370
+ className="max-w-full truncate rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[10px] text-[#3565c5]"
4371
+ key={`${tool.name}-${index}`}
4372
+ title={tool.description}
3714
4373
  >
3715
- {value(item.name ?? "prompt")}
4374
+ {tool.name}
3716
4375
  </span>
3717
- );
3718
- })}
3719
- </div>
3720
- </div>
3721
- ) : null}
3722
- {Array.isArray(data?.servers) && data.servers.length > 0 ? (
3723
- <div className="grid gap-2">
3724
- {data.servers.map((server, index) => {
3725
- const item = typeof server === "object" && server !== null ? (server as Record<string, unknown>) : {};
3726
- return (
3727
- <div
3728
- className="flex items-center justify-between rounded-lg border border-[#e3e7ee] bg-white px-3 py-2 text-[10px]"
3729
- key={`${value(item.id ?? "server")}-${index}`}
3730
- >
3731
- <span className="font-mono text-[#30343b]">{value(item.id ?? "server")}</span>
3732
- <span className="text-[#14733f]">{value(item.status ?? "unknown")}</span>
4376
+ ))}
4377
+ </div>
4378
+ ) : null}
4379
+ {view.resources.length > 0 ? (
4380
+ <div className="grid gap-2">
4381
+ <span className="text-[10px] font-semibold uppercase tracking-[0.12em] text-[#687381]">资源</span>
4382
+ <div className="flex flex-wrap gap-2">
4383
+ {view.resources.map((resource, index) => (
4384
+ <span
4385
+ className="max-w-full truncate rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[10px] text-[#65707b]"
4386
+ key={`${resource.uri}-${index}`}
4387
+ title={resource.uri}
4388
+ >
4389
+ {resource.name ?? resource.uri}
4390
+ </span>
4391
+ ))}
3733
4392
  </div>
3734
- );
3735
- })}
4393
+ </div>
4394
+ ) : null}
4395
+ {view.prompts.length > 0 ? (
4396
+ <div className="grid gap-2">
4397
+ <span className="text-[10px] font-semibold uppercase tracking-[0.12em] text-[#687381]">提示模板</span>
4398
+ <div className="flex flex-wrap gap-2">
4399
+ {view.prompts.map((prompt, index) => (
4400
+ <span
4401
+ className="max-w-full truncate rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[10px] text-[#65707b]"
4402
+ key={`${prompt.name}-${index}`}
4403
+ title={prompt.description}
4404
+ >
4405
+ {prompt.name}
4406
+ </span>
4407
+ ))}
4408
+ </div>
4409
+ </div>
4410
+ ) : null}
4411
+ {view.servers.length > 0 ? (
4412
+ <div className="grid gap-2">
4413
+ {view.servers.map((server, index) => (
4414
+ <div
4415
+ className="flex items-center justify-between rounded-lg border border-[#e3e7ee] bg-white px-3 py-2 text-[10px]"
4416
+ key={`${server.id}-${index}`}
4417
+ >
4418
+ <span className="truncate font-mono text-[#30343b]">{server.id}</span>
4419
+ <span className={server.status === "running" ? "text-[#14733f]" : "text-[#687381]"}>{server.status}</span>
4420
+ </div>
4421
+ ))}
4422
+ </div>
4423
+ ) : null}
4424
+ {view.inventory.tools.truncated || view.inventory.resources.truncated || view.inventory.prompts.truncated || view.inventory.servers.truncated ? (
4425
+ <p className="text-[10px] text-[#687381]">面板仅显示受限预览;完整清单请使用对应 MCP 列表工具。</p>
4426
+ ) : null}
4427
+ <p className="font-mono text-[9px] text-[#8a94a1]">
4428
+ 响应上限 {Math.round(view.limits.responseBytes / 1024)} KiB · 请求超时 {Math.round(view.limits.requestTimeoutMs / 1000)} 秒
4429
+ </p>
3736
4430
  </div>
3737
- ) : null}
3738
- </div>
4431
+ );
4432
+ })()
3739
4433
  ) : panel.id === "mcp-panel" ? (
3740
4434
  (() => {
3741
4435
  const servers = Array.isArray(data?.servers) ? data.servers : [];
@@ -3786,7 +4480,9 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
3786
4480
  <div className="mt-3 grid gap-3">
3787
4481
  <div className="flex items-center justify-between rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3">
3788
4482
  <span className="font-mono text-[11px] text-[#30343b]">{data?.enabled === true ? "已启用" : "已停用"}</span>
3789
- <span className="font-mono text-[10px] text-[#687381]">{value(data?.platform ?? "unknown")}</span>
4483
+ <span className="font-mono text-[10px] text-[#687381]">
4484
+ {value(data?.platform ?? "unknown")} · {value(data?.timeoutMs ?? 10_000)}ms
4485
+ </span>
3790
4486
  </div>
3791
4487
  {Array.isArray(data?.notifications) && data.notifications.length > 0 ? (
3792
4488
  <div className="grid gap-2">
@@ -3794,8 +4490,12 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
3794
4490
  const item = typeof notification === "object" && notification !== null ? (notification as Record<string, unknown>) : {};
3795
4491
  return (
3796
4492
  <div className="rounded-lg border border-[#e3e7ee] bg-white px-3 py-2 text-[10px]" key={`${value(item.time ?? "notification")}-${index}`}>
3797
- <strong className="block text-[#30343b]">{value(item.title ?? "Pi Harness")}</strong>
4493
+ <div className="flex items-center justify-between gap-2">
4494
+ <strong className="text-[#30343b]">{value(item.title ?? "Pi Harness")}</strong>
4495
+ <span className={item.delivered === true ? "text-[#14733f]" : "text-[#b42318]"}>{item.delivered === true ? "已送达" : "未送达"}</span>
4496
+ </div>
3798
4497
  <span className="mt-1 block text-[#65707b]">{value(item.message, "")}</span>
4498
+ {item.delivered !== true && item.reason ? <span className="mt-1 block break-words text-[#b42318]">{value(item.reason)}</span> : null}
3799
4499
  </div>
3800
4500
  );
3801
4501
  })}
@@ -3866,188 +4566,358 @@ function PluginPanelCard({ panel, inline = false }: { panel: ClientPluginPanel;
3866
4566
  </p>
3867
4567
  </div>
3868
4568
  ) : panel.id === "browser-fetch-panel" ? (
3869
- <div className="mt-3 grid gap-3">
3870
- {data?.latest !== null && data?.latest !== undefined && typeof data.latest === "object" ? (
3871
- (() => {
3872
- const result = data.latest as Record<string, unknown>;
3873
- return (
4569
+ (() => {
4570
+ const view = browserFetchPanelView(data);
4571
+ if (view.malformed) {
4572
+ return (
4573
+ <div className="rounded-lg border border-[#f4caca] bg-[#fff5f5] px-3 py-3 text-[11px] text-[#b42318]">
4574
+ <strong className="block text-[12px]">Browser Fetch 面板数据异常</strong>
4575
+ <span className="mt-1 block">面板数据不完整或不可信,请重新加载后再抓取。</span>
4576
+ </div>
4577
+ );
4578
+ }
4579
+ const result = view.latest;
4580
+ return (
4581
+ <div className="mt-3 grid gap-3">
4582
+ {result === null ? (
4583
+ <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">
4584
+ 还没有抓取网页。默认阻止本地和私有网络目标。
4585
+ </div>
4586
+ ) : (
3874
4587
  <>
3875
4588
  <div className="flex items-center justify-between gap-3 rounded-lg bg-[#f6f8fa] px-3 py-3">
3876
- <span className="truncate font-mono text-[11px] text-[#30343b]">{value(result.finalUrl ?? result.url ?? "page")}</span>
3877
- <strong className="font-mono text-[12px] text-[#14733f]">HTTP {value(result.status ?? "—")}</strong>
4589
+ <span className="truncate font-mono text-[11px] text-[#30343b]">{value(result.finalUrl || result.url || "page")}</span>
4590
+ <strong className="font-mono text-[12px] text-[#14733f]">HTTP {value(result.status || "—")}</strong>
3878
4591
  </div>
3879
4592
  <pre className="max-h-48 overflow-auto rounded-lg border border-[#edf0f3] bg-[#fbfcfd] p-3 text-[10px] leading-4 text-[#65707b]">
3880
4593
  {value(result.text, "")}
3881
4594
  </pre>
4595
+ {result.previewTruncated || result.truncated ? (
4596
+ <p className="text-[10px] text-[#9a6700]">
4597
+ {result.truncated ? "响应正文已达到抓取上限;" : ""}
4598
+ {result.previewTruncated ? "面板仅显示有界预览。" : ""}
4599
+ </p>
4600
+ ) : null}
3882
4601
  </>
3883
- );
3884
- })()
3885
- ) : (
3886
- <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">
3887
- 还没有抓取网页。默认阻止本地和私有网络目标。
4602
+ )}
4603
+ <div className="flex flex-wrap gap-2">
4604
+ <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[10px] text-[#3565c5]">
4605
+ max:{value(Math.round(view.limits.responseBytes / 1024))}KiB
4606
+ </span>
4607
+ <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[10px] text-[#3565c5]">
4608
+ timeout:{value(view.limits.timeoutMs)}ms
4609
+ </span>
4610
+ <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[10px] text-[#3565c5]">
4611
+ redirects:{value(view.limits.redirects)}
4612
+ </span>
4613
+ <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[10px] text-[#3565c5]">scripts:disabled</span>
4614
+ <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[10px] text-[#3565c5]">
4615
+ private:{value(view.allowPrivate ? "allowed" : "blocked")}
4616
+ </span>
4617
+ </div>
3888
4618
  </div>
3889
- )}
3890
- <div className="flex flex-wrap gap-2">
3891
- <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[10px] text-[#3565c5]">max:512KiB</span>
3892
- <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[10px] text-[#3565c5]">scripts:disabled</span>
3893
- <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1 font-mono text-[10px] text-[#3565c5]">
3894
- private:{value(data?.allowPrivate === true ? "allowed" : "blocked")}
3895
- </span>
3896
- </div>
3897
- </div>
4619
+ );
4620
+ })()
3898
4621
  ) : panel.id === "i18n-pair-panel" ? (
3899
- <div className="mt-3 grid gap-3">
3900
- {data?.report !== null && data?.report !== undefined && typeof data.report === "object" ? (
3901
- (() => {
3902
- const report = data.report as Record<string, unknown>;
3903
- const missing = Array.isArray(report.missing) ? report.missing : [];
3904
- const extra = Array.isArray(report.extra) ? report.extra : [];
3905
- const healthy = missing.length === 0 && extra.length === 0;
3906
- return (
4622
+ (() => {
4623
+ const view = i18nPairPanelView(data);
4624
+ const report = view.report;
4625
+ const healthy = report !== null && report.missingTotal === 0 && report.extraTotal === 0;
4626
+ const statusLabel =
4627
+ view.status.state === "unknown"
4628
+ ? "数据异常"
4629
+ : view.status.state === "running"
4630
+ ? "检查中"
4631
+ : view.status.state === "failed"
4632
+ ? "检查失败"
4633
+ : view.status.state === "cancelled"
4634
+ ? "已取消"
4635
+ : view.status.state === "completed"
4636
+ ? "已完成"
4637
+ : "等待检查";
4638
+ return (
4639
+ <div className="mt-3 grid gap-3">
4640
+ <div className="flex items-center justify-between gap-3 text-[10px] text-[#687381]">
4641
+ <span className="rounded-full border border-[#dce5f5] bg-[#f6f8fa] px-2 py-1 font-semibold text-[#3565c5]">{statusLabel}</span>
4642
+ {view.status.at !== null ? <time className="font-mono">{new Date(view.status.at).toLocaleString()}</time> : null}
4643
+ </div>
4644
+ {view.status.error !== null ? (
4645
+ <div className="rounded-lg border border-[#f4caca] bg-[#fff5f5] px-3 py-2 text-[10px] leading-4 text-[#b42318]">{view.status.error}</div>
4646
+ ) : null}
4647
+ {view.malformed ? (
4648
+ <div className="rounded-lg border border-[#f4caca] bg-[#fff5f5] px-3 py-2 text-[10px] leading-4 text-[#b42318]">
4649
+ 面板数据不完整或不可信,未显示语言包统计。
4650
+ </div>
4651
+ ) : null}
4652
+ {report !== null ? (
3907
4653
  <>
3908
4654
  <div
3909
4655
  className={`rounded-lg border px-3 py-3 text-[11px] ${healthy ? "border-[#b9e6c9] bg-[#f0fbf4] text-[#14733f]" : "border-[#f4caca] bg-[#fff5f5] text-[#b42318]"}`}
3910
4656
  >
3911
- {healthy ? "语言包键完全一致。" : `缺失 ${missing.length} 个,额外 ${extra.length} 个。`}
4657
+ {healthy ? "语言包键完全一致。" : `缺失 ${report.missingTotal} 个,额外 ${report.extraTotal} 个。`}
4658
+ </div>
4659
+ <div className="grid gap-2 rounded-lg border border-[#edf0f3] bg-[#fbfcfd] px-3 py-3 font-mono text-[10px]">
4660
+ <div className="grid grid-cols-[3rem_minmax(0,1fr)] gap-2">
4661
+ <span className="text-[#687381]">基准</span>
4662
+ <span className="truncate text-[#30343b]" title={report.base}>
4663
+ {report.base}
4664
+ </span>
4665
+ </div>
4666
+ <div className="grid grid-cols-[3rem_minmax(0,1fr)] gap-2">
4667
+ <span className="text-[#687381]">目标</span>
4668
+ <span className="truncate text-[#30343b]" title={report.target}>
4669
+ {report.target}
4670
+ </span>
4671
+ </div>
3912
4672
  </div>
3913
4673
  <div className="grid grid-cols-2 gap-2">
3914
4674
  <div className="rounded-lg bg-[#f6f8fa] px-3 py-2">
3915
4675
  <span className="block text-[10px] text-[#687381]">基准键</span>
3916
- <strong className="mt-1 block text-[17px] text-[#30343b]">{value(report.baseKeys ?? 0)}</strong>
4676
+ <strong className="mt-1 block text-[17px] text-[#30343b]">{report.baseKeys}</strong>
3917
4677
  </div>
3918
4678
  <div className="rounded-lg bg-[#f6f8fa] px-3 py-2">
3919
4679
  <span className="block text-[10px] text-[#687381]">目标键</span>
3920
- <strong className="mt-1 block text-[17px] text-[#30343b]">{value(report.targetKeys ?? 0)}</strong>
4680
+ <strong className="mt-1 block text-[17px] text-[#30343b]">{report.targetKeys}</strong>
3921
4681
  </div>
3922
4682
  </div>
4683
+ {report.missing.length > 0 || report.extra.length > 0 ? (
4684
+ <div className="grid gap-2 sm:grid-cols-2">
4685
+ {[
4686
+ { label: `缺失 · ${report.missingTotal}`, keys: report.missing, tone: "text-[#b42318]" },
4687
+ { label: `额外 · ${report.extraTotal}`, keys: report.extra, tone: "text-[#9a6700]" },
4688
+ ].map((group) => (
4689
+ <div className="min-w-0 rounded-lg border border-[#edf0f3] bg-[#fbfcfd] p-3" key={group.label}>
4690
+ <strong className={`text-[10px] ${group.tone}`}>{group.label}</strong>
4691
+ <ul className="mt-2 max-h-36 space-y-1 overflow-auto font-mono text-[10px] text-[#30343b]">
4692
+ {group.keys.map((key, index) => (
4693
+ <li className="truncate" key={`${key}-${index}`} title={key}>
4694
+ {key}
4695
+ </li>
4696
+ ))}
4697
+ </ul>
4698
+ </div>
4699
+ ))}
4700
+ </div>
4701
+ ) : null}
4702
+ {report.truncated ? <p className="text-[10px] text-[#9a6700]">面板仅显示有界键列表;完整结果保留在工具调用详情中。</p> : null}
3923
4703
  </>
3924
- );
3925
- })()
3926
- ) : (
3927
- <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">
3928
- 还没有检查语言包。可让 Agent 调用 i18n_check。
4704
+ ) : (
4705
+ <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">
4706
+ 还没有检查语言包。可让 Agent 调用 i18n_check。
4707
+ </div>
4708
+ )}
4709
+ <div className="flex flex-wrap gap-2 font-mono text-[10px] text-[#3565c5]">
4710
+ <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1">file:{Math.round(view.limits.fileBytes / 1_048_576)}MiB</span>
4711
+ <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1">depth:{view.limits.depth}</span>
4712
+ <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1">keys:{view.limits.keysPerFile}</span>
4713
+ </div>
3929
4714
  </div>
3930
- )}
3931
- </div>
4715
+ );
4716
+ })()
3932
4717
  ) : panel.id === "cleaner-panel" ? (
3933
- <div className="mt-3 grid gap-3">
3934
- <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3">
3935
- <div className="flex items-center justify-between gap-3">
3936
- <span className="text-[11px] font-semibold text-[#30343b]">快照清理</span>
3937
- <strong className="font-mono text-[12px] text-[#3565c5]">{value(Array.isArray(data?.capsules) ? data.capsules.length : 0)} 个</strong>
4718
+ (() => {
4719
+ const view = cleanerPanelView(data);
4720
+ if (view.malformed || view.inventory === null) {
4721
+ return (
4722
+ <div className="mt-3 rounded-lg border border-[#f4caca] bg-[#fff5f5] px-3 py-3 text-[11px] text-[#b42318]">
4723
+ <strong className="block text-[12px]">Cleaner 面板数据异常</strong>
4724
+ <span className="mt-1 block">面板数据不完整或不可信,请重新加载后再执行清理。</span>
4725
+ </div>
4726
+ );
4727
+ }
4728
+ const inventory = view.inventory;
4729
+ const activity = view.lastCleanup;
4730
+ const statusLabel =
4731
+ activity?.status === "running"
4732
+ ? "清理中"
4733
+ : activity?.status === "completed"
4734
+ ? "已完成"
4735
+ : activity?.status === "cancelled"
4736
+ ? "已取消"
4737
+ : activity?.status === "failed"
4738
+ ? "清理失败"
4739
+ : "尚未清理";
4740
+ return (
4741
+ <div className="mt-3 grid gap-3">
4742
+ <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3">
4743
+ <div className="flex items-center justify-between gap-3">
4744
+ <span className="text-[11px] font-semibold text-[#30343b]">Git 胶囊库存</span>
4745
+ <strong className="font-mono text-[12px] text-[#3565c5]">{inventory.total} 个</strong>
4746
+ </div>
4747
+ <p className="mt-2 text-[11px] text-[#687381]">仅清理 agent 数据目录中的 .patch 胶囊,必须显式 confirm=true。</p>
4748
+ <div className="mt-3 flex flex-wrap gap-2 font-mono text-[10px] text-[#3565c5]">
4749
+ <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1">capsules:{view.limits.capsules}</span>
4750
+ <span className="rounded-md border border-[#dce5f5] bg-white px-2 py-1">scan:{view.limits.directoryEntries}</span>
4751
+ </div>
4752
+ </div>
4753
+ {activity !== null ? (
4754
+ <div className="rounded-lg border border-[#edf0f3] bg-[#fbfcfd] px-3 py-3">
4755
+ <div className="flex items-center justify-between gap-3 text-[10px]">
4756
+ <strong className={activity.status === "failed" ? "text-[#b42318]" : "text-[#30343b]"}>{statusLabel}</strong>
4757
+ {activity.at !== null ? <time className="font-mono text-[#687381]">{new Date(activity.at).toLocaleString()}</time> : null}
4758
+ </div>
4759
+ <div className="mt-2 flex gap-4 text-[11px] text-[#687381]">
4760
+ <span>
4761
+ 已删 <strong className="font-mono text-[#30343b]">{activity.removed}</strong>
4762
+ </span>
4763
+ <span>
4764
+ 保留 <strong className="font-mono text-[#30343b]">{activity.kept ?? "—"}</strong>
4765
+ </span>
4766
+ <span>
4767
+ 请求保留 <strong className="font-mono text-[#30343b]">{activity.requestedKeep}</strong>
4768
+ </span>
4769
+ </div>
4770
+ {activity.error !== null ? <p className="mt-2 break-words text-[10px] leading-4 text-[#b42318]">{activity.error}</p> : null}
4771
+ </div>
4772
+ ) : null}
4773
+ {view.capsules.length > 0 ? (
4774
+ <div className="max-h-48 overflow-auto rounded-lg border border-[#edf0f3] bg-[#fbfcfd]">
4775
+ {view.capsules.map((capsule, index) => (
4776
+ <div
4777
+ className="flex items-center justify-between gap-3 border-b border-[#edf0f3] px-3 py-2 last:border-b-0"
4778
+ key={`${capsule.name}-${index}`}
4779
+ >
4780
+ <span className="truncate font-mono text-[10px] text-[#30343b]" title={capsule.name}>
4781
+ {capsule.name}
4782
+ </span>
4783
+ <span className="shrink-0 font-mono text-[9px] text-[#687381]">{capsule.bytes.toLocaleString()} B</span>
4784
+ </div>
4785
+ ))}
4786
+ </div>
4787
+ ) : (
4788
+ <div className="rounded-lg border border-[#e3e7ee] bg-[#f6f8fa] px-3 py-3 text-[11px] text-[#687381]">当前没有可清理的 Git 胶囊。</div>
4789
+ )}
4790
+ {inventory.truncated ? (
4791
+ <p className="text-[10px] text-[#9a6700]">
4792
+ 面板显示 {inventory.shown} / {inventory.total} 个条目;清理工具仍按完整的有界库存执行。
4793
+ </p>
4794
+ ) : null}
3938
4795
  </div>
3939
- <p className="mt-2 text-[11px] text-[#687381]">仅清理 agent 数据目录中的 .patch 快照,必须显式 confirm=true。</p>
3940
- </div>
3941
- <div className="flex items-center justify-between text-[11px] text-[#687381]">
3942
- <span>上次清理</span>
3943
- <strong className="font-mono text-[#3565c5]">{value(data?.lastRemoved ?? 0)} 个</strong>
3944
- </div>
3945
- </div>
4796
+ );
4797
+ })()
3946
4798
  ) : panel.id === "fail-logger-panel" ? (
3947
4799
  <div className="mt-3 grid gap-3">
3948
- <div className="flex items-center justify-between rounded-lg bg-[#fff5f5] px-3 py-3">
3949
- <span className="text-[11px] font-semibold text-[#7f1d1d]">去重后的失败记录</span>
3950
- <strong className="font-mono text-[17px] text-[#b42318]">{value(data?.total ?? 0)}</strong>
3951
- </div>
3952
- <div className="max-h-48 overflow-auto rounded-lg border border-[#edf0f3]">
3953
- {Array.isArray(data?.failures) && data.failures.length > 0 ? (
3954
- data.failures.map((item, index) => {
3955
- const failure = item !== null && typeof item === "object" ? (item as Record<string, unknown>) : {};
3956
- return (
3957
- <div
3958
- className="grid grid-cols-[auto_1fr] gap-2 border-b border-[#edf0f3] px-3 py-2 last:border-b-0"
3959
- key={`${value(failure.time ?? "failure")}-${index}`}
3960
- >
3961
- <span className="font-mono text-[10px] text-[#b42318]">{value(failure.source ?? "runtime")}</span>
3962
- <span className="break-words text-[11px] leading-4 text-[#65707b]">{value(failure.message ?? "未知错误")}</span>
4800
+ {(() => {
4801
+ const view = failLoggerPanelView(data);
4802
+ return (
4803
+ <>
4804
+ <div className="rounded-lg bg-[#fff5f5] px-3 py-3">
4805
+ <div className="flex items-center justify-between">
4806
+ <span className="text-[11px] font-semibold text-[#7f1d1d]">聚合后的失败记录</span>
4807
+ <strong className="font-mono text-[17px] text-[#b42318]">{view.total}</strong>
3963
4808
  </div>
3964
- );
3965
- })
3966
- ) : (
3967
- <div className="px-3 py-4 text-[12px] text-[#687381]">暂无失败记录。</div>
3968
- )}
3969
- </div>
4809
+ <div className="mt-2 flex flex-wrap gap-3 text-[10px] text-[#8b4a4a]">
4810
+ <span>观测 {view.observed} 次</span>
4811
+ <span>
4812
+ 容量 {view.total} / {view.capacity}
4813
+ </span>
4814
+ {view.dropped > 0 ? <span>已淘汰 {view.dropped} 条旧记录</span> : null}
4815
+ {view.truncated ? <span>面板明细已截断</span> : null}
4816
+ </div>
4817
+ </div>
4818
+ <div className="max-h-56 overflow-auto rounded-lg border border-[#edf0f3]">
4819
+ {view.failures.length > 0 ? (
4820
+ view.failures.map((failure, index) => (
4821
+ <div className="border-b border-[#edf0f3] px-3 py-2 last:border-b-0" key={`${failure.time ?? "failure"}-${index}`}>
4822
+ <div className="flex items-center justify-between gap-2">
4823
+ <span className="font-mono text-[10px] text-[#b42318]">{failure.source}</span>
4824
+ <span className="flex shrink-0 items-center gap-2 font-mono text-[9px] text-[#8a94a0]">
4825
+ {failure.occurrences > 1 ? <strong className="text-[#b42318]">×{failure.occurrences}</strong> : null}
4826
+ {failure.time === null ? "时间未知" : `${failure.time.slice(11, 19)} UTC`}
4827
+ </span>
4828
+ </div>
4829
+ <p className="mt-1 break-words text-[11px] leading-4 text-[#65707b]">{failure.message}</p>
4830
+ </div>
4831
+ ))
4832
+ ) : (
4833
+ <div className="px-3 py-4 text-[12px] text-[#687381]">暂无失败记录。</div>
4834
+ )}
4835
+ </div>
4836
+ </>
4837
+ );
4838
+ })()}
3970
4839
  </div>
3971
4840
  ) : panel.id === "context-insight-panel" ? (
3972
- <div className="mt-3 grid gap-3">
3973
- <div className="rounded-lg border border-[#e3eaf8] bg-[#f6f8ff] px-3 py-3">
3974
- <div className="flex items-center justify-between gap-3">
3975
- <span className="font-mono text-[10px] uppercase tracking-[0.08em] text-[#5d6d82]">上下文占用</span>
3976
- <strong className="text-[13px] font-semibold text-[#315fb8]">
3977
- {data?.percent === null || data?.percent === undefined ? "—" : `${value(data.percent)}%`}
3978
- </strong>
3979
- </div>
3980
- <div className="mt-2 h-2 overflow-hidden rounded-full bg-[#dfe8fb]">
3981
- <div
3982
- className="h-full rounded-full bg-[#5d8bea] transition-[width] duration-300"
3983
- style={{ width: `${Math.max(0, Math.min(100, typeof data?.percent === "number" ? data.percent : 0))}%` }}
3984
- />
3985
- </div>
3986
- <p className="mt-2 text-[11px] text-[#5d6d82]">
3987
- {data?.tokens === null || data?.tokens === undefined ? "令牌数未知" : `${value(data.tokens)} tokens`}
3988
- {data?.contextWindow === null || data?.contextWindow === undefined ? "" : ` / ${value(data.contextWindow)} 上限`}
3989
- </p>
3990
- </div>
3991
- <div className="grid grid-cols-3 gap-2">
3992
- {[
3993
- ["消息", data?.messages ?? 0],
3994
- ["事件", data?.events ?? 0],
3995
- ["压缩", data?.compactions ?? 0],
3996
- ].map(([label, item]) => (
3997
- <div className="rounded-lg bg-[#f6f8fa] px-3 py-2" key={value(label)}>
3998
- <span className="block text-[10px] text-[#687381]">{value(label)}</span>
3999
- <strong className="mt-1 block text-[17px] font-semibold text-[#30343b]">{value(item)}</strong>
4841
+ (() => {
4842
+ const view = contextInsightsPanelView(data);
4843
+ return (
4844
+ <div className="mt-3 grid gap-3">
4845
+ <div className="rounded-lg border border-[#e3eaf8] bg-[#f6f8ff] px-3 py-3">
4846
+ <div className="flex items-center justify-between gap-3">
4847
+ <span className="font-mono text-[10px] uppercase tracking-[0.08em] text-[#5d6d82]">上下文占用</span>
4848
+ <strong className="text-[13px] font-semibold text-[#315fb8]">{view.percent === null ? "—" : `${view.percent}%`}</strong>
4849
+ </div>
4850
+ <div className="mt-2 h-2 overflow-hidden rounded-full bg-[#dfe8fb]">
4851
+ <div className="h-full rounded-full bg-[#5d8bea] transition-[width] duration-300" style={{ width: `${Math.min(100, view.percent ?? 0)}%` }} />
4852
+ </div>
4853
+ <p className="mt-2 text-[11px] text-[#5d6d82]">
4854
+ {view.tokens === null ? "令牌数未知" : `${view.tokens.toLocaleString()} tokens`}
4855
+ {view.contextWindow === null ? "" : ` / ${view.contextWindow.toLocaleString()} 上限`}
4856
+ </p>
4000
4857
  </div>
4001
- ))}
4002
- </div>
4003
- <div className="rounded-lg border border-[#edf0f3] bg-white px-3 py-3">
4004
- <div className="flex items-center justify-between">
4005
- <span className="text-[11px] font-semibold text-[#30343b]">消息组成</span>
4006
- <span className="text-[10px] text-[#687381]">按角色统计</span>
4007
- </div>
4008
- <div className="mt-2 grid grid-cols-5 gap-1.5">
4009
- {[
4010
- ["用户", (data?.composition as Record<string, unknown> | undefined)?.user ?? 0],
4011
- ["助手", (data?.composition as Record<string, unknown> | undefined)?.assistant ?? 0],
4012
- ["工具", (data?.composition as Record<string, unknown> | undefined)?.toolResult ?? 0],
4013
- ["系统", (data?.composition as Record<string, unknown> | undefined)?.system ?? 0],
4014
- ["其他", (data?.composition as Record<string, unknown> | undefined)?.other ?? 0],
4015
- ].map(([label, item]) => (
4016
- <div className="rounded bg-[#f6f8fa] px-2 py-1.5 text-center" key={value(label)}>
4017
- <span className="block text-[10px] text-[#687381]">{value(label)}</span>
4018
- <strong className="mt-0.5 block font-mono text-[13px] text-[#30343b]">{value(item)}</strong>
4858
+ <div className="grid grid-cols-3 gap-2">
4859
+ {[
4860
+ ["消息", view.messages],
4861
+ ["事件", view.events],
4862
+ ["压缩", view.compactions],
4863
+ ].map(([label, item]) => (
4864
+ <div className="rounded-lg bg-[#f6f8fa] px-3 py-2" key={value(label)}>
4865
+ <span className="block text-[10px] text-[#687381]">{value(label)}</span>
4866
+ <strong className="mt-1 block text-[17px] font-semibold text-[#30343b]">{value(item)}</strong>
4867
+ </div>
4868
+ ))}
4869
+ </div>
4870
+ <div className="rounded-lg border border-[#edf0f3] bg-white px-3 py-3">
4871
+ <div className="flex items-center justify-between">
4872
+ <span className="text-[11px] font-semibold text-[#30343b]">消息组成</span>
4873
+ <span className="text-[10px] text-[#687381]">
4874
+ {view.messagesTruncated ? `最近 ${view.scannedMessages} / ${view.messages} 条` : `全部 ${view.scannedMessages} 条`}
4875
+ </span>
4019
4876
  </div>
4020
- ))}
4021
- </div>
4022
- </div>
4023
- <div className="rounded-lg border border-[#edf0f3] bg-white px-3 py-3">
4024
- <div className="flex items-center justify-between">
4025
- <span className="text-[11px] font-semibold text-[#30343b]">最近上下文事件</span>
4026
- <span className="text-[10px] text-[#687381]">最多保留 50 条</span>
4027
- </div>
4028
- <div className="mt-2 max-h-28 overflow-auto">
4029
- {Array.isArray(data?.recentEvents) && data.recentEvents.length > 0 ? (
4030
- data.recentEvents
4031
- .slice(-6)
4032
- .reverse()
4033
- .map((item, index) => {
4034
- const event = item !== null && typeof item === "object" ? (item as Record<string, unknown>) : {};
4035
- return (
4036
- <div
4037
- className="flex items-center justify-between border-b border-[#f0f2f5] py-1.5 last:border-b-0"
4038
- key={`${value(event.type)}-${value(event.at)}-${index}`}
4039
- >
4040
- <span className="font-mono text-[10px] text-[#5d6d82]">{value(event.type, "unknown")}</span>
4041
- <span className="text-[10px] text-[#687381]">{typeof event.at === "number" ? new Date(event.at).toLocaleTimeString() : "—"}</span>
4042
- </div>
4043
- );
4044
- })
4045
- ) : (
4046
- <div className="py-2 text-[11px] text-[#687381]">暂无上下文事件。</div>
4047
- )}
4877
+ <div className="mt-2 grid grid-cols-5 gap-1.5">
4878
+ {[
4879
+ ["用户", view.composition.user],
4880
+ ["助手", view.composition.assistant],
4881
+ ["工具", view.composition.toolResult],
4882
+ ["系统", view.composition.system],
4883
+ ["其他", view.composition.other],
4884
+ ].map(([label, item]) => (
4885
+ <div className="rounded bg-[#f6f8fa] px-2 py-1.5 text-center" key={value(label)}>
4886
+ <span className="block text-[10px] text-[#687381]">{value(label)}</span>
4887
+ <strong className="mt-0.5 block font-mono text-[13px] text-[#30343b]">{value(item)}</strong>
4888
+ </div>
4889
+ ))}
4890
+ </div>
4891
+ </div>
4892
+ <div className="rounded-lg border border-[#edf0f3] bg-white px-3 py-3">
4893
+ <div className="flex items-center justify-between">
4894
+ <span className="text-[11px] font-semibold text-[#30343b]">最近上下文事件</span>
4895
+ <span className="text-[10px] text-[#687381]">
4896
+ 显示 {view.limits.displayedEvents} / 保留 {view.limits.retainedEvents} 条
4897
+ </span>
4898
+ </div>
4899
+ <div className="mt-2 max-h-28 overflow-auto">
4900
+ {view.recentEvents.length > 0 ? (
4901
+ view.recentEvents.map((event, index) => {
4902
+ return (
4903
+ <div
4904
+ className="flex items-center justify-between border-b border-[#f0f2f5] py-1.5 last:border-b-0"
4905
+ key={`${event.type}-${event.at ?? "unknown"}-${index}`}
4906
+ >
4907
+ <span className="font-mono text-[10px] text-[#5d6d82]">{event.type}</span>
4908
+ <span className="text-[10px] text-[#687381]">{event.at === null ? "—" : new Date(event.at).toLocaleTimeString()}</span>
4909
+ </div>
4910
+ );
4911
+ })
4912
+ ) : (
4913
+ <div className="py-2 text-[11px] text-[#687381]">暂无上下文事件。</div>
4914
+ )}
4915
+ </div>
4916
+ {view.recentEventsTruncated ? <p className="mt-2 text-[10px] text-[#687381]">更早事件已按浏览器显示上限省略。</p> : null}
4917
+ </div>
4048
4918
  </div>
4049
- </div>
4050
- </div>
4919
+ );
4920
+ })()
4051
4921
  ) : (
4052
4922
  <div className="mt-3 grid gap-2">
4053
4923
  {entries.map(([key, item]) => (