@cmodjs/core 0.2.3 → 1.0.0

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 (273) hide show
  1. package/docs/commands.md +58 -10
  2. package/docs/dependencies.md +12 -12
  3. package/docs/hooks.md +41 -28
  4. package/docs/index.md +29 -25
  5. package/docs/install-steps.md +9 -7
  6. package/docs/jobs.md +59 -111
  7. package/docs/mod.md +200 -174
  8. package/docs/options.md +2 -2
  9. package/docs/permissions.md +27 -16
  10. package/docs/session.md +248 -0
  11. package/docs/state.md +11 -7
  12. package/docs/testing.md +66 -23
  13. package/docs/ui.md +108 -76
  14. package/jobs/check.d.ts.map +1 -1
  15. package/jobs/check.js +5 -2
  16. package/jobs/context.d.ts +7 -8
  17. package/jobs/context.d.ts.map +1 -1
  18. package/jobs/context.js +23 -73
  19. package/jobs/permissions/decide-permission.d.ts +5 -3
  20. package/jobs/permissions/decide-permission.d.ts.map +1 -1
  21. package/jobs/permissions/decide-permission.js +6 -4
  22. package/jobs/permissions/find-project-scope.d.ts +1 -1
  23. package/jobs/permissions/find-project-scope.d.ts.map +1 -1
  24. package/jobs/permissions/find-project-scope.js +8 -11
  25. package/jobs/permissions/match-target.d.ts +2 -2
  26. package/jobs/permissions/match-target.d.ts.map +1 -1
  27. package/jobs/permissions.d.ts +1 -1
  28. package/jobs/permissions.d.ts.map +1 -1
  29. package/jobs/permissions.js +6 -4
  30. package/jobs/program.d.ts.map +1 -1
  31. package/jobs/program.js +8 -3
  32. package/jobs/prompt.d.ts +4 -2
  33. package/jobs/prompt.d.ts.map +1 -1
  34. package/jobs/prompt.js +16 -15
  35. package/jobs/schedule.d.ts +2 -2
  36. package/jobs/schedule.d.ts.map +1 -1
  37. package/jobs/schedule.js +9 -9
  38. package/jobs/slash-command.d.ts +4 -4
  39. package/jobs/slash-command.d.ts.map +1 -1
  40. package/jobs/slash-command.js +14 -9
  41. package/jobs/status-line.d.ts +1 -11
  42. package/jobs/status-line.d.ts.map +1 -1
  43. package/jobs/status-line.js +8 -12
  44. package/jobs/tool.d.ts +2 -2
  45. package/jobs/tool.d.ts.map +1 -1
  46. package/jobs/tool.js +15 -9
  47. package/mod.d.ts +154 -75
  48. package/mod.d.ts.map +1 -1
  49. package/mod.js +94 -3
  50. package/options.d.ts +2 -2
  51. package/options.js +19 -19
  52. package/package.json +3 -3
  53. package/records.d.ts +10 -8
  54. package/records.d.ts.map +1 -1
  55. package/records.js +28 -17
  56. package/register.d.ts.map +1 -1
  57. package/register.js +18 -6
  58. package/runtime/announce.d.ts +18 -0
  59. package/runtime/announce.d.ts.map +1 -0
  60. package/runtime/announce.js +66 -0
  61. package/runtime/bound.d.ts +4 -0
  62. package/runtime/bound.d.ts.map +1 -0
  63. package/runtime/bound.js +9 -0
  64. package/runtime/claude.d.ts +3 -3
  65. package/runtime/claude.d.ts.map +1 -1
  66. package/runtime/conversations.d.ts +16 -0
  67. package/runtime/conversations.d.ts.map +1 -0
  68. package/runtime/conversations.js +291 -0
  69. package/runtime/deadline.d.ts +0 -1
  70. package/runtime/deadline.d.ts.map +1 -1
  71. package/runtime/deadline.js +1 -1
  72. package/runtime/dependencies.d.ts +2 -0
  73. package/runtime/dependencies.d.ts.map +1 -1
  74. package/runtime/dependencies.js +9 -0
  75. package/runtime/engine.d.ts +17 -0
  76. package/runtime/engine.d.ts.map +1 -0
  77. package/runtime/engine.js +10 -0
  78. package/runtime/grants.d.ts +4 -0
  79. package/runtime/grants.d.ts.map +1 -1
  80. package/runtime/grants.js +63 -33
  81. package/runtime/hooks.d.ts +5 -4
  82. package/runtime/hooks.d.ts.map +1 -1
  83. package/runtime/hooks.js +10 -5
  84. package/runtime/installer.d.ts.map +1 -1
  85. package/runtime/installer.js +11 -9
  86. package/runtime/lifecycle.d.ts +3 -1
  87. package/runtime/lifecycle.d.ts.map +1 -1
  88. package/runtime/lifecycle.js +317 -186
  89. package/runtime/metadata.d.ts +3 -1
  90. package/runtime/metadata.d.ts.map +1 -1
  91. package/runtime/metadata.js +21 -11
  92. package/runtime/options.d.ts +3 -1
  93. package/runtime/options.d.ts.map +1 -1
  94. package/runtime/options.js +4 -4
  95. package/runtime/programs.d.ts +8 -0
  96. package/runtime/programs.d.ts.map +1 -1
  97. package/runtime/programs.js +39 -1
  98. package/runtime/router.d.ts +2 -1
  99. package/runtime/router.d.ts.map +1 -1
  100. package/runtime/router.js +11 -3
  101. package/runtime/sessions.d.ts +36 -0
  102. package/runtime/sessions.d.ts.map +1 -0
  103. package/runtime/sessions.js +235 -0
  104. package/runtime/state.d.ts +6 -2
  105. package/runtime/state.d.ts.map +1 -1
  106. package/runtime/state.js +46 -13
  107. package/runtime/toaster.d.ts +31 -0
  108. package/runtime/toaster.d.ts.map +1 -0
  109. package/runtime/toaster.js +176 -0
  110. package/runtime/ui.d.ts +6 -17
  111. package/runtime/ui.d.ts.map +1 -1
  112. package/runtime/ui.js +36 -112
  113. package/session/context/context.d.ts +10 -0
  114. package/session/context/context.d.ts.map +1 -0
  115. package/session/context/context.js +2 -0
  116. package/session/context/turn/message/document.d.ts +7 -0
  117. package/session/context/turn/message/document.d.ts.map +1 -0
  118. package/session/context/turn/message/document.js +1 -0
  119. package/session/context/turn/message/message.d.ts +54 -0
  120. package/session/context/turn/message/message.d.ts.map +1 -0
  121. package/session/context/turn/message/message.js +137 -0
  122. package/session/context/turn/message/note.d.ts +8 -0
  123. package/session/context/turn/message/note.d.ts.map +1 -0
  124. package/session/context/turn/message/note.js +1 -0
  125. package/session/context/turn/message/notice.d.ts +6 -0
  126. package/session/context/turn/message/notice.d.ts.map +1 -0
  127. package/session/context/turn/message/notice.js +1 -0
  128. package/session/context/turn/message/prompt.d.ts +8 -0
  129. package/session/context/turn/message/prompt.d.ts.map +1 -0
  130. package/session/context/turn/message/prompt.js +1 -0
  131. package/session/context/turn/message/reply.d.ts +6 -0
  132. package/session/context/turn/message/reply.d.ts.map +1 -0
  133. package/session/context/turn/message/reply.js +1 -0
  134. package/session/context/turn/message/sender.d.ts +14 -0
  135. package/session/context/turn/message/sender.d.ts.map +1 -0
  136. package/session/context/turn/message/sender.js +30 -0
  137. package/session/context/turn/message/skill.d.ts +7 -0
  138. package/session/context/turn/message/skill.d.ts.map +1 -0
  139. package/session/context/turn/message/skill.js +1 -0
  140. package/session/context/turn/message/tool-call.d.ts +9 -0
  141. package/session/context/turn/message/tool-call.d.ts.map +1 -0
  142. package/session/context/turn/message/tool-call.js +1 -0
  143. package/session/context/turn/message/tool-result.d.ts +8 -0
  144. package/session/context/turn/message/tool-result.d.ts.map +1 -0
  145. package/session/context/turn/message/tool-result.js +1 -0
  146. package/session/context/turn/turn.d.ts +12 -0
  147. package/session/context/turn/turn.d.ts.map +1 -0
  148. package/session/context/turn/turn.js +2 -0
  149. package/session/conversation.d.ts +64 -0
  150. package/session/conversation.d.ts.map +1 -0
  151. package/session/conversation.js +123 -0
  152. package/session/goal/goal.d.ts +10 -0
  153. package/session/goal/goal.d.ts.map +1 -0
  154. package/session/goal/goal.js +1 -0
  155. package/session/goal/task.d.ts +16 -0
  156. package/session/goal/task.d.ts.map +1 -0
  157. package/session/goal/task.js +3 -0
  158. package/session/session.d.ts +99 -0
  159. package/session/session.d.ts.map +1 -0
  160. package/session/session.js +1 -0
  161. package/src/jobs/check.ts +7 -4
  162. package/src/jobs/context.ts +24 -82
  163. package/src/jobs/permissions/decide-permission.ts +10 -8
  164. package/src/jobs/permissions/find-project-scope.ts +8 -14
  165. package/src/jobs/permissions/match-target.ts +3 -3
  166. package/src/jobs/permissions.ts +8 -6
  167. package/src/jobs/program.ts +7 -3
  168. package/src/jobs/prompt.ts +21 -24
  169. package/src/jobs/schedule.ts +14 -14
  170. package/src/jobs/slash-command.ts +20 -14
  171. package/src/jobs/status-line.ts +9 -21
  172. package/src/jobs/tool.ts +17 -11
  173. package/src/mod.ts +209 -97
  174. package/src/options.ts +22 -22
  175. package/src/records.ts +35 -23
  176. package/src/register.ts +18 -6
  177. package/src/runtime/announce.ts +74 -0
  178. package/src/runtime/bound.ts +12 -0
  179. package/src/runtime/claude.ts +5 -3
  180. package/src/runtime/conversations.ts +302 -0
  181. package/src/runtime/deadline.ts +2 -2
  182. package/src/runtime/dependencies.ts +12 -0
  183. package/src/runtime/engine.ts +22 -0
  184. package/src/runtime/grants.ts +66 -31
  185. package/src/runtime/hooks.ts +19 -10
  186. package/src/runtime/installer.ts +10 -9
  187. package/src/runtime/lifecycle.ts +313 -181
  188. package/src/runtime/metadata.ts +33 -11
  189. package/src/runtime/options.ts +19 -4
  190. package/src/runtime/programs.ts +40 -1
  191. package/src/runtime/router.ts +11 -4
  192. package/src/runtime/sessions.ts +242 -0
  193. package/src/runtime/state.ts +50 -14
  194. package/src/runtime/toaster.ts +218 -0
  195. package/src/runtime/ui.ts +42 -139
  196. package/src/session/context/context.ts +12 -0
  197. package/src/session/context/turn/message/document.ts +8 -0
  198. package/src/session/context/turn/message/message.ts +165 -0
  199. package/src/session/context/turn/message/note.ts +9 -0
  200. package/src/session/context/turn/message/notice.ts +7 -0
  201. package/src/session/context/turn/message/prompt.ts +9 -0
  202. package/src/session/context/turn/message/reply.ts +7 -0
  203. package/src/session/context/turn/message/sender.ts +38 -0
  204. package/src/session/context/turn/message/skill.ts +8 -0
  205. package/src/session/context/turn/message/tool-call.ts +10 -0
  206. package/src/session/context/turn/message/tool-result.ts +9 -0
  207. package/src/session/context/turn/turn.ts +14 -0
  208. package/src/session/conversation.ts +169 -0
  209. package/src/session/goal/goal.ts +9 -0
  210. package/src/session/goal/task.ts +19 -0
  211. package/src/session/session.ts +94 -0
  212. package/src/testing/fake-claude.ts +23 -18
  213. package/src/testing/fake-elements.ts +3 -2
  214. package/src/testing/fake-files.ts +1 -1
  215. package/src/testing/fake-sessions.ts +203 -0
  216. package/src/testing.ts +112 -33
  217. package/src/ui/components.ts +3 -3
  218. package/src/ui/elements.ts +22 -8
  219. package/src/ui/markdown.ts +22 -26
  220. package/src/ui/places.ts +49 -0
  221. package/src/utils/call-effects.ts +3 -3
  222. package/src/utils/changelog.ts +32 -0
  223. package/src/utils/matcher.ts +37 -0
  224. package/src/utils/metadata.ts +17 -15
  225. package/src/utils/parse-shell.ts +24 -16
  226. package/src/utils/paths.ts +15 -1
  227. package/src/utils/text.ts +4 -0
  228. package/testing/fake-claude.d.ts +4 -2
  229. package/testing/fake-claude.d.ts.map +1 -1
  230. package/testing/fake-claude.js +18 -12
  231. package/testing/fake-elements.js +4 -2
  232. package/testing/fake-files.js +1 -1
  233. package/testing/fake-sessions.d.ts +74 -0
  234. package/testing/fake-sessions.d.ts.map +1 -0
  235. package/testing/fake-sessions.js +170 -0
  236. package/testing.d.ts +33 -13
  237. package/testing.d.ts.map +1 -1
  238. package/testing.js +92 -21
  239. package/ui/components.d.ts +2 -3
  240. package/ui/components.d.ts.map +1 -1
  241. package/ui/components.js +3 -3
  242. package/ui/elements.d.ts.map +1 -1
  243. package/ui/elements.js +19 -9
  244. package/ui/markdown.d.ts +35 -33
  245. package/ui/markdown.d.ts.map +1 -1
  246. package/ui/markdown.js +14 -16
  247. package/ui/places.d.ts +43 -0
  248. package/ui/places.d.ts.map +1 -0
  249. package/ui/places.js +31 -0
  250. package/utils/call-effects.d.ts +1 -1
  251. package/utils/call-effects.d.ts.map +1 -1
  252. package/utils/call-effects.js +2 -2
  253. package/utils/changelog.d.ts +9 -0
  254. package/utils/changelog.d.ts.map +1 -0
  255. package/utils/changelog.js +29 -0
  256. package/utils/matcher.d.ts +13 -0
  257. package/utils/matcher.d.ts.map +1 -0
  258. package/utils/matcher.js +32 -0
  259. package/utils/metadata.d.ts +3 -3
  260. package/utils/metadata.js +18 -14
  261. package/utils/parse-shell.d.ts +1 -0
  262. package/utils/parse-shell.d.ts.map +1 -1
  263. package/utils/parse-shell.js +22 -13
  264. package/utils/paths.d.ts +2 -0
  265. package/utils/paths.d.ts.map +1 -1
  266. package/utils/paths.js +13 -1
  267. package/utils/text.d.ts +1 -0
  268. package/utils/text.d.ts.map +1 -1
  269. package/utils/text.js +3 -0
  270. package/src/ui/slots.ts +0 -36
  271. package/ui/slots.d.ts +0 -208
  272. package/ui/slots.d.ts.map +0 -1
  273. package/ui/slots.js +0 -19
@@ -1 +1 @@
1
- {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../src/ui/markdown.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AAEjD,KAAK,KAAK,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE/D,KAAK,YAAY,CAAC,KAAK,SAAS,MAAM,GAAG,MAAM,IAAI,IAAI,CAAC,KAAK,EAAE;IAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE;IAAE,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAA;CAAE,CAAC,CAAA;AAYjI,MAAM,MAAM,aAAa,CAAC,MAAM,IAAI;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAA;AAElH,MAAM,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,SAAS,aAAa,CAAC,MAAM,CAAC,EAAE,CAAA;AAEzJ,MAAM,MAAM,YAAY,GAAG;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,YAAY,EAAE,MAAM,cAAc,CAAA;CAC5C,CAAA;AAoID,eAAO,MAAM,aAAa;IACxB,OAAO;wBAtJoB,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC;;IAuJhD,SAAS;IACT,SAAS;uBAvJc,MAAM,GAAG,SAAS;uBAAiB,MAAM,GAAG,SAAS;wBAAkB,MAAM;;IAwJpG,UAAU;IACV,IAAI;0BAxJsB,OAAO;wBAAkB,MAAM,GAAG,SAAS;yBAAmB,OAAO;;IAyJ/F,KAAK;wBAxJoB,SAAS,CAAC,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,IAAI,CAAC,EAAE;;IAyJxE,aAAa;IACb,SAAS;wBAzJe,MAAM;;CA0J/B,CAAA;AAED,wBAAgB,cAAc,CAAC,CAAC,SAAS,YAAY,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,CAG7G"}
1
+ {"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../src/ui/markdown.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE7C,KAAK,KAAK,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE/D,KAAK,WAAW,GAAG;IACjB,OAAO,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;KAAE,CAAA;IAClD,IAAI,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;IACtG,IAAI,EAAE;QAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;KAAE,CAAA;IACjG,KAAK,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,IAAI,CAAC,EAAE,CAAA;KAAE,CAAA;IAC1E,IAAI,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAA;CACjC,CAAA;AAED,MAAM,MAAM,UAAU,CAAC,IAAI,SAAS,MAAM,IAAI,IAAI,SAAS,MAAM,WAAW,GAAG,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,KAAK,CAAA;AAEhH,MAAM,MAAM,aAAa,CAAC,MAAM,IAAI;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAA;AAElH,MAAM,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,SAAS,aAAa,CAAC,MAAM,CAAC,EAAE,CAAA;AAEzJ,MAAM,MAAM,aAAa,CAAC,IAAI,SAAS,MAAM,GAAG,MAAM,IAAI;IACxD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAA;IACvB,YAAY,IAAI,cAAc,CAAA;CAC/B,CAAA;AAMD,eAAO,MAAM,OAAO,0BAAsC,CAAA;AAC1D,eAAO,MAAM,SAAS,4BAA0C,CAAA;AAChE,eAAO,MAAM,SAAS,uBAAqC,CAAA;AAC3D,eAAO,MAAM,UAAU,6BAA4C,CAAA;AACnE,eAAO,MAAM,IAAI,uBAAgC,CAAA;AACjD,eAAO,MAAM,KAAK,wBAAkC,CAAA;AACpD,eAAO,MAAM,aAAa,gCAAkD,CAAA;AAC5E,eAAO,MAAM,SAAS,uBAAqC,CAAA;AA4B3D,wBAAgB,YAAY,IAAI,cAAc,CA0C7C;AA0DD,wBAAgB,cAAc,CAAC,CAAC,SAAS,aAAa,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,CAGhH"}
package/ui/markdown.js CHANGED
@@ -1,4 +1,15 @@
1
1
  import { fromMarkdown, gfm, gfmFromMarkdown, toString } from '../vendor-markdown.js';
2
+ function markdownPlace(name, markdown) {
3
+ return { name, markdown, createReader };
4
+ }
5
+ export const Heading = markdownPlace('Heading', 'heading');
6
+ export const Paragraph = markdownPlace('Paragraph', 'paragraph');
7
+ export const CodeBlock = markdownPlace('CodeBlock', 'code');
8
+ export const BlockQuote = markdownPlace('BlockQuote', 'blockquote');
9
+ export const List = markdownPlace('List', 'list');
10
+ export const Table = markdownPlace('Table', 'table');
11
+ export const ThematicBreak = markdownPlace('ThematicBreak', 'thematicBreak');
12
+ export const HtmlBlock = markdownPlace('HtmlBlock', 'html');
2
13
  const keptReplies = 64;
3
14
  const extensions = [gfm()];
4
15
  const mdastExtensions = [gfmFromMarkdown()];
@@ -6,7 +17,7 @@ const lineByLine = new Set(['list', 'listItem', 'blockquote', 'table', 'tableRow
6
17
  const definitions = new Set(['definition', 'footnoteDefinition']);
7
18
  const blankLine = /\n[^\S\n]*\n/;
8
19
  const fence = /^ {0,3}(`{3}|~{3})/;
9
- function createReader() {
20
+ export function createReader() {
10
21
  const replies = [];
11
22
  const remember = (reply) => {
12
23
  replies.push(reply);
@@ -109,20 +120,7 @@ function plainText(node) {
109
120
  return toString(node);
110
121
  return node.children.map(plainText).join(node.type === 'tableRow' ? '\t' : '\n');
111
122
  }
112
- function markdownSlot(name, type) {
113
- return { markdown: { name, type, createReader } };
114
- }
115
- export const markdownSlots = {
116
- Heading: markdownSlot('Heading', 'heading'),
117
- Paragraph: markdownSlot('Paragraph', 'paragraph'),
118
- CodeBlock: markdownSlot('CodeBlock', 'code'),
119
- BlockQuote: markdownSlot('BlockQuote', 'blockquote'),
120
- List: markdownSlot('List', 'list'),
121
- Table: markdownSlot('Table', 'table'),
122
- ThematicBreak: markdownSlot('ThematicBreak', 'thematicBreak'),
123
- HtmlBlock: markdownSlot('HtmlBlock', 'html'),
124
- };
125
- export function markdownBlocks(text, slot) {
126
- const blocks = parsed(text, 0).filter((block) => block.type === slot.markdown.type);
123
+ export function markdownBlocks(text, place) {
124
+ const blocks = parsed(text, 0).filter((block) => block.type === place.markdown);
127
125
  return blocks.map((block) => block.props);
128
126
  }
package/ui/places.d.ts ADDED
@@ -0,0 +1,43 @@
1
+ import type { Frozen, RenderComponent, RenderElement, RenderPropsOf } from 'claude-code';
2
+ import type { BlockProps, MarkdownPlace } from './markdown.js';
3
+ export declare const ToolGroup = "toolGroup";
4
+ export declare const ToolProgress = "toolProgress";
5
+ export declare const CommandOutput = "commandOutput";
6
+ export declare const AskUserQuestion = "askUserQuestion";
7
+ export declare const Spinner = "spinner";
8
+ export declare const TurnDuration = "turnDuration";
9
+ export declare const SessionMode = "sessionMode";
10
+ export declare const PromptHint = "promptHint";
11
+ export declare const AbovePrompt = "abovePrompt";
12
+ declare const components: {
13
+ readonly prompt: 'UserMessage';
14
+ readonly reply: 'AssistantMessage';
15
+ readonly toolCall: 'ToolUse';
16
+ readonly toolResult: 'ToolResult';
17
+ readonly notice: 'InfoNotice';
18
+ readonly toolGroup: 'ToolGroup';
19
+ readonly toolProgress: 'ToolProgress';
20
+ readonly commandOutput: 'CommandOutput';
21
+ readonly askUserQuestion: 'AskUserQuestion';
22
+ readonly spinner: 'Spinner';
23
+ readonly turnDuration: 'TurnDuration';
24
+ readonly sessionMode: 'SessionMode';
25
+ readonly promptHint: 'PromptHint';
26
+ readonly abovePrompt: 'AbovePrompt';
27
+ };
28
+ export type ComponentPlace = keyof typeof components;
29
+ export type Place = ComponentPlace | MarkdownPlace;
30
+ type ComponentProps = {
31
+ readonly [P in ComponentPlace]: RenderPropsOf[(typeof components)[P]];
32
+ };
33
+ type PropsOf<P extends Place> = P extends ComponentPlace ? ComponentProps[P] : P extends MarkdownPlace<infer Type> ? BlockProps<Type> : never;
34
+ type DefaultOf<P extends Place> = P extends ComponentPlace ? Partial<Omit<ComponentProps[P], 'onScreen'>> : {
35
+ readonly source?: string;
36
+ };
37
+ export type PlaceProps<P extends Place> = Frozen<PropsOf<P>> & {
38
+ readonly Default: (props: Frozen<DefaultOf<P>>) => RenderElement;
39
+ };
40
+ export declare function componentOf(place: Place): Exclude<RenderComponent, 'Pane'> | undefined;
41
+ export declare function nameOf(place: Place): string;
42
+ export {};
43
+ //# sourceMappingURL=places.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"places.d.ts","sourceRoot":"","sources":["../src/ui/places.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,eAAe,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AACxF,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAE9D,eAAO,MAAM,SAAS,cAAc,CAAA;AACpC,eAAO,MAAM,YAAY,iBAAiB,CAAA;AAC1C,eAAO,MAAM,aAAa,kBAAkB,CAAA;AAC5C,eAAO,MAAM,eAAe,oBAAoB,CAAA;AAChD,eAAO,MAAM,OAAO,YAAY,CAAA;AAChC,eAAO,MAAM,YAAY,iBAAiB,CAAA;AAC1C,eAAO,MAAM,WAAW,gBAAgB,CAAA;AACxC,eAAO,MAAM,UAAU,eAAe,CAAA;AACtC,eAAO,MAAM,WAAW,gBAAgB,CAAA;AAExC,QAAA,MAAM,UAAU;qBACN,aAAa;oBACd,kBAAkB;uBACf,SAAS;yBACP,YAAY;qBAChB,YAAY;wBACP,WAAW;2BACR,cAAc;4BACb,eAAe;8BACb,iBAAiB;sBACzB,SAAS;2BACJ,cAAc;0BACf,aAAa;yBACd,YAAY;0BACX,aAAa;CACiD,CAAA;AAE/E,MAAM,MAAM,cAAc,GAAG,MAAM,OAAO,UAAU,CAAA;AAEpD,MAAM,MAAM,KAAK,GAAG,cAAc,GAAG,aAAa,CAAA;AAElD,KAAK,cAAc,GAAG;IAAE,QAAQ,EAAE,CAAC,IAAI,cAAc,GAAG,aAAa,CAAC,CAAC,OAAO,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;CAAE,CAAA;AAE/F,KAAK,OAAO,CAAC,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,cAAc,GAAG,cAAc,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,aAAa,CAAC,MAAM,IAAI,CAAC,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,KAAK,CAAA;AAE7I,KAAK,SAAS,CAAC,CAAC,SAAS,KAAK,IAAI,CAAC,SAAS,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,GAAG;IAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAExI,MAAM,MAAM,UAAU,CAAC,CAAC,SAAS,KAAK,IAAI,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,KAAK,aAAa,CAAA;CAAE,CAAA;AAEnI,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,eAAe,EAAE,MAAM,CAAC,GAAG,SAAS,CAEtF;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAE3C"}
package/ui/places.js ADDED
@@ -0,0 +1,31 @@
1
+ export const ToolGroup = 'toolGroup';
2
+ export const ToolProgress = 'toolProgress';
3
+ export const CommandOutput = 'commandOutput';
4
+ export const AskUserQuestion = 'askUserQuestion';
5
+ export const Spinner = 'spinner';
6
+ export const TurnDuration = 'turnDuration';
7
+ export const SessionMode = 'sessionMode';
8
+ export const PromptHint = 'promptHint';
9
+ export const AbovePrompt = 'abovePrompt';
10
+ const components = {
11
+ prompt: 'UserMessage',
12
+ reply: 'AssistantMessage',
13
+ toolCall: 'ToolUse',
14
+ toolResult: 'ToolResult',
15
+ notice: 'InfoNotice',
16
+ [ToolGroup]: 'ToolGroup',
17
+ [ToolProgress]: 'ToolProgress',
18
+ [CommandOutput]: 'CommandOutput',
19
+ [AskUserQuestion]: 'AskUserQuestion',
20
+ [Spinner]: 'Spinner',
21
+ [TurnDuration]: 'TurnDuration',
22
+ [SessionMode]: 'SessionMode',
23
+ [PromptHint]: 'PromptHint',
24
+ [AbovePrompt]: 'AbovePrompt',
25
+ };
26
+ export function componentOf(place) {
27
+ return typeof place === 'string' && Object.hasOwn(components, place) ? components[place] : undefined;
28
+ }
29
+ export function nameOf(place) {
30
+ return typeof place === 'string' ? `${place.charAt(0).toUpperCase()}${place.slice(1)}` : place.name;
31
+ }
@@ -18,7 +18,7 @@ export type FileCall = CallBase & {
18
18
  export type FetchCall = CallBase & {
19
19
  url: string;
20
20
  };
21
- export type ToolCall = CommandCall | FileCall | FetchCall | CallBase;
21
+ export type Call = CommandCall | FileCall | FetchCall | CallBase;
22
22
  export type Contents = {
23
23
  content?: string;
24
24
  previousContent?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"call-effects.d.ts","sourceRoot":"","sources":["../src/utils/call-effects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAChE,OAAO,EAAc,KAAK,UAAU,EAAE,MAAM,YAAY,CAAA;AAGxD,MAAM,MAAM,QAAQ,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AACvH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG;IAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,EAAE,CAAC;IAAC,aAAa,EAAE,OAAO,CAAA;CAAE,CAAA;AAClG,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAC9F,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AAClD,MAAM,MAAM,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAA;AAEpE,MAAM,MAAM,QAAQ,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AACrE,MAAM,MAAM,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,CAAC,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,SAAS,CAAA;CAAE,CAAA;AAC1F,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,YAAY,EAAE,CAAC;QAAC,aAAa,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS,CAAA;IACrF,KAAK,EAAE,UAAU,EAAE,CAAA;IACnB,MAAM,EAAE,UAAU,EAAE,CAAA;IACpB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;CAC7B,CAAA;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,UAAU,CAAA;CAAE,GAAG,WAAW,CAsChH;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAEzE;AAED,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,QAAQ,GAAG,QAAQ,CAElF"}
1
+ {"version":3,"file":"call-effects.d.ts","sourceRoot":"","sources":["../src/utils/call-effects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAA;AAChE,OAAO,EAAyB,KAAK,UAAU,EAAE,MAAM,YAAY,CAAA;AAGnE,MAAM,MAAM,QAAQ,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AACvH,MAAM,MAAM,WAAW,GAAG,QAAQ,GAAG;IAAE,QAAQ,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,EAAE,CAAC;IAAC,aAAa,EAAE,OAAO,CAAA;CAAE,CAAA;AAClG,MAAM,MAAM,QAAQ,GAAG,QAAQ,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAC9F,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,CAAA;AAClD,MAAM,MAAM,IAAI,GAAG,WAAW,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,CAAA;AAEhE,MAAM,MAAM,QAAQ,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AACrE,MAAM,MAAM,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,CAAC,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC,GAAG,SAAS,CAAA;CAAE,CAAA;AAC1F,MAAM,MAAM,WAAW,GAAG;IACxB,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,YAAY,EAAE,CAAC;QAAC,aAAa,EAAE,OAAO,CAAA;KAAE,GAAG,SAAS,CAAA;IACrF,KAAK,EAAE,UAAU,EAAE,CAAA;IACnB,MAAM,EAAE,UAAU,EAAE,CAAA;IACpB,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAA;CAC7B,CAAA;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,QAAQ,EAAE,SAAS,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,UAAU,CAAA;CAAE,GAAG,WAAW,CAsChH;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAEzE;AAED,wBAAgB,UAAU,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,QAAQ,GAAG,QAAQ,CAElF"}
@@ -1,5 +1,5 @@
1
1
  import { parseShell } from './parse-shell.js';
2
- import { expandHome } from './paths.js';
2
+ import { expandHome, ifMissing } from './paths.js';
3
3
  import { resolve } from '../vendor.js';
4
4
  export function callEffects(use, workspace) {
5
5
  const { fs } = workspace;
@@ -69,7 +69,7 @@ async function editedContents(use, path, fs) {
69
69
  return contentsOf(content, previousContent);
70
70
  }
71
71
  async function previousContentOf(path, fs) {
72
- const stat = await fs.stat(path).catch(() => undefined);
72
+ const stat = await fs.stat(path).catch(ifMissing(undefined));
73
73
  return stat?.kind === 'file' ? fs.read(path) : undefined;
74
74
  }
75
75
  function contentsOf(content, previousContent) {
@@ -0,0 +1,9 @@
1
+ export type ChangelogSection = {
2
+ readonly version: string;
3
+ readonly date?: string;
4
+ readonly text: string;
5
+ };
6
+ export declare const unreleased = "Unreleased";
7
+ export declare function changelogSections(markdown: string): ChangelogSection[];
8
+ export declare function changeLines(text: string): string[];
9
+ //# sourceMappingURL=changelog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"changelog.d.ts","sourceRoot":"","sources":["../src/utils/changelog.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG;IAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAA;AAE1G,eAAO,MAAM,UAAU,eAAe,CAAA;AAMtC,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAQtE;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAalD"}
@@ -0,0 +1,29 @@
1
+ export const unreleased = 'Unreleased';
2
+ const heading = /^##\s+\[?([^\]\s]+)\]?(?:\s+-\s+(\S+))?\s*$/;
3
+ const linkReference = /^\[[^\]]+\]:\s/;
4
+ export function changelogSections(markdown) {
5
+ const sections = [];
6
+ for (const line of markdown.split('\n')) {
7
+ const match = heading.exec(line);
8
+ if (match !== null)
9
+ sections.push({ version: match[1], date: match[2], lines: [] });
10
+ else if (!linkReference.test(line))
11
+ sections.at(-1)?.lines.push(line);
12
+ }
13
+ return sections.map(({ version, date, lines }) => ({ version, ...(date === undefined ? {} : { date }), text: lines.join('\n').trim() }));
14
+ }
15
+ export function changeLines(text) {
16
+ let group;
17
+ return text.split('\n').flatMap((line) => {
18
+ const trimmed = line.trim();
19
+ const subheading = /^###\s+(.+)$/.exec(trimmed)?.[1];
20
+ if (subheading !== undefined) {
21
+ group = subheading;
22
+ return [];
23
+ }
24
+ const item = /^[-*]\s+(.+)$/.exec(trimmed)?.[1] ?? trimmed;
25
+ if (item === '')
26
+ return [];
27
+ return [group === undefined ? item : `${group}: ${item}`];
28
+ });
29
+ }
@@ -0,0 +1,13 @@
1
+ export type Matcher<Value> = Value extends string ? string | RegExp : Value extends number | boolean | null | undefined ? Value : Value extends readonly (infer Item)[] ? Matcher<Item> : Value extends (...args: never[]) => unknown ? never : Value extends object ? {
2
+ readonly [Key in keyof Value]?: Matcher<Value[Key]>;
3
+ } : Value;
4
+ export type SentMatcher = string | number | boolean | null | {
5
+ readonly regexp: string;
6
+ readonly flags: string;
7
+ } | {
8
+ readonly [key: string]: SentMatcher;
9
+ } | readonly SentMatcher[];
10
+ export declare function matches(value: unknown, matcher: unknown): boolean;
11
+ export declare function sentMatcher(matcher: unknown): SentMatcher;
12
+ export declare function receivedMatcher(sent: SentMatcher): unknown;
13
+ //# sourceMappingURL=matcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matcher.d.ts","sourceRoot":"","sources":["../src/utils/matcher.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,OAAO,CAAC,KAAK,IAAI,KAAK,SAAS,MAAM,GAC7C,MAAM,GAAG,MAAM,GACf,KAAK,SAAS,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG,SAAS,GAC/C,KAAK,GACL,KAAK,SAAS,SAAS,CAAC,MAAM,IAAI,CAAC,EAAE,GACnC,OAAO,CAAC,IAAI,CAAC,GACb,KAAK,SAAS,CAAC,GAAG,IAAI,EAAE,KAAK,EAAE,KAAK,OAAO,GACzC,KAAK,GACL,KAAK,SAAS,MAAM,GAClB;IAAE,QAAQ,EAAE,GAAG,IAAI,MAAM,KAAK,CAAC,CAAC,EAAE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;CAAE,GACvD,KAAK,CAAA;AAEjB,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,IAAI,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,WAAW,CAAA;CAAE,GAAG,SAAS,WAAW,EAAE,CAAA;AAEnL,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAOjE;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,OAAO,GAAG,WAAW,CAKzD;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAM1D"}
@@ -0,0 +1,32 @@
1
+ export function matches(value, matcher) {
2
+ if (matcher instanceof RegExp)
3
+ return matcher.test(String(value));
4
+ if (Array.isArray(matcher))
5
+ return matcher.some((each) => matches(value, each));
6
+ if (typeof matcher !== 'object' || matcher === null)
7
+ return value === matcher;
8
+ if (Array.isArray(value))
9
+ return value.some((each) => matches(each, matcher));
10
+ if (typeof value !== 'object' || value === null)
11
+ return false;
12
+ return Object.entries(matcher).every(([key, wanted]) => wanted === undefined || matches(value[key], wanted));
13
+ }
14
+ export function sentMatcher(matcher) {
15
+ if (matcher instanceof RegExp)
16
+ return { regexp: matcher.source, flags: matcher.flags };
17
+ if (Array.isArray(matcher))
18
+ return matcher.map(sentMatcher);
19
+ if (typeof matcher !== 'object' || matcher === null)
20
+ return matcher;
21
+ return Object.fromEntries(Object.entries(matcher).filter(([, value]) => value !== undefined).map(([key, value]) => [key, sentMatcher(value)]));
22
+ }
23
+ export function receivedMatcher(sent) {
24
+ if (Array.isArray(sent))
25
+ return sent.map(receivedMatcher);
26
+ if (typeof sent !== 'object' || sent === null)
27
+ return sent;
28
+ const fields = sent;
29
+ if (typeof fields['regexp'] === 'string' && typeof fields['flags'] === 'string' && Object.keys(fields).length === 2)
30
+ return new RegExp(fields['regexp'], fields['flags']);
31
+ return Object.fromEntries(Object.entries(fields).map(([key, value]) => [key, receivedMatcher(value)]));
32
+ }
@@ -1,10 +1,10 @@
1
1
  export type MetadataFormat = {
2
- readonly kind: 'frontmatter';
2
+ readonly type: 'frontmatter';
3
3
  } | {
4
- readonly kind: 'comment';
4
+ readonly type: 'comment';
5
5
  readonly prefix: string;
6
6
  } | {
7
- readonly kind: 'sidecar';
7
+ readonly type: 'sidecar';
8
8
  };
9
9
  export type ReadMetadata = {
10
10
  readonly metadata: Readonly<Record<string, string>>;
package/utils/metadata.js CHANGED
@@ -16,34 +16,34 @@ export function formatOf(path, firstLine) {
16
16
  const dot = name.lastIndexOf('.');
17
17
  const extension = dot <= 0 ? '' : name.slice(dot + 1).toLowerCase();
18
18
  if (markdown.includes(extension))
19
- return { kind: 'frontmatter' };
19
+ return { type: 'frontmatter' };
20
20
  if (hashComments.includes(extension) || hashCommentNames.includes(name))
21
- return { kind: 'comment', prefix: '#' };
21
+ return { type: 'comment', prefix: '#' };
22
22
  if (slashComments.includes(extension))
23
- return { kind: 'comment', prefix: '//' };
23
+ return { type: 'comment', prefix: '//' };
24
24
  if (dashComments.includes(extension))
25
- return { kind: 'comment', prefix: '--' };
25
+ return { type: 'comment', prefix: '--' };
26
26
  if (extension === '' && firstLine?.startsWith('#!') === true)
27
- return { kind: 'comment', prefix: '#' };
28
- return { kind: 'sidecar' };
27
+ return { type: 'comment', prefix: '#' };
28
+ return { type: 'sidecar' };
29
29
  }
30
30
  export function readMetadata(text, format) {
31
31
  const lines = text.split('\n');
32
- if (format.kind === 'comment') {
32
+ if (format.type === 'comment') {
33
33
  const region = commentRegion(lines, format.prefix);
34
34
  return { metadata: region === undefined ? {} : asRecord(mapEntries(region.lines, region.start + 2, 0)) };
35
35
  }
36
- const region = format.kind === 'frontmatter' ? frontmatterRegion(lines) : { start: -1, end: lines.length, lines };
36
+ const region = format.type === 'frontmatter' ? frontmatterRegion(lines) : { start: -1, end: lines.length, lines };
37
37
  if (region === undefined)
38
38
  return { metadata: {} };
39
39
  const block = metadataBlock(region);
40
- const name = format.kind === 'frontmatter' ? topLevelScalar(region, 'name') : undefined;
40
+ const name = format.type === 'frontmatter' ? topLevelScalar(region, 'name') : undefined;
41
41
  return { metadata: block === undefined ? {} : asRecord(block.entries), ...(name === undefined ? {} : { name }) };
42
42
  }
43
43
  export function writeMetadata(text, format, metadata) {
44
44
  const lines = text.split('\n');
45
45
  const entries = Object.entries(metadata);
46
- if (format.kind === 'comment') {
46
+ if (format.type === 'comment') {
47
47
  const { prefix } = format;
48
48
  const block = entries.length === 0 ? [] : [`${prefix} /// metadata`, ...entries.map(([key, value]) => `${prefix} ${scalar(key)}: ${scalar(value)}`), `${prefix} ///`];
49
49
  const region = commentRegion(lines, prefix);
@@ -55,7 +55,7 @@ export function writeMetadata(text, format, metadata) {
55
55
  return [...lines.slice(0, at), ...block, ...lines.slice(at)].join('\n');
56
56
  }
57
57
  const map = entries.length === 0 ? [] : ['metadata:', ...entries.map(([key, value]) => ` ${scalar(key)}: ${scalar(value)}`)];
58
- if (format.kind === 'sidecar') {
58
+ if (format.type === 'sidecar') {
59
59
  const block = metadataBlock({ start: -1, end: lines.length, lines });
60
60
  const rest = block === undefined ? lines : [...lines.slice(0, block.start), ...lines.slice(block.end)];
61
61
  const kept = rest.join('\n').trim();
@@ -214,7 +214,9 @@ function unquoted(text, lineNumber) {
214
214
  try {
215
215
  return JSON.parse(text);
216
216
  }
217
- catch {
217
+ catch (error) {
218
+ if (!(error instanceof SyntaxError))
219
+ throw error;
218
220
  throw new MetadataError(lineNumber, `${text} is not a double-quoted text. Escape a " inside it as \\".`);
219
221
  }
220
222
  }
@@ -235,8 +237,10 @@ function topLevelScalar(region, key) {
235
237
  try {
236
238
  return unquoted(text, region.start + 2 + at);
237
239
  }
238
- catch {
239
- return undefined;
240
+ catch (error) {
241
+ if (error instanceof MetadataError)
242
+ return undefined;
243
+ throw error;
240
244
  }
241
245
  }
242
246
  function asRecord(entries) {
@@ -1,6 +1,7 @@
1
1
  export type ShellCommand = {
2
2
  argv: [string, ...string[]];
3
3
  folder: string;
4
+ input?: number;
4
5
  };
5
6
  export type ParsedShell = {
6
7
  commands: ShellCommand[];
@@ -1 +1 @@
1
- {"version":3,"file":"parse-shell.d.ts","sourceRoot":"","sources":["../src/utils/parse-shell.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,YAAY,GAAG;IAAE,IAAI,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAE1E,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,YAAY,EAAE,CAAA;IACxB,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,aAAa,EAAE,OAAO,CAAA;CACvB,CAAA;AA2BD,eAAO,MAAM,cAAc,QAAS,CAAA;AAiKpC,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAIpD"}
1
+ {"version":3,"file":"parse-shell.d.ts","sourceRoot":"","sources":["../src/utils/parse-shell.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,YAAY,GAAG;IAAE,IAAI,EAAE,CAAC,MAAM,EAAE,GAAG,MAAM,EAAE,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAE1F,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,YAAY,EAAE,CAAA;IACxB,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,KAAK,EAAE,MAAM,EAAE,CAAA;IACf,OAAO,EAAE,MAAM,EAAE,CAAA;IACjB,aAAa,EAAE,OAAO,CAAA;CACvB,CAAA;AA4BD,eAAO,MAAM,cAAc,QAAS,CAAA;AAiKpC,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAIpD"}
@@ -175,7 +175,9 @@ function parseLine(line, folder, result) {
175
175
  const { text, markers } = scan(line, 0, false);
176
176
  walk(parse(text, (name) => (name === '' ? undefined : `$${name}`)), markers, folder, result);
177
177
  }
178
- catch {
178
+ catch (error) {
179
+ if (!(error instanceof SyntaxError) && !(error instanceof Error && error.message.startsWith('Bad substitution: ')))
180
+ throw error;
179
181
  result.isFullyParsed = false;
180
182
  }
181
183
  }
@@ -453,7 +455,7 @@ function readHeredocBodies(source, from, heredocs) {
453
455
  function walk(tokens, markers, start, result) {
454
456
  let folder = start;
455
457
  const subshells = [];
456
- let command = newCommand(false);
458
+ let command = newCommand(undefined);
457
459
  let caseState;
458
460
  for (let index = 0; index < tokens.length; index += 1) {
459
461
  const token = tokens[index];
@@ -492,12 +494,14 @@ function walk(tokens, markers, start, result) {
492
494
  }
493
495
  const following = tokens[index + 1];
494
496
  if (operator === '(' && command.words.length === 1 && following !== undefined && !isWordToken(following) && 'op' in following && following.op === ')') {
495
- command = newCommand(false);
497
+ command = newCommand(undefined);
496
498
  index += 1;
497
499
  continue;
498
500
  }
501
+ const before = result.commands.length;
499
502
  folder = finish(command, operator, folder, result);
500
- command = newCommand(operator === '|' || operator === '|&');
503
+ const writer = result.commands.length > before ? result.commands.length - 1 : undefined;
504
+ command = newCommand(operator === '|' || operator === '|&' ? { writer } : undefined);
501
505
  if (operator === '(')
502
506
  subshells.push(folder);
503
507
  else if (operator === ')') {
@@ -513,8 +517,8 @@ function walk(tokens, markers, start, result) {
513
517
  }
514
518
  finish(command, ';', folder, result);
515
519
  }
516
- function newCommand(isPipedIn) {
517
- return { words: [], redirects: [], isPipedIn };
520
+ function newCommand(pipe) {
521
+ return { words: [], redirects: [], pipe };
518
522
  }
519
523
  function isWordToken(token) {
520
524
  return typeof token === 'string' || ('op' in token && token.op === 'glob');
@@ -539,9 +543,14 @@ function finish(command, operator, folder, result) {
539
543
  if (first === undefined || first.text === 'for' || first.text === 'select')
540
544
  return folder;
541
545
  const here = command.redirects.findLast((redirect) => redirect.operator === '<<<');
542
- const stdin = here !== undefined ? { kind: 'text', text: here.target.text } : command.isPipedIn ? { kind: 'pipe' } : undefined;
546
+ const stdin = here !== undefined ? { type: 'text', text: here.target.text } : command.pipe !== undefined ? { type: 'pipe' } : undefined;
547
+ const reader = result.commands.length;
543
548
  const changed = addCommand(first, args, folder, stdin, result);
544
- const isPiped = command.isPipedIn || operator === '|' || operator === '|&' || operator === '&';
549
+ const read = result.commands[reader];
550
+ const writer = command.pipe?.writer;
551
+ if (read !== undefined && writer !== undefined && here === undefined)
552
+ result.commands[reader] = { ...read, input: writer };
553
+ const isPiped = command.pipe !== undefined || operator === '|' || operator === '|&' || operator === '&';
545
554
  return changed === undefined || isPiped ? folder : changed;
546
555
  }
547
556
  function withoutPrefixes(words) {
@@ -628,7 +637,7 @@ function findStarts(args) {
628
637
  }
629
638
  function addWrapper(first, program, args, folder, stdin, result) {
630
639
  const wrapper = wrappers.get(program);
631
- if (program === 'xargs' && stdin?.kind !== 'text')
640
+ if (program === 'xargs' && stdin?.type !== 'text')
632
641
  result.isFullyParsed = false;
633
642
  const { options, operands } = readArguments(args, wrapper, true);
634
643
  let start = args.length - operands.length;
@@ -684,8 +693,8 @@ function addEffects(program, args, flags, folder, stdin, result) {
684
693
  if (program === 'perl' && readArguments(args, perl, false).options.some((option) => option.name === '-i'))
685
694
  addFileArguments(perl, args, folder, result);
686
695
  const script = args.find((word) => !word.text.startsWith('-') || word.text === '-');
687
- const readsCodeFromPipe = stdin?.kind === 'pipe' && (script === undefined || script.text === '-');
688
- if (flags.some((flag) => inlineFlags.includes(flag)) || stdin?.kind === 'text' || readsCodeFromPipe)
696
+ const readsCodeFromPipe = stdin?.type === 'pipe' && (script === undefined || script.text === '-');
697
+ if (flags.some((flag) => inlineFlags.includes(flag)) || stdin?.type === 'text' || readsCodeFromPipe)
689
698
  result.isFullyParsed = false;
690
699
  }
691
700
  }
@@ -719,9 +728,9 @@ function addFetches(fetcher, args, result) {
719
728
  result.fetches.push(/^[a-z][a-z0-9+.-]*:\/\//i.test(url.text) ? url.text : `http://${url.text}`);
720
729
  }
721
730
  function addStdinCode(stdin, folder, result) {
722
- if (stdin?.kind === 'text')
731
+ if (stdin?.type === 'text')
723
732
  parseLine(stdin.text, folder, result);
724
- if (stdin?.kind === 'pipe')
733
+ if (stdin?.type === 'pipe')
725
734
  result.isFullyParsed = false;
726
735
  }
727
736
  function addCopy(program, args, folder, result) {
package/utils/paths.d.ts CHANGED
@@ -1,3 +1,5 @@
1
+ export declare function isMissing(error: unknown): boolean;
2
+ export declare function ifMissing<Value>(value: Value): (error: unknown) => Value;
1
3
  export type FileSystem = {
2
4
  read: (path: string) => Promise<string>;
3
5
  stat: (path: string) => Promise<{
@@ -1 +1 @@
1
- {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/utils/paths.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IACvC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACtF,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CAC3C,CAAA;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAI3E;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAK1F"}
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/utils/paths.ts"],"names":[],"mappings":"AAKA,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAEjD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,GAAG,CAAC,KAAK,EAAE,OAAO,KAAK,KAAK,CAKxE;AAED,MAAM,MAAM,UAAU,GAAG;IACvB,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAA;IACvC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,OAAO,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACtF,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAA;CAC3C,CAAA;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAG7D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAI3E;AAED,wBAAsB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAK1F"}
package/utils/paths.js CHANGED
@@ -1,4 +1,16 @@
1
1
  import { basename, dirname, resolve } from '../vendor.js';
2
+ import { messageOf } from './text.js';
3
+ const missingPath = /(?:^|: )(?:ENOENT|ENOTDIR)\b/;
4
+ export function isMissing(error) {
5
+ return missingPath.test(messageOf(error));
6
+ }
7
+ export function ifMissing(value) {
8
+ return (error) => {
9
+ if (isMissing(error))
10
+ return value;
11
+ throw error;
12
+ };
13
+ }
2
14
  export function expandHome(path, home) {
3
15
  const prefix = /^(~|\$HOME)(?=\/|$)/.exec(path)?.[0];
4
16
  return prefix === undefined ? path : `${home}${path.slice(prefix.length)}`;
@@ -10,7 +22,7 @@ export function relativePath(base, path) {
10
22
  return path.startsWith(prefix) ? path.slice(prefix.length) : undefined;
11
23
  }
12
24
  export async function realPathOf(path, fs) {
13
- const stat = await fs.stat(path).catch(() => undefined);
25
+ const stat = await fs.stat(path).catch(ifMissing(undefined));
14
26
  if (stat !== undefined || path === '/')
15
27
  return stat?.realPath;
16
28
  const folder = await realPathOf(dirname(path), fs);
package/utils/text.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export declare function listed(items: readonly string[]): string;
2
+ export declare function firstLine(text: string): string;
2
3
  export declare function messageOf(error: unknown): string;
3
4
  export declare function formatExit(code: number | null, reason: string): string;
4
5
  //# sourceMappingURL=text.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../src/utils/text.ts"],"names":[],"mappings":"AAAA,wBAAgB,MAAM,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAGvD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEhD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAItE"}
1
+ {"version":3,"file":"text.d.ts","sourceRoot":"","sources":["../src/utils/text.ts"],"names":[],"mappings":"AAAA,wBAAgB,MAAM,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAGvD;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9C;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAEhD;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAItE"}
package/utils/text.js CHANGED
@@ -3,6 +3,9 @@ export function listed(items) {
3
3
  return items.join('');
4
4
  return `${items.slice(0, -1).join(', ')} and ${items.at(-1)}`;
5
5
  }
6
+ export function firstLine(text) {
7
+ return text.split('\n').find((line) => line.trim() !== '')?.trim() ?? '';
8
+ }
6
9
  export function messageOf(error) {
7
10
  return error instanceof Error ? error.message : String(error);
8
11
  }
package/src/ui/slots.ts DELETED
@@ -1,36 +0,0 @@
1
- import type { Frozen, RenderComponent, RenderElement, RenderPropsOf } from 'claude-code'
2
- import type { MarkdownKind } from './markdown.js'
3
-
4
- declare const props: unique symbol
5
-
6
- declare const defaultProps: unique symbol
7
-
8
- type Place = { readonly component: RenderComponent } | { readonly markdown: MarkdownKind }
9
-
10
- export type Slot<Props extends object = object, DefaultProps extends object = object, Where extends Place = Place> = Where & {
11
- readonly [props]: Props
12
- readonly [defaultProps]: DefaultProps
13
- }
14
-
15
- export type SlotProps<S extends Slot> = Frozen<S[typeof props]> & { readonly Default: (props: Frozen<S[typeof defaultProps]>) => RenderElement }
16
-
17
- function slot<Component extends Exclude<RenderComponent, 'Pane'>>(component: Component): Slot<RenderPropsOf[Component], Partial<Omit<RenderPropsOf[Component], 'onScreen'>>, { readonly component: Component }> {
18
- return { component } as Slot<RenderPropsOf[Component], Partial<Omit<RenderPropsOf[Component], 'onScreen'>>, { readonly component: Component }>
19
- }
20
-
21
- export const slots = {
22
- AssistantMessage: slot('AssistantMessage'),
23
- UserMessage: slot('UserMessage'),
24
- ToolUse: slot('ToolUse'),
25
- ToolResult: slot('ToolResult'),
26
- ToolGroup: slot('ToolGroup'),
27
- ToolProgress: slot('ToolProgress'),
28
- CommandOutput: slot('CommandOutput'),
29
- AskUserQuestion: slot('AskUserQuestion'),
30
- InfoNotice: slot('InfoNotice'),
31
- Spinner: slot('Spinner'),
32
- TurnDuration: slot('TurnDuration'),
33
- SessionMode: slot('SessionMode'),
34
- PromptHint: slot('PromptHint'),
35
- AbovePrompt: slot('AbovePrompt'),
36
- }