@monkey-mini-app/dsh-mini-app 0.1.1 → 0.1.4

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 (312) hide show
  1. package/README.md +29 -27
  2. package/lib/client.js +2024 -783
  3. package/lib/index.d.ts +2 -0
  4. package/lib/index.js +20 -7
  5. package/package.json +10 -9
  6. package/skills/monkey-mini-app/SKILL.md +181 -114
  7. package/skills/monkey-mini-app/references/catalog.md +236 -99
  8. package/skills/monkey-mini-app/references/contracts/accordion.md +30 -0
  9. package/skills/monkey-mini-app/references/contracts/activity-feed.md +12 -2
  10. package/skills/monkey-mini-app/references/contracts/alert-dialog.md +38 -0
  11. package/skills/monkey-mini-app/references/contracts/alert.md +38 -0
  12. package/skills/monkey-mini-app/references/contracts/app-shell.md +2 -2
  13. package/skills/monkey-mini-app/references/contracts/aspect-ratio.md +25 -0
  14. package/skills/monkey-mini-app/references/contracts/attachment-gallery.md +12 -2
  15. package/skills/monkey-mini-app/references/contracts/attachment.md +35 -0
  16. package/skills/monkey-mini-app/references/contracts/autocomplete.md +12 -2
  17. package/skills/monkey-mini-app/references/contracts/avatar.md +24 -0
  18. package/skills/monkey-mini-app/references/contracts/badge.md +26 -0
  19. package/skills/monkey-mini-app/references/contracts/breadcrumb.md +33 -0
  20. package/skills/monkey-mini-app/references/contracts/bubble.md +30 -0
  21. package/skills/monkey-mini-app/references/contracts/button-group.md +36 -0
  22. package/skills/monkey-mini-app/references/contracts/button.md +26 -0
  23. package/skills/monkey-mini-app/references/contracts/calendar.md +20 -0
  24. package/skills/monkey-mini-app/references/contracts/card.md +41 -0
  25. package/skills/monkey-mini-app/references/contracts/cascader.md +12 -2
  26. package/skills/monkey-mini-app/references/contracts/chart.md +32 -0
  27. package/skills/monkey-mini-app/references/contracts/checkbox.md +19 -0
  28. package/skills/monkey-mini-app/references/contracts/code-block.md +20 -2
  29. package/skills/monkey-mini-app/references/contracts/code-editor.md +30 -4
  30. package/skills/monkey-mini-app/references/contracts/collapsible.md +21 -0
  31. package/skills/monkey-mini-app/references/contracts/color-picker.md +12 -2
  32. package/skills/monkey-mini-app/references/contracts/combobox.md +34 -0
  33. package/skills/monkey-mini-app/references/contracts/command.md +41 -0
  34. package/skills/monkey-mini-app/references/contracts/comment-thread.md +12 -2
  35. package/skills/monkey-mini-app/references/contracts/commit-graph.md +50 -0
  36. package/skills/monkey-mini-app/references/contracts/confirm-dialog.md +20 -2
  37. package/skills/monkey-mini-app/references/contracts/context-menu.md +41 -0
  38. package/skills/monkey-mini-app/references/contracts/copyable.md +12 -2
  39. package/skills/monkey-mini-app/references/contracts/currency-input.md +12 -2
  40. package/skills/monkey-mini-app/references/contracts/dashboard-shell.md +41 -0
  41. package/skills/monkey-mini-app/references/contracts/data-grid.md +13 -6
  42. package/skills/monkey-mini-app/references/contracts/date-picker.md +20 -2
  43. package/skills/monkey-mini-app/references/contracts/date-range-picker.md +10 -2
  44. package/skills/monkey-mini-app/references/contracts/date-time-picker.md +20 -2
  45. package/skills/monkey-mini-app/references/contracts/date-time-range-picker.md +20 -2
  46. package/skills/monkey-mini-app/references/contracts/description-list.md +12 -2
  47. package/skills/monkey-mini-app/references/contracts/detail-panel.md +10 -2
  48. package/skills/monkey-mini-app/references/contracts/dialog.md +44 -0
  49. package/skills/monkey-mini-app/references/contracts/diff-viewer.md +21 -2
  50. package/skills/monkey-mini-app/references/contracts/donut-chart.md +12 -2
  51. package/skills/monkey-mini-app/references/contracts/drawer.md +29 -0
  52. package/skills/monkey-mini-app/references/contracts/dropdown-menu.md +49 -0
  53. package/skills/monkey-mini-app/references/contracts/duration-input.md +20 -2
  54. package/skills/monkey-mini-app/references/contracts/empty.md +40 -0
  55. package/skills/monkey-mini-app/references/contracts/env-badge.md +12 -2
  56. package/skills/monkey-mini-app/references/contracts/env-table.md +46 -0
  57. package/skills/monkey-mini-app/references/contracts/event-calendar.md +28 -20
  58. package/skills/monkey-mini-app/references/contracts/field.md +34 -0
  59. package/skills/monkey-mini-app/references/contracts/file-dropzone.md +20 -2
  60. package/skills/monkey-mini-app/references/contracts/file-tree.md +12 -2
  61. package/skills/monkey-mini-app/references/contracts/filter-bar.md +2 -2
  62. package/skills/monkey-mini-app/references/contracts/form-sheet.md +51 -0
  63. package/skills/monkey-mini-app/references/contracts/gantt.md +20 -2
  64. package/skills/monkey-mini-app/references/contracts/gauge.md +12 -2
  65. package/skills/monkey-mini-app/references/contracts/hover-card.md +21 -0
  66. package/skills/monkey-mini-app/references/contracts/input-group.md +24 -0
  67. package/skills/monkey-mini-app/references/contracts/input.md +33 -0
  68. package/skills/monkey-mini-app/references/contracts/item.md +36 -0
  69. package/skills/monkey-mini-app/references/contracts/jira-wiki.md +3 -4
  70. package/skills/monkey-mini-app/references/contracts/jql-input.md +15 -8
  71. package/skills/monkey-mini-app/references/contracts/json-viewer.md +20 -2
  72. package/skills/monkey-mini-app/references/contracts/kanban-issue-panel.md +12 -2
  73. package/skills/monkey-mini-app/references/contracts/kanban.md +10 -2
  74. package/skills/monkey-mini-app/references/contracts/kbd.md +20 -0
  75. package/skills/monkey-mini-app/references/contracts/label.md +33 -0
  76. package/skills/monkey-mini-app/references/contracts/list-detail.md +46 -0
  77. package/skills/monkey-mini-app/references/contracts/log-viewer.md +45 -4
  78. package/skills/monkey-mini-app/references/contracts/markdown-editor.md +20 -2
  79. package/skills/monkey-mini-app/references/contracts/markdown.md +12 -2
  80. package/skills/monkey-mini-app/references/contracts/marker.md +30 -0
  81. package/skills/monkey-mini-app/references/contracts/menubar.md +34 -0
  82. package/skills/monkey-mini-app/references/contracts/message-scroller.md +24 -0
  83. package/skills/monkey-mini-app/references/contracts/message.md +24 -0
  84. package/skills/monkey-mini-app/references/contracts/mini-calendar.md +20 -2
  85. package/skills/monkey-mini-app/references/contracts/native-select.md +21 -0
  86. package/skills/monkey-mini-app/references/contracts/navigation-menu.md +27 -0
  87. package/skills/monkey-mini-app/references/contracts/notification-center.md +12 -2
  88. package/skills/monkey-mini-app/references/contracts/number-field.md +20 -2
  89. package/skills/monkey-mini-app/references/contracts/page-header.md +2 -2
  90. package/skills/monkey-mini-app/references/contracts/pagination.md +33 -0
  91. package/skills/monkey-mini-app/references/contracts/password-field.md +12 -2
  92. package/skills/monkey-mini-app/references/contracts/phone-input.md +12 -2
  93. package/skills/monkey-mini-app/references/contracts/popover.md +32 -0
  94. package/skills/monkey-mini-app/references/contracts/progress-ring.md +12 -2
  95. package/skills/monkey-mini-app/references/contracts/progress.md +39 -0
  96. package/skills/monkey-mini-app/references/contracts/questionnaire.md +33 -0
  97. package/skills/monkey-mini-app/references/contracts/radar-chart.md +12 -2
  98. package/skills/monkey-mini-app/references/contracts/radio-group.md +20 -0
  99. package/skills/monkey-mini-app/references/contracts/rating.md +12 -2
  100. package/skills/monkey-mini-app/references/contracts/relative-date-picker.md +20 -2
  101. package/skills/monkey-mini-app/references/contracts/request-inspector.md +12 -2
  102. package/skills/monkey-mini-app/references/contracts/resizable.md +29 -0
  103. package/skills/monkey-mini-app/references/contracts/reveal.md +31 -0
  104. package/skills/monkey-mini-app/references/contracts/rich-text-editor.md +14 -2
  105. package/skills/monkey-mini-app/references/contracts/run-timeline.md +20 -2
  106. package/skills/monkey-mini-app/references/contracts/scroll-area.md +20 -0
  107. package/skills/monkey-mini-app/references/contracts/scrollspy.md +20 -2
  108. package/skills/monkey-mini-app/references/contracts/search-input.md +12 -2
  109. package/skills/monkey-mini-app/references/contracts/select.md +36 -0
  110. package/skills/monkey-mini-app/references/contracts/separator.md +27 -0
  111. package/skills/monkey-mini-app/references/contracts/settings-split.md +53 -0
  112. package/skills/monkey-mini-app/references/contracts/severity-chip.md +12 -2
  113. package/skills/monkey-mini-app/references/contracts/sheet.md +34 -0
  114. package/skills/monkey-mini-app/references/contracts/sidebar.md +42 -0
  115. package/skills/monkey-mini-app/references/contracts/skeleton.md +33 -0
  116. package/skills/monkey-mini-app/references/contracts/slider-range.md +12 -2
  117. package/skills/monkey-mini-app/references/contracts/slider.md +25 -0
  118. package/skills/monkey-mini-app/references/contracts/sortable-list.md +20 -2
  119. package/skills/monkey-mini-app/references/contracts/sparkline.md +12 -2
  120. package/skills/monkey-mini-app/references/contracts/spinner.md +31 -0
  121. package/skills/monkey-mini-app/references/contracts/stacked-bar-chart.md +16 -2
  122. package/skills/monkey-mini-app/references/contracts/stat-card.md +2 -2
  123. package/skills/monkey-mini-app/references/contracts/status-badge.md +2 -2
  124. package/skills/monkey-mini-app/references/contracts/stepper-item.md +39 -0
  125. package/skills/monkey-mini-app/references/contracts/stepper.md +38 -11
  126. package/skills/monkey-mini-app/references/contracts/switch.md +25 -0
  127. package/skills/monkey-mini-app/references/contracts/table-page.md +41 -0
  128. package/skills/monkey-mini-app/references/contracts/table.md +42 -0
  129. package/skills/monkey-mini-app/references/contracts/tabs.md +31 -0
  130. package/skills/monkey-mini-app/references/contracts/tag-input.md +12 -2
  131. package/skills/monkey-mini-app/references/contracts/terminal.md +13 -2
  132. package/skills/monkey-mini-app/references/contracts/test-step-list.md +12 -2
  133. package/skills/monkey-mini-app/references/contracts/textarea.md +25 -0
  134. package/skills/monkey-mini-app/references/contracts/time-picker.md +18 -2
  135. package/skills/monkey-mini-app/references/contracts/time-range-picker.md +20 -2
  136. package/skills/monkey-mini-app/references/contracts/time-wheel.md +6 -2
  137. package/skills/monkey-mini-app/references/contracts/timeline.md +20 -2
  138. package/skills/monkey-mini-app/references/contracts/timezone-select.md +20 -2
  139. package/skills/monkey-mini-app/references/contracts/toast.md +39 -0
  140. package/skills/monkey-mini-app/references/contracts/toggle-group.md +28 -0
  141. package/skills/monkey-mini-app/references/contracts/toggle.md +26 -0
  142. package/skills/monkey-mini-app/references/contracts/tooltip.md +30 -0
  143. package/skills/monkey-mini-app/references/contracts/transfer.md +12 -2
  144. package/skills/monkey-mini-app/references/contracts/tree-view.md +20 -2
  145. package/skills/monkey-mini-app/references/contracts/trend-card.md +12 -2
  146. package/skills/monkey-mini-app/references/contracts/user-picker.md +12 -2
  147. package/skills/monkey-mini-app/references/contracts/wizard-shell.md +56 -0
  148. package/skills/monkey-mini-app/references/ctx.md +123 -53
  149. package/skills/monkey-mini-app/references/eval.md +115 -0
  150. package/skills/monkey-mini-app/references/examples/alert/alert-01.tsx +17 -0
  151. package/skills/monkey-mini-app/references/examples/aspect-ratio/aspect-ratio-01.tsx +16 -0
  152. package/skills/monkey-mini-app/references/examples/attachment/attachment-01.tsx +19 -0
  153. package/skills/monkey-mini-app/references/examples/breadcrumb/breadcrumb-01.tsx +31 -0
  154. package/skills/monkey-mini-app/references/examples/bubble/bubble-01.tsx +16 -0
  155. package/skills/monkey-mini-app/references/examples/button-group/button-group-01.tsx +23 -0
  156. package/skills/monkey-mini-app/references/examples/card/card-01.tsx +19 -0
  157. package/skills/monkey-mini-app/references/examples/charts-blocks.md +15 -0
  158. package/skills/monkey-mini-app/references/examples/code-block/code-block-01.tsx +14 -0
  159. package/skills/monkey-mini-app/references/examples/code-editor/code-editor-01.tsx +15 -0
  160. package/skills/monkey-mini-app/references/examples/command/command-01.tsx +30 -0
  161. package/skills/monkey-mini-app/references/examples/confirm-dialog/confirm-dialog-01.tsx +33 -0
  162. package/skills/monkey-mini-app/references/examples/context-menu/context-menu-01.tsx +29 -0
  163. package/skills/monkey-mini-app/references/examples/dashboard-shell/dashboard-shell-01.tsx +78 -0
  164. package/skills/monkey-mini-app/references/examples/data-grid/data-grid-01.tsx +34 -0
  165. package/skills/monkey-mini-app/references/examples/data-grid/data-grid-02.tsx +88 -0
  166. package/skills/monkey-mini-app/references/examples/date-picker/date-picker-01.tsx +14 -0
  167. package/skills/monkey-mini-app/references/examples/date-range-picker/date-range-picker-01.tsx +14 -0
  168. package/skills/monkey-mini-app/references/examples/date-time-picker/date-time-picker-01.tsx +16 -0
  169. package/skills/monkey-mini-app/references/examples/date-time-range-picker/date-time-range-picker-01.tsx +15 -0
  170. package/skills/monkey-mini-app/references/examples/detail-panel/detail-panel-01.tsx +21 -0
  171. package/skills/monkey-mini-app/references/examples/dialog/dialog-01.tsx +30 -0
  172. package/skills/monkey-mini-app/references/examples/diff-viewer/diff-viewer-01.tsx +10 -0
  173. package/skills/monkey-mini-app/references/examples/dropdown-menu/dropdown-menu-01.tsx +31 -0
  174. package/skills/monkey-mini-app/references/examples/duration-input/duration-input-01.tsx +20 -0
  175. package/skills/monkey-mini-app/references/examples/editors.md +11 -0
  176. package/skills/monkey-mini-app/references/examples/empty/empty-01.tsx +19 -0
  177. package/skills/monkey-mini-app/references/examples/event-calendar/event-calendar-01.tsx +53 -0
  178. package/skills/monkey-mini-app/references/examples/file-dropzone/file-dropzone-01.tsx +14 -0
  179. package/skills/monkey-mini-app/references/examples/form-sheet/form-sheet-01.tsx +85 -0
  180. package/skills/monkey-mini-app/references/examples/forms.md +16 -0
  181. package/skills/monkey-mini-app/references/examples/gantt/gantt-01.tsx +29 -0
  182. package/skills/monkey-mini-app/references/examples/input/input-01.tsx +10 -0
  183. package/skills/monkey-mini-app/references/examples/item/item-01.tsx +19 -0
  184. package/skills/monkey-mini-app/references/examples/jql-input/jql-input-01.tsx +33 -0
  185. package/skills/monkey-mini-app/references/examples/json-viewer/json-viewer-01.tsx +10 -0
  186. package/skills/monkey-mini-app/references/examples/kanban/kanban-01.tsx +60 -0
  187. package/skills/monkey-mini-app/references/examples/label/label-01.tsx +10 -0
  188. package/skills/monkey-mini-app/references/examples/list-detail/list-detail-01.tsx +117 -0
  189. package/skills/monkey-mini-app/references/examples/log-viewer/log-viewer-01.tsx +20 -0
  190. package/skills/monkey-mini-app/references/examples/markdown-editor/markdown-editor-01.tsx +18 -0
  191. package/skills/monkey-mini-app/references/examples/marker/marker-01.tsx +16 -0
  192. package/skills/monkey-mini-app/references/examples/mini-calendar/mini-calendar-01.tsx +14 -0
  193. package/skills/monkey-mini-app/references/examples/misc-charts-blocks/misc-charts-blocks-01.tsx +20 -0
  194. package/skills/monkey-mini-app/references/examples/misc-charts-blocks/misc-charts-blocks-02.tsx +32 -0
  195. package/skills/monkey-mini-app/references/examples/misc-charts-blocks/misc-charts-blocks-03.tsx +47 -0
  196. package/skills/monkey-mini-app/references/examples/misc-charts-blocks/misc-charts-blocks-04.tsx +20 -0
  197. package/skills/monkey-mini-app/references/examples/misc-charts-blocks/misc-charts-blocks-05.tsx +24 -0
  198. package/skills/monkey-mini-app/references/examples/misc-charts-blocks/misc-charts-blocks-06.tsx +89 -0
  199. package/skills/monkey-mini-app/references/examples/misc-editors/misc-editors-01.tsx +114 -0
  200. package/skills/monkey-mini-app/references/examples/misc-editors/misc-editors-02.tsx +33 -0
  201. package/skills/monkey-mini-app/references/examples/misc-forms/misc-forms-01.tsx +22 -0
  202. package/skills/monkey-mini-app/references/examples/misc-forms/misc-forms-02.tsx +37 -0
  203. package/skills/monkey-mini-app/references/examples/misc-forms/misc-forms-03.tsx +42 -0
  204. package/skills/monkey-mini-app/references/examples/misc-forms/misc-forms-04.tsx +25 -0
  205. package/skills/monkey-mini-app/references/examples/misc-forms/misc-forms-05.tsx +27 -0
  206. package/skills/monkey-mini-app/references/examples/misc-forms/misc-forms-06.tsx +33 -0
  207. package/skills/monkey-mini-app/references/examples/misc-forms/misc-forms-07.tsx +44 -0
  208. package/skills/monkey-mini-app/references/examples/misc-overlays/misc-overlays-01.tsx +43 -0
  209. package/skills/monkey-mini-app/references/examples/misc-overlays/misc-overlays-02.tsx +38 -0
  210. package/skills/monkey-mini-app/references/examples/misc-primitives/misc-primitives-01.tsx +21 -0
  211. package/skills/monkey-mini-app/references/examples/misc-primitives/misc-primitives-02.tsx +52 -0
  212. package/skills/monkey-mini-app/references/examples/misc-primitives/misc-primitives-03.tsx +44 -0
  213. package/skills/monkey-mini-app/references/examples/number-field/number-field-01.tsx +22 -0
  214. package/skills/monkey-mini-app/references/examples/overlays.md +11 -0
  215. package/skills/monkey-mini-app/references/examples/pagination/pagination-01.tsx +51 -0
  216. package/skills/monkey-mini-app/references/examples/primitives.md +12 -0
  217. package/skills/monkey-mini-app/references/examples/progress/progress-01.tsx +10 -0
  218. package/skills/monkey-mini-app/references/examples/relative-date-picker/relative-date-picker-01.tsx +19 -0
  219. package/skills/monkey-mini-app/references/examples/rich-text-editor/rich-text-editor-01.tsx +15 -0
  220. package/skills/monkey-mini-app/references/examples/run-timeline/run-timeline-01.tsx +17 -0
  221. package/skills/monkey-mini-app/references/examples/scrollspy/scrollspy-01.tsx +29 -0
  222. package/skills/monkey-mini-app/references/examples/separator/separator-01.tsx +10 -0
  223. package/skills/monkey-mini-app/references/examples/settings-split/settings-split-01.tsx +84 -0
  224. package/skills/monkey-mini-app/references/examples/shared/jira-wiki-sample.ts +38 -0
  225. package/skills/monkey-mini-app/references/examples/skeleton/skeleton-01.tsx +10 -0
  226. package/skills/monkey-mini-app/references/examples/slider/slider-01.tsx +22 -0
  227. package/skills/monkey-mini-app/references/examples/sortable-list/sortable-list-01.tsx +18 -0
  228. package/skills/monkey-mini-app/references/examples/spinner/spinner-01.tsx +10 -0
  229. package/skills/monkey-mini-app/references/examples/stepper/stepper-01.tsx +41 -0
  230. package/skills/monkey-mini-app/references/examples/table/table-01.tsx +25 -0
  231. package/skills/monkey-mini-app/references/examples/table-page/table-page-01.tsx +103 -0
  232. package/skills/monkey-mini-app/references/examples/time-picker/time-picker-01.tsx +19 -0
  233. package/skills/monkey-mini-app/references/examples/time-range-picker/time-range-picker-01.tsx +14 -0
  234. package/skills/monkey-mini-app/references/examples/timeline/timeline-01.tsx +18 -0
  235. package/skills/monkey-mini-app/references/examples/timezone-select/timezone-select-01.tsx +15 -0
  236. package/skills/monkey-mini-app/references/examples/toggle/toggle-01.tsx +20 -0
  237. package/skills/monkey-mini-app/references/examples/toggle-group/toggle-group-01.tsx +22 -0
  238. package/skills/monkey-mini-app/references/examples/tree-view/tree-view-01.tsx +25 -0
  239. package/skills/monkey-mini-app/references/examples/wizard-shell/wizard-shell-01.tsx +58 -0
  240. package/skills/monkey-mini-app/references/history.md +23 -7
  241. package/skills/monkey-mini-app/references/icons.md +99 -69
  242. package/skills/monkey-mini-app/references/llm-json.md +39 -26
  243. package/skills/monkey-mini-app/references/loader.md +47 -20
  244. package/skills/monkey-mini-app/references/looks/aurora-bento.md +88 -0
  245. package/skills/monkey-mini-app/references/looks/desk-split.md +89 -0
  246. package/skills/monkey-mini-app/references/looks/editorial.md +78 -0
  247. package/skills/monkey-mini-app/references/looks/glass-island.md +90 -0
  248. package/skills/monkey-mini-app/references/looks/index.md +18 -0
  249. package/skills/monkey-mini-app/references/looks/signage.md +74 -0
  250. package/skills/monkey-mini-app/references/looks/tape.md +22 -0
  251. package/skills/monkey-mini-app/references/looks/terminal.md +88 -0
  252. package/skills/monkey-mini-app/references/looks/void.md +22 -0
  253. package/skills/monkey-mini-app/references/styling.md +189 -0
  254. package/skills/monkey-mini-app/references/test.md +12 -12
  255. package/skills/monkey-mini-app/references/theme.md +197 -0
  256. package/skills/monkey-mini-app/references/tools.md +12 -12
  257. package/skills/monkey-mini-app/references/troubleshoot.md +165 -12
  258. package/skills/monkey-mini-app/templates/README.md +33 -21
  259. package/skills/monkey-mini-app/templates/{jira → board}/main.api.ts +11 -11
  260. package/skills/monkey-mini-app/templates/board/manifest.json +8 -0
  261. package/skills/monkey-mini-app/templates/board/theme.css +46 -0
  262. package/skills/monkey-mini-app/templates/board/ui.tsx +546 -0
  263. package/skills/monkey-mini-app/templates/chores/main.api.ts +35 -0
  264. package/skills/monkey-mini-app/templates/chores/manifest.json +8 -0
  265. package/skills/monkey-mini-app/templates/chores/theme.css +46 -0
  266. package/skills/monkey-mini-app/templates/chores/ui.tsx +117 -0
  267. package/skills/monkey-mini-app/templates/minimal/main.api.ts +5 -5
  268. package/skills/monkey-mini-app/templates/minimal/manifest.json +1 -2
  269. package/skills/monkey-mini-app/templates/minimal/ui.tsx +17 -8
  270. package/skills/monkey-mini-app/templates/radar/api/scan.ts +79 -0
  271. package/skills/monkey-mini-app/templates/radar/main.api.ts +29 -0
  272. package/skills/monkey-mini-app/templates/radar/manifest.json +8 -0
  273. package/skills/monkey-mini-app/templates/radar/shared/events.ts +25 -0
  274. package/skills/monkey-mini-app/templates/{insights/lib → radar/shared}/sample.ts +1 -1
  275. package/skills/monkey-mini-app/templates/radar/theme.css +47 -0
  276. package/skills/monkey-mini-app/templates/radar/ui/brief.tsx +31 -0
  277. package/skills/monkey-mini-app/templates/radar/ui.tsx +131 -0
  278. package/skills/monkey-mini-app/templates/runner/main.api.ts +91 -0
  279. package/skills/monkey-mini-app/templates/runner/manifest.json +8 -0
  280. package/skills/monkey-mini-app/templates/runner/shared/events.ts +14 -0
  281. package/skills/monkey-mini-app/templates/runner/theme.css +46 -0
  282. package/skills/monkey-mini-app/templates/runner/ui.tsx +213 -0
  283. package/skills/monkey-mini-app/templates/sheets/main.api.ts +276 -0
  284. package/skills/monkey-mini-app/templates/sheets/manifest.json +8 -0
  285. package/skills/monkey-mini-app/templates/sheets/theme.css +46 -0
  286. package/skills/monkey-mini-app/templates/sheets/ui.tsx +419 -0
  287. package/skills/monkey-mini-app/templates/{todo → today}/main.api.ts +8 -8
  288. package/skills/monkey-mini-app/templates/today/manifest.json +8 -0
  289. package/skills/monkey-mini-app/templates/today/theme.css +45 -0
  290. package/skills/monkey-mini-app/templates/today/ui/item-row.tsx +25 -0
  291. package/skills/monkey-mini-app/templates/today/ui.tsx +406 -0
  292. package/skills/monkey-mini-app/templates/{monitor → watch}/main.api.ts +8 -8
  293. package/skills/monkey-mini-app/templates/watch/manifest.json +8 -0
  294. package/skills/monkey-mini-app/templates/watch/ui.tsx +187 -0
  295. package/skills/monkey-mini-app/tsconfig.json +31 -0
  296. package/skills/monkey-mini-app/types/cdn.d.ts +1 -0
  297. package/tsup.config.ts +1 -0
  298. package/skills/monkey-mini-app/templates/agentrun/main.api.ts +0 -78
  299. package/skills/monkey-mini-app/templates/agentrun/manifest.json +0 -9
  300. package/skills/monkey-mini-app/templates/agentrun/ui.tsx +0 -125
  301. package/skills/monkey-mini-app/templates/insights/main.api.ts +0 -101
  302. package/skills/monkey-mini-app/templates/insights/manifest.json +0 -9
  303. package/skills/monkey-mini-app/templates/insights/ui.tsx +0 -138
  304. package/skills/monkey-mini-app/templates/jira/manifest.json +0 -9
  305. package/skills/monkey-mini-app/templates/jira/ui.tsx +0 -318
  306. package/skills/monkey-mini-app/templates/monitor/manifest.json +0 -9
  307. package/skills/monkey-mini-app/templates/monitor/ui.tsx +0 -176
  308. package/skills/monkey-mini-app/templates/review/main.api.ts +0 -68
  309. package/skills/monkey-mini-app/templates/review/manifest.json +0 -9
  310. package/skills/monkey-mini-app/templates/review/ui.tsx +0 -159
  311. package/skills/monkey-mini-app/templates/todo/manifest.json +0 -8
  312. package/skills/monkey-mini-app/templates/todo/ui.tsx +0 -177
@@ -0,0 +1,406 @@
1
+ import { useCallback, useEffect, useState } from "react";
2
+
3
+ import {
4
+ Button,
5
+ Empty,
6
+ EmptyDescription,
7
+ EmptyHeader,
8
+ EmptyTitle,
9
+ Icon,
10
+ Input,
11
+ ListDetail,
12
+ useApp,
13
+ } from "@monkey-mini-app/ui";
14
+
15
+ import { ItemRow, type Item } from "./ui/item-row";
16
+
17
+ type Filter = "all" | "active" | "done";
18
+ type Stats = { total: number; active: number; done: number };
19
+
20
+ const FILTERS: { id: Filter; label: string }[] = [
21
+ { id: "all", label: "全部" },
22
+ { id: "active", label: "先干" },
23
+ { id: "done", label: "已完" },
24
+ ];
25
+
26
+ const WEEK_LABELS = ["一", "二", "三", "四", "五", "六", "日"];
27
+
28
+ /*
29
+ * Real liquid glass, not frosted glass: the background is *displaced*, so the pane bends what is
30
+ * behind it. `backdrop-filter` accepts an SVG filter alongside the functions (verified in
31
+ * Chromium: `blur(2px) url(#id)` survives as written) — `LiquidDefs` below carries that filter.
32
+ *
33
+ * A displacement map can only bend structure that exists. Over a smooth gradient it renders
34
+ * nothing at all, which is why the sky carries grain and tight bokeh — see the wash layer.
35
+ *
36
+ * The refraction is gentle on purpose (`scale="45"`, `yChannelSelector="B"`): push it to
37
+ * `scale="130"` / `yChannelSelector="G"` and the text inside the pane starts wobbling — water, not glass.
38
+ *
39
+ * Non-Chromium engines drop `url()` here, so fall back to the old frost rather than a plain box.
40
+ */
41
+ const REFRACTS =
42
+ typeof CSS !== "undefined" &&
43
+ typeof CSS.supports === "function" &&
44
+ CSS.supports("backdrop-filter", "blur(2px) url(#mma-liquid)");
45
+
46
+ const GLASS = {
47
+ // Radius lives on the style, not a class: the old `ISLAND = "rounded-3xl"` was defined and
48
+ // never applied, which is why the panes looked hard-edged. Token so theme.css owns the size.
49
+ borderRadius: "var(--radius)",
50
+ backgroundColor: "color-mix(in oklch, var(--card) 14%, transparent)",
51
+ boxShadow:
52
+ "inset 0 1px 0 color-mix(in oklch, var(--card) 60%, transparent)," +
53
+ "inset 0 -1px 0 color-mix(in oklch, var(--card) 22%, transparent)," +
54
+ "inset 0 0 24px color-mix(in oklch, var(--card) 14%, transparent)," +
55
+ "0 14px 36px -10px var(--shadow)",
56
+ border: "1px solid color-mix(in oklch, var(--card) 28%, transparent)",
57
+ backdropFilter: REFRACTS
58
+ ? "blur(2px) saturate(160%) url(#mma-liquid)"
59
+ : "blur(18px) saturate(200%) brightness(1.08)",
60
+ WebkitBackdropFilter: REFRACTS
61
+ ? "blur(2px) saturate(160%)"
62
+ : "blur(18px) saturate(200%) brightness(1.08)",
63
+ } as const;
64
+
65
+ /** Soft card for the working set — not liquid. A full-bleed displaced pane eats the sky
66
+ * and is why the facade never matched the floating-pill prototype. */
67
+ const WORK = {
68
+ borderRadius: "var(--radius)",
69
+ backgroundColor: "color-mix(in oklch, var(--card) 78%, transparent)",
70
+ boxShadow: "0 10px 28px -12px var(--shadow)",
71
+ border: "1px solid color-mix(in oklch, var(--card) 40%, transparent)",
72
+ backdropFilter: "blur(12px) saturate(140%)",
73
+ WebkitBackdropFilter: "blur(12px) saturate(140%)",
74
+ } as const;
75
+
76
+ /**
77
+ * The filter lives in the app's own document — `backdrop-filter: url(#id)` resolves against the
78
+ * same DOM tree, so a mini-app carries its liquid glass with it. Hidden, zero-size, off-screen:
79
+ * a `width=0` svg still exposes its `<defs>` to the document.
80
+ */
81
+ function LiquidDefs() {
82
+ return (
83
+ <svg
84
+ aria-hidden
85
+ className="pointer-events-none fixed -left-[9999px] top-0 h-0 w-0"
86
+ >
87
+ <defs>
88
+ {/* noise → blur (so the bend is smooth, not fuzzy) → displace the backdrop pixels */}
89
+ <filter
90
+ id="mma-liquid"
91
+ x="0%"
92
+ y="0%"
93
+ width="100%"
94
+ height="100%"
95
+ filterUnits="objectBoundingBox"
96
+ >
97
+ <feTurbulence
98
+ type="fractalNoise"
99
+ baseFrequency="0.004"
100
+ numOctaves="2"
101
+ seed="3"
102
+ result="n"
103
+ />
104
+ <feGaussianBlur in="n" stdDeviation="1.8" result="m" />
105
+ <feDisplacementMap
106
+ in="SourceGraphic"
107
+ in2="m"
108
+ scale="45"
109
+ xChannelSelector="R"
110
+ yChannelSelector="B"
111
+ />
112
+ </filter>
113
+ {/* fine grain for the sky: the lens needs high-frequency detail behind it to read at all */}
114
+ <filter id="mma-grain">
115
+ <feTurbulence
116
+ type="fractalNoise"
117
+ baseFrequency="0.9"
118
+ numOctaves="2"
119
+ />
120
+ <feColorMatrix type="saturate" values="0" />
121
+ </filter>
122
+ </defs>
123
+ </svg>
124
+ );
125
+ }
126
+
127
+ export default function Ui() {
128
+ const { call } = useApp();
129
+ const [filter, setFilter] = useState<Filter>("all");
130
+ const [draft, setDraft] = useState("");
131
+ const [items, setItems] = useState<Item[]>([]);
132
+ const [stats, setStats] = useState<Stats>({ total: 0, active: 0, done: 0 });
133
+ const [sel, setSel] = useState<string | null>(null);
134
+ const [error, setError] = useState<string | null>(null);
135
+ const [loading, setLoading] = useState(true);
136
+
137
+ // ⭐ key: refresh depends on filter; useCallback avoids an infinite loop
138
+ const refresh = useCallback(async () => {
139
+ setLoading(true);
140
+ setError(null);
141
+ try {
142
+ const pack = (await call("list", { filter })) as {
143
+ items: Item[];
144
+ stats: Stats;
145
+ };
146
+ setItems(Array.isArray(pack?.items) ? pack.items : []);
147
+ setStats(pack?.stats ?? { total: 0, active: 0, done: 0 });
148
+ } catch (e) {
149
+ setError(String((e as Error)?.message || e));
150
+ } finally {
151
+ setLoading(false);
152
+ }
153
+ }, [call, filter]);
154
+
155
+ useEffect(() => {
156
+ void refresh();
157
+ }, [refresh]);
158
+
159
+ const current = items.find((i) => i.id === sel) ?? null;
160
+
161
+ async function act(job: () => Promise<unknown>) {
162
+ setError(null);
163
+ try {
164
+ await job();
165
+ await refresh();
166
+ } catch (e) {
167
+ setError(String((e as Error)?.message || e));
168
+ }
169
+ }
170
+
171
+ async function add() {
172
+ const title = draft.trim();
173
+ if (!title) return;
174
+ await act(async () => {
175
+ const item = (await call("add", { title })) as Item;
176
+ setDraft("");
177
+ setSel(item.id);
178
+ });
179
+ }
180
+
181
+ const now = new Date();
182
+ const weekday = now.toLocaleDateString("zh-CN", { weekday: "long" });
183
+ const dateLabel = `${now.getMonth() + 1} 月 ${now.getDate()} 日`;
184
+ // this week, Monday-first, today marked — the wide island's whole job
185
+ const week = Array.from({ length: 7 }, (_, i) => {
186
+ const d = new Date(now);
187
+ d.setDate(now.getDate() - ((now.getDay() + 6) % 7) + i);
188
+ return {
189
+ label: WEEK_LABELS[i],
190
+ day: d.getDate(),
191
+ today: d.toDateString() === now.toDateString(),
192
+ };
193
+ });
194
+
195
+ return (
196
+ // ⭐ Look: glass-island (references/looks/glass-island.md) — a cluster of frosted widgets
197
+ // floating on the sky, then the working set. The sky IS the palette: this app ships
198
+ // theme.css, so `bg-background` is the look's own blue-grey. Do not paint a gradient over
199
+ // it (that flattens the ground and the slabs stop reading as glass), and do not turn this
200
+ // into a page-wide tile wall — that is aurora-bento.
201
+ <div className="bg-background relative flex h-full min-h-0 flex-col gap-3 overflow-hidden p-5">
202
+ <LiquidDefs />
203
+ {/* The lens can only bend what is there: soft pools for hue depth, tight bokeh and grain for
204
+ something with edges. Token-derived `color-mix()` on --primary / --card / --foreground, so a
205
+ different ThemePop choice or dark mode keeps working and the app ships no colour literal. */}
206
+ <div
207
+ aria-hidden
208
+ className="pointer-events-none absolute inset-0"
209
+ style={{
210
+ // Floating haze: large soft orbs in white / mist-blue, low contrast. Light mode is
211
+ // haze-grey + white + a whisper of blue — not a saturated sky. Still enough structure
212
+ // (orb edges + grain) for the liquid lens to bend.
213
+ // Floating orbs must read against the haze ground: higher alpha, clearer edges,
214
+ // white + soft primary only (still not a saturated sky).
215
+ background:
216
+ "radial-gradient(55% 58% at 10% -4%, color-mix(in oklch, var(--card) 92%, transparent), transparent 68%)," +
217
+ "radial-gradient(48% 52% at 92% 4%, color-mix(in oklch, var(--primary) 38%, transparent), transparent 66%)," +
218
+ "radial-gradient(50% 45% at 72% 88%, color-mix(in oklch, var(--card) 80%, transparent), transparent 64%)," +
219
+ "radial-gradient(42% 48% at 12% 82%, color-mix(in oklch, var(--primary) 28%, transparent), transparent 64%)," +
220
+ "radial-gradient(160px 160px at 32% 28%, color-mix(in oklch, var(--card) 95%, transparent), transparent 70%)," +
221
+ "radial-gradient(130px 130px at 78% 36%, color-mix(in oklch, var(--primary) 32%, transparent), transparent 70%)," +
222
+ "radial-gradient(140px 140px at 52% 62%, color-mix(in oklch, var(--card) 88%, transparent), transparent 68%)," +
223
+ "radial-gradient(110px 110px at 22% 58%, color-mix(in oklch, var(--primary) 24%, transparent), transparent 70%)",
224
+ }}
225
+ />
226
+ {/* grain: finest structure; opacity high enough that the bend is legible on a mid sky */}
227
+ <svg
228
+ aria-hidden
229
+ className="pointer-events-none absolute inset-0 h-full w-full opacity-[0.2]"
230
+ >
231
+ <rect width="100%" height="100%" filter="url(#mma-grain)" />
232
+ </svg>
233
+
234
+ {/* the island cluster: unequal spans, each widget says exactly one thing */}
235
+ {/* The sky has to stay visible around the cluster: an island stretched to every edge is
236
+ just a page with rounded corners. Cap the content and let `--background` frame it.
237
+ 6 columns are written out rather than switched on at `md:` — a mini-app lives in a
238
+ panel of whatever width the user dragged it to, and this arrangement *is* the look. */}
239
+ <div className="relative mx-auto flex h-full min-h-0 w-full max-w-5xl flex-col gap-3">
240
+ <div className="grid grid-cols-6 gap-3">
241
+ <div
242
+ style={GLASS}
243
+ className="col-span-2 row-span-2 flex flex-col justify-between p-4"
244
+ >
245
+ <p className="text-muted-foreground text-xs tracking-[0.18em] uppercase">
246
+ {weekday}
247
+ </p>
248
+ <p className="font-serif text-6xl leading-[0.82] font-medium tracking-tight tabular-nums">
249
+ {now.getDate()}
250
+ </p>
251
+ <p className="text-muted-foreground text-xs">{dateLabel}</p>
252
+ </div>
253
+
254
+ <div
255
+ style={GLASS}
256
+ className="col-span-4 flex items-center justify-between p-3"
257
+ >
258
+ {week.map((d) => (
259
+ <span
260
+ key={d.label}
261
+ className={
262
+ d.today
263
+ ? "bg-foreground text-background flex size-9 flex-col items-center justify-center rounded-full text-[11px] leading-tight"
264
+ : "text-muted-foreground flex size-9 flex-col items-center justify-center rounded-full text-[11px] leading-tight"
265
+ }
266
+ >
267
+ <span className="opacity-70">{d.label}</span>
268
+ <span className="tabular-nums">{d.day}</span>
269
+ </span>
270
+ ))}
271
+ </div>
272
+
273
+ <div style={GLASS} className="col-span-2 p-4">
274
+ <p className="text-muted-foreground text-[11px]">进行中</p>
275
+ <p className="mt-1 text-2xl font-medium tabular-nums">
276
+ {stats.active}
277
+ </p>
278
+ </div>
279
+ <div style={GLASS} className="col-span-2 p-4">
280
+ <p className="text-muted-foreground text-[11px]">已完</p>
281
+ <p className="mt-1 text-2xl font-medium tabular-nums">
282
+ {stats.done}
283
+ </p>
284
+ </div>
285
+ </div>
286
+
287
+ {/* the working set: controls in its own header, ListDetail owns the remaining height */}
288
+ {/* Working set is a soft card, not liquid glass — wall-to-wall displacement ate the sky
289
+ and is why the facade never matched the floating-pill prototype. */}
290
+ <div style={WORK} className="relative flex min-h-0 flex-1 flex-col">
291
+ <div className="border-border/60 flex flex-wrap items-center gap-2 border-b p-3">
292
+ {FILTERS.map((f) => (
293
+ <Button
294
+ key={f.id}
295
+ size="sm"
296
+ variant={filter === f.id ? "default" : "ghost"}
297
+ onClick={() => setFilter(f.id)}
298
+ >
299
+ {f.label}
300
+ </Button>
301
+ ))}
302
+ <Button
303
+ size="sm"
304
+ variant="ghost"
305
+ className="ml-auto"
306
+ onClick={() => void act(() => call("archive", {}))}
307
+ >
308
+ <Icon.Archive size={16} strokeWidth={2} /> 归档
309
+ </Button>
310
+ <div className="flex w-full gap-2">
311
+ <Input
312
+ value={draft}
313
+ placeholder="加一件,回车"
314
+ onChange={(e) => setDraft(e.target.value)}
315
+ onKeyDown={(e) => {
316
+ if (e.key === "Enter") void add();
317
+ }}
318
+ />
319
+ <Button onClick={() => void add()} disabled={!draft.trim()}>
320
+ <Icon.Plus size={16} strokeWidth={2} />
321
+ </Button>
322
+ </div>
323
+ {error ? (
324
+ <p className="text-destructive w-full text-sm">{error}</p>
325
+ ) : null}
326
+ </div>
327
+
328
+ <div className="min-h-0 flex-1">
329
+ <ListDetail
330
+ list={
331
+ <ul>
332
+ {loading && !items.length ? (
333
+ <li className="text-muted-foreground px-3 py-4 text-sm">
334
+ 加载中…
335
+ </li>
336
+ ) : null}
337
+ {!loading && !items.length ? (
338
+ <li className="p-4">
339
+ <Empty>
340
+ <EmptyHeader>
341
+ <EmptyTitle>这一屏还空着</EmptyTitle>
342
+ <EmptyDescription>
343
+ 上面加一件,它会出现在左边。
344
+ </EmptyDescription>
345
+ </EmptyHeader>
346
+ </Empty>
347
+ </li>
348
+ ) : null}
349
+ {items.map((it) => (
350
+ <li key={it.id}>
351
+ <ItemRow
352
+ item={it}
353
+ selected={sel === it.id}
354
+ onSelect={() => setSel(it.id)}
355
+ />
356
+ </li>
357
+ ))}
358
+ </ul>
359
+ }
360
+ detail={
361
+ current ? (
362
+ <div className="flex flex-col gap-3 p-4">
363
+ <h2 className="text-lg font-semibold">{current.title}</h2>
364
+ <p className="text-muted-foreground text-sm">
365
+ {new Date(current.createdAt).toLocaleString("zh-CN")}
366
+ </p>
367
+ <div className="flex gap-2">
368
+ <Button
369
+ size="sm"
370
+ variant="outline"
371
+ onClick={() =>
372
+ void act(() => call("toggle", { id: current.id }))
373
+ }
374
+ >
375
+ {current.done ? "标为未完" : "标为完成"}
376
+ </Button>
377
+ <Button
378
+ size="sm"
379
+ variant="ghost"
380
+ onClick={() =>
381
+ void act(async () => {
382
+ await call("remove", { id: current.id });
383
+ setSel(null);
384
+ })
385
+ }
386
+ >
387
+ 删除
388
+ </Button>
389
+ </div>
390
+ </div>
391
+ ) : undefined
392
+ }
393
+ empty={
394
+ <p className="text-muted-foreground p-4 text-sm">
395
+ 点左边一条,这边打开。
396
+ </p>
397
+ }
398
+ mobileView={current ? "detail" : "list"}
399
+ onMobileBack={() => setSel(null)}
400
+ />
401
+ </div>
402
+ </div>
403
+ </div>
404
+ </div>
405
+ );
406
+ }
@@ -1,7 +1,7 @@
1
- import { defineDashboard } from "@monkeyagent/dashboard";
1
+ import { defineApp } from "@monkey-mini-app/api";
2
2
 
3
- // ⭐ 关键:host 已经把 OS 基础指标给到 ctx.system.metrics()(内存/CPU/负载/uptime 都有),
4
- // 不要再用 bash 重算。ctx.bash 只用于拿 host 没有的:ps(进程)、df(磁盘)。
3
+ // ⭐ key: the host already exposes OS basics via ctx.system.metrics() (memory/CPU/load/uptime are all there),
4
+ // so don't recompute them with bash. Use ctx.bash only for what the host lacks: ps (processes), df (disk).
5
5
  type Proc = { pid: string; cpu: number; mem: number; name: string };
6
6
 
7
7
  function fmtBytes(n: number): string {
@@ -26,7 +26,7 @@ async function sh(ctx, cmd: string): Promise<string> {
26
26
  }
27
27
 
28
28
  function parseProcesses(text: string): Proc[] {
29
- // 最后一列是 comm,可能含空格;用最后一段当 name,前面 4 段是 pid/cpu/mem
29
+ // the last column is comm and may contain spaces; join the trailing tokens as name, the leading columns are pid/cpu/mem
30
30
  if (!text) return [];
31
31
  return text
32
32
  .split("\n")
@@ -53,14 +53,14 @@ function parseDisk(text: string): { total: number; used: number; avail: number;
53
53
  return { total, used, avail, usedPct, mount: cols[5] || "/" };
54
54
  }
55
55
 
56
- export default defineDashboard({
57
- name: "系统监控",
58
- description: "CPU / 内存 / 磁盘 / 进程实时指标",
56
+ export default defineApp({
57
+ name: "值班屏",
58
+ description: "打开就自己在跳。没有开始按钮。",
59
59
  api: {
60
60
  async getSnapshot(ctx) {
61
61
  const base = await ctx.system.metrics();
62
62
  const platform = base?.platform || "";
63
- // 内存/CPU/负载由 metrics 提供,这里只补 host 没有的:进程 + 磁盘
63
+ // memory/CPU/load come from metrics; only fill in what the host lacks here: processes + disk
64
64
  const [psText, dfLine] = await Promise.all([
65
65
  sh(ctx, platform === "darwin" ? "ps -axo pid,pcpu,pmem,comm -r | head -n 9" : "ps -axo pid,pcpu,pmem,comm --sort=-pcpu | head -n 9"),
66
66
  sh(ctx, "df -k / | tail -1"),
@@ -0,0 +1,8 @@
1
+ {
2
+ "id": "com.example.watch",
3
+ "name": "值班屏",
4
+ "description": "打开就自己在跳。没有开始按钮。",
5
+ "version": "0.1.0",
6
+ "entry": "ui.tsx",
7
+ "acronym": "ZB"
8
+ }
@@ -0,0 +1,187 @@
1
+ import { useEffect, useState } from "react";
2
+
3
+ import {
4
+ DashboardShell,
5
+ Reveal,
6
+ Sparkline,
7
+ Table,
8
+ TableBody,
9
+ TableCell,
10
+ TableHead,
11
+ TableHeader,
12
+ TableRow,
13
+ useApp,
14
+ } from "@monkey-mini-app/ui";
15
+
16
+ type Snapshot = {
17
+ hostname?: string;
18
+ platform?: string;
19
+ arch?: string;
20
+ loadavg?: Record<string, number>;
21
+ uptimeSec?: number;
22
+ collectedAt: number;
23
+ cpu: { model: string; count: number };
24
+ processes: { pid: string; cpu: number; mem: number; name: string }[];
25
+ memory: { total: number; used: number; free: number; usedPct: number };
26
+ disk: { total: string; used: string; free: string; usedPct: number } | null;
27
+ };
28
+
29
+ export default function Ui() {
30
+ const { call } = useApp();
31
+ const [snap, setSnap] = useState<Snapshot | null>(null);
32
+ const [error, setError] = useState<string | null>(null);
33
+ const [memHist, setMemHist] = useState<number[]>([]);
34
+ const [loadHist, setLoadHist] = useState<number[]>([]);
35
+
36
+ // ⭐ key: polling — fetch every 2s; stop when the page is hidden (in background) to avoid wasted runs.
37
+ // busy prevents issuing the next tick before the previous one returns; alive prevents setState after unmount.
38
+ useEffect(() => {
39
+ let alive = true;
40
+ let busy = false;
41
+ async function tick() {
42
+ if (busy) return;
43
+ busy = true;
44
+ try {
45
+ const next = (await call("getSnapshot", {})) as Snapshot;
46
+ if (!alive) return;
47
+ setSnap(next);
48
+ setError(null);
49
+ setMemHist((prev) => prev.concat(next.memory.usedPct).slice(-48));
50
+ const load = Number(next.loadavg?.["1m"] ?? 0);
51
+ setLoadHist((prev) => prev.concat(load).slice(-48));
52
+ } catch (e) {
53
+ if (alive) setError(String((e as Error)?.message || e));
54
+ } finally {
55
+ busy = false;
56
+ }
57
+ }
58
+ void tick();
59
+ const id = setInterval(() => void tick(), 2000);
60
+ const stop = () => {
61
+ if (document.hidden) clearInterval(id);
62
+ };
63
+ document.addEventListener("visibilitychange", stop);
64
+ return () => {
65
+ alive = false;
66
+ clearInterval(id);
67
+ document.removeEventListener("visibilitychange", stop);
68
+ };
69
+ }, [call]);
70
+
71
+ const procs = snap?.processes ?? [];
72
+ const load = snap?.loadavg;
73
+ const memPct = snap?.memory.usedPct ?? 0;
74
+
75
+ return (
76
+ // ⭐ Look: tape — numerals + vertical rules, no card chrome. The shape is DashboardShell:
77
+ // the hostname row and the KPI band are pinned, and the sparklines + process table are the
78
+ // one scroller. Hand-rolled, that scroller tends to land on the outer column, and the first
79
+ // table scroll takes the numbers off the top of a screen meant to be read from across a room.
80
+ <div className="h-full min-h-0 font-mono">
81
+ <DashboardShell
82
+ header={
83
+ <div className="text-muted-foreground flex items-center justify-between border-b px-4 py-2 text-xs tracking-widest uppercase">
84
+ <span>{snap?.hostname ?? "值班屏"}</span>
85
+ <span>每 2 秒 · {fmtUptime(snap?.uptimeSec ?? 0)}</span>
86
+ </div>
87
+ }
88
+ kpis={
89
+ <Reveal>
90
+ {/* four columns written out, not switched on at `md:` — the panel width is
91
+ user-dragged, so a breakpoint here is a lie (see `today`). */}
92
+ <div className="grid grid-cols-4 divide-x divide-border">
93
+ <div className="px-4 py-5">
94
+ <div className="text-muted-foreground text-[10px] tracking-widest uppercase">
95
+ Load
96
+ </div>
97
+ <div className="mt-1 text-3xl font-medium tracking-tight tabular-nums">
98
+ {load ? Number(load["1m"]).toFixed(2) : "—"}
99
+ </div>
100
+ </div>
101
+ <div className="px-4 py-5">
102
+ <div className="text-muted-foreground text-[10px] tracking-widest uppercase">
103
+ Mem
104
+ </div>
105
+ <div className="mt-1 text-3xl font-medium tracking-tight tabular-nums">
106
+ {memPct}%
107
+ </div>
108
+ </div>
109
+ <div className="px-4 py-5">
110
+ <div className="text-muted-foreground text-[10px] tracking-widest uppercase">
111
+ Disk
112
+ </div>
113
+ <div className="mt-1 text-3xl font-medium tracking-tight tabular-nums">
114
+ {snap?.disk ? `${snap.disk.usedPct}%` : "—"}
115
+ </div>
116
+ </div>
117
+ <div className="px-4 py-5">
118
+ <div className="text-muted-foreground text-[10px] tracking-widest uppercase">
119
+ CPU
120
+ </div>
121
+ <div className="mt-1 text-3xl font-medium tracking-tight tabular-nums">
122
+ {snap ? snap.cpu.count : "—"}
123
+ </div>
124
+ </div>
125
+ </div>
126
+ </Reveal>
127
+ }
128
+ main={
129
+ <>
130
+ {error ? (
131
+ <p className="text-destructive px-4 py-2 text-sm">{error}</p>
132
+ ) : null}
133
+ <div className="grid grid-cols-2 gap-0 border-t">
134
+ <div className="border-r p-4">
135
+ <Sparkline data={memHist.map((v) => ({ value: v }))} />
136
+ </div>
137
+ <div className="p-4">
138
+ <Sparkline data={loadHist.map((v) => ({ value: v }))} />
139
+ </div>
140
+ </div>
141
+ <div className="border-t">
142
+ <Table>
143
+ <TableHeader>
144
+ <TableRow>
145
+ <TableHead className="w-20">PID</TableHead>
146
+ <TableHead className="w-24">CPU%</TableHead>
147
+ <TableHead className="w-24">MEM%</TableHead>
148
+ <TableHead>PROC</TableHead>
149
+ </TableRow>
150
+ </TableHeader>
151
+ <TableBody>
152
+ {procs.map((p) => (
153
+ <TableRow key={p.pid}>
154
+ <TableCell className="font-mono">{p.pid}</TableCell>
155
+ <TableCell>{p.cpu.toFixed(1)}</TableCell>
156
+ <TableCell>{p.mem.toFixed(1)}</TableCell>
157
+ <TableCell className="max-w-[420px] truncate">
158
+ {p.name}
159
+ </TableCell>
160
+ </TableRow>
161
+ ))}
162
+ </TableBody>
163
+ </Table>
164
+ </div>
165
+ </>
166
+ }
167
+ />
168
+ </div>
169
+ );
170
+ }
171
+
172
+ function fmtBytes(n: number): string {
173
+ if (!Number.isFinite(n) || n <= 0) return "—";
174
+ const units = ["B", "KB", "MB", "GB", "TB"];
175
+ let i = 0;
176
+ while (n >= 1024 && i < units.length - 1) {
177
+ n /= 1024;
178
+ i++;
179
+ }
180
+ return n.toFixed(i ? 1 : 0) + units[i];
181
+ }
182
+
183
+ function fmtUptime(sec: number): string {
184
+ const h = Math.floor(sec / 3600);
185
+ const m = Math.floor((sec % 3600) / 60);
186
+ return h ? `${h}h ${m}m` : `${m}m`;
187
+ }
@@ -0,0 +1,31 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "jsx": "react-jsx",
7
+ "lib": ["ES2022", "DOM"],
8
+ "strict": true,
9
+ "noImplicitAny": false,
10
+ "skipLibCheck": true,
11
+ "noEmit": true,
12
+ // main.api.ts runs on Node: Buffer/process are part of the backend authoring surface
13
+ // (the host's own static check whitelists the same names). exceljs and friends come
14
+ // from the repo's devDependencies so a template that names one still type-checks here.
15
+ "types": ["node"],
16
+ "paths": {
17
+ "@monkey-mini-app/api": ["../../packages/api/src/index.ts"],
18
+ "@monkey-mini-app/ui": ["../../packages/ui/src/index.ts"],
19
+ "@monkey-mini-app/ui/*": ["../../packages/ui/src/*"],
20
+ // The iframe vendors. An app directory has no node_modules, so these rows are the
21
+ // only reason `lodash` / `motion` are not red in the author's editor. Both motion
22
+ // rows are the **react** declaration, matching what /mma/vendors/motion.js ships
23
+ // (motion's own bare entry is the vanilla API and has no `motion.div`).
24
+ "lodash": ["../../node_modules/lodash-es"],
25
+ "lodash/*": ["../../node_modules/lodash-es/*"],
26
+ "motion": ["../../node_modules/motion/dist/react.d.ts"],
27
+ "motion/react": ["../../node_modules/motion/dist/react.d.ts"]
28
+ }
29
+ },
30
+ "include": ["templates/**/*.ts", "templates/**/*.tsx", "types/**/*.d.ts"]
31
+ }
@@ -0,0 +1 @@
1
+ declare module "https://esm.sh/*";