larkup 0.1.39 → 0.1.41

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 (248) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/build-manifest.json +3 -3
  3. package/.next/diagnostics/route-bundle-stats.json +22 -21
  4. package/.next/fallback-build-manifest.json +3 -3
  5. package/.next/required-server-files.js +1 -1
  6. package/.next/required-server-files.json +1 -1
  7. package/.next/server/app/_global-error.html +1 -1
  8. package/.next/server/app/_global-error.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  14. package/.next/server/app/_not-found/page.js.nft.json +1 -1
  15. package/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  16. package/.next/server/app/_not-found.html +1 -1
  17. package/.next/server/app/_not-found.rsc +18 -18
  18. package/.next/server/app/_not-found.segments/_full.segment.rsc +18 -18
  19. package/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  20. package/.next/server/app/_not-found.segments/_index.segment.rsc +12 -12
  21. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  22. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  23. package/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  24. package/.next/server/app/analytics/page.js.nft.json +1 -1
  25. package/.next/server/app/analytics/page_client-reference-manifest.js +1 -1
  26. package/.next/server/app/analytics.html +1 -1
  27. package/.next/server/app/analytics.rsc +19 -19
  28. package/.next/server/app/analytics.segments/_full.segment.rsc +19 -19
  29. package/.next/server/app/analytics.segments/_head.segment.rsc +4 -4
  30. package/.next/server/app/analytics.segments/_index.segment.rsc +12 -12
  31. package/.next/server/app/analytics.segments/_tree.segment.rsc +2 -2
  32. package/.next/server/app/analytics.segments/analytics/__PAGE__.segment.rsc +3 -3
  33. package/.next/server/app/analytics.segments/analytics.segment.rsc +3 -3
  34. package/.next/server/app/chat/page.js.nft.json +1 -1
  35. package/.next/server/app/chat/page_client-reference-manifest.js +1 -1
  36. package/.next/server/app/chat.html +1 -1
  37. package/.next/server/app/chat.rsc +19 -19
  38. package/.next/server/app/chat.segments/_full.segment.rsc +19 -19
  39. package/.next/server/app/chat.segments/_head.segment.rsc +4 -4
  40. package/.next/server/app/chat.segments/_index.segment.rsc +12 -12
  41. package/.next/server/app/chat.segments/_tree.segment.rsc +2 -2
  42. package/.next/server/app/chat.segments/chat/__PAGE__.segment.rsc +3 -3
  43. package/.next/server/app/chat.segments/chat.segment.rsc +3 -3
  44. package/.next/server/app/data/page.js.nft.json +1 -1
  45. package/.next/server/app/data/page_client-reference-manifest.js +1 -1
  46. package/.next/server/app/data.html +1 -1
  47. package/.next/server/app/data.rsc +25 -26
  48. package/.next/server/app/data.segments/_full.segment.rsc +25 -26
  49. package/.next/server/app/data.segments/_head.segment.rsc +4 -4
  50. package/.next/server/app/data.segments/_index.segment.rsc +12 -12
  51. package/.next/server/app/data.segments/_tree.segment.rsc +2 -2
  52. package/.next/server/app/data.segments/data/__PAGE__.segment.rsc +3 -3
  53. package/.next/server/app/data.segments/data.segment.rsc +3 -3
  54. package/.next/server/app/index.html +1 -1
  55. package/.next/server/app/index.rsc +17 -17
  56. package/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  57. package/.next/server/app/index.segments/_full.segment.rsc +17 -17
  58. package/.next/server/app/index.segments/_head.segment.rsc +4 -4
  59. package/.next/server/app/index.segments/_index.segment.rsc +12 -12
  60. package/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  61. package/.next/server/app/page.js.nft.json +1 -1
  62. package/.next/server/app/page_client-reference-manifest.js +1 -1
  63. package/.next/server/app/settings/page.js.nft.json +1 -1
  64. package/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  65. package/.next/server/app/settings.html +1 -1
  66. package/.next/server/app/settings.rsc +19 -19
  67. package/.next/server/app/settings.segments/_full.segment.rsc +19 -19
  68. package/.next/server/app/settings.segments/_head.segment.rsc +4 -4
  69. package/.next/server/app/settings.segments/_index.segment.rsc +12 -12
  70. package/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  71. package/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
  72. package/.next/server/app/settings.segments/settings.segment.rsc +3 -3
  73. package/.next/server/chunks/0598_next_dist_esm_build_templates_app-route_0kbcuk-.js +8 -7
  74. package/.next/server/chunks/0598_next_dist_esm_build_templates_app-route_0sbf4ny.js +2 -2
  75. package/.next/server/chunks/[root-of-the-server]__0j2l54r._.js +1 -1
  76. package/.next/server/chunks/packages_scraper_src_0kkcv_v._.js +1 -1
  77. package/.next/server/chunks/ssr/{[root-of-the-server]__0m21fli._.js → [root-of-the-server]__0pgotbk._.js} +2 -2
  78. package/.next/server/chunks/ssr/[root-of-the-server]__1k1mxo2._.js +3 -0
  79. package/.next/server/chunks/ssr/_169pdlf._.js +5 -5
  80. package/.next/server/chunks/ssr/_18jagqc._.js +2 -2
  81. package/.next/server/chunks/ssr/_1hetwwu._.js +2 -2
  82. package/.next/{standalone/apps/web/.next/server/chunks/ssr/_0s8403d._.js → server/chunks/ssr/_1p6lb7s._.js} +2 -2
  83. package/.next/server/chunks/ssr/_1yqlx1m._.js +1 -1
  84. package/.next/server/chunks/ssr/apps_web_components_analytics_analytics-dashboard_tsx_1056-z3._.js +1 -1
  85. package/.next/server/middleware-build-manifest.js +3 -3
  86. package/.next/server/pages/404.html +1 -1
  87. package/.next/server/pages/500.html +1 -1
  88. package/.next/standalone/apps/web/.next/BUILD_ID +1 -1
  89. package/.next/standalone/apps/web/.next/build-manifest.json +3 -3
  90. package/.next/standalone/apps/web/.next/required-server-files.json +1 -1
  91. package/.next/standalone/apps/web/.next/server/app/_global-error.html +1 -1
  92. package/.next/standalone/apps/web/.next/server/app/_global-error.rsc +1 -1
  93. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  94. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  95. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  96. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  97. package/.next/standalone/apps/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  98. package/.next/standalone/apps/web/.next/server/app/_not-found/page.js.nft.json +1 -1
  99. package/.next/standalone/apps/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  100. package/.next/standalone/apps/web/.next/server/app/_not-found.html +1 -1
  101. package/.next/standalone/apps/web/.next/server/app/_not-found.rsc +18 -18
  102. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_full.segment.rsc +18 -18
  103. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_head.segment.rsc +4 -4
  104. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_index.segment.rsc +12 -12
  105. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  106. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_not-found.segment.rsc +3 -3
  107. package/.next/standalone/apps/web/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  108. package/.next/standalone/apps/web/.next/server/app/analytics/page.js.nft.json +1 -1
  109. package/.next/standalone/apps/web/.next/server/app/analytics/page_client-reference-manifest.js +1 -1
  110. package/.next/standalone/apps/web/.next/server/app/analytics.html +1 -1
  111. package/.next/standalone/apps/web/.next/server/app/analytics.rsc +19 -19
  112. package/.next/standalone/apps/web/.next/server/app/analytics.segments/_full.segment.rsc +19 -19
  113. package/.next/standalone/apps/web/.next/server/app/analytics.segments/_head.segment.rsc +4 -4
  114. package/.next/standalone/apps/web/.next/server/app/analytics.segments/_index.segment.rsc +12 -12
  115. package/.next/standalone/apps/web/.next/server/app/analytics.segments/_tree.segment.rsc +2 -2
  116. package/.next/standalone/apps/web/.next/server/app/analytics.segments/analytics/__PAGE__.segment.rsc +3 -3
  117. package/.next/standalone/apps/web/.next/server/app/analytics.segments/analytics.segment.rsc +3 -3
  118. package/.next/standalone/apps/web/.next/server/app/chat/page.js.nft.json +1 -1
  119. package/.next/standalone/apps/web/.next/server/app/chat/page_client-reference-manifest.js +1 -1
  120. package/.next/standalone/apps/web/.next/server/app/chat.html +1 -1
  121. package/.next/standalone/apps/web/.next/server/app/chat.rsc +19 -19
  122. package/.next/standalone/apps/web/.next/server/app/chat.segments/_full.segment.rsc +19 -19
  123. package/.next/standalone/apps/web/.next/server/app/chat.segments/_head.segment.rsc +4 -4
  124. package/.next/standalone/apps/web/.next/server/app/chat.segments/_index.segment.rsc +12 -12
  125. package/.next/standalone/apps/web/.next/server/app/chat.segments/_tree.segment.rsc +2 -2
  126. package/.next/standalone/apps/web/.next/server/app/chat.segments/chat/__PAGE__.segment.rsc +3 -3
  127. package/.next/standalone/apps/web/.next/server/app/chat.segments/chat.segment.rsc +3 -3
  128. package/.next/standalone/apps/web/.next/server/app/data/page.js.nft.json +1 -1
  129. package/.next/standalone/apps/web/.next/server/app/data/page_client-reference-manifest.js +1 -1
  130. package/.next/standalone/apps/web/.next/server/app/data.html +1 -1
  131. package/.next/standalone/apps/web/.next/server/app/data.rsc +25 -26
  132. package/.next/standalone/apps/web/.next/server/app/data.segments/_full.segment.rsc +25 -26
  133. package/.next/standalone/apps/web/.next/server/app/data.segments/_head.segment.rsc +4 -4
  134. package/.next/standalone/apps/web/.next/server/app/data.segments/_index.segment.rsc +12 -12
  135. package/.next/standalone/apps/web/.next/server/app/data.segments/_tree.segment.rsc +2 -2
  136. package/.next/standalone/apps/web/.next/server/app/data.segments/data/__PAGE__.segment.rsc +3 -3
  137. package/.next/standalone/apps/web/.next/server/app/data.segments/data.segment.rsc +3 -3
  138. package/.next/standalone/apps/web/.next/server/app/index.html +1 -1
  139. package/.next/standalone/apps/web/.next/server/app/index.rsc +17 -17
  140. package/.next/standalone/apps/web/.next/server/app/index.segments/__PAGE__.segment.rsc +2 -2
  141. package/.next/standalone/apps/web/.next/server/app/index.segments/_full.segment.rsc +17 -17
  142. package/.next/standalone/apps/web/.next/server/app/index.segments/_head.segment.rsc +4 -4
  143. package/.next/standalone/apps/web/.next/server/app/index.segments/_index.segment.rsc +12 -12
  144. package/.next/standalone/apps/web/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  145. package/.next/standalone/apps/web/.next/server/app/page.js.nft.json +1 -1
  146. package/.next/standalone/apps/web/.next/server/app/page_client-reference-manifest.js +1 -1
  147. package/.next/standalone/apps/web/.next/server/app/settings/page.js.nft.json +1 -1
  148. package/.next/standalone/apps/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  149. package/.next/standalone/apps/web/.next/server/app/settings.html +1 -1
  150. package/.next/standalone/apps/web/.next/server/app/settings.rsc +19 -19
  151. package/.next/standalone/apps/web/.next/server/app/settings.segments/_full.segment.rsc +19 -19
  152. package/.next/standalone/apps/web/.next/server/app/settings.segments/_head.segment.rsc +4 -4
  153. package/.next/standalone/apps/web/.next/server/app/settings.segments/_index.segment.rsc +12 -12
  154. package/.next/standalone/apps/web/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  155. package/.next/standalone/apps/web/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +4 -4
  156. package/.next/standalone/apps/web/.next/server/app/settings.segments/settings.segment.rsc +3 -3
  157. package/.next/standalone/apps/web/.next/server/chunks/0598_next_dist_esm_build_templates_app-route_0kbcuk-.js +8 -7
  158. package/.next/standalone/apps/web/.next/server/chunks/0598_next_dist_esm_build_templates_app-route_0sbf4ny.js +2 -2
  159. package/.next/standalone/apps/web/.next/server/chunks/[root-of-the-server]__0j2l54r._.js +1 -1
  160. package/.next/standalone/apps/web/.next/server/chunks/packages_scraper_src_0kkcv_v._.js +1 -1
  161. package/.next/standalone/apps/web/.next/server/chunks/ssr/{[root-of-the-server]__0m21fli._.js → [root-of-the-server]__0pgotbk._.js} +2 -2
  162. package/.next/standalone/apps/web/.next/server/chunks/ssr/[root-of-the-server]__1k1mxo2._.js +3 -0
  163. package/.next/standalone/apps/web/.next/server/chunks/ssr/_169pdlf._.js +5 -5
  164. package/.next/standalone/apps/web/.next/server/chunks/ssr/_18jagqc._.js +2 -2
  165. package/.next/standalone/apps/web/.next/server/chunks/ssr/_1hetwwu._.js +2 -2
  166. package/.next/{server/chunks/ssr/_0s8403d._.js → standalone/apps/web/.next/server/chunks/ssr/_1p6lb7s._.js} +2 -2
  167. package/.next/standalone/apps/web/.next/server/chunks/ssr/_1yqlx1m._.js +1 -1
  168. package/.next/standalone/apps/web/.next/server/chunks/ssr/apps_web_components_analytics_analytics-dashboard_tsx_1056-z3._.js +1 -1
  169. package/.next/standalone/apps/web/.next/server/middleware-build-manifest.js +3 -3
  170. package/.next/standalone/apps/web/.next/server/pages/404.html +1 -1
  171. package/.next/standalone/apps/web/.next/server/pages/500.html +1 -1
  172. package/.next/standalone/apps/web/.next/static/chunks/0f_k7h1yraes3.js +1 -0
  173. package/.next/standalone/apps/web/.next/static/chunks/1j_-mc43_9-b3.js +121 -0
  174. package/.next/standalone/apps/web/.next/static/chunks/23efo4rpc31kr.js +1 -0
  175. package/.next/standalone/apps/web/.next/static/chunks/2dvtyg2k2op4x.js +11 -0
  176. package/.next/standalone/apps/web/.next/static/chunks/{2ljwki2xxnblc.js → 2h-80z3n8mi3d.js} +7 -7
  177. package/.next/{static/chunks/1ov69q-i9ybqi.js → standalone/apps/web/.next/static/chunks/2x1t8sqst0ipu.js} +1 -1
  178. package/.next/standalone/apps/web/.next/static/chunks/37j20in7beze4.js +1 -0
  179. package/.next/standalone/apps/web/.next/static/chunks/{1cxabi5yzqz57.js → 38f3p67a1uufx.js} +1 -1
  180. package/.next/standalone/apps/web/.next/static/chunks/3fe06cefiv690.css +1 -0
  181. package/.next/standalone/apps/web/CHANGELOG.md +21 -0
  182. package/.next/standalone/apps/web/app/api/chat/route.ts +34 -13
  183. package/.next/standalone/apps/web/app/api/chat/tools.ts +10 -1
  184. package/.next/standalone/apps/web/app/api/media/process/route.ts +34 -1
  185. package/.next/standalone/apps/web/app/settings/page.tsx +16 -5
  186. package/.next/standalone/apps/web/bin/larkup.js +12 -1
  187. package/.next/standalone/apps/web/components/chat/message-item.tsx +68 -3
  188. package/.next/standalone/apps/web/components/data/data-workspace.tsx +53 -120
  189. package/.next/standalone/apps/web/components/data/firecrawl-notice.tsx +3 -13
  190. package/.next/standalone/apps/web/components/data/media-panel.tsx +182 -25
  191. package/.next/standalone/apps/web/components/data/scrape-panel.tsx +4 -12
  192. package/.next/standalone/apps/web/components/data/upload-panel.tsx +0 -1
  193. package/.next/standalone/apps/web/components/index/index-workspace.tsx +48 -25
  194. package/.next/standalone/apps/web/components/settings/marketplace-section.tsx +1 -1
  195. package/.next/standalone/apps/web/components/settings/settings-layout.tsx +1 -2
  196. package/.next/standalone/apps/web/package.json +1 -1
  197. package/.next/standalone/apps/web/server.js +1 -1
  198. package/.next/standalone/packages/tools/doc-editor/CHANGELOG.md +7 -0
  199. package/.next/standalone/packages/tools/doc-editor/dist/editor.js +1 -15
  200. package/.next/standalone/packages/tools/doc-editor/package.json +1 -1
  201. package/.next/standalone/packages/tools/doc-editor/src/editor.ts +1 -15
  202. package/.next/standalone/packages/tools/video-audio/CHANGELOG.md +6 -0
  203. package/.next/standalone/packages/tools/video-audio/dist/url-importer.js +37 -5
  204. package/.next/standalone/packages/tools/video-audio/package.json +1 -1
  205. package/.next/standalone/packages/tools/video-audio/src/url-importer.ts +61 -25
  206. package/.next/static/chunks/0f_k7h1yraes3.js +1 -0
  207. package/.next/static/chunks/1j_-mc43_9-b3.js +121 -0
  208. package/.next/static/chunks/23efo4rpc31kr.js +1 -0
  209. package/.next/static/chunks/2dvtyg2k2op4x.js +11 -0
  210. package/.next/static/chunks/{2ljwki2xxnblc.js → 2h-80z3n8mi3d.js} +7 -7
  211. package/.next/{standalone/apps/web/.next/static/chunks/1ov69q-i9ybqi.js → static/chunks/2x1t8sqst0ipu.js} +1 -1
  212. package/.next/static/chunks/37j20in7beze4.js +1 -0
  213. package/.next/static/chunks/{1cxabi5yzqz57.js → 38f3p67a1uufx.js} +1 -1
  214. package/.next/static/chunks/3fe06cefiv690.css +1 -0
  215. package/CHANGELOG.md +21 -0
  216. package/app/api/chat/route.ts +34 -13
  217. package/app/api/chat/tools.ts +10 -1
  218. package/app/api/media/process/route.ts +34 -1
  219. package/app/settings/page.tsx +16 -5
  220. package/bin/larkup.js +12 -1
  221. package/components/chat/message-item.tsx +68 -3
  222. package/components/data/data-workspace.tsx +53 -120
  223. package/components/data/firecrawl-notice.tsx +3 -13
  224. package/components/data/media-panel.tsx +182 -25
  225. package/components/data/scrape-panel.tsx +4 -12
  226. package/components/data/upload-panel.tsx +0 -1
  227. package/components/index/index-workspace.tsx +48 -25
  228. package/components/settings/marketplace-section.tsx +1 -1
  229. package/components/settings/settings-layout.tsx +1 -2
  230. package/package.json +6 -6
  231. package/.next/server/chunks/ssr/[root-of-the-server]__0t8ud_u._.js +0 -3
  232. package/.next/standalone/apps/web/.next/server/chunks/ssr/[root-of-the-server]__0t8ud_u._.js +0 -3
  233. package/.next/standalone/apps/web/.next/static/chunks/03ju_837pa9ul.js +0 -11
  234. package/.next/standalone/apps/web/.next/static/chunks/0ge3nirnmx_np.js +0 -1
  235. package/.next/standalone/apps/web/.next/static/chunks/19krxv-ou9c8c.js +0 -121
  236. package/.next/standalone/apps/web/.next/static/chunks/1_nk3imchwn8a.css +0 -1
  237. package/.next/standalone/apps/web/.next/static/chunks/25rt2v27sz0io.js +0 -1
  238. package/.next/static/chunks/03ju_837pa9ul.js +0 -11
  239. package/.next/static/chunks/0ge3nirnmx_np.js +0 -1
  240. package/.next/static/chunks/19krxv-ou9c8c.js +0 -121
  241. package/.next/static/chunks/1_nk3imchwn8a.css +0 -1
  242. package/.next/static/chunks/25rt2v27sz0io.js +0 -1
  243. /package/.next/standalone/apps/web/.next/static/{iCALZzxFfElF4z3wYZwsC → whR5PvI0kapiCtaze5Lb0}/_buildManifest.js +0 -0
  244. /package/.next/standalone/apps/web/.next/static/{iCALZzxFfElF4z3wYZwsC → whR5PvI0kapiCtaze5Lb0}/_clientMiddlewareManifest.js +0 -0
  245. /package/.next/standalone/apps/web/.next/static/{iCALZzxFfElF4z3wYZwsC → whR5PvI0kapiCtaze5Lb0}/_ssgManifest.js +0 -0
  246. /package/.next/static/{iCALZzxFfElF4z3wYZwsC → whR5PvI0kapiCtaze5Lb0}/_buildManifest.js +0 -0
  247. /package/.next/static/{iCALZzxFfElF4z3wYZwsC → whR5PvI0kapiCtaze5Lb0}/_clientMiddlewareManifest.js +0 -0
  248. /package/.next/static/{iCALZzxFfElF4z3wYZwsC → whR5PvI0kapiCtaze5Lb0}/_ssgManifest.js +0 -0
@@ -19,6 +19,8 @@ import {
19
19
  Store,
20
20
  Link2,
21
21
  Sparkles,
22
+ Pause,
23
+ Play,
22
24
  } from 'lucide-react';
23
25
  import { Button } from '@/components/ui/button';
24
26
  import { cn } from '@/lib/utils';
@@ -35,6 +37,16 @@ import {
35
37
  DialogTitle,
36
38
  DialogTrigger,
37
39
  } from '@/components/ui/dialog';
40
+ import {
41
+ AlertDialog,
42
+ AlertDialogAction,
43
+ AlertDialogCancel,
44
+ AlertDialogContent,
45
+ AlertDialogDescription,
46
+ AlertDialogFooter,
47
+ AlertDialogHeader,
48
+ AlertDialogTitle,
49
+ } from '@/components/ui/alert-dialog';
38
50
 
39
51
  /* ------------------------------------------------------------------ */
40
52
  /* Types */
@@ -64,6 +76,7 @@ interface MediaAsset {
64
76
  processingStatus: 'pending' | 'processing' | 'completed' | 'failed';
65
77
  processingError?: string;
66
78
  processingMessage?: string;
79
+ processingPaused?: boolean;
67
80
  processingProgress?: number;
68
81
  processingSteps?: MediaProcessingStep[];
69
82
  processingRevision?: number;
@@ -571,6 +584,8 @@ function MediaContent({
571
584
  const [remoteEstimates, setRemoteEstimates] = useState<RemoteEstimate[] | null>(null);
572
585
  const [checkingUrls, setCheckingUrls] = useState(false);
573
586
  const [importingUrls, setImportingUrls] = useState(false);
587
+ const [playlistAlertOpen, setPlaylistAlertOpen] = useState(false);
588
+ const [assetToRemove, setAssetToRemove] = useState<MediaAsset | null>(null);
574
589
  const [importMode, setImportMode] = useState<'upload' | 'url'>('upload');
575
590
  const mediaApiUrl = serverId
576
591
  ? `/api/media?serverId=${encodeURIComponent(serverId)}`
@@ -687,10 +702,24 @@ function MediaContent({
687
702
  }
688
703
  }
689
704
 
690
- async function importRemoteUrls() {
691
- const urls = parsedUrls();
705
+ async function importRemoteUrls(ignorePlaylist = false) {
706
+ let urls = parsedUrls();
692
707
  if (urls.length === 0 || !remoteEstimates) return;
693
708
  if (!ensureAudioConfiguration()) return;
709
+
710
+ if (ignorePlaylist) {
711
+ urls = urls.map((url) => {
712
+ try {
713
+ const u = new URL(url);
714
+ if (u.hostname.includes('youtube.com')) {
715
+ u.searchParams.delete('list');
716
+ return u.toString();
717
+ }
718
+ } catch {}
719
+ return url;
720
+ });
721
+ }
722
+
694
723
  setImportingUrls(true);
695
724
  try {
696
725
  const res = await fetch(mediaApiUrl, {
@@ -701,8 +730,12 @@ function MediaContent({
701
730
  const data = await res.json();
702
731
  if (!res.ok) throw new Error(data.error ?? 'Media import failed');
703
732
  const ids = (data.assets as MediaAsset[]).map((asset) => asset.id);
733
+ toast.success(`${mediaType === 'video' ? 'Video' : 'Audio'} import started`, {
734
+ description:
735
+ 'Queued for download and indexing. Live progress will appear once the source starts responding; you can safely leave in the meantime.',
736
+ duration: 8_000,
737
+ });
704
738
  await processAssets(ids);
705
- toast.success(`${mediaType === 'video' ? 'Video' : 'Audio'} indexing started`);
706
739
  setUrlsText('');
707
740
  setRemoteEstimates(null);
708
741
  setProgress(null);
@@ -757,7 +790,15 @@ function MediaContent({
757
790
  }
758
791
  const mediaLabel =
759
792
  mediaType === 'video' ? 'Video' : mediaType === 'audio' ? 'Audio' : 'Image';
760
- toast.success(`${mediaLabel} indexing started`);
793
+ toast.success(`${mediaLabel} indexing started`, {
794
+ description:
795
+ mediaType === 'image'
796
+ ? 'You can safely leave while we make it searchable.'
797
+ : `Expected time: about ${stagedEstimate.processingMinutes} minute${
798
+ stagedEstimate.processingMinutes === 1 ? '' : 's'
799
+ }. You can safely leave while we index it.`,
800
+ duration: 8_000,
801
+ });
761
802
  setProgress(null);
762
803
 
763
804
  staged.forEach((f) => {
@@ -791,6 +832,26 @@ function MediaContent({
791
832
  }
792
833
  }
793
834
 
835
+ async function togglePause(asset: MediaAsset) {
836
+ try {
837
+ const res = await fetch('/api/media/process', {
838
+ method: 'POST',
839
+ headers: { 'Content-Type': 'application/json' },
840
+ body: JSON.stringify({
841
+ action: asset.processingPaused ? 'resume' : 'pause',
842
+ assetId: asset.id,
843
+ serverId,
844
+ }),
845
+ });
846
+ const body = await res.json();
847
+ if (!res.ok) throw new Error(body.error || 'Could not update media indexing.');
848
+ toast.success(asset.processingPaused ? 'Media indexing resumed.' : 'Media indexing paused.');
849
+ await onMutate();
850
+ } catch (error) {
851
+ showErrorToast(error);
852
+ }
853
+ }
854
+
794
855
  async function handleRetry(assetId: string) {
795
856
  setProgress({ message: 'Retrying media processing...', current: 0, total: 1 });
796
857
  try {
@@ -831,7 +892,11 @@ function MediaContent({
831
892
  )}
832
893
 
833
894
  {activeAssets.length > 0 ? (
834
- <ActiveIndexingList assets={activeAssets} onCancel={handleDelete} />
895
+ <ActiveIndexingList
896
+ assets={activeAssets}
897
+ onPause={togglePause}
898
+ onRemove={setAssetToRemove}
899
+ />
835
900
  ) : null}
836
901
 
837
902
  {mediaType !== 'image' && (
@@ -902,7 +967,18 @@ function MediaContent({
902
967
  size="sm"
903
968
  className="h-9 text-xs"
904
969
  disabled={!remoteEstimates || importingUrls}
905
- onClick={importRemoteUrls}
970
+ onClick={() => {
971
+ const totalEntries =
972
+ remoteEstimates?.reduce(
973
+ (sum: number, item: any) => sum + (item.entryCount ?? 1),
974
+ 0,
975
+ ) ?? 0;
976
+ if (totalEntries > 1) {
977
+ setPlaylistAlertOpen(true);
978
+ } else {
979
+ importRemoteUrls();
980
+ }
981
+ }}
906
982
  >
907
983
  {importingUrls ? (
908
984
  <Loader2 className="mr-1.5 size-3 animate-spin" />
@@ -912,6 +988,38 @@ function MediaContent({
912
988
  Import
913
989
  </Button>
914
990
  </div>
991
+
992
+ <AlertDialog open={playlistAlertOpen} onOpenChange={setPlaylistAlertOpen}>
993
+ <AlertDialogContent>
994
+ <AlertDialogHeader>
995
+ <AlertDialogTitle>Playlist Detected</AlertDialogTitle>
996
+ <AlertDialogDescription>
997
+ You entered a URL that points to a playlist. Do you want to download and index the
998
+ entire playlist, or just the single video?
999
+ </AlertDialogDescription>
1000
+ </AlertDialogHeader>
1001
+ <AlertDialogFooter>
1002
+ <AlertDialogCancel>Cancel</AlertDialogCancel>
1003
+ <Button
1004
+ variant="outline"
1005
+ onClick={() => {
1006
+ setPlaylistAlertOpen(false);
1007
+ importRemoteUrls(true);
1008
+ }}
1009
+ >
1010
+ Single Video
1011
+ </Button>
1012
+ <AlertDialogAction
1013
+ onClick={() => {
1014
+ setPlaylistAlertOpen(false);
1015
+ importRemoteUrls(false);
1016
+ }}
1017
+ >
1018
+ Entire Playlist
1019
+ </AlertDialogAction>
1020
+ </AlertDialogFooter>
1021
+ </AlertDialogContent>
1022
+ </AlertDialog>
915
1023
  <p className="mt-2 pl-1 text-[11px] leading-relaxed text-muted-foreground">
916
1024
  Direct {mediaType} links
917
1025
  {mediaType === 'video' ? ', YouTube videos, or playlists' : ''}. Add up to 10 URLs
@@ -951,17 +1059,7 @@ function MediaContent({
951
1059
  />
952
1060
  </div>
953
1061
 
954
- {isPlaylist ? (
955
- <div className="flex items-start gap-2 rounded-lg border border-amber-200 bg-amber-50/60 dark:border-amber-800/50 dark:bg-amber-950/30 px-3 py-2.5">
956
- <AlertCircle className="size-3.5 shrink-0 mt-0.5 text-amber-600 dark:text-amber-400" />
957
- <p className="text-[11px] text-amber-800 dark:text-amber-300 leading-relaxed">
958
- <span className="font-medium">Playlist detected</span> — this will
959
- download and index{' '}
960
- <span className="font-semibold">{totalEntries} items</span> (max 10). Each
961
- item is transcribed and analyzed separately.
962
- </p>
963
- </div>
964
- ) : null}
1062
+ {/* Playlist warning moved to AlertDialog */}
965
1063
 
966
1064
  {(mediaType === 'audio'
967
1065
  ? remoteEstimates.slice(0, 1)
@@ -1238,12 +1336,20 @@ function MediaContent({
1238
1336
  </DialogHeader>
1239
1337
  <div className="flex-1 overflow-y-auto px-6 py-4">
1240
1338
  {mediaType === 'image' ? (
1241
- <ImageGallery assets={assets} onDelete={handleDelete} serverId={serverId} />
1339
+ <ImageGallery
1340
+ assets={assets}
1341
+ onDelete={(id) =>
1342
+ setAssetToRemove(assets.find((asset) => asset.id === id) ?? null)
1343
+ }
1344
+ serverId={serverId}
1345
+ />
1242
1346
  ) : (
1243
1347
  <FileList
1244
1348
  assets={assets}
1245
1349
  mediaType={mediaType}
1246
- onDelete={handleDelete}
1350
+ onDelete={(id) =>
1351
+ setAssetToRemove(assets.find((asset) => asset.id === id) ?? null)
1352
+ }
1247
1353
  onProcess={handleRetry}
1248
1354
  />
1249
1355
  )}
@@ -1258,6 +1364,34 @@ function MediaContent({
1258
1364
  </div>
1259
1365
  ) : null}
1260
1366
 
1367
+ <AlertDialog
1368
+ open={Boolean(assetToRemove)}
1369
+ onOpenChange={(open) => !open && setAssetToRemove(null)}
1370
+ >
1371
+ <AlertDialogContent>
1372
+ <AlertDialogHeader>
1373
+ <AlertDialogTitle>Remove this {assetToRemove?.type ?? 'media'} file?</AlertDialogTitle>
1374
+ <AlertDialogDescription>
1375
+ {assetToRemove && isActiveJob(assetToRemove)
1376
+ ? 'This will stop its indexing job and permanently remove any progress already made.'
1377
+ : 'This permanently removes the file and its searchable data from your knowledge base.'}
1378
+ </AlertDialogDescription>
1379
+ </AlertDialogHeader>
1380
+ <AlertDialogFooter>
1381
+ <AlertDialogCancel>Keep file</AlertDialogCancel>
1382
+ <AlertDialogAction
1383
+ className="bg-destructive text-white hover:bg-destructive/90"
1384
+ onClick={() => {
1385
+ if (assetToRemove) void handleDelete(assetToRemove.id);
1386
+ setAssetToRemove(null);
1387
+ }}
1388
+ >
1389
+ Remove file
1390
+ </AlertDialogAction>
1391
+ </AlertDialogFooter>
1392
+ </AlertDialogContent>
1393
+ </AlertDialog>
1394
+
1261
1395
  {/* Storage warning */}
1262
1396
  {/* {storageUsedBytes > 1024 * 1024 * 1024 && (
1263
1397
  <div className="flex items-start gap-2.5 rounded-lg border border-amber-200 bg-amber-50 px-3.5 py-3">
@@ -1310,7 +1444,6 @@ function ImageGallery({
1310
1444
  className="size-full object-cover transition-transform duration-300 group-hover:scale-105"
1311
1445
  loading="lazy"
1312
1446
  onError={(e) => {
1313
- // Fallback to original if no thumbnail
1314
1447
  (e.target as HTMLImageElement).src = mediaAssetUrl(asset.id, serverId);
1315
1448
  }}
1316
1449
  />
@@ -1599,10 +1732,12 @@ function StatusBadge({ asset }: { asset: MediaAsset }) {
1599
1732
 
1600
1733
  function ActiveIndexingList({
1601
1734
  assets,
1602
- onCancel,
1735
+ onPause,
1736
+ onRemove,
1603
1737
  }: {
1604
1738
  assets: MediaAsset[];
1605
- onCancel: (id: string) => void;
1739
+ onPause: (asset: MediaAsset) => void;
1740
+ onRemove: (asset: MediaAsset) => void;
1606
1741
  }) {
1607
1742
  return (
1608
1743
  <section
@@ -1637,10 +1772,30 @@ function ActiveIndexingList({
1637
1772
  <span className="shrink-0 text-[10px] font-medium tabular-nums text-emerald-600 dark:text-emerald-400">
1638
1773
  {Math.round(progress)}%
1639
1774
  </span>
1775
+ {asset.type !== 'image' ? (
1776
+ <button
1777
+ type="button"
1778
+ title={asset.processingPaused ? 'Resume Indexing' : 'Pause Indexing'}
1779
+ aria-label={
1780
+ asset.processingPaused
1781
+ ? `Resume ${asset.fileName}`
1782
+ : `Pause ${asset.fileName}`
1783
+ }
1784
+ onClick={() => onPause(asset)}
1785
+ className="rounded-full p-1 text-muted-foreground transition-colors hover:bg-muted hover:text-foreground"
1786
+ >
1787
+ {asset.processingPaused ? (
1788
+ <Play className="size-3" />
1789
+ ) : (
1790
+ <Pause className="size-3" />
1791
+ )}
1792
+ </button>
1793
+ ) : null}
1640
1794
  <button
1641
1795
  type="button"
1642
- title="Cancel Indexing"
1643
- onClick={() => onCancel(asset.id)}
1796
+ title="Remove file"
1797
+ aria-label={`Remove ${asset.fileName}`}
1798
+ onClick={() => onRemove(asset)}
1644
1799
  className="p-1 -mr-1 rounded-full text-muted-foreground hover:bg-red-100 hover:text-red-600 dark:hover:bg-red-900/30 transition-colors"
1645
1800
  >
1646
1801
  <X className="size-3" />
@@ -1657,7 +1812,9 @@ function ActiveIndexingList({
1657
1812
  <div className="flex items-center gap-1.5">
1658
1813
  <ElapsedTime startTime={asset.createdAt} />
1659
1814
  <p className="truncate text-[10px] text-muted-foreground animate-pulse">
1660
- {asset.processingMessage || 'Preparing media indexing...'}
1815
+ {asset.processingPaused
1816
+ ? 'Paused — resume when you are ready.'
1817
+ : asset.processingMessage || 'Preparing media indexing...'}
1661
1818
  </p>
1662
1819
  </div>
1663
1820
  {/* {asset.processingSteps?.length ? (
@@ -397,7 +397,7 @@ export function ScrapePanel({
397
397
  queries.map((q) => searchGeneric(q, activeProvider, 1, queries.length > 1, false)),
398
398
  );
399
399
  } catch (err) {
400
- toast.info(`${activeProvider} search failed. Falling back to local crawler...`);
400
+ toast.info(`using local crawler...`);
401
401
  await Promise.all(queries.map((q) => searchFirecrawl(q, queries.length > 1)));
402
402
  }
403
403
  }
@@ -576,20 +576,12 @@ export function ScrapePanel({
576
576
  const data = await res.json();
577
577
  if (!res.ok) throw new Error(data.error ?? 'Could not start job');
578
578
 
579
- const { totalPages, estimatedSeconds } = estimateEtlDuration(
580
- selectedUrls.length,
581
- effectiveScope,
582
- specificUrls ? 1 : pageLimit,
583
- );
584
-
585
- toast.success('Scraping started, running in background', {
579
+ toast.success('Scrape queued', {
586
580
  description: specificUrls
587
- ? `Scraping ${selectedUrls.length} specific URL(s) only, no deep crawl. You can navigate away. Progress is tracked automatically.`
581
+ ? `We will connect to ${selectedUrls.length} specific URL(s) and show real page progress as each response arrives. You can navigate away.`
588
582
  : `${selectedUrls.length} ${
589
583
  effectiveScope === 'domain' ? 'domain(s)' : 'page(s)'
590
- } · ~${totalPages} pages · ETA ${formatDuration(
591
- estimatedSeconds,
592
- )}. You can navigate away. Progress is tracked automatically.`,
584
+ } selected. We will show real page progress as each response arrives; no artificial completion estimate. You can navigate away.`,
593
585
  duration: 8000,
594
586
  });
595
587
 
@@ -181,7 +181,6 @@ export function UploadPanel({ onAdded }: { onAdded: () => void }) {
181
181
  indexAsTabular: true,
182
182
  });
183
183
  } else {
184
- // fallback to plain
185
184
  next.push({
186
185
  id,
187
186
  name: file.name,
@@ -64,7 +64,8 @@ const ACTIVE: IndexRun['status'][] = ['chunking', 'embedding', 'upserting'];
64
64
  export function IndexWorkspace({
65
65
  onDone,
66
66
  onClose,
67
- }: { onDone?: () => void; onClose?: () => void } = {}) {
67
+ automatic = false,
68
+ }: { onDone?: () => void; onClose?: () => void; automatic?: boolean } = {}) {
68
69
  const [starting, setStarting] = useState(false);
69
70
  const [isIndexing, setIsIndexing] = useState(false);
70
71
 
@@ -94,7 +95,21 @@ export function IndexWorkspace({
94
95
  setIsIndexing(true);
95
96
  } else if (isIndexing && status === 'completed') {
96
97
  setIsIndexing(false);
97
- toast.success('Indexing completed successfully!');
98
+ toast.success('Indexing complete. Your data is ready to use.');
99
+ try {
100
+ const context = new (window.AudioContext || (window as any).webkitAudioContext)();
101
+ const oscillator = context.createOscillator();
102
+ const gain = context.createGain();
103
+ oscillator.connect(gain);
104
+ gain.connect(context.destination);
105
+ oscillator.frequency.setValueAtTime(880, context.currentTime);
106
+ gain.gain.setValueAtTime(0.04, context.currentTime);
107
+ gain.gain.exponentialRampToValueAtTime(0.001, context.currentTime + 0.12);
108
+ oscillator.start();
109
+ oscillator.stop(context.currentTime + 0.12);
110
+ } catch {
111
+ // Browsers may block notification sounds until a user gesture.
112
+ }
98
113
  onClose?.();
99
114
  }
100
115
  }, [data?.run?.status, isIndexing, onClose]);
@@ -215,29 +230,37 @@ export function IndexWorkspace({
215
230
  </Alert>
216
231
  )} */}
217
232
 
218
- <div className="flex w-full items-center justify-between pt-4 mt-2">
219
- <Button onClick={() => onClose?.()} size="lg" variant="outline">
220
- Cancel
221
- </Button>
222
- <Button
223
- onClick={() => build(run?.status === 'completed')}
224
- disabled={
225
- !ready || running || starting || (run?.status === 'completed' && unindexedCount === 0)
226
- }
227
- size="lg"
228
- >
229
- {running || starting ? (
230
- <Loader2 className="size-4 animate-spin mr-2" />
231
- ) : (
232
- <Play className="size-4 mr-2" />
233
- )}
234
- {running
235
- ? 'Indexing…'
236
- : run?.status === 'completed'
237
- ? `Index new documents (${unindexedCount})`
238
- : `Start indexing (${unindexedCount})`}
239
- </Button>
240
- </div>
233
+ {automatic ? (
234
+ <div className="flex justify-end pt-2">
235
+ <Button onClick={() => onClose?.()} variant="outline">
236
+ Continue working
237
+ </Button>
238
+ </div>
239
+ ) : (
240
+ <div className="flex w-full items-center justify-between pt-4 mt-2">
241
+ <Button onClick={() => onClose?.()} size="lg" variant="outline">
242
+ Cancel
243
+ </Button>
244
+ <Button
245
+ onClick={() => build(run?.status === 'completed')}
246
+ disabled={
247
+ !ready || running || starting || (run?.status === 'completed' && unindexedCount === 0)
248
+ }
249
+ size="lg"
250
+ >
251
+ {running || starting ? (
252
+ <Loader2 className="size-4 animate-spin mr-2" />
253
+ ) : (
254
+ <Play className="size-4 mr-2" />
255
+ )}
256
+ {running
257
+ ? 'Indexing…'
258
+ : run?.status === 'completed'
259
+ ? `Index new documents (${unindexedCount})`
260
+ : `Start indexing (${unindexedCount})`}
261
+ </Button>
262
+ </div>
263
+ )}
241
264
  </div>
242
265
  );
243
266
  }
@@ -99,7 +99,7 @@ export function MarketplaceSection() {
99
99
  async (toolId: string) => {
100
100
  setInstalling(toolId);
101
101
  const toastId = toast.loading('Downloading and installing tool…', {
102
- description: 'This may take a moment on first install.',
102
+ description: 'This may take a minute on first install.',
103
103
  });
104
104
  try {
105
105
  const res = await fetch(`/api/marketplace/${toolId}`, {
@@ -10,7 +10,6 @@ import {
10
10
  Database,
11
11
  Plug,
12
12
  Store,
13
- Share2,
14
13
  type LucideIcon,
15
14
  Grid2X2Plus,
16
15
  } from 'lucide-react';
@@ -82,7 +81,7 @@ export function SettingsLayout({ activeSection, onSectionChange, children }: Set
82
81
 
83
82
  return (
84
83
  <div className="flex h-full w-full flex-1 min-h-0 bg-transparent">
85
- <nav className="hidden md:flex w-[240px] shrink-0 flex-col overflow-y-auto h-full bg-transparent border-r border-border/40">
84
+ <nav className="hidden md:flex w-60 shrink-0 flex-col overflow-y-auto h-full bg-transparent border-r border-border/40">
86
85
  <div className="flex flex-col gap-6 py-6 px-4">
87
86
  {SECTION_GROUPS.map((group) => (
88
87
  <div key={group.label}>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "larkup",
3
- "version": "0.1.39",
3
+ "version": "0.1.41",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "larkup": "./bin/larkup.js"
@@ -53,13 +53,13 @@
53
53
  "xlsx": "^0.18.5",
54
54
  "zod": "^4.4.3",
55
55
  "zustand": "^5.0.14",
56
- "@larkup/scraper": "0.1.27",
57
- "@larkup/core": "0.2.4",
58
56
  "@larkup/sandbox": "0.1.2",
59
- "@larkup/tool-doc-editor": "0.2.5",
57
+ "@larkup/marketplace": "0.1.11",
58
+ "@larkup/core": "0.2.5",
59
+ "@larkup/scraper": "0.1.29",
60
60
  "@larkup/vector-stores": "0.1.23",
61
- "@larkup/tool-video-audio": "0.2.3",
62
- "@larkup/marketplace": "0.1.10"
61
+ "@larkup/tool-video-audio": "0.2.4",
62
+ "@larkup/tool-doc-editor": "0.2.6"
63
63
  },
64
64
  "devDependencies": {
65
65
  "@tailwindcss/postcss": "^4.2.0",
@@ -1,3 +0,0 @@
1
- module.exports=[688947,(a,b,c)=>{b.exports=a.x("stream",()=>require("stream"))},491543,a=>{"use strict";let b=(0,a.i(326729).default)("zap",[["path",{d:"M15.914 4a1.5 1.5 0 00-2.474-1.561l-9 9A1.5 1.5 0 005.5 14h4.002a.5.5 0 01.471.666L8.086 20a1.5 1.5 0 002.475 1.56l9-9A1.5 1.5 0 0018.5 10h-3.997a.5.5 0 01-.472-.667z",key:"1v7up4"}]]);a.s(["Zap",0,b],491543)},683389,a=>{a.v(b=>Promise.all(["server/chunks/ssr/apps_web_lib_pdf-images_ts_13-l5wa._.js","server/chunks/ssr/0uph_pdfjs-dist_build_pdf_mjs_0pn2q_y._.js"].map(b=>a.l(b))).then(()=>b(802183)))}];
2
-
3
- //# sourceMappingURL=%5Broot-of-the-server%5D__0t8ud_u._.js.map
@@ -1,3 +0,0 @@
1
- module.exports=[688947,(a,b,c)=>{b.exports=a.x("stream",()=>require("stream"))},491543,a=>{"use strict";let b=(0,a.i(326729).default)("zap",[["path",{d:"M15.914 4a1.5 1.5 0 00-2.474-1.561l-9 9A1.5 1.5 0 005.5 14h4.002a.5.5 0 01.471.666L8.086 20a1.5 1.5 0 002.475 1.56l9-9A1.5 1.5 0 0018.5 10h-3.997a.5.5 0 01-.472-.667z",key:"1v7up4"}]]);a.s(["Zap",0,b],491543)},683389,a=>{a.v(b=>Promise.all(["server/chunks/ssr/apps_web_lib_pdf-images_ts_13-l5wa._.js","server/chunks/ssr/0uph_pdfjs-dist_build_pdf_mjs_0pn2q_y._.js"].map(b=>a.l(b))).then(()=>b(802183)))}];
2
-
3
- //# sourceMappingURL=%5Broot-of-the-server%5D__0t8ud_u._.js.map