feat: HLS streaming, transcripts, agent course generation & landing-page course previews (#663)

New features:
- HLS video encoding/streaming (hls routes, hls-encoder) and a media
  transcripts pipeline (transcripts route + media-transcript queries)
- AI assistant chat vs. run model: agent-course-generation worker/queue,
  run-monitor pane, chat-changes card, content ask-ai bar
- Per-theme course-page previews across org landing-page themes (bold,
  classic, corporate, editorial, etc.) with a shared course token/component set
- View-as-student mode and login-link / link-invite invite flows

Refactor:
- Extract packages/core consolidating config (env, storage, dashboard-url),
  services and utils previously duplicated under apps/api/src/config
- Remove legacy agent service modules (chat-tools, chat-context,
  context-window, document, fetch-url, lesson-content)
- Relax Cross-Origin-Resource-Policy to allow cross-origin media embedding
- Add format script to tenant-router so turbo run format covers it
This commit is contained in:
Rotimi Best
2026-06-07 18:43:05 +01:00
committed by GitHub
parent a2e70779a0
commit d5b07d356e
496 changed files with 19050 additions and 8312 deletions
@@ -25,7 +25,11 @@
bind:ref
data-slot="dialog-content"
class={cn(
'ui:bg-background ui:border ui:data-[state=open]:animate-in ui:data-[state=closed]:animate-out ui:data-[state=closed]:fade-out-0 ui:data-[state=open]:fade-in-0 ui:data-[state=closed]:zoom-out-95 ui:data-[state=open]:zoom-in-95 ui:fixed ui:left-[50%] ui:top-[50%] ui:z-200 ui:grid ui:w-full ui:max-w-[calc(100%-2rem)] ui:translate-x-[-50%] ui:translate-y-[-50%] ui:gap-4 ui:rounded-lg ui:p-6 ui:shadow-lg ui:duration-200 ui:sm:max-w-lg',
// `has-[[data-slot=dialog-footer][data-sticky=true]]:pb-0` drops the
// dialog's own bottom padding when a sticky footer is rendered —
// the footer's own `py-4` provides the bottom spacing instead, and
// it pins flush with the dialog's bottom edge.
'ui:bg-background ui:border ui:data-[state=open]:animate-in ui:data-[state=closed]:animate-out ui:data-[state=closed]:fade-out-0 ui:data-[state=open]:fade-in-0 ui:data-[state=closed]:zoom-out-95 ui:data-[state=open]:zoom-in-95 ui:fixed ui:left-[50%] ui:top-[50%] ui:z-200 ui:grid ui:w-full ui:max-w-[calc(100%-2rem)] ui:translate-x-[-50%] ui:translate-y-[-50%] ui:gap-4 ui:rounded-lg ui:p-6 ui:[&:has([data-slot=dialog-footer][data-sticky=true])]:pb-0 ui:shadow-lg ui:duration-200 ui:sm:max-w-lg',
className
)}
{...restProps}
@@ -5,15 +5,33 @@
let {
ref = $bindable(null),
class: className,
sticky = false,
children,
...restProps
}: WithElementRef<HTMLAttributes<HTMLDivElement>> = $props();
}: WithElementRef<HTMLAttributes<HTMLDivElement>> & {
/**
* Pin the footer to the bottom of the scrolling `Dialog.Content` so
* the primary action stays visible in tall dialogs. We use plain
* `bottom: 0` (no negative offset) because `overflow-y-auto` clips
* sticky children at the padding box — pushing the footer past that
* line makes it disappear entirely. A top border + solid background
* separates the footer from the scrolling content behind it; negative
* horizontal margins bleed past Content's `px-6` so the border spans
* edge-to-edge.
*/
sticky?: boolean;
} = $props();
</script>
<div
bind:this={ref}
data-slot="dialog-footer"
class={cn('ui:flex ui:flex-col-reverse ui:gap-2 ui:sm:flex-row ui:sm:justify-end', className)}
data-sticky={sticky ? 'true' : undefined}
class={cn(
'ui:flex ui:flex-col-reverse ui:gap-2 ui:sm:flex-row ui:sm:justify-end',
sticky && 'ui:bg-background ui:sticky ui:bottom-0 ui:z-10 ui:-mx-6 ui:-mb-6 ui:border-t ui:px-6 ui:py-4',
className
)}
{...restProps}
>
{@render children?.()}
+4 -1
View File
@@ -13,7 +13,10 @@
<div
bind:this={ref}
data-slot="page"
class={cn('ui:flex ui:flex-col ui:gap-4 ui:min-h-[calc(100vh-48px)] ui:w-full', className)}
class={cn(
'ui:flex ui:flex-col ui:gap-4 ui:min-h-[calc(100vh-48px)] ui:w-full ui:overflow-x-hidden ui:md:overflow-x-auto',
className
)}
{...restProps}
>
{@render children?.()}
@@ -24,6 +24,8 @@
)}
{...restProps}
>
{@render children?.()}
<span class="ui:flex ui:min-w-0 ui:flex-1 ui:items-center ui:gap-2 ui:truncate ui:text-left">
{@render children?.()}
</span>
<ChevronDownIcon class="ui:size-4 ui:opacity-50" />
</SelectPrimitive.Trigger>