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
@@ -0,0 +1,49 @@
#!/usr/bin/env node
// After `tsc && tsc-alias`, the emitted .d.ts files reference workspace deps
// through relative node_modules paths like `../../../node_modules/@cio/utils/dist/...`.
// Cross-package consumers (apps/api) then trip TS2742 because they see those
// types as a different copy of @cio/utils. Rewrite those references back to
// bare package specifiers so the .d.ts is portable across the workspace.
import { readdir, readFile, writeFile, stat } from 'node:fs/promises';
import { join } from 'node:path';
const DIST = new URL('../dist/', import.meta.url).pathname;
const PATTERNS = [
// `../../../node_modules/@cio/utils/dist/validation/course/index.js`
// -> `@cio/utils/validation/course`
{
regex: /(['"])(?:\.\.\/)+node_modules\/(@cio\/[a-z-]+)\/dist\/(.*?)(?:\/index)?\.js\1/g,
replace: (_match, q, pkg, subpath) => `${q}${pkg}/${subpath}${q}`
},
// `.../node_modules/@cio/utils/dist/index.js` -> `@cio/utils`
{
regex: /(['"])(?:\.\.\/)+node_modules\/(@cio\/[a-z-]+)\/dist\/index\.js\1/g,
replace: (_match, q, pkg) => `${q}${pkg}${q}`
}
];
async function walk(dir) {
const out = [];
for (const entry of await readdir(dir)) {
const full = join(dir, entry);
const s = await stat(full);
if (s.isDirectory()) out.push(...(await walk(full)));
else if (entry.endsWith('.d.ts')) out.push(full);
}
return out;
}
const files = await walk(DIST);
let touched = 0;
for (const file of files) {
const before = await readFile(file, 'utf8');
let after = before;
for (const { regex, replace } of PATTERNS) after = after.replace(regex, replace);
if (after !== before) {
await writeFile(file, after);
touched += 1;
}
}
console.log(`restore-bare-specifiers: rewrote ${touched}/${files.length} files`);