Files
classroomio/apps/jobs/src/bootstrap.ts
T
Rotimi Best 65420320e7 feat(ai-assistant): odt support, document-to-lesson attach, upload UX fixes
- Add .odt (application/vnd.oasis.opendocument.text) as a supported upload
  format; extract text via JSZip + content.xml parsing
- Add attach_document_to_lesson agent tool so the AI can attach an uploaded
  document to a lesson as a downloadable material
- Instruct the agent to create a "Course Materials" lesson (first lesson of
  the first section) and attach the uploaded document to it on implementation
- Suppress hallucinated references: uploaded documents do not count as fetched
  URLs — omit the References section when no fetch_documentation_url calls
  were made
- Surface specific upload error snackbars (file_too_large, unsupported_file_type)
  instead of silently logging; fix generic fallback message
- Allow typing in the chat textarea while a document is uploading; only block
  Enter/send, not the whole input
- Fix retry endpoint to return the current run instead of erroring when the run
  is already active (queued/running/waiting_for_input/paused)
- Connect @cio/core Redis singleton in the jobs bootstrap so course-generation
  workers no longer fail with "The client is closed"
- Expose documentAssets (assetId + fileName) alongside documentText in
  AgentContext and pass it through both the chat route and course runner
2026-06-29 12:29:47 +01:00

29 lines
774 B
TypeScript

import 'dotenv/config';
import { env } from './config/env';
import { warnIfFfmpegMissing } from './utils/ffmpeg';
import { log } from './utils/logger';
import { connectRedis } from '@cio/core/utils/redis/redis';
void warnIfFfmpegMissing();
if (!env.REDIS_URL) {
throw new Error('REDIS_URL is required to start a worker process.');
}
void connectRedis();
log.info('worker-bootstrap', {
nodeEnv: env.NODE_ENV,
pid: process.pid,
hasOpenAi: Boolean(env.OPENAI_API_KEY)
});
process.on('uncaughtException', (error) => {
log.error('uncaught-exception', { message: error.message, stack: error.stack });
});
process.on('unhandledRejection', (reason) => {
log.error('unhandled-rejection', { reason: reason instanceof Error ? reason.message : String(reason) });
});