Work Generation Service
The WorkGenerationService is the central orchestrator for all content generation operations within a work. It coordinates data generation, markdown rendering, website scaffolding, item submission, image capture, and scheduled updates.
Source: packages/agent/src/services/work-generation.service.ts
Overview
This service handles both initial generation (creating items from scratch) and incremental updates (adding new items or refreshing existing ones). It supports both synchronous (in-process) and asynchronous (dispatched to Trigger.dev) execution modes.
| Operation | Required Role | Description |
|---|---|---|
generateItems | Editor | Triggers initial item generation from a prompt |
updateItemsGenerator | Editor | Re-runs generation with updated parameters |
submitItem | Editor | Submits a single item to the work |
removeItem | Editor | Removes a single item from the work |
updateItemMetadata | Editor | Updates metadata (featured, order) on an existing item |
regenerateMarkdown | Editor | Recreates the markdown repository from data |
updateReadme | Editor | Updates the README from markdown templates |
updateWebsiteRepository | Editor | Pushes latest changes to the website repository |
bulkCaptureImages | Editor | Captures screenshots for items missing images |
updateDomainType | Editor | Sets the domain classification for a work |
runScheduledUpdate | System | Executes a scheduled generation run |
Generation Pipeline
Initial Generation (generateItems)
The generateItems method performs these steps:
- Access check -- Verifies the user has Editor or higher role via
ownershipService.ensureCanEdit(). - Provider preparation -- Auto-enables selected plugins, validates providers, and processes form configuration.
- History record -- Creates a
WorkGenerationHistoryentry with statusGENERATING. - Dispatch or run -- Based on
awaitCompletion, either runs in-process or dispatches to the background task system. - Returns an
ItemsGeneratorResponseDtowith statuspendingand the history ID.
const result = await generationService.generateItems(
workId,
{
name: 'AI Tools Work',
prompt: 'Find the best AI developer tools',
generation_method: GenerationMethod.CREATE_UPDATE,
providers: { ai: 'openai', search: 'exa' }
},
user,
true // awaitCompletion
);
Update Generation (updateItemsGenerator)
The update path reuses previous configuration merged with new overrides:
- Loads
last_request_datafrom the data repository config. - For scheduled triggers, uses
initial_promptinstead of the last run prompt to prevent drift. - Applies safe per-run defaults:
generation_method: CREATE_UPDATE,update_with_pull_request: true. - Deep-merges provider overrides.
- For schedule-triggered runs, applies conservative config limits (e.g.,
max_search_queries: 10).
Trigger Context
Every generation carries a GenerationTriggerContext:
interface GenerationTriggerContext {
triggeredBy: 'user' | 'api' | 'schedule';
scheduleId?: string;
billingMode?: WorkScheduleBillingMode;
}
This context determines error handling behavior, billing, and whether the run updates schedule state.
Execution Modes
In-Process Generation
When awaitCompletion is true, the full pipeline runs within the request lifecycle:
- Sets work status to
GENERATING. - Calls
dataGenerator.initialize()to run the AI pipeline. - On success with new/updated items, triggers
markdownGenerator.initialize(). - If items exist, triggers
websiteGenerator.initialize(). - Updates status to
GENERATEDorERRORbased on outcome.
Background Dispatch
When awaitCompletion is false:
- Immediately sets work status to
GENERATINGfor instant UI feedback. - Builds a
WorkGenerationPayloadand dispatches viagenerationDispatcher. - If dispatch fails, falls back to in-process execution (sequential for schedules, fire-and-forget for user triggers).
interface WorkGenerationPayload {
workId: string;
userId: string;
mode: 'create' | 'update';
dto: CreateItemsGeneratorDto;
historyId: string;
historyStartedAt: string;
triggerSource: string;
scheduleId?: string;
}
Item Operations
Submit Item
Delegates to ItemSubmissionService.submitItem(), which creates a new item in the data repository. On success, triggers markdown regeneration with either RECREATE (if auto-merged) or CREATE_UPDATE method.
Remove Item
Delegates to ItemSubmissionService.removeItem(), which removes an item work from the data repository and triggers markdown regeneration with CREATE_UPDATE method.
Update Item Metadata
Delegates to ItemSubmissionService.updateItem() for changing featured status or order on existing items.
Bulk Image Capture
The bulkCaptureImages method processes multiple items to capture screenshots:
| Mode | Behavior |
|---|---|
missing | Only processes items without existing images |
all | Processes all items with source URLs |
Items can be filtered by itemSlugs. The method returns aggregated statistics:
interface BulkCaptureImagesResponseDto {
status: 'success' | 'partial' | 'error';
results: BulkCaptureResultDto[];
totalProcessed: number;
successCount: number;
errorCount: number;
}
Scheduled Updates
The runScheduledUpdate method handles schedule-triggered generation:
- Resolves the user and validates plan entitlements.
- For works with a
sourceRepository, delegates torunScheduledSync()which performs an import sync. - For standard works, calls
updateItemsGenerator()with schedule-specific overrides.
Scheduled Sync Flow
Works imported from external sources (e.g., awesome-lists) use a sync flow:
- Creates a history record with
type: 'sync'. - Sets work status to
GENERATINGwith stepsyncing. - Calls
workImportService.syncWork(). - On success/failure, updates both the schedule and work status.
Error Handling and Notifications
Generation errors are classified using classifyGenerationError() and, for account-level issues, trigger notifications via NotificationService.notifySchedulePaused(). Error classifications help distinguish between transient failures (API rate limits), configuration issues (missing API keys), and unknown errors.
Events
On generation completion (success or failure), the service emits:
this.eventEmitter.emit(WorkGenerationCompletedEvent.EVENT_NAME, new WorkGenerationCompletedEvent(work));
Downstream listeners can use this event to trigger post-generation workflows such as deployment or cache invalidation.