taskchef 8.6.2 → 8.7.1

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 (630) hide show
  1. package/.codex-plugin/plugin.json +1 -1
  2. package/README.md +8 -4
  3. package/assets/README.md +19 -0
  4. package/assets/taskchef-app-rounded.png +0 -0
  5. package/assets/taskchef-avatar-square.png +0 -0
  6. package/assets/taskchef-avatar-square.svg +8 -0
  7. package/assets/taskchef-sidebar-dark.svg +6 -0
  8. package/assets/taskchef-sidebar-light.svg +6 -0
  9. package/assets/taskchef-sidebar.svg +6 -0
  10. package/docs/advanced-guide.md +20 -29
  11. package/docs/dashboard-ui.md +15 -0
  12. package/docs/diagrams/taskchef-next-reply-lookup.drawio +38 -0
  13. package/docs/diagrams/taskchef-next-reply-lookup.drawio.png +0 -0
  14. package/docs/diagrams/taskchef-next-storage.drawio +41 -0
  15. package/docs/diagrams/taskchef-next-storage.drawio.png +0 -0
  16. package/docs/images/taskchef-pr-icon-comparison.jpg +0 -0
  17. package/docs/images/taskchef-unified-status-popup.jpg +0 -0
  18. package/docs/mcp-app.md +278 -6
  19. package/docs/spec.md +24 -69
  20. package/docs/taskchef-next-github.md +206 -0
  21. package/docs/taskchef-next-status-research.md +102 -0
  22. package/docs/taskchef-next-storage.md +167 -0
  23. package/docs/workflows.md +4 -2
  24. package/node_modules/@napi-rs/keyring/LICENSE +21 -0
  25. package/node_modules/@napi-rs/keyring/README.md +45 -0
  26. package/node_modules/@napi-rs/keyring/index.d.ts +232 -0
  27. package/node_modules/@napi-rs/keyring/index.js +706 -0
  28. package/node_modules/@napi-rs/keyring/keytar.d.ts +53 -0
  29. package/node_modules/@napi-rs/keyring/keytar.js +26 -0
  30. package/node_modules/@napi-rs/keyring/package.json +126 -0
  31. package/node_modules/@napi-rs/keyring-darwin-arm64/README.md +3 -0
  32. package/node_modules/@napi-rs/keyring-darwin-arm64/keyring.darwin-arm64.node +0 -0
  33. package/node_modules/@napi-rs/keyring-darwin-arm64/package.json +32 -0
  34. package/node_modules/@napi-rs/keyring-darwin-x64/README.md +3 -0
  35. package/node_modules/@napi-rs/keyring-darwin-x64/keyring.darwin-x64.node +0 -0
  36. package/node_modules/@napi-rs/keyring-darwin-x64/package.json +32 -0
  37. package/node_modules/@napi-rs/keyring-linux-arm64-gnu/README.md +3 -0
  38. package/node_modules/@napi-rs/keyring-linux-arm64-gnu/keyring.linux-arm64-gnu.node +0 -0
  39. package/node_modules/@napi-rs/keyring-linux-arm64-gnu/package.json +35 -0
  40. package/node_modules/@napi-rs/keyring-linux-arm64-musl/README.md +3 -0
  41. package/node_modules/@napi-rs/keyring-linux-arm64-musl/keyring.linux-arm64-musl.node +0 -0
  42. package/node_modules/@napi-rs/keyring-linux-arm64-musl/package.json +35 -0
  43. package/node_modules/@napi-rs/keyring-linux-x64-gnu/README.md +3 -0
  44. package/node_modules/@napi-rs/keyring-linux-x64-gnu/keyring.linux-x64-gnu.node +0 -0
  45. package/node_modules/@napi-rs/keyring-linux-x64-gnu/package.json +35 -0
  46. package/node_modules/@napi-rs/keyring-linux-x64-musl/README.md +3 -0
  47. package/node_modules/@napi-rs/keyring-linux-x64-musl/keyring.linux-x64-musl.node +0 -0
  48. package/node_modules/@napi-rs/keyring-linux-x64-musl/package.json +35 -0
  49. package/node_modules/@napi-rs/keyring-win32-arm64-msvc/README.md +3 -0
  50. package/node_modules/@napi-rs/keyring-win32-arm64-msvc/keyring.win32-arm64-msvc.node +0 -0
  51. package/node_modules/@napi-rs/keyring-win32-arm64-msvc/package.json +32 -0
  52. package/node_modules/@napi-rs/keyring-win32-x64-msvc/README.md +3 -0
  53. package/node_modules/@napi-rs/keyring-win32-x64-msvc/keyring.win32-x64-msvc.node +0 -0
  54. package/node_modules/@napi-rs/keyring-win32-x64-msvc/package.json +32 -0
  55. package/node_modules/@types/debug/LICENSE +21 -0
  56. package/node_modules/@types/debug/README.md +69 -0
  57. package/node_modules/@types/debug/index.d.ts +50 -0
  58. package/node_modules/@types/debug/package.json +58 -0
  59. package/node_modules/@types/mdast/LICENSE +21 -0
  60. package/node_modules/@types/mdast/README.md +15 -0
  61. package/node_modules/@types/mdast/index.d.ts +1123 -0
  62. package/node_modules/@types/mdast/package.json +47 -0
  63. package/node_modules/@types/ms/LICENSE +21 -0
  64. package/node_modules/@types/ms/README.md +82 -0
  65. package/node_modules/@types/ms/index.d.ts +63 -0
  66. package/node_modules/@types/ms/package.json +26 -0
  67. package/node_modules/@types/unist/LICENSE +21 -0
  68. package/node_modules/@types/unist/README.md +15 -0
  69. package/node_modules/@types/unist/index.d.ts +119 -0
  70. package/node_modules/@types/unist/package.json +60 -0
  71. package/node_modules/character-entities/index.d.ts +6 -0
  72. package/node_modules/character-entities/index.js +2132 -0
  73. package/node_modules/character-entities/license +22 -0
  74. package/node_modules/character-entities/package.json +78 -0
  75. package/node_modules/character-entities/readme.md +152 -0
  76. package/node_modules/decode-named-character-reference/index.d.ts +13 -0
  77. package/node_modules/decode-named-character-reference/index.d.ts.map +1 -0
  78. package/node_modules/decode-named-character-reference/index.dom.d.ts +6 -0
  79. package/node_modules/decode-named-character-reference/index.dom.d.ts.map +1 -0
  80. package/node_modules/decode-named-character-reference/index.dom.js +32 -0
  81. package/node_modules/decode-named-character-reference/index.js +19 -0
  82. package/node_modules/decode-named-character-reference/license +22 -0
  83. package/node_modules/decode-named-character-reference/package.json +90 -0
  84. package/node_modules/decode-named-character-reference/readme.md +136 -0
  85. package/node_modules/dequal/dist/index.js +86 -0
  86. package/node_modules/dequal/dist/index.min.js +1 -0
  87. package/node_modules/dequal/dist/index.mjs +84 -0
  88. package/node_modules/dequal/index.d.ts +1 -0
  89. package/node_modules/dequal/license +21 -0
  90. package/node_modules/dequal/lite/index.d.ts +1 -0
  91. package/node_modules/dequal/lite/index.js +31 -0
  92. package/node_modules/dequal/lite/index.min.js +1 -0
  93. package/node_modules/dequal/lite/index.mjs +29 -0
  94. package/node_modules/dequal/package.json +57 -0
  95. package/node_modules/dequal/readme.md +112 -0
  96. package/node_modules/devlop/lib/default.js +9 -0
  97. package/node_modules/devlop/lib/development.d.ts +84 -0
  98. package/node_modules/devlop/lib/development.js +238 -0
  99. package/node_modules/devlop/license +22 -0
  100. package/node_modules/devlop/package.json +80 -0
  101. package/node_modules/devlop/readme.md +360 -0
  102. package/node_modules/mdast-util-from-markdown/dev/index.d.ts +23 -0
  103. package/node_modules/mdast-util-from-markdown/dev/index.js +2 -0
  104. package/node_modules/mdast-util-from-markdown/dev/lib/index.d.ts +53 -0
  105. package/node_modules/mdast-util-from-markdown/dev/lib/index.d.ts.map +1 -0
  106. package/node_modules/mdast-util-from-markdown/dev/lib/index.js +1348 -0
  107. package/node_modules/mdast-util-from-markdown/dev/lib/types.d.ts +295 -0
  108. package/node_modules/mdast-util-from-markdown/dev/lib/types.js +2 -0
  109. package/node_modules/mdast-util-from-markdown/index.d.ts +23 -0
  110. package/node_modules/mdast-util-from-markdown/index.js +2 -0
  111. package/node_modules/mdast-util-from-markdown/lib/index.d.ts +53 -0
  112. package/node_modules/mdast-util-from-markdown/lib/index.js +1177 -0
  113. package/node_modules/mdast-util-from-markdown/lib/types.d.ts +295 -0
  114. package/node_modules/mdast-util-from-markdown/lib/types.js +2 -0
  115. package/node_modules/mdast-util-from-markdown/license +22 -0
  116. package/node_modules/mdast-util-from-markdown/package.json +139 -0
  117. package/node_modules/mdast-util-from-markdown/readme.md +537 -0
  118. package/node_modules/mdast-util-to-string/index.d.ts +2 -0
  119. package/node_modules/mdast-util-to-string/index.js +5 -0
  120. package/node_modules/mdast-util-to-string/lib/index.d.ts +31 -0
  121. package/node_modules/mdast-util-to-string/lib/index.js +108 -0
  122. package/node_modules/mdast-util-to-string/license +22 -0
  123. package/node_modules/mdast-util-to-string/package.json +78 -0
  124. package/node_modules/mdast-util-to-string/readme.md +218 -0
  125. package/node_modules/micromark/dev/index.d.ts +82 -0
  126. package/node_modules/micromark/dev/index.d.ts.map +1 -0
  127. package/node_modules/micromark/dev/index.js +68 -0
  128. package/node_modules/micromark/dev/lib/compile.d.ts +16 -0
  129. package/node_modules/micromark/dev/lib/compile.d.ts.map +1 -0
  130. package/node_modules/micromark/dev/lib/compile.js +1162 -0
  131. package/node_modules/micromark/dev/lib/constructs.d.ts +73 -0
  132. package/node_modules/micromark/dev/lib/constructs.d.ts.map +1 -0
  133. package/node_modules/micromark/dev/lib/constructs.js +101 -0
  134. package/node_modules/micromark/dev/lib/create-tokenizer.d.ts +46 -0
  135. package/node_modules/micromark/dev/lib/create-tokenizer.d.ts.map +1 -0
  136. package/node_modules/micromark/dev/lib/create-tokenizer.js +718 -0
  137. package/node_modules/micromark/dev/lib/initialize/content.d.ts +4 -0
  138. package/node_modules/micromark/dev/lib/initialize/content.d.ts.map +1 -0
  139. package/node_modules/micromark/dev/lib/initialize/content.js +99 -0
  140. package/node_modules/micromark/dev/lib/initialize/document.d.ts +10 -0
  141. package/node_modules/micromark/dev/lib/initialize/document.d.ts.map +1 -0
  142. package/node_modules/micromark/dev/lib/initialize/document.js +449 -0
  143. package/node_modules/micromark/dev/lib/initialize/flow.d.ts +4 -0
  144. package/node_modules/micromark/dev/lib/initialize/flow.d.ts.map +1 -0
  145. package/node_modules/micromark/dev/lib/initialize/flow.js +86 -0
  146. package/node_modules/micromark/dev/lib/initialize/text.d.ts +8 -0
  147. package/node_modules/micromark/dev/lib/initialize/text.d.ts.map +1 -0
  148. package/node_modules/micromark/dev/lib/initialize/text.js +248 -0
  149. package/node_modules/micromark/dev/lib/parse.d.ts +10 -0
  150. package/node_modules/micromark/dev/lib/parse.d.ts.map +1 -0
  151. package/node_modules/micromark/dev/lib/parse.js +58 -0
  152. package/node_modules/micromark/dev/lib/postprocess.d.ts +9 -0
  153. package/node_modules/micromark/dev/lib/postprocess.d.ts.map +1 -0
  154. package/node_modules/micromark/dev/lib/postprocess.js +19 -0
  155. package/node_modules/micromark/dev/lib/preprocess.d.ts +13 -0
  156. package/node_modules/micromark/dev/lib/preprocess.d.ts.map +1 -0
  157. package/node_modules/micromark/dev/lib/preprocess.js +139 -0
  158. package/node_modules/micromark/dev/stream.d.ts +35 -0
  159. package/node_modules/micromark/dev/stream.d.ts.map +1 -0
  160. package/node_modules/micromark/dev/stream.js +270 -0
  161. package/node_modules/micromark/index.d.ts +82 -0
  162. package/node_modules/micromark/index.d.ts.map +1 -0
  163. package/node_modules/micromark/index.js +60 -0
  164. package/node_modules/micromark/lib/compile.d.ts +16 -0
  165. package/node_modules/micromark/lib/compile.d.ts.map +1 -0
  166. package/node_modules/micromark/lib/compile.js +1068 -0
  167. package/node_modules/micromark/lib/constructs.d.ts +73 -0
  168. package/node_modules/micromark/lib/constructs.d.ts.map +1 -0
  169. package/node_modules/micromark/lib/constructs.js +85 -0
  170. package/node_modules/micromark/lib/create-tokenizer.d.ts +46 -0
  171. package/node_modules/micromark/lib/create-tokenizer.d.ts.map +1 -0
  172. package/node_modules/micromark/lib/create-tokenizer.js +613 -0
  173. package/node_modules/micromark/lib/initialize/content.d.ts +4 -0
  174. package/node_modules/micromark/lib/initialize/content.d.ts.map +1 -0
  175. package/node_modules/micromark/lib/initialize/content.js +79 -0
  176. package/node_modules/micromark/lib/initialize/document.d.ts +10 -0
  177. package/node_modules/micromark/lib/initialize/document.d.ts.map +1 -0
  178. package/node_modules/micromark/lib/initialize/document.js +370 -0
  179. package/node_modules/micromark/lib/initialize/flow.d.ts +4 -0
  180. package/node_modules/micromark/lib/initialize/flow.d.ts.map +1 -0
  181. package/node_modules/micromark/lib/initialize/flow.js +58 -0
  182. package/node_modules/micromark/lib/initialize/text.d.ts +8 -0
  183. package/node_modules/micromark/lib/initialize/text.d.ts.map +1 -0
  184. package/node_modules/micromark/lib/initialize/text.js +216 -0
  185. package/node_modules/micromark/lib/parse.d.ts +10 -0
  186. package/node_modules/micromark/lib/parse.d.ts.map +1 -0
  187. package/node_modules/micromark/lib/parse.js +56 -0
  188. package/node_modules/micromark/lib/postprocess.d.ts +9 -0
  189. package/node_modules/micromark/lib/postprocess.d.ts.map +1 -0
  190. package/node_modules/micromark/lib/postprocess.js +18 -0
  191. package/node_modules/micromark/lib/preprocess.d.ts +13 -0
  192. package/node_modules/micromark/lib/preprocess.d.ts.map +1 -0
  193. package/node_modules/micromark/lib/preprocess.js +112 -0
  194. package/node_modules/micromark/license +22 -0
  195. package/node_modules/micromark/package.json +87 -0
  196. package/node_modules/micromark/readme.md +488 -0
  197. package/node_modules/micromark/stream.d.ts +35 -0
  198. package/node_modules/micromark/stream.d.ts.map +1 -0
  199. package/node_modules/micromark/stream.js +256 -0
  200. package/node_modules/micromark-core-commonmark/dev/index.d.ts +23 -0
  201. package/node_modules/micromark-core-commonmark/dev/index.d.ts.map +1 -0
  202. package/node_modules/micromark-core-commonmark/dev/index.js +22 -0
  203. package/node_modules/micromark-core-commonmark/dev/lib/attention.d.ts +4 -0
  204. package/node_modules/micromark-core-commonmark/dev/lib/attention.d.ts.map +1 -0
  205. package/node_modules/micromark-core-commonmark/dev/lib/attention.js +294 -0
  206. package/node_modules/micromark-core-commonmark/dev/lib/autolink.d.ts +4 -0
  207. package/node_modules/micromark-core-commonmark/dev/lib/autolink.d.ts.map +1 -0
  208. package/node_modules/micromark-core-commonmark/dev/lib/autolink.js +269 -0
  209. package/node_modules/micromark-core-commonmark/dev/lib/blank-line.d.ts +4 -0
  210. package/node_modules/micromark-core-commonmark/dev/lib/blank-line.d.ts.map +1 -0
  211. package/node_modules/micromark-core-commonmark/dev/lib/blank-line.js +62 -0
  212. package/node_modules/micromark-core-commonmark/dev/lib/block-quote.d.ts +4 -0
  213. package/node_modules/micromark-core-commonmark/dev/lib/block-quote.d.ts.map +1 -0
  214. package/node_modules/micromark-core-commonmark/dev/lib/block-quote.js +162 -0
  215. package/node_modules/micromark-core-commonmark/dev/lib/character-escape.d.ts +4 -0
  216. package/node_modules/micromark-core-commonmark/dev/lib/character-escape.d.ts.map +1 -0
  217. package/node_modules/micromark-core-commonmark/dev/lib/character-escape.js +69 -0
  218. package/node_modules/micromark-core-commonmark/dev/lib/character-reference.d.ts +4 -0
  219. package/node_modules/micromark-core-commonmark/dev/lib/character-reference.d.ts.map +1 -0
  220. package/node_modules/micromark-core-commonmark/dev/lib/character-reference.js +166 -0
  221. package/node_modules/micromark-core-commonmark/dev/lib/code-fenced.d.ts +4 -0
  222. package/node_modules/micromark-core-commonmark/dev/lib/code-fenced.d.ts.map +1 -0
  223. package/node_modules/micromark-core-commonmark/dev/lib/code-fenced.js +472 -0
  224. package/node_modules/micromark-core-commonmark/dev/lib/code-indented.d.ts +4 -0
  225. package/node_modules/micromark-core-commonmark/dev/lib/code-indented.d.ts.map +1 -0
  226. package/node_modules/micromark-core-commonmark/dev/lib/code-indented.js +178 -0
  227. package/node_modules/micromark-core-commonmark/dev/lib/code-text.d.ts +4 -0
  228. package/node_modules/micromark-core-commonmark/dev/lib/code-text.d.ts.map +1 -0
  229. package/node_modules/micromark-core-commonmark/dev/lib/code-text.js +257 -0
  230. package/node_modules/micromark-core-commonmark/dev/lib/content.d.ts +7 -0
  231. package/node_modules/micromark-core-commonmark/dev/lib/content.d.ts.map +1 -0
  232. package/node_modules/micromark-core-commonmark/dev/lib/content.js +185 -0
  233. package/node_modules/micromark-core-commonmark/dev/lib/definition.d.ts +4 -0
  234. package/node_modules/micromark-core-commonmark/dev/lib/definition.d.ts.map +1 -0
  235. package/node_modules/micromark-core-commonmark/dev/lib/definition.js +295 -0
  236. package/node_modules/micromark-core-commonmark/dev/lib/hard-break-escape.d.ts +4 -0
  237. package/node_modules/micromark-core-commonmark/dev/lib/hard-break-escape.d.ts.map +1 -0
  238. package/node_modules/micromark-core-commonmark/dev/lib/hard-break-escape.js +65 -0
  239. package/node_modules/micromark-core-commonmark/dev/lib/heading-atx.d.ts +4 -0
  240. package/node_modules/micromark-core-commonmark/dev/lib/heading-atx.d.ts.map +1 -0
  241. package/node_modules/micromark-core-commonmark/dev/lib/heading-atx.js +229 -0
  242. package/node_modules/micromark-core-commonmark/dev/lib/html-flow.d.ts +4 -0
  243. package/node_modules/micromark-core-commonmark/dev/lib/html-flow.d.ts.map +1 -0
  244. package/node_modules/micromark-core-commonmark/dev/lib/html-flow.js +938 -0
  245. package/node_modules/micromark-core-commonmark/dev/lib/html-text.d.ts +4 -0
  246. package/node_modules/micromark-core-commonmark/dev/lib/html-text.d.ts.map +1 -0
  247. package/node_modules/micromark-core-commonmark/dev/lib/html-text.js +783 -0
  248. package/node_modules/micromark-core-commonmark/dev/lib/label-end.d.ts +4 -0
  249. package/node_modules/micromark-core-commonmark/dev/lib/label-end.d.ts.map +1 -0
  250. package/node_modules/micromark-core-commonmark/dev/lib/label-end.js +658 -0
  251. package/node_modules/micromark-core-commonmark/dev/lib/label-start-image.d.ts +4 -0
  252. package/node_modules/micromark-core-commonmark/dev/lib/label-start-image.d.ts.map +1 -0
  253. package/node_modules/micromark-core-commonmark/dev/lib/label-start-image.js +119 -0
  254. package/node_modules/micromark-core-commonmark/dev/lib/label-start-link.d.ts +4 -0
  255. package/node_modules/micromark-core-commonmark/dev/lib/label-start-link.d.ts.map +1 -0
  256. package/node_modules/micromark-core-commonmark/dev/lib/label-start-link.js +71 -0
  257. package/node_modules/micromark-core-commonmark/dev/lib/line-ending.d.ts +4 -0
  258. package/node_modules/micromark-core-commonmark/dev/lib/line-ending.d.ts.map +1 -0
  259. package/node_modules/micromark-core-commonmark/dev/lib/line-ending.js +34 -0
  260. package/node_modules/micromark-core-commonmark/dev/lib/list.d.ts +4 -0
  261. package/node_modules/micromark-core-commonmark/dev/lib/list.d.ts.map +1 -0
  262. package/node_modules/micromark-core-commonmark/dev/lib/list.js +306 -0
  263. package/node_modules/micromark-core-commonmark/dev/lib/partial-non-lazy-continuation.d.ts +4 -0
  264. package/node_modules/micromark-core-commonmark/dev/lib/partial-non-lazy-continuation.d.ts.map +1 -0
  265. package/node_modules/micromark-core-commonmark/dev/lib/partial-non-lazy-continuation.js +67 -0
  266. package/node_modules/micromark-core-commonmark/dev/lib/setext-underline.d.ts +4 -0
  267. package/node_modules/micromark-core-commonmark/dev/lib/setext-underline.d.ts.map +1 -0
  268. package/node_modules/micromark-core-commonmark/dev/lib/setext-underline.js +213 -0
  269. package/node_modules/micromark-core-commonmark/dev/lib/thematic-break.d.ts +4 -0
  270. package/node_modules/micromark-core-commonmark/dev/lib/thematic-break.d.ts.map +1 -0
  271. package/node_modules/micromark-core-commonmark/dev/lib/thematic-break.js +120 -0
  272. package/node_modules/micromark-core-commonmark/index.d.ts +23 -0
  273. package/node_modules/micromark-core-commonmark/index.d.ts.map +1 -0
  274. package/node_modules/micromark-core-commonmark/index.js +22 -0
  275. package/node_modules/micromark-core-commonmark/lib/attention.d.ts +4 -0
  276. package/node_modules/micromark-core-commonmark/lib/attention.d.ts.map +1 -0
  277. package/node_modules/micromark-core-commonmark/lib/attention.js +231 -0
  278. package/node_modules/micromark-core-commonmark/lib/autolink.d.ts +4 -0
  279. package/node_modules/micromark-core-commonmark/lib/autolink.d.ts.map +1 -0
  280. package/node_modules/micromark-core-commonmark/lib/autolink.js +233 -0
  281. package/node_modules/micromark-core-commonmark/lib/blank-line.d.ts +4 -0
  282. package/node_modules/micromark-core-commonmark/lib/blank-line.d.ts.map +1 -0
  283. package/node_modules/micromark-core-commonmark/lib/blank-line.js +61 -0
  284. package/node_modules/micromark-core-commonmark/lib/block-quote.d.ts +4 -0
  285. package/node_modules/micromark-core-commonmark/lib/block-quote.d.ts.map +1 -0
  286. package/node_modules/micromark-core-commonmark/lib/block-quote.js +143 -0
  287. package/node_modules/micromark-core-commonmark/lib/character-escape.d.ts +4 -0
  288. package/node_modules/micromark-core-commonmark/lib/character-escape.d.ts.map +1 -0
  289. package/node_modules/micromark-core-commonmark/lib/character-escape.js +64 -0
  290. package/node_modules/micromark-core-commonmark/lib/character-reference.d.ts +4 -0
  291. package/node_modules/micromark-core-commonmark/lib/character-reference.d.ts.map +1 -0
  292. package/node_modules/micromark-core-commonmark/lib/character-reference.js +149 -0
  293. package/node_modules/micromark-core-commonmark/lib/code-fenced.d.ts +4 -0
  294. package/node_modules/micromark-core-commonmark/lib/code-fenced.d.ts.map +1 -0
  295. package/node_modules/micromark-core-commonmark/lib/code-fenced.js +422 -0
  296. package/node_modules/micromark-core-commonmark/lib/code-indented.d.ts +4 -0
  297. package/node_modules/micromark-core-commonmark/lib/code-indented.d.ts.map +1 -0
  298. package/node_modules/micromark-core-commonmark/lib/code-indented.js +159 -0
  299. package/node_modules/micromark-core-commonmark/lib/code-text.d.ts +4 -0
  300. package/node_modules/micromark-core-commonmark/lib/code-text.d.ts.map +1 -0
  301. package/node_modules/micromark-core-commonmark/lib/code-text.js +225 -0
  302. package/node_modules/micromark-core-commonmark/lib/content.d.ts +7 -0
  303. package/node_modules/micromark-core-commonmark/lib/content.d.ts.map +1 -0
  304. package/node_modules/micromark-core-commonmark/lib/content.js +163 -0
  305. package/node_modules/micromark-core-commonmark/lib/definition.d.ts +4 -0
  306. package/node_modules/micromark-core-commonmark/lib/definition.d.ts.map +1 -0
  307. package/node_modules/micromark-core-commonmark/lib/definition.js +254 -0
  308. package/node_modules/micromark-core-commonmark/lib/hard-break-escape.d.ts +4 -0
  309. package/node_modules/micromark-core-commonmark/lib/hard-break-escape.d.ts.map +1 -0
  310. package/node_modules/micromark-core-commonmark/lib/hard-break-escape.js +60 -0
  311. package/node_modules/micromark-core-commonmark/lib/heading-atx.d.ts +4 -0
  312. package/node_modules/micromark-core-commonmark/lib/heading-atx.d.ts.map +1 -0
  313. package/node_modules/micromark-core-commonmark/lib/heading-atx.js +191 -0
  314. package/node_modules/micromark-core-commonmark/lib/html-flow.d.ts +4 -0
  315. package/node_modules/micromark-core-commonmark/lib/html-flow.d.ts.map +1 -0
  316. package/node_modules/micromark-core-commonmark/lib/html-flow.js +827 -0
  317. package/node_modules/micromark-core-commonmark/lib/html-text.d.ts +4 -0
  318. package/node_modules/micromark-core-commonmark/lib/html-text.d.ts.map +1 -0
  319. package/node_modules/micromark-core-commonmark/lib/html-text.js +678 -0
  320. package/node_modules/micromark-core-commonmark/lib/label-end.d.ts +4 -0
  321. package/node_modules/micromark-core-commonmark/lib/label-end.d.ts.map +1 -0
  322. package/node_modules/micromark-core-commonmark/lib/label-end.js +561 -0
  323. package/node_modules/micromark-core-commonmark/lib/label-start-image.d.ts +4 -0
  324. package/node_modules/micromark-core-commonmark/lib/label-start-image.d.ts.map +1 -0
  325. package/node_modules/micromark-core-commonmark/lib/label-start-image.js +110 -0
  326. package/node_modules/micromark-core-commonmark/lib/label-start-link.d.ts +4 -0
  327. package/node_modules/micromark-core-commonmark/lib/label-start-link.d.ts.map +1 -0
  328. package/node_modules/micromark-core-commonmark/lib/label-start-link.js +63 -0
  329. package/node_modules/micromark-core-commonmark/lib/line-ending.d.ts +4 -0
  330. package/node_modules/micromark-core-commonmark/lib/line-ending.d.ts.map +1 -0
  331. package/node_modules/micromark-core-commonmark/lib/line-ending.js +33 -0
  332. package/node_modules/micromark-core-commonmark/lib/list.d.ts +4 -0
  333. package/node_modules/micromark-core-commonmark/lib/list.d.ts.map +1 -0
  334. package/node_modules/micromark-core-commonmark/lib/list.js +213 -0
  335. package/node_modules/micromark-core-commonmark/lib/partial-non-lazy-continuation.d.ts +4 -0
  336. package/node_modules/micromark-core-commonmark/lib/partial-non-lazy-continuation.d.ts.map +1 -0
  337. package/node_modules/micromark-core-commonmark/lib/partial-non-lazy-continuation.js +61 -0
  338. package/node_modules/micromark-core-commonmark/lib/setext-underline.d.ts +4 -0
  339. package/node_modules/micromark-core-commonmark/lib/setext-underline.d.ts.map +1 -0
  340. package/node_modules/micromark-core-commonmark/lib/setext-underline.js +187 -0
  341. package/node_modules/micromark-core-commonmark/lib/thematic-break.d.ts +4 -0
  342. package/node_modules/micromark-core-commonmark/lib/thematic-break.d.ts.map +1 -0
  343. package/node_modules/micromark-core-commonmark/lib/thematic-break.js +102 -0
  344. package/node_modules/micromark-core-commonmark/license +22 -0
  345. package/node_modules/micromark-core-commonmark/package.json +62 -0
  346. package/node_modules/micromark-core-commonmark/readme.md +171 -0
  347. package/node_modules/micromark-factory-destination/dev/index.d.ts +42 -0
  348. package/node_modules/micromark-factory-destination/dev/index.d.ts.map +1 -0
  349. package/node_modules/micromark-factory-destination/dev/index.js +255 -0
  350. package/node_modules/micromark-factory-destination/index.d.ts +42 -0
  351. package/node_modules/micromark-factory-destination/index.d.ts.map +1 -0
  352. package/node_modules/micromark-factory-destination/index.js +206 -0
  353. package/node_modules/micromark-factory-destination/license +22 -0
  354. package/node_modules/micromark-factory-destination/package.json +57 -0
  355. package/node_modules/micromark-factory-destination/readme.md +234 -0
  356. package/node_modules/micromark-factory-label/dev/index.d.ts +37 -0
  357. package/node_modules/micromark-factory-label/dev/index.d.ts.map +1 -0
  358. package/node_modules/micromark-factory-label/dev/index.js +172 -0
  359. package/node_modules/micromark-factory-label/index.d.ts +37 -0
  360. package/node_modules/micromark-factory-label/index.d.ts.map +1 -0
  361. package/node_modules/micromark-factory-label/index.js +148 -0
  362. package/node_modules/micromark-factory-label/license +22 -0
  363. package/node_modules/micromark-factory-label/package.json +60 -0
  364. package/node_modules/micromark-factory-label/readme.md +224 -0
  365. package/node_modules/micromark-factory-space/dev/index.d.ts +60 -0
  366. package/node_modules/micromark-factory-space/dev/index.d.ts.map +1 -0
  367. package/node_modules/micromark-factory-space/dev/index.js +122 -0
  368. package/node_modules/micromark-factory-space/index.d.ts +60 -0
  369. package/node_modules/micromark-factory-space/index.d.ts.map +1 -0
  370. package/node_modules/micromark-factory-space/index.js +116 -0
  371. package/node_modules/micromark-factory-space/license +22 -0
  372. package/node_modules/micromark-factory-space/package.json +46 -0
  373. package/node_modules/micromark-factory-space/readme.md +225 -0
  374. package/node_modules/micromark-factory-title/dev/index.d.ts +36 -0
  375. package/node_modules/micromark-factory-title/dev/index.d.ts.map +1 -0
  376. package/node_modules/micromark-factory-title/dev/index.js +169 -0
  377. package/node_modules/micromark-factory-title/index.d.ts +36 -0
  378. package/node_modules/micromark-factory-title/index.d.ts.map +1 -0
  379. package/node_modules/micromark-factory-title/index.js +158 -0
  380. package/node_modules/micromark-factory-title/license +22 -0
  381. package/node_modules/micromark-factory-title/package.json +58 -0
  382. package/node_modules/micromark-factory-title/readme.md +229 -0
  383. package/node_modules/micromark-factory-whitespace/dev/index.d.ts +22 -0
  384. package/node_modules/micromark-factory-whitespace/dev/index.d.ts.map +1 -0
  385. package/node_modules/micromark-factory-whitespace/dev/index.js +53 -0
  386. package/node_modules/micromark-factory-whitespace/index.d.ts +22 -0
  387. package/node_modules/micromark-factory-whitespace/index.d.ts.map +1 -0
  388. package/node_modules/micromark-factory-whitespace/index.js +44 -0
  389. package/node_modules/micromark-factory-whitespace/license +22 -0
  390. package/node_modules/micromark-factory-whitespace/package.json +57 -0
  391. package/node_modules/micromark-factory-whitespace/readme.md +205 -0
  392. package/node_modules/micromark-util-character/dev/index.d.ts +195 -0
  393. package/node_modules/micromark-util-character/dev/index.d.ts.map +1 -0
  394. package/node_modules/micromark-util-character/dev/index.js +252 -0
  395. package/node_modules/micromark-util-character/index.d.ts +195 -0
  396. package/node_modules/micromark-util-character/index.d.ts.map +1 -0
  397. package/node_modules/micromark-util-character/index.js +246 -0
  398. package/node_modules/micromark-util-character/license +22 -0
  399. package/node_modules/micromark-util-character/package.json +57 -0
  400. package/node_modules/micromark-util-character/readme.md +446 -0
  401. package/node_modules/micromark-util-chunked/dev/index.d.ts +41 -0
  402. package/node_modules/micromark-util-chunked/dev/index.d.ts.map +1 -0
  403. package/node_modules/micromark-util-chunked/dev/index.js +89 -0
  404. package/node_modules/micromark-util-chunked/index.d.ts +41 -0
  405. package/node_modules/micromark-util-chunked/index.d.ts.map +1 -0
  406. package/node_modules/micromark-util-chunked/index.js +81 -0
  407. package/node_modules/micromark-util-chunked/license +22 -0
  408. package/node_modules/micromark-util-chunked/package.json +57 -0
  409. package/node_modules/micromark-util-chunked/readme.md +219 -0
  410. package/node_modules/micromark-util-classify-character/dev/index.d.ts +18 -0
  411. package/node_modules/micromark-util-classify-character/dev/index.d.ts.map +1 -0
  412. package/node_modules/micromark-util-classify-character/dev/index.js +38 -0
  413. package/node_modules/micromark-util-classify-character/index.d.ts +18 -0
  414. package/node_modules/micromark-util-classify-character/index.d.ts.map +1 -0
  415. package/node_modules/micromark-util-classify-character/index.js +27 -0
  416. package/node_modules/micromark-util-classify-character/license +22 -0
  417. package/node_modules/micromark-util-classify-character/package.json +59 -0
  418. package/node_modules/micromark-util-classify-character/readme.md +205 -0
  419. package/node_modules/micromark-util-combine-extensions/index.d.ts +22 -0
  420. package/node_modules/micromark-util-combine-extensions/index.d.ts.map +1 -0
  421. package/node_modules/micromark-util-combine-extensions/index.js +143 -0
  422. package/node_modules/micromark-util-combine-extensions/license +22 -0
  423. package/node_modules/micromark-util-combine-extensions/package.json +52 -0
  424. package/node_modules/micromark-util-combine-extensions/readme.md +201 -0
  425. package/node_modules/micromark-util-decode-numeric-character-reference/dev/index.d.ts +16 -0
  426. package/node_modules/micromark-util-decode-numeric-character-reference/dev/index.d.ts.map +1 -0
  427. package/node_modules/micromark-util-decode-numeric-character-reference/dev/index.js +42 -0
  428. package/node_modules/micromark-util-decode-numeric-character-reference/index.d.ts +16 -0
  429. package/node_modules/micromark-util-decode-numeric-character-reference/index.d.ts.map +1 -0
  430. package/node_modules/micromark-util-decode-numeric-character-reference/index.js +32 -0
  431. package/node_modules/micromark-util-decode-numeric-character-reference/license +22 -0
  432. package/node_modules/micromark-util-decode-numeric-character-reference/package.json +59 -0
  433. package/node_modules/micromark-util-decode-numeric-character-reference/readme.md +184 -0
  434. package/node_modules/micromark-util-decode-string/dev/index.d.ts +14 -0
  435. package/node_modules/micromark-util-decode-string/dev/index.d.ts.map +1 -0
  436. package/node_modules/micromark-util-decode-string/dev/index.js +53 -0
  437. package/node_modules/micromark-util-decode-string/index.d.ts +14 -0
  438. package/node_modules/micromark-util-decode-string/index.d.ts.map +1 -0
  439. package/node_modules/micromark-util-decode-string/index.js +45 -0
  440. package/node_modules/micromark-util-decode-string/license +22 -0
  441. package/node_modules/micromark-util-decode-string/package.json +63 -0
  442. package/node_modules/micromark-util-decode-string/readme.md +179 -0
  443. package/node_modules/micromark-util-edit-map/dev/index.d.ts +78 -0
  444. package/node_modules/micromark-util-edit-map/dev/index.d.ts.map +1 -0
  445. package/node_modules/micromark-util-edit-map/dev/index.js +237 -0
  446. package/node_modules/micromark-util-edit-map/index.d.ts +78 -0
  447. package/node_modules/micromark-util-edit-map/index.d.ts.map +1 -0
  448. package/node_modules/micromark-util-edit-map/index.js +225 -0
  449. package/node_modules/micromark-util-edit-map/license +22 -0
  450. package/node_modules/micromark-util-edit-map/package.json +48 -0
  451. package/node_modules/micromark-util-edit-map/readme.md +234 -0
  452. package/node_modules/micromark-util-encode/index.d.ts +14 -0
  453. package/node_modules/micromark-util-encode/index.d.ts.map +1 -0
  454. package/node_modules/micromark-util-encode/index.js +33 -0
  455. package/node_modules/micromark-util-encode/license +22 -0
  456. package/node_modules/micromark-util-encode/package.json +47 -0
  457. package/node_modules/micromark-util-encode/readme.md +176 -0
  458. package/node_modules/micromark-util-html-tag-name/index.d.ts +30 -0
  459. package/node_modules/micromark-util-html-tag-name/index.d.ts.map +1 -0
  460. package/node_modules/micromark-util-html-tag-name/index.js +93 -0
  461. package/node_modules/micromark-util-html-tag-name/license +22 -0
  462. package/node_modules/micromark-util-html-tag-name/package.json +47 -0
  463. package/node_modules/micromark-util-html-tag-name/readme.md +193 -0
  464. package/node_modules/micromark-util-normalize-identifier/dev/index.d.ts +21 -0
  465. package/node_modules/micromark-util-normalize-identifier/dev/index.d.ts.map +1 -0
  466. package/node_modules/micromark-util-normalize-identifier/dev/index.js +38 -0
  467. package/node_modules/micromark-util-normalize-identifier/index.d.ts +21 -0
  468. package/node_modules/micromark-util-normalize-identifier/index.d.ts.map +1 -0
  469. package/node_modules/micromark-util-normalize-identifier/index.js +33 -0
  470. package/node_modules/micromark-util-normalize-identifier/license +22 -0
  471. package/node_modules/micromark-util-normalize-identifier/package.json +58 -0
  472. package/node_modules/micromark-util-normalize-identifier/readme.md +187 -0
  473. package/node_modules/micromark-util-resolve-all/index.d.ts +22 -0
  474. package/node_modules/micromark-util-resolve-all/index.d.ts.map +1 -0
  475. package/node_modules/micromark-util-resolve-all/index.js +32 -0
  476. package/node_modules/micromark-util-resolve-all/license +22 -0
  477. package/node_modules/micromark-util-resolve-all/package.json +48 -0
  478. package/node_modules/micromark-util-resolve-all/readme.md +238 -0
  479. package/node_modules/micromark-util-sanitize-uri/dev/index.d.ts +36 -0
  480. package/node_modules/micromark-util-sanitize-uri/dev/index.d.ts.map +1 -0
  481. package/node_modules/micromark-util-sanitize-uri/dev/index.js +124 -0
  482. package/node_modules/micromark-util-sanitize-uri/index.d.ts +36 -0
  483. package/node_modules/micromark-util-sanitize-uri/index.d.ts.map +1 -0
  484. package/node_modules/micromark-util-sanitize-uri/index.js +107 -0
  485. package/node_modules/micromark-util-sanitize-uri/license +22 -0
  486. package/node_modules/micromark-util-sanitize-uri/package.json +59 -0
  487. package/node_modules/micromark-util-sanitize-uri/readme.md +214 -0
  488. package/node_modules/micromark-util-subtokenize/dev/index.d.ts +12 -0
  489. package/node_modules/micromark-util-subtokenize/dev/index.d.ts.map +1 -0
  490. package/node_modules/micromark-util-subtokenize/dev/index.js +284 -0
  491. package/node_modules/micromark-util-subtokenize/dev/lib/splice-buffer.d.ts +161 -0
  492. package/node_modules/micromark-util-subtokenize/dev/lib/splice-buffer.d.ts.map +1 -0
  493. package/node_modules/micromark-util-subtokenize/dev/lib/splice-buffer.js +288 -0
  494. package/node_modules/micromark-util-subtokenize/index.d.ts +12 -0
  495. package/node_modules/micromark-util-subtokenize/index.d.ts.map +1 -0
  496. package/node_modules/micromark-util-subtokenize/index.js +228 -0
  497. package/node_modules/micromark-util-subtokenize/lib/splice-buffer.d.ts +161 -0
  498. package/node_modules/micromark-util-subtokenize/lib/splice-buffer.d.ts.map +1 -0
  499. package/node_modules/micromark-util-subtokenize/lib/splice-buffer.js +251 -0
  500. package/node_modules/micromark-util-subtokenize/license +22 -0
  501. package/node_modules/micromark-util-subtokenize/package.json +60 -0
  502. package/node_modules/micromark-util-subtokenize/readme.md +181 -0
  503. package/node_modules/micromark-util-symbol/lib/codes.d.ts +139 -0
  504. package/node_modules/micromark-util-symbol/lib/codes.d.ts.map +1 -0
  505. package/node_modules/micromark-util-symbol/lib/codes.js +158 -0
  506. package/node_modules/micromark-util-symbol/lib/constants.d.ts +37 -0
  507. package/node_modules/micromark-util-symbol/lib/constants.d.ts.map +1 -0
  508. package/node_modules/micromark-util-symbol/lib/constants.js +44 -0
  509. package/node_modules/micromark-util-symbol/lib/default.d.ts +5 -0
  510. package/node_modules/micromark-util-symbol/lib/default.d.ts.map +1 -0
  511. package/node_modules/micromark-util-symbol/lib/default.js +4 -0
  512. package/node_modules/micromark-util-symbol/lib/types.d.ts +106 -0
  513. package/node_modules/micromark-util-symbol/lib/types.d.ts.map +1 -0
  514. package/node_modules/micromark-util-symbol/lib/types.js +453 -0
  515. package/node_modules/micromark-util-symbol/lib/values.d.ts +102 -0
  516. package/node_modules/micromark-util-symbol/lib/values.d.ts.map +1 -0
  517. package/node_modules/micromark-util-symbol/lib/values.js +109 -0
  518. package/node_modules/micromark-util-symbol/license +22 -0
  519. package/node_modules/micromark-util-symbol/package.json +43 -0
  520. package/node_modules/micromark-util-symbol/readme.md +168 -0
  521. package/node_modules/micromark-util-types/index.d.ts +1315 -0
  522. package/node_modules/micromark-util-types/index.js +2 -0
  523. package/node_modules/micromark-util-types/license +22 -0
  524. package/node_modules/micromark-util-types/package.json +37 -0
  525. package/node_modules/micromark-util-types/readme.md +151 -0
  526. package/node_modules/smol-toml/LICENSE +24 -0
  527. package/node_modules/smol-toml/README.md +605 -0
  528. package/node_modules/smol-toml/dist/date.d.ts +41 -0
  529. package/node_modules/smol-toml/dist/date.js +156 -0
  530. package/node_modules/smol-toml/dist/error.d.ts +37 -0
  531. package/node_modules/smol-toml/dist/error.js +67 -0
  532. package/node_modules/smol-toml/dist/extract.js +289 -0
  533. package/node_modules/smol-toml/dist/index.cjs +770 -0
  534. package/node_modules/smol-toml/dist/index.d.ts +44 -0
  535. package/node_modules/smol-toml/dist/index.js +34 -0
  536. package/node_modules/smol-toml/dist/parse.d.ts +73 -0
  537. package/node_modules/smol-toml/dist/parse.js +164 -0
  538. package/node_modules/smol-toml/dist/primitive.js +151 -0
  539. package/node_modules/smol-toml/dist/stringify.d.ts +32 -0
  540. package/node_modules/smol-toml/dist/stringify.js +219 -0
  541. package/node_modules/smol-toml/dist/struct.js +156 -0
  542. package/node_modules/smol-toml/dist/util.d.ts +43 -0
  543. package/node_modules/smol-toml/dist/util.js +57 -0
  544. package/node_modules/smol-toml/package.json +68 -0
  545. package/node_modules/unist-util-stringify-position/index.d.ts +1 -0
  546. package/node_modules/unist-util-stringify-position/index.js +1 -0
  547. package/node_modules/unist-util-stringify-position/lib/index.d.ts +61 -0
  548. package/node_modules/unist-util-stringify-position/lib/index.js +84 -0
  549. package/node_modules/unist-util-stringify-position/license +22 -0
  550. package/node_modules/unist-util-stringify-position/package.json +80 -0
  551. package/node_modules/unist-util-stringify-position/readme.md +206 -0
  552. package/package.json +27 -8
  553. package/scripts/prepare-github-keyring.js +29 -0
  554. package/src/codex-app.js +20 -2
  555. package/src/codex-pricing.js +79 -0
  556. package/src/codex-projects.js +90 -0
  557. package/src/codex-session-scanner.js +748 -0
  558. package/src/codex-session-usage.js +332 -0
  559. package/src/dashboard/app.js +2 -2
  560. package/src/dashboard/dist/app.js +135 -60
  561. package/src/dashboard/dist/app.js.map +1 -1
  562. package/src/dashboard/dist/styles.css +1 -1
  563. package/src/dashboard/react/components/AnimatedUsage.test.tsx +78 -0
  564. package/src/dashboard/react/components/CardStatusIcons.test.tsx +146 -0
  565. package/src/dashboard/react/components/CardStatusIcons.tsx +138 -0
  566. package/src/dashboard/react/components/ImageGallery.tsx +22 -0
  567. package/src/dashboard/react/components/ModelSettings.test.tsx +4 -4
  568. package/src/dashboard/react/components/ModelSettings.tsx +1 -1
  569. package/src/dashboard/react/components/OpenChatButton.test.tsx +19 -0
  570. package/src/dashboard/react/components/OpenChatButton.tsx +2 -1
  571. package/src/dashboard/react/components/PrGlyph.tsx +35 -0
  572. package/src/dashboard/react/components/PullRequestBadges.tsx +18 -0
  573. package/src/dashboard/react/components/QueuedPrompts.test.tsx +42 -0
  574. package/src/dashboard/react/components/QueuedPrompts.tsx +34 -0
  575. package/src/dashboard/react/components/RelativeTime.test.tsx +100 -0
  576. package/src/dashboard/react/components/RelativeTime.tsx +46 -11
  577. package/src/dashboard/react/components/ReplyCover.test.tsx +30 -0
  578. package/src/dashboard/react/components/ReplyCover.tsx +33 -0
  579. package/src/dashboard/react/components/ReplyImagePreview.test.tsx +90 -0
  580. package/src/dashboard/react/components/ReplyImagePreview.tsx +34 -0
  581. package/src/dashboard/react/components/ReplyMarkdown.test.tsx +108 -0
  582. package/src/dashboard/react/components/ReplyMarkdown.tsx +112 -0
  583. package/src/dashboard/react/components/SavedUsageFormat.test.tsx +11 -0
  584. package/src/dashboard/react/components/SavedUsageFormat.tsx +68 -0
  585. package/src/dashboard/react/components/StatusBadge.tsx +2 -2
  586. package/src/dashboard/react/components/TaskBoard.test.tsx +256 -1
  587. package/src/dashboard/react/components/TaskBoard.tsx +136 -28
  588. package/src/dashboard/react/components/TaskCard.tsx +7 -4
  589. package/src/dashboard/react/components/TaskDetail.test.tsx +92 -1
  590. package/src/dashboard/react/components/TaskDetail.tsx +37 -10
  591. package/src/dashboard/react/components/TurnContent.test.tsx +44 -0
  592. package/src/dashboard/react/components/TurnContent.tsx +53 -0
  593. package/src/dashboard/react/components/UsagePanel.tsx +2 -2
  594. package/src/dashboard/react/image-cache.test.ts +23 -0
  595. package/src/dashboard/react/image-cache.ts +33 -0
  596. package/src/dashboard/react/presentation.test.tsx +31 -0
  597. package/src/dashboard/react/styles.css +126 -2
  598. package/src/dashboard/react/types.ts +55 -1
  599. package/src/dashboard/time.js +39 -0
  600. package/src/dashboard.js +4 -3
  601. package/src/data/codex-pricing.json +537 -0
  602. package/src/mcp-app/dist/index.html +216 -112
  603. package/src/mcp-app/react/AppearancePicker.test.tsx +50 -0
  604. package/src/mcp-app/react/AppearancePicker.tsx +56 -0
  605. package/src/mcp-app/react/GitHubConnection.test.tsx +78 -0
  606. package/src/mcp-app/react/GitHubConnection.tsx +78 -0
  607. package/src/mcp-app/react/NextNotificationCenter.test.tsx +121 -0
  608. package/src/mcp-app/react/NextNotificationCenter.tsx +94 -0
  609. package/src/mcp-app/react/NextTaskDetail.test.tsx +124 -0
  610. package/src/mcp-app/react/NextTaskDetail.tsx +147 -0
  611. package/src/mcp-app/react/ProjectPicker.tsx +49 -0
  612. package/src/mcp-app/react/main.test.tsx +499 -49
  613. package/src/mcp-app/react/main.tsx +359 -86
  614. package/src/mcp-app/react/styles.css +186 -9
  615. package/src/mcp-app/react/themes.test.ts +34 -0
  616. package/src/mcp-app/react/themes.ts +112 -0
  617. package/src/mcp-app.js +238 -120
  618. package/src/mcp.js +8 -1
  619. package/src/next-cache.js +16 -0
  620. package/src/next-github.js +273 -0
  621. package/src/next-notifications.js +90 -0
  622. package/src/recorded-usage-tracker.js +92 -0
  623. package/src/reply-image.js +65 -0
  624. package/src/usage-tracker.js +7 -6
  625. package/src/usage.js +7 -355
  626. package/src/user-prompt.js +55 -0
  627. package/src/version.js +2 -1
  628. package/node_modules/proper-lockfile/CHANGELOG.md +0 -108
  629. package/node_modules/which/CHANGELOG.md +0 -166
  630. package/src/resolve-ccusage.js +0 -17
@@ -0,0 +1,78 @@
1
+ import { act, cleanup, render, screen } from "@testing-library/react";
2
+ import { afterEach, beforeEach, expect, test, vi } from "vitest";
3
+ import type { SavedUsage } from "../types";
4
+ import { useAnimatedUsage } from "./SavedUsageFormat";
5
+
6
+ const motion = vi.hoisted(() => ({ reduced: false }));
7
+ vi.mock("@mantine/hooks", () => ({ useReducedMotion: () => motion.reduced }));
8
+ const usage = (tokens: number, cost: number): SavedUsage => ({
9
+ tokens: { input_tokens: tokens, cached_input_tokens: 0, cache_write_input_tokens: 0, output_tokens: 0, reasoning_output_tokens: 0, total_tokens: tokens },
10
+ samples: 1, costUsd: cost, partial: false, costPartial: false,
11
+ });
12
+ function Counter({ value, running = true, identity = "turn-1" }: { value?: SavedUsage; running?: boolean; identity?: string }) {
13
+ const displayed = useAnimatedUsage(value, running, identity);
14
+ return <output data-testid="counter">{displayed ? `${displayed.tokens.total_tokens}:${displayed.costUsd}` : "missing"}</output>;
15
+ }
16
+ let clock = 0, nextFrame = 0;
17
+ const frames = new Map<number, FrameRequestCallback>();
18
+ function advance(now: number) {
19
+ act(() => {
20
+ clock = now;
21
+ const pending = [...frames.values()];
22
+ frames.clear();
23
+ pending.forEach(callback => callback(now));
24
+ });
25
+ }
26
+ function displayed() { return screen.getByTestId("counter").textContent; }
27
+ beforeEach(() => {
28
+ clock = 0; nextFrame = 0; motion.reduced = false; frames.clear();
29
+ vi.spyOn(performance, "now").mockImplementation(() => clock);
30
+ vi.stubGlobal("requestAnimationFrame", (callback: FrameRequestCallback) => { frames.set(++nextFrame, callback); return nextFrame; });
31
+ vi.stubGlobal("cancelAnimationFrame", (id: number) => frames.delete(id));
32
+ });
33
+ afterEach(() => { cleanup(); vi.restoreAllMocks(); vi.unstubAllGlobals(); });
34
+
35
+ test("running usage catches up and continues from the displayed amount when another update arrives", () => {
36
+ const view = render(<Counter value={usage(1000, 2)} />);
37
+ expect(displayed()).toBe("0:0");
38
+ advance(400);
39
+ expect(displayed()).toBe("875:1.75");
40
+ view.rerender(<Counter value={usage(2000, 4)} />);
41
+ expect(displayed()).toBe("875:1.75");
42
+ advance(800);
43
+ expect(displayed()).toBe("1859:3.71875");
44
+ advance(1200);
45
+ expect(displayed()).toBe("2000:4");
46
+ expect(frames.size).toBe(0);
47
+ });
48
+
49
+ test("late usage animates from zero and a new turn does not inherit the old counter", () => {
50
+ const view = render(<Counter />);
51
+ expect(displayed()).toBe("missing");
52
+ view.rerender(<Counter value={usage(1000, 2)} />);
53
+ advance(800);
54
+ expect(displayed()).toBe("1000:2");
55
+ view.rerender(<Counter value={usage(300, 0.5)} identity="turn-2" />);
56
+ expect(displayed()).toBe("0:0");
57
+ advance(1600);
58
+ expect(displayed()).toBe("300:0.5");
59
+ });
60
+
61
+ test("completed chats and reduced motion show the exact total and cancel pending animation", () => {
62
+ const view = render(<Counter value={usage(1000, 2)} />);
63
+ advance(200);
64
+ view.rerender(<Counter value={usage(1000, 2)} running={false} />);
65
+ expect(displayed()).toBe("1000:2");
66
+ expect(frames.size).toBe(0);
67
+ motion.reduced = true;
68
+ view.rerender(<Counter value={usage(2000, 4)} />);
69
+ expect(displayed()).toBe("2000:4");
70
+ expect(frames.size).toBe(0);
71
+ });
72
+
73
+ test("unmount cancels the counter's pending frame", () => {
74
+ const view = render(<Counter value={usage(1000, 2)} />);
75
+ expect(frames.size).toBe(1);
76
+ view.unmount();
77
+ expect(frames.size).toBe(0);
78
+ });
@@ -0,0 +1,146 @@
1
+ import { MantineProvider } from "@mantine/core";
2
+ import { cleanup, fireEvent, render, screen } from "@testing-library/react";
3
+ import { afterEach, expect, test, vi } from "vitest";
4
+ import { nextRunLabel, prPresentation, PullRequestIcons, PullRequestInfo, CardStatusLine } from "./CardStatusIcons";
5
+ import type { PullRequestStatus } from "../types";
6
+ // Test TaskChef's rows and keyboard handlers without jsdom layout work.
7
+ // Browser QA separately exercises Mantine's real popup and positioning.
8
+ vi.mock("@mantine/core", async () => {
9
+ const actual = await vi.importActual<typeof import("@mantine/core")>("@mantine/core");
10
+ const React = await import("react");
11
+ const Open = React.createContext(false);
12
+ const Popover = Object.assign(
13
+ ({opened, children}: {opened: boolean; children: React.ReactNode}) => <Open value={opened}>{children}</Open>,
14
+ {
15
+ Target: ({children}: {children: React.ReactNode}) => children,
16
+ Dropdown: React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>((props, ref) =>
17
+ React.useContext(Open) ? <div {...props} ref={ref} /> : null),
18
+ },
19
+ );
20
+ return {...actual, Popover};
21
+ });
22
+
23
+ afterEach(cleanup);
24
+ const url="https://github.com/example/repo/pull/12";
25
+ const pr:PullRequestStatus={url,state:"open",checks:"passed",title:"Improve search"};
26
+ test("cards keep PR status in an accessible icon without extra text",()=>{
27
+ render(<MantineProvider><PullRequestIcons pullRequests={[pr,{...pr,url:"https://github.com/example/repo/pull/13",state:"unknown"}]}/></MantineProvider>);
28
+ expect(screen.getByLabelText("#12 Improve search: Checks passed")).toBeInTheDocument();
29
+ expect(screen.getByLabelText("#13 Improve search: PR status not checked or unavailable")).toBeInTheDocument();
30
+ expect(screen.queryByText(/unavailable/)).not.toBeInTheDocument();
31
+ });
32
+ test("PR presentation follows Codex priority for drafts, conflicts, CI and merge readiness",()=>{
33
+ expect(prPresentation({...pr,state:"draft",checks:"failed"}).dot).toBeNull();
34
+ expect(prPresentation({...pr,hasMergeConflicts:true}).label).toBe("Merge conflicts");
35
+ expect(prPresentation({...pr,canMerge:true}).label).toBe("Ready to merge");
36
+ expect(prPresentation({...pr,checks:"pending"}).label).toBe("Checks pending");
37
+ expect(prPresentation({...pr,state:"merged",checks:"failed"}).label).toBe("Merged");
38
+ });
39
+ test("next run uses Today and Tomorrow and never invents missing times",()=>{
40
+ const now=new Date(2026,9,10,10);
41
+ expect(nextRunLabel(new Date(2026,9,10,15).toISOString(),now)).toMatch(/^Next run: Today at /);
42
+ expect(nextRunLabel(new Date(2026,9,11,9).toISOString(),now)).toMatch(/^Next run: Tomorrow at /);
43
+ expect(nextRunLabel(null,now)).toBe("Next run time unavailable");
44
+ });
45
+
46
+
47
+ test("popup content keeps CI for merged and unknown PRs and links only supported URLs",()=>{
48
+ const {rerender}=render(<MantineProvider><PullRequestInfo pr={{...pr,state:"merged"}}/></MantineProvider>);
49
+ expect(screen.getByText("CI passed")).toBeInTheDocument();
50
+ expect(screen.getByRole("link",{name:"#12 Improve search"})).toHaveAttribute("href",url);
51
+ rerender(<MantineProvider><PullRequestInfo pr={{...pr,state:"unknown",checks:"unknown",url:"javascript:alert(1)"}}/></MantineProvider>);
52
+ expect(screen.queryByText(/CI status unknown/)).not.toBeInTheDocument();
53
+ expect(screen.queryByRole("link")).not.toBeInTheDocument();
54
+ });
55
+
56
+
57
+ test("one status popup shows available lines, survives movement onto links, and closes with Escape", async () => {
58
+ render(<MantineProvider env="test"><CardStatusLine durationMs={905 * 60000} pullRequests={[{...pr, canMerge: true, checkedAt: new Date().toISOString()}]} scheduled nextRunAt={new Date(Date.now()+3600000).toISOString()}><span>Oct 7th</span></CardStatusLine></MantineProvider>);
59
+ const line = screen.getByLabelText("Turn status details");
60
+ fireEvent.mouseEnter(line);
61
+ expect(screen.getByText("Worked for 15h 5m")).toBeInTheDocument();
62
+ const link = screen.getByRole("link", {name:"#12 Improve search",hidden:true});
63
+ expect(link).toHaveAttribute("href",url);
64
+ expect(screen.queryByText("CI passed")).not.toBeInTheDocument();
65
+ expect(screen.getByText(/^Next run:/)).toBeInTheDocument();
66
+ expect(screen.queryByText(/Checked |Ready to merge/)).not.toBeInTheDocument();
67
+ fireEvent.focus(line);
68
+ fireEvent.keyDown(line,{key:"Tab"});
69
+ expect(link).toHaveFocus();
70
+ fireEvent.keyDown(link,{key:"Escape"});
71
+ expect(line).toHaveFocus();
72
+ });
73
+
74
+ test("popup omits missing duration, CI and schedule time instead of unavailable lines", async () => {
75
+ render(<MantineProvider env="test"><CardStatusLine durationMs={null} scheduled nextRunAt={null} pullRequests={[{...pr,checks:"unknown"}]}><span>Oct 7th</span></CardStatusLine></MantineProvider>);
76
+ fireEvent.mouseEnter(screen.getByLabelText("Turn status details"));
77
+ expect(screen.getByRole("link",{name:"#12 Improve search",hidden:true})).toBeInTheDocument();
78
+ expect(screen.queryByText(/Worked for|Next run:|CI status|unavailable/)).not.toBeInTheDocument();
79
+ });
80
+
81
+
82
+ test("status line describes PR state to keyboard and screen-reader users", () => {
83
+ render(<MantineProvider><CardStatusLine pullRequests={[{...pr,state:"merged"},{...pr,url:"https://github.com/example/repo/pull/13",state:"draft"}]}><span>Oct 7th</span></CardStatusLine></MantineProvider>);
84
+ expect(screen.getByLabelText("Turn status details")).toHaveAccessibleDescription("#12 Improve search: Merged. #13 Improve search: Draft");
85
+ });
86
+
87
+
88
+ test("Tab preserves the time control before handing focus to the PR link", () => {
89
+ render(<MantineProvider env="test"><CardStatusLine pullRequests={[pr]}><button>Oct 7th</button></CardStatusLine></MantineProvider>);
90
+ const line = screen.getByLabelText("Turn status details");
91
+ fireEvent.focus(line);
92
+ expect(fireEvent.keyDown(line, {key:"Tab"})).toBe(true);
93
+ const time = screen.getByRole("button", {name:"Oct 7th"});
94
+ time.focus();
95
+ fireEvent.keyDown(time, {key:"Tab"});
96
+ expect(screen.getByRole("link", {name:"#12 Improve search",hidden:true})).toHaveFocus();
97
+ });
98
+
99
+ test("shows subagents and repository access action with number first", () => {
100
+ render(<MantineProvider><CardStatusLine subagentCount={155} pullRequests={[{...pr,state:"unknown",checks:"unknown",accessIssue:"denied"}]}><span>Oct 7th</span></CardStatusLine></MantineProvider>);
101
+ fireEvent.mouseEnter(screen.getByLabelText("Turn status details"));
102
+ expect(screen.queryByText("155 subagents")).toBeNull();
103
+ expect(screen.getByText(/Access denied to example\/repo/)).toBeInTheDocument();
104
+ expect(screen.getByRole("link",{name:"Grant access"})).toHaveAttribute("href","https://github.com/apps/taskchef/installations/new");
105
+ expect(screen.getByRole("link",{name:"#12 Improve search"})).toHaveClass("taskchef-status-pr-title");
106
+ });
107
+
108
+ test("card and popup use latest turn usage and omit incomplete markers", () => {
109
+ const turnUsage = {tokens:{input_tokens:1000,cached_input_tokens:200,cache_write_input_tokens:0,output_tokens:100,reasoning_output_tokens:40,total_tokens:1100},costUsd:2.34,samples:1,partial:true,costPartial:true};
110
+ render(<MantineProvider env="test"><CardStatusLine turnUsage={turnUsage}><span>1h</span></CardStatusLine></MantineProvider>);
111
+ expect(screen.getByText("1.10K • $2.34")).toBeVisible();
112
+ fireEvent.focus(screen.getByLabelText("Turn status details"));
113
+ expect(screen.getByText("Turn usage: 1.10K • $2.34")).toBeVisible();
114
+ });
115
+
116
+ test("missing turn records show plain placeholders without an explanation", () => {
117
+ const turnUsage={tokens:{input_tokens:0,cached_input_tokens:0,cache_write_input_tokens:0,output_tokens:0,reasoning_output_tokens:0,total_tokens:0},costUsd:0,samples:0,partial:true,costPartial:true};
118
+ render(<MantineProvider env="test"><CardStatusLine turnUsage={turnUsage}><span>1h</span></CardStatusLine></MantineProvider>);
119
+ expect(screen.getByText("— • —")).toBeVisible();
120
+ fireEvent.focus(screen.getByLabelText("Turn status details"));
121
+ expect(screen.getByText("Turn usage: — • —")).toBeVisible();
122
+ expect(screen.queryByText(/Some usage records/)).toBeNull();
123
+ });
124
+
125
+ test("earlier-turn PR is labeled in the popup and latest-turn PRs take priority", () => {
126
+ const earlier={...pr,state:"merged" as const};
127
+ const view=render(<MantineProvider><CardStatusLine earlierPullRequest={earlier}><span>1h</span></CardStatusLine></MantineProvider>);
128
+ expect(screen.getByLabelText("#12 Improve search: Merged")).toBeInTheDocument();
129
+ fireEvent.mouseEnter(screen.getByLabelText("Turn status details"));
130
+ expect(screen.getByText("(Earlier turn PR)")).toBeInTheDocument();
131
+ expect(screen.getByRole("link",{name:"#12 Improve search",hidden:true})).toHaveAttribute("href",url);
132
+ view.rerender(<MantineProvider><CardStatusLine earlierPullRequest={earlier} pullRequests={[{...pr,url:"https://github.com/example/repo/pull/13",title:"Current change"}]}><span>1h</span></CardStatusLine></MantineProvider>);
133
+ expect(screen.queryByText("(Earlier turn PR)")).toBeNull();
134
+ expect(screen.queryByRole("link",{name:"#12 Improve search",hidden:true})).toBeNull();
135
+ expect(screen.getByRole("link",{name:"#13 Current change",hidden:true})).toBeInTheDocument();
136
+ });
137
+
138
+ test("earlier PR note stays directly below the link before an access warning", () => {
139
+ render(<MantineProvider><CardStatusLine earlierPullRequest={{...pr,accessIssue:'denied'}}><span>1h</span></CardStatusLine></MantineProvider>);
140
+ fireEvent.mouseEnter(screen.getByLabelText('Turn status details'));
141
+ const link=screen.getByRole('link',{name:'#12 Improve search',hidden:true});
142
+ const note=screen.getByText('(Earlier turn PR)');
143
+ const warning=screen.getByText(/Access denied to/);
144
+ expect(link.compareDocumentPosition(note) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
145
+ expect(note.compareDocumentPosition(warning) & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
146
+ });
@@ -0,0 +1,138 @@
1
+ import { PrOpenIcon, PrStatusIcon, PrDraftIcon, PrMergedIcon, PrClosedIcon } from "./PrGlyph";
2
+ import { Anchor, Box, Popover, Stack, Text, VisuallyHidden } from "@mantine/core";
3
+ import { IconAlertTriangle, IconHourglass, IconCircleCheck, IconCircleX, IconLoader, IconMinus, IconClock, IconChartBar } from "@tabler/icons-react";
4
+ import { useEffect, useId, useRef, useState, type CSSProperties, type ReactNode } from "react";
5
+ import { formatWorkedDuration } from "../../time.js";
6
+ import { turnUsageLabel, useAnimatedUsage } from "./SavedUsageFormat";
7
+ import type { SavedUsage, PullRequestStatus } from "../types";
8
+
9
+ export function nextRunLabel(value?: string | null, now = new Date()) {
10
+ if (!value || !Number.isFinite(new Date(value).getTime())) return "Next run time unavailable";
11
+ const date = new Date(value);
12
+ const tomorrow = new Date(now); tomorrow.setDate(tomorrow.getDate() + 1);
13
+ const day = date.toDateString() === now.toDateString() ? "Today" : date.toDateString() === tomorrow.toDateString() ? "Tomorrow"
14
+ : date.toLocaleDateString(undefined, { month: "short", day: "numeric", ...(date.getFullYear() !== now.getFullYear() ? { year: "numeric" } : {}) });
15
+ return `Next run: ${day} at ${date.toLocaleTimeString(undefined, { hour: "numeric", minute: "2-digit" })}`;
16
+ }
17
+
18
+ export function prPresentation(pr: PullRequestStatus) {
19
+ if (pr.state === "merged") return { Icon: PrMergedIcon, color: "#b28bdf", dot: null, label: "Merged" };
20
+ if (pr.state === "closed") return { Icon: PrClosedIcon, color: "#f0787e", dot: null, label: "Closed, not merged" };
21
+ if (pr.state === "draft") return { Icon: PrDraftIcon, color: "var(--taskchef-muted)", dot: null, label: "Draft" };
22
+ if (pr.accessIssue && pr.state === "unknown") return { Icon: IconAlertTriangle, color: "#eac54f", dot: null, label: "Repository access needed" };
23
+ if (pr.state === "unknown") return { Icon: PrOpenIcon, color: "var(--taskchef-muted)", dot: null, label: "PR status not checked or unavailable" };
24
+ if (pr.hasMergeConflicts || pr.checks === "failed") return { Icon: PrStatusIcon, color: "var(--taskchef-muted)", dot: "#e56b6f", label: pr.hasMergeConflicts ? "Merge conflicts" : "Checks failed" };
25
+ if (pr.canMerge || pr.checks === "passed") return { Icon: PrStatusIcon, color: "var(--taskchef-muted)", dot: "#39c681", label: pr.canMerge ? "Ready to merge" : "Checks passed" };
26
+ return { Icon: PrStatusIcon, color: "var(--taskchef-muted)", dot: "#eac54f", label: pr.checks === "none" ? "No checks" : pr.checks === "pending" ? "Checks pending" : "Open PR" };
27
+ }
28
+
29
+ export function PullRequestIcons({ pullRequests = [] }: { pullRequests?: PullRequestStatus[] }) {
30
+ return <Box className="taskchef-card-pr-icons">{pullRequests.map(pr => {
31
+ const { Icon, color, dot, label } = prPresentation(pr);
32
+ return <span key={pr.url} className="taskchef-card-status-icon" aria-label={`${prTitle(pr)}: ${label}`} style={{ color, "--taskchef-pr-dot-color": dot ?? "currentColor" } as CSSProperties}>
33
+ <Icon size={15} stroke={1.5} aria-hidden />
34
+ {pr.accessIssue && pr.state !== "unknown" && <IconAlertTriangle className="taskchef-pr-access-warning" size={10} aria-hidden />}
35
+ </span>;
36
+ })}</Box>;
37
+ }
38
+
39
+ export function CardStatusLine({ children, pullRequests = [], earlierPullRequest, scheduled, nextRunAt, durationMs, startedAt, subagentCount, turnUsage, turnId, animateUsage }: {
40
+ subagentCount?: number;
41
+ turnUsage?: SavedUsage;
42
+ turnId?: string | null;
43
+ animateUsage?: boolean;
44
+ children: ReactNode;
45
+ pullRequests?: PullRequestStatus[];
46
+ earlierPullRequest?: PullRequestStatus;
47
+ scheduled?: boolean;
48
+ nextRunAt?: string | null;
49
+ durationMs?: number | null;
50
+ startedAt?: string | null;
51
+ }) {
52
+ const showEarlierPr = !pullRequests.length && !!earlierPullRequest;
53
+ const displayedPrs = showEarlierPr ? [earlierPullRequest!] : pullRequests;
54
+ const descriptionId = useId();
55
+ const [opened, setOpened] = useState(false);
56
+ const [now, setNow] = useState(Date.now);
57
+ const start = startedAt ? Date.parse(startedAt) : NaN;
58
+ const running = Number.isFinite(start);
59
+ const animatedUsage = useAnimatedUsage(turnUsage, animateUsage ?? running, turnId ?? startedAt);
60
+ useEffect(() => {
61
+ if (!running) return;
62
+ setNow(Date.now());
63
+ const tick = window.setInterval(() => setNow(Date.now()), 60000);
64
+ return () => window.clearInterval(tick);
65
+ }, [running, startedAt]);
66
+ const duration = formatWorkedDuration(running ? Math.max(0, now - start) : durationMs);
67
+ const hasNextRun = scheduled && !!nextRunAt && Number.isFinite(Date.parse(nextRunAt));
68
+ const hasUsage = !!turnUsage && (!!turnUsage.samples || turnUsage.partial || turnUsage.costPartial);
69
+ const hasInfo = hasUsage || duration !== "—" || displayedPrs.length > 0 || hasNextRun;
70
+ const timer = useRef<ReturnType<typeof setTimeout> | null>(null);
71
+ const target = useRef<HTMLDivElement>(null);
72
+ const popup = useRef<HTMLDivElement>(null);
73
+ function show() { if (timer.current) clearTimeout(timer.current); if (hasInfo) { setNow(Date.now()); setOpened(true); } }
74
+ function leave() {
75
+ if (timer.current) clearTimeout(timer.current);
76
+ timer.current = setTimeout(() => {
77
+ if (!target.current?.contains(document.activeElement) && !popup.current?.contains(document.activeElement)) setOpened(false);
78
+ }, 180);
79
+ }
80
+ useEffect(() => () => { if (timer.current) clearTimeout(timer.current); }, []);
81
+ useEffect(() => { if (!hasInfo) setOpened(false); }, [hasInfo]);
82
+ return <Popover opened={opened && hasInfo} onChange={setOpened} position="top" withArrow withinPortal width={300} zIndex={400}>
83
+ <Popover.Target>
84
+ <Box ref={target} className="taskchef-card-stats" tabIndex={hasInfo ? 0 : undefined} aria-label="Turn status details" aria-describedby={displayedPrs.length ? descriptionId : undefined}
85
+ onMouseEnter={show} onMouseLeave={leave} onFocus={show} onBlur={leave} onClick={show}
86
+ onKeyDown={event => {
87
+ if (event.key === "Escape") { setOpened(false); event.stopPropagation(); }
88
+ if (event.key === "Tab" && !event.shiftKey && opened && popup.current?.querySelector("a")
89
+ && (event.target !== target.current || !target.current?.querySelector('button:not(:disabled), [tabindex="0"]'))) {
90
+ event.preventDefault(); popup.current.querySelector("a")?.focus();
91
+ }
92
+ }}>
93
+ {children}
94
+ {hasUsage && <span className="taskchef-card-turn-usage">{turnUsageLabel(animatedUsage!)}</span>}
95
+ {scheduled && <span className="taskchef-card-status-icon" aria-label="Active schedule"><IconClock className="taskchef-schedule-clock" size={15} stroke={1.5} aria-hidden /></span>}
96
+ <PullRequestIcons pullRequests={displayedPrs} />
97
+ {displayedPrs.length > 0 && <VisuallyHidden id={descriptionId}>{showEarlierPr ? "Earlier turn PR. " : ""}{displayedPrs.map(pr => `${prTitle(pr)}: ${pr.state === "merged" ? "Merged" : pr.state === "closed" ? "Closed, not merged" : pr.state === "draft" ? "Draft" : pr.state === "unknown" ? "PR status not checked or unavailable" : pr.hasMergeConflicts ? "Open, merge conflicts" : "Open"}`).join(". ")}</VisuallyHidden>}
98
+ </Box>
99
+ </Popover.Target>
100
+ <Popover.Dropdown className="taskchef-status-tooltip" p={9} ref={popup} onMouseEnter={show} onMouseLeave={leave} onFocus={show} onBlur={leave}
101
+ onKeyDown={event => { if (event.key === "Escape") { setOpened(false); target.current?.focus(); setOpened(false); event.stopPropagation(); } }}>
102
+ <Stack gap={5}>
103
+ {duration !== "—" && <StatusRow icon={<IconHourglass size={15} stroke={1.5} />}>Worked for {duration}</StatusRow>}
104
+ {hasUsage && <StatusRow icon={<IconChartBar size={15} stroke={1.5} />}>Turn usage: {turnUsageLabel(animatedUsage!)}</StatusRow>}
105
+ {displayedPrs.map(pr => <PullRequestInfo key={pr.url} pr={pr} showChecks={false} earlierTurn={showEarlierPr} />)}
106
+ {hasNextRun && <StatusRow icon={<IconClock className="taskchef-schedule-clock" size={15} stroke={1.5} />}>{nextRunLabel(nextRunAt)}</StatusRow>}
107
+ </Stack>
108
+ </Popover.Dropdown>
109
+ </Popover>;
110
+ }
111
+
112
+ function prTitle(pr: PullRequestStatus) {
113
+ const number = pr.url.match(/\/pull\/(\d+)/)?.[1];
114
+ const title = pr.title || pr.url.match(/github\.com\/(.+)\/pull\/\d+/)?.[1] || "Pull request";
115
+ return `${number ? `#${number} ` : ""}${title}`;
116
+ }
117
+
118
+ function StatusRow({ icon, children }: { icon: ReactNode; children: ReactNode }) {
119
+ return <Box className="taskchef-status-row"><span className="taskchef-status-row-icon" aria-hidden>{icon}</span><Box className="taskchef-status-row-content">{children}</Box></Box>;
120
+ }
121
+
122
+ export function PullRequestInfo({ pr, showAccess = true, showChecks = true, earlierTurn = false }: { pr: PullRequestStatus; showAccess?: boolean; showChecks?: boolean; earlierTurn?: boolean }) {
123
+ const title = prTitle(pr);
124
+ const safeLink = /^https:\/\/github\.com\/[A-Za-z0-9-]+\/[A-Za-z0-9_.-]+\/pull\/[1-9]\d*\/?$/.test(pr.url);
125
+ const { Icon, color, dot } = prPresentation(pr);
126
+ const CiIcon = pr.checks === "passed" ? IconCircleCheck : pr.checks === "failed" ? IconCircleX : pr.checks === "pending" ? IconLoader : IconMinus;
127
+ const repo = safeLink ? pr.url.match(/github\.com\/(.+)\/pull\//)?.[1] : null;
128
+ return <Stack gap={5}>
129
+ <StatusRow icon={<span className="taskchef-popup-pr-icon" style={{ color, "--taskchef-pr-dot-color": dot ?? "currentColor" } as CSSProperties}><Icon size={15} stroke={1.5} /></span>}>
130
+ {safeLink ? <Anchor className="taskchef-status-pr-title" href={pr.url} target="_blank" rel="noopener noreferrer" title={title}>{title}</Anchor> : <Text className="taskchef-status-pr-title">{title}</Text>}
131
+ </StatusRow>
132
+ {earlierTurn && <StatusRow icon={null}><Text size="xs" c="dimmed">(Earlier turn PR)</Text></StatusRow>}
133
+ {showChecks && pr.checks !== "unknown" && <StatusRow icon={<CiIcon size={15} stroke={1.5} />}>{pr.checks === "passed" ? "CI passed" : pr.checks === "failed" ? "CI failed" : pr.checks === "pending" ? "CI pending" : "No CI checks"}</StatusRow>}
134
+ {showAccess && pr.accessIssue && safeLink && <Box className="taskchef-pr-access-alert">
135
+ <StatusRow icon={null}><Text size="xs">{pr.accessIssue === "denied" ? `Access denied to ${repo}.` : `PR #${pr.url.match(/\/pull\/(\d+)/)?.[1]} is unavailable. It may be private or removed.`} <Anchor size="xs" href="https://github.com/apps/taskchef/installations/new" target="_blank" rel="noopener noreferrer">{pr.accessIssue === "denied" ? "Grant access" : "Check access"}</Anchor></Text></StatusRow>
136
+ </Box>}
137
+ </Stack>;
138
+ }
@@ -0,0 +1,22 @@
1
+ import { useEffect, useState } from "react";
2
+ import type { Task } from "../types";
3
+ import { ReplyImagePreview } from "./ReplyImagePreview";
4
+
5
+ type Image = { url: string; alt: string };
6
+ export function ImageGallery({ task, images, loadImage, onLightboxChange }: { task: Task; images: Image[]; loadImage: (task: Task, url?: string) => Promise<string | null>; onLightboxChange?: (opened: boolean) => void }) {
7
+ const signature = JSON.stringify([task.id, task.turnId, images.map(image => image.url)]);
8
+ const [loaded, setLoaded] = useState<{ signature: string; sources: (string | null)[] } | null>(null);
9
+ useEffect(() => {
10
+ let cancelled = false;
11
+ void Promise.all(images.map(image => loadImage(task, image.url).catch(() => null))).then(sources => {
12
+ if (!cancelled) setLoaded({ signature, sources });
13
+ });
14
+ return () => { cancelled = true; };
15
+ }, [signature, loadImage]);
16
+ const sources = loaded?.signature === signature ? loaded.sources : null;
17
+ return <div className="taskchef-prompt-images" aria-busy={!sources}>
18
+ {images.map((image, index) => sources
19
+ ? sources[index] && <ReplyImagePreview key={`${signature}:${index}`} task={task} url={image.url} alt={image.alt} loadImage={loadImage} source={sources[index]} onLightboxChange={onLightboxChange} />
20
+ : <span key={image.url + index} className="taskchef-image-placeholder" role="status" aria-label={`Loading ${image.alt}`} />)}
21
+ </div>;
22
+ }
@@ -19,18 +19,18 @@ vi.mock('@mantine/core', async () => {
19
19
 
20
20
  afterEach(() => { cleanup(); vi.unstubAllGlobals(); vi.clearAllMocks(); });
21
21
 
22
- test('shows the ccusage version pinned by TaskChef without an availability status', async () => {
22
+ test('shows the built-in TaskChef usage engine without an availability status', async () => {
23
23
  vi.stubGlobal('fetch', vi.fn().mockResolvedValue({
24
24
  ok: true,
25
25
  json: async () => ({
26
26
  profiles: [],
27
- usageProvider: { provider: 'ccusage', version: '20.0.21' },
27
+ usageProvider: { provider: 'TaskChef', version: '8.6.2' },
28
28
  }),
29
29
  }));
30
30
  render(<MantineProvider><ModelSettings /></MantineProvider>);
31
- expect(await screen.findByText('ccusage 20.0.21')).toBeInTheDocument();
31
+ expect(await screen.findByText('TaskChef 8.6.2')).toBeInTheDocument();
32
32
  expect(screen.getByText('Usage provider')).toBeInTheDocument();
33
- expect(screen.getByText(/Version pinned by TaskChef/)).toBeInTheDocument();
33
+ expect(screen.getByText(/TaskChef’s accounting engine/)).toBeInTheDocument();
34
34
  expect(screen.queryByText('available')).not.toBeInTheDocument();
35
35
  });
36
36
 
@@ -99,7 +99,7 @@ export function ModelSettings() {
99
99
  <Stack gap="xs">
100
100
  <Title order={3} size="h5">Usage provider</Title>
101
101
  <Text size="sm">{usageProvider.provider}{usageProvider.version ? ` ${usageProvider.version}` : ' version unavailable'}</Text>
102
- <Text c="dimmed" size="sm">Version pinned by TaskChef for token and cost estimates.</Text>
102
+ <Text c="dimmed" size="sm">Reads saved Codex usage with TaskChef’s accounting engine.</Text>
103
103
  </Stack>
104
104
  </Paper>}
105
105
  </Stack>;
@@ -21,3 +21,22 @@ test("uses the shared open-chat presentation and accessible task label", () => {
21
21
  fireEvent.click(button);
22
22
  expect(onClick).toHaveBeenCalledOnce();
23
23
  });
24
+
25
+ test("opening a chat keeps its label and icon still while preventing another click", () => {
26
+ const click = vi.fn();
27
+ const view = render(<MantineProvider><OpenChatButton loading onClick={click} taskTitle="Example" /></MantineProvider>);
28
+ const button = screen.getByRole("button", {name:"Open chat for Example"});
29
+ expect(button).toBeDisabled();
30
+ expect(button).toHaveAttribute("aria-busy", "true");
31
+ expect(button).not.toHaveAttribute("data-loading");
32
+ expect(button.querySelector(".mantine-Button-loader")).toBeNull();
33
+ expect(button).toHaveTextContent("Open chat");
34
+ expect(button.querySelector("svg")).toHaveAttribute("aria-hidden", "true");
35
+ fireEvent.click(button);
36
+ expect(click).not.toHaveBeenCalled();
37
+ view.rerender(<MantineProvider><OpenChatButton onClick={click} taskTitle="Example" /></MantineProvider>);
38
+ expect(button).toBeEnabled();
39
+ expect(button).not.toHaveAttribute("aria-busy");
40
+ fireEvent.click(button);
41
+ expect(click).toHaveBeenCalledOnce();
42
+ });
@@ -15,7 +15,8 @@ export function OpenChatButton({
15
15
  aria-label={`Open chat for ${taskTitle}`}
16
16
  className="taskchef-open-chat"
17
17
  leftSection={<IconArrowUpRight aria-hidden size={15} stroke={1.6} />}
18
- loading={loading}
18
+ disabled={loading}
19
+ aria-busy={loading || undefined}
19
20
  onClick={onClick}
20
21
  size="compact-sm"
21
22
  variant="default"
@@ -0,0 +1,35 @@
1
+ import type { SVGProps } from "react";
2
+
3
+ type Props = Omit<SVGProps<SVGSVGElement>, "stroke"> & { size?: number; stroke?: number };
4
+ type Shape = "open" | "status" | "draft" | "merged" | "closed";
5
+
6
+ // Drawn on a 20px grid to match Codex's branch layout and node sizes.
7
+ // The status dot replaces the right node; it is not an external badge.
8
+ function PrGlyph({ shape, size = 15, stroke: _stroke, ...props }: Props & { shape: Shape }) {
9
+ return <svg width={size} height={size} viewBox="0 0 20 20" fill="none" stroke="currentColor" strokeWidth={1.33} strokeLinecap="round" strokeLinejoin="round" {...props}>
10
+ <circle cx={5.42} cy={5} r={1.875} />
11
+ <path d="M5.42 6.875V13.125" />
12
+ <circle cx={5.42} cy={15} r={1.875} />
13
+ {shape === "merged" ? <>
14
+ <path d="M6.2 6.6C7.1 10.2 9.3 11.9 12.71 12.5" />
15
+ <circle cx={14.58} cy={12.5} r={1.875} />
16
+ </> : shape === "draft" ? <>
17
+ <circle cx={14.58} cy={5} r={1} fill="currentColor" stroke="none" />
18
+ <circle cx={14.58} cy={9.25} r={1} fill="currentColor" stroke="none" />
19
+ <circle cx={14.58} cy={15} r={1.875} />
20
+ </> : shape === "closed" ? <>
21
+ <path d="M12.92 3.33L16.25 6.67M16.25 3.33L12.92 6.67M14.58 9.58V13.125" />
22
+ <circle cx={14.58} cy={15} r={1.875} />
23
+ </> : <>
24
+ <path d="M11.67 3.33L10 5L11.67 6.67M10 5H13.33Q15 5 15 6.67V9.17" />
25
+ {shape === "status" ? <circle cx={15.14} cy={15.14} r={3.14} fill="var(--taskchef-pr-dot-color, currentColor)" stroke="none" />
26
+ : <path d="M15 12.5V16.67M12.92 14.58H17.08" />}
27
+ </>}
28
+ </svg>;
29
+ }
30
+
31
+ export function PrOpenIcon(props: Props) { return <PrGlyph {...props} shape="open" />; }
32
+ export function PrStatusIcon(props: Props) { return <PrGlyph {...props} shape="status" />; }
33
+ export function PrDraftIcon(props: Props) { return <PrGlyph {...props} shape="draft" />; }
34
+ export function PrMergedIcon(props: Props) { return <PrGlyph {...props} shape="merged" />; }
35
+ export function PrClosedIcon(props: Props) { return <PrGlyph {...props} shape="closed" />; }
@@ -0,0 +1,18 @@
1
+ import { Badge, Group } from "@mantine/core";
2
+ import { IconGitMerge, IconGitPullRequest, IconGitPullRequestDraft } from "@tabler/icons-react";
3
+ import type { PullRequestStatus } from "../types";
4
+
5
+ export function PullRequestBadges({ pullRequests = [] }: { pullRequests?: PullRequestStatus[] }) {
6
+ if (!pullRequests.length) return null;
7
+ return <Group gap={4} wrap="wrap" aria-label="Attached pull requests">
8
+ {pullRequests.map((pr) => {
9
+ const merged = pr.state === "merged";
10
+ const draft = pr.state === "draft";
11
+ const label = merged ? "Merged" : draft ? "Draft" : pr.state === "closed" ? "Closed, not merged" : pr.state === "unknown" ? "Status unavailable" : pr.checks === "passed" ? "Checks passed" : pr.checks === "none" ? "No checks" : pr.checks === "pending" ? "Checks pending" : pr.checks === "failed" ? "Checks failed" : "Checks unavailable";
12
+ const Icon = merged ? IconGitMerge : draft ? IconGitPullRequestDraft : IconGitPullRequest;
13
+ const color = merged ? "violet" : draft || pr.state === "unknown" ? "gray" : pr.state === "closed" || pr.checks === "failed" ? "red" : pr.checks === "passed" ? "green" : "yellow";
14
+ const safeLink = /^https:\/\/github\.com\/[A-Za-z0-9-]+\/[A-Za-z0-9_.-]+\/pull\/[1-9]\d*\/?$/.test(pr.url);
15
+ return <Badge key={pr.url} component="a" href={safeLink ? pr.url : undefined} target="_blank" rel="noopener noreferrer" variant="light" color={color} size="xs" leftSection={<Icon size={12} aria-hidden />} title={`${pr.url}\n${label}${pr.error ? `: ${pr.error}` : ""}${pr.checkedAt ? `\nChecked ${new Date(pr.checkedAt).toLocaleString()}` : ""}`} style={{ cursor: "pointer", textTransform: "none", maxWidth: "100%" }}>#{pr.url.match(/\/pull\/(\d+)/)?.[1] ?? "PR"} · {label}</Badge>;
16
+ })}
17
+ </Group>;
18
+ }
@@ -0,0 +1,42 @@
1
+ import { MantineProvider } from '@mantine/core';
2
+ import { render, screen, cleanup, fireEvent, waitFor } from '@testing-library/react';
3
+ import { afterEach, expect, test, vi } from 'vitest';
4
+ import { QueuedPrompts } from './QueuedPrompts';
5
+ import { fixtureTask } from '../fixtures';
6
+ afterEach(()=>{cleanup();vi.restoreAllMocks();});
7
+ const prompts=[{id:'first',text:'First follow-up',images:[]},{id:'second',text:'Second follow-up\n'+ 'More details. '.repeat(30),images:[]}];
8
+ test('queue preserves execution order and removes started prompts on refresh',()=>{
9
+ const task={...fixtureTask(),queuedPrompts:prompts};
10
+ const {rerender}=render(<MantineProvider><QueuedPrompts task={task} compact /></MantineProvider>);
11
+ expect(screen.getByText('2 queued')).toBeVisible();
12
+ expect(screen.getAllByRole('listitem')[0]).toHaveTextContent('First follow-up');
13
+ for (const item of screen.getAllByRole('listitem')) expect(item.firstElementChild).toHaveClass('taskchef-queue-icon');
14
+ rerender(<MantineProvider><QueuedPrompts task={{...task,queuedPrompts:prompts.slice(1)}} compact /></MantineProvider>);
15
+ expect(screen.getByText('1 queued')).toBeVisible(); expect(screen.queryByText('First follow-up')).toBeNull();
16
+ rerender(<MantineProvider><QueuedPrompts task={{...task,queuedPrompts:[]}} compact /></MantineProvider>);
17
+ expect(screen.queryByRole('region',{name:'Queued prompts'})).toBeNull();
18
+ });
19
+ test('Details provides expansion and clickable queued image thumbnails', async()=>{
20
+ vi.spyOn(HTMLElement.prototype,'scrollHeight','get').mockReturnValue(200);
21
+ vi.spyOn(HTMLElement.prototype,'clientHeight','get').mockReturnValue(60);
22
+ const load=vi.fn().mockResolvedValue('data:image/png;base64,iVBORw0KGgo=');
23
+ const task={...fixtureTask(),queuedPrompts:[{...prompts[1],images:[{url:'taskchef-queue:second:0',alt:'Queued screenshot'}]}]};
24
+ render(<MantineProvider><QueuedPrompts task={task} loadImage={load}/></MantineProvider>);
25
+ expect(screen.getByText('Queued prompts (1)')).toBeVisible();
26
+ expect(screen.getByRole('listitem').firstElementChild).toHaveClass('taskchef-queue-icon');
27
+ fireEvent.click(screen.getByRole('button',{name:'Show more…'}));
28
+ expect(screen.getByRole('button',{name:'Show less'})).toHaveAttribute('aria-expanded','true');
29
+ const thumbnail=await screen.findByRole('button',{name:'Enlarge Queued screenshot'});
30
+ fireEvent.click(thumbnail);
31
+ await waitFor(()=>expect(screen.getByRole('dialog',{name:'Queued screenshot'})).toBeVisible());
32
+ });
33
+
34
+ test('short queued text offers expansion when narrow wrapping exceeds three rendered lines',()=>{
35
+ vi.spyOn(HTMLElement.prototype,'scrollHeight','get').mockReturnValue(100);
36
+ vi.spyOn(HTMLElement.prototype,'clientHeight','get').mockReturnValue(60);
37
+ const task={...fixtureTask(),queuedPrompts:[{id:'short',text:'A short request that wraps on a narrow screen.',images:[]}]};
38
+ render(<MantineProvider><QueuedPrompts task={task}/></MantineProvider>);
39
+ expect(screen.getByRole('button',{name:'Show more…'})).toBeVisible();
40
+ fireEvent.click(screen.getByRole('button',{name:'Show more…'}));
41
+ expect(screen.getByRole('button',{name:'Show less'})).toHaveAttribute('aria-expanded','true');
42
+ });
@@ -0,0 +1,34 @@
1
+ import { CollapsedMarkdown } from "./TurnContent";
2
+ import type { Task } from "../types";
3
+ import { ReplyMarkdown } from "./ReplyMarkdown";
4
+ import { ImageGallery } from "./ImageGallery";
5
+ import { ReplyCover } from "./ReplyCover";
6
+
7
+ function QueueIcon() {
8
+ return <svg className="taskchef-queue-icon" width="16" height="16" viewBox="0 0 20 20" fill="none" stroke="currentColor" strokeWidth="1.33" strokeLinecap="round" strokeLinejoin="round" aria-hidden="true">
9
+ <path d="M3.33 3.33V11c0 3.2.8 4 4 4h9.34M14.58 12.92 16.67 15l-2.09 2.08M7.5 5h6.67M7.5 9.58h4.17" />
10
+ </svg>;
11
+ }
12
+
13
+ export function QueuedPrompts({ task, compact = false, loadImage, onLightboxChange, onOpen }: { task: Task; compact?: boolean; loadImage?: (task: Task, url?: string) => Promise<string | null>; onLightboxChange?: (opened: boolean) => void; onOpen?: () => void }) {
14
+ if (!task.queuedPrompts?.length) return null;
15
+ return <section className={`taskchef-queued-prompts${compact ? " is-compact" : ""}`} aria-label="Queued prompts">
16
+ <div className="taskchef-queued-heading">{compact ? `${task.queuedPrompts.length} queued` : `Queued prompts (${task.queuedPrompts.length})`}</div>
17
+ <ol>{task.queuedPrompts.map(prompt => compact
18
+ ? <li key={prompt.id}>
19
+ <QueueIcon />
20
+ {loadImage && onOpen && prompt.images[0] && <ReplyCover task={task} image={prompt.images[0]} loadImage={loadImage} onOpen={onOpen} />}
21
+ <span><ReplyMarkdown text={prompt.text} compact hideRequestLabels renderImage={() => null} /></span>
22
+ </li>
23
+ : <QueuedPrompt key={prompt.id} task={task} prompt={prompt} loadImage={loadImage} onLightboxChange={onLightboxChange} />)}</ol>
24
+ </section>;
25
+ }
26
+ function QueuedPrompt({ task, prompt, loadImage, onLightboxChange }: { task: Task; prompt: NonNullable<Task['queuedPrompts']>[number]; loadImage?: (task: Task, url?: string) => Promise<string | null>; onLightboxChange?: (opened: boolean) => void }) {
27
+ return <li>
28
+ <QueueIcon />
29
+ <div className="taskchef-queue-content">
30
+ {loadImage && prompt.images.length > 0 && <ImageGallery task={task} images={prompt.images} loadImage={loadImage} onLightboxChange={onLightboxChange} />}
31
+ <CollapsedMarkdown text={prompt.text} />
32
+ </div>
33
+ </li>;
34
+ }