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