Skip to main content

Work Operations Module

The Work Operations Module (@ever-works/agent/work-operations) provides a centralized service layer for managing work lifecycle state during content generation. It handles generation status tracking, pull request metadata, generation timing, event emission, and generation history persistence.

Overview

PropertyValue
Import path@ever-works/agent/work-operations
Source locationpackages/agent/src/work-operations/
NestJS moduleWorkOperationsModule
Primary serviceWorkOperationsService
Database dependencyDatabaseModule (TypeORM repositories)

The module acts as the single point of truth for all work state mutations that occur during AI-powered content generation, import operations, and scheduled updates. Other modules -- such as the generators, import system, and pipeline -- depend on this module to record progress and outcomes.

Module Structure

packages/agent/src/work-operations/
├── index.ts # Barrel exports
├── work-operations.module.ts # NestJS module definition
└── work-operations.service.ts # Core service + helper functions

Module Registration

WorkOperationsModule imports DatabaseModule and provides WorkOperationsService as an injectable singleton:

import { Module } from '@nestjs/common';
import { DatabaseModule } from '@src/database/database.module';
import { WorkOperationsService } from './work-operations.service';

@Module({
imports: [DatabaseModule],
providers: [WorkOperationsService],
exports: [WorkOperationsService, DatabaseModule]
})
export class WorkOperationsModule {}

Both WorkOperationsService and the underlying DatabaseModule are re-exported so consumers gain access to repository classes without importing DatabaseModule separately.

Key Classes and Services

WorkOperationsService

The central @Injectable() service that coordinates work state changes. It depends on three injected collaborators:

DependencyDescription
WorkRepositoryTypeORM repository for the works table
WorkGenerationHistoryRepositoryTypeORM repository for the work_generation_history table
EventEmitter2 (optional)NestJS event emitter for broadcasting lifecycle events

The EventEmitter2 dependency is marked @Optional(), which allows the service to function in contexts where the event-emitter module is not registered (such as unit tests or CLI tools).

API Reference

WorkOperationsService Methods

MethodSignatureDescription
updateWork(id: string, updateData: Partial<Work>) => Promise<void>Applies a partial update to any fields on the Work entity.
getGenerateStatus(id: string) => Promise<GenerateStatus | undefined>Retrieves the current generation status object for a work. Returns undefined if the work is not found.
updateGenerateStatus(id: string, status: GenerateStatus) => Promise<void>Persists a new generation status. Automatically deduplicates the warnings array if present.
updateLastPullRequest(id: string, payload: { main?: PRUpdate; data?: PRUpdate }) => Promise<void>Records metadata about the most recent pull request(s) created during generation.
recordGenerationStartTime(id: string, startedAt: Date) => Promise<void>Stamps the generationStartedAt timestamp on the work record.
recordGenerationFinishTime(id: string, finishedAt: Date) => Promise<void>Stamps the generationFinishedAt timestamp on the work record.
emitGenerationCompleted(workId: string) => Promise<void>Emits a WorkGenerationCompletedEvent via the event emitter. No-ops gracefully if the emitter is unavailable or the work is not found.
updateGenerationHistory(workId: string, historyId: string, updates: GenerationHistoryUpdateInput) => Promise<void>Updates a specific generation history entry with status, item counts, metrics, and timing data.

Helper Functions

Two standalone utility functions convert generation results into the GenerationHistoryUpdateInput shape:

buildStatsUpdate

function buildStatsUpdate(
stats: GenerationStats | null | undefined
): Pick<GenerationHistoryUpdateInput, 'newItemsCount' | 'updatedItemsCount' | 'totalItemsCount' | 'metrics'>;

Transforms a GenerationStats object (from data-generator) into a partial update suitable for updateGenerationHistory. Defaults numeric fields to 0 when the input is null or undefined.

buildImportStatsUpdate

function buildImportStatsUpdate(
result: WorkImportResult | null | undefined
): Pick<GenerationHistoryUpdateInput, 'newItemsCount' | 'updatedItemsCount' | 'totalItemsCount' | 'metrics'>;

Transforms a WorkImportResult (from the import system) into the same partial update shape. Extracts token usage and cost metrics from the import result when available.

GenerationHistoryUpdateInput Type

The type used to update generation history entries:

type GenerationHistoryUpdateInput = {
status?: GenerateStatusType;
newItemsCount?: number;
updatedItemsCount?: number;
totalItemsCount?: number;
startedAt?: Date | null;
finishedAt?: Date | null;
durationInSeconds?: number | null;
errorMessage?: string | null;
metrics?: GenerationMetrics | null;
parameters?: Record<string, any> | null;
};

GenerationMetrics Type

Tracks resource consumption for a generation run:

type GenerationMetrics = {
urls_scanned?: number;
pages_processed?: number;
items_extracted_current_run?: number;
new_items_added_to_store?: number;
total_items_in_store?: number;
total_tokens_used?: number;
total_cost?: number;
};

Events

The module emits the following event when generation completes:

EventConstantPayload
work.generation.completedWorkGenerationCompletedEvent.EVENT_NAMEWorkGenerationCompletedEvent containing the full Work entity

Listeners can subscribe via the NestJS @OnEvent() decorator:

import { OnEvent } from '@nestjs/event-emitter';
import { WorkGenerationCompletedEvent } from '@ever-works/agent/events';

@Injectable()
export class NotificationListener {
@OnEvent(WorkGenerationCompletedEvent.EVENT_NAME)
handleGenerationCompleted(event: WorkGenerationCompletedEvent) {
const work = event.work;
// Send notification, update dashboards, etc.
}
}

Configuration

The module itself requires no explicit configuration. It inherits database connection settings from the DatabaseModule that it imports. Ensure that the following entities are registered in your TypeORM configuration:

  • Work (table: works)
  • WorkGenerationHistory (table: work_generation_history)

Dependencies

DependencyTypePurpose
DatabaseModuleNestJS moduleProvides WorkRepository and WorkGenerationHistoryRepository
@nestjs/event-emitterPeer dependency (optional)Enables emitGenerationCompleted event broadcasting
@src/entities/work.entityEntityThe Work TypeORM entity
@src/entities/work-generation-history.entityEntityThe WorkGenerationHistory TypeORM entity
@src/eventsEvent classesWorkGenerationCompletedEvent
@src/generators/data-generatorType importGenerationStats type
@src/tasks/work-import.typesType importWorkImportResult type

Usage Examples

Recording a Full Generation Lifecycle

import { WorkOperationsService, buildStatsUpdate } from '@ever-works/agent/work-operations';

@Injectable()
export class GenerationOrchestrator {
constructor(private readonly dirOps: WorkOperationsService) {}

async runGeneration(workId: string, historyId: string) {
const startedAt = new Date();

// Mark generation as started
await this.dirOps.recordGenerationStartTime(workId, startedAt);
await this.dirOps.updateGenerateStatus(workId, {
type: 'generating',
message: 'Content generation in progress'
});

try {
// ... perform generation, obtain stats ...
const stats = await this.generate(workId);

// Record completion
const finishedAt = new Date();
await this.dirOps.recordGenerationFinishTime(workId, finishedAt);
await this.dirOps.updateGenerationHistory(workId, historyId, {
status: 'completed',
finishedAt,
durationInSeconds: (finishedAt.getTime() - startedAt.getTime()) / 1000,
...buildStatsUpdate(stats)
});

// Notify listeners
await this.dirOps.emitGenerationCompleted(workId);
} catch (error) {
await this.dirOps.updateGenerationHistory(workId, historyId, {
status: 'failed',
errorMessage: error.message,
finishedAt: new Date()
});
}
}
}

Recording Import Results

import { buildImportStatsUpdate } from '@ever-works/agent/work-operations';

// After an import completes
const importResult = await importService.importWork(source);

await dirOps.updateGenerationHistory(workId, historyId, {
status: 'completed',
finishedAt: new Date(),
...buildImportStatsUpdate(importResult)
});

Updating Pull Request Metadata

await dirOps.updateLastPullRequest(workId, {
main: { number: 42, url: 'https://github.com/org/repo/pull/42' },
data: { number: 43, url: 'https://github.com/org/repo-data/pull/43' }
});

Exports

The barrel index.ts re-exports all public API:

  • WorkOperationsService -- The injectable service
  • WorkOperationsModule -- The NestJS module
  • GenerationHistoryUpdateInput -- Type for history updates
  • buildStatsUpdate -- Helper for generation stats
  • buildImportStatsUpdate -- Helper for import stats