Items Module
Overview
The Items module in @ever-works/agent handles individual item lifecycle within a work -- submission, removal, metadata updates, and content enrichment. Items are the fundamental content units of a work, stored as structured data in per-item works within the Git-backed data repository.
The module supports two workflow modes for item modifications: direct-commit (changes are pushed to the main branch immediately) and PR-based (changes are submitted as pull requests for review). The PR-based workflow integrates with the community PR processing system for external contributions.
Module Structure
packages/agent/src/
items-generator/
item-submission.service.ts # Core item submission, removal, update
items-generator.module.ts # NestJS module definition
generators/
data-generator/
data-repository.ts # Item file I/O (data.json, content.md)
services/
work-generation.service.ts # Higher-level item operations (submitItem, removeItem, etc.)
dto/
submit-item.dto.ts # Submission validation
Key Classes and Services
ItemSubmissionService
The core service for item-level operations that manages Git repository interactions:
submitItem(work, user, itemData, options)
Adds a new item to the work:
- Clones or pulls the data repository locally
- Creates the item work structure (
data/<item-slug>/) - Writes
data.json(structured metadata) andcontent.md(markdown description) - If a
source_urlis provided, attempts to auto-capture a screenshot via the screenshot facade - Commits the changes with a descriptive message
- Either pushes directly to main or creates a pull request, based on the
autoapprovalsetting
removeItem(work, user, itemSlug, options)
Removes an item from the work:
- Clones or pulls the data repository
- Verifies the item work exists
- Removes the entire item work
- Commits and pushes (direct or PR-based)
updateItem(work, user, itemSlug, metadata, options)
Updates item metadata without changing content:
- Clones or pulls the data repository
- Reads the existing
data.json - Merges in the metadata updates (e.g.,
featured,order, custom fields) - Writes back and commits
Workflow modes:
| Mode | Behavior |
|---|---|
| Direct commit | Changes pushed to main branch immediately. Used when the user is the work owner/editor. |
| PR-based | Changes submitted as a pull request. Used for community contributions or when approval is required. |
The mode is determined by the autoapproval option and the user's role in the work.
DataRepository (Item Methods)
Low-level file operations for item data:
getItems()-- scan all item works underdata/and parse theirdata.jsonfilesgetItem(slug)-- read a single item's datacreateItemDir(itemData)-- create thedata/<slug>/workwriteItem(itemData)-- writedata.jsonwith structured fieldswriteItemMarkdown(itemData, markdown)-- writecontent.mdremoveItemDir(slug)-- delete an item work
Item Data Structure
Each item is stored in data/<item-slug>/ with two files:
data.json:
{
"name": "Example Tool",
"slug": "example-tool",
"description": "A brief description of the tool",
"source_url": "https://example.com",
"category": "developer-tools",
"tags": ["open-source", "freemium"],
"images": ["screenshot.png"],
"featured": false,
"order": 0,
"metadata": {}
}
content.md:
# Example Tool
A detailed description of the tool with markdown formatting.
## Features
- Feature 1
- Feature 2
API Reference
ItemSubmissionService
submitItem(
work: Work,
user: User,
itemData: {
name: string;
slug?: string;
description: string;
source_url?: string;
category?: string;
tags?: string[];
content?: string;
},
options?: {
autoapproval?: boolean;
prTitle?: string;
prBody?: string;
}
): Promise<{ slug: string; prUrl?: string }>
removeItem(
work: Work,
user: User,
itemSlug: string,
options?: { autoapproval?: boolean }
): Promise<{ prUrl?: string }>
updateItem(
work: Work,
user: User,
itemSlug: string,
metadata: {
featured?: boolean;
order?: number;
[key: string]: unknown;
},
options?: { autoapproval?: boolean }
): Promise<void>
WorkGenerationService (Item Operations)
Higher-level wrappers that add validation, notifications, and item count tracking:
submitItem(work: Work, user: User, itemData: SubmitItemDto): Promise<void>
removeItem(work: Work, user: User, itemSlug: string): Promise<void>
updateItemMetadata(work: Work, user: User, slug: string, metadata: object): Promise<void>
extractItemDetails(work: Work, user: User, url: string): Promise<ExtractedItemDetails>
Configuration
Auto-Screenshot Capture
When a source_url is provided during item submission, the system attempts to capture a screenshot if the screenshot facade is configured. The captured image is saved to the item's work and referenced in data.json.
This behavior is automatic and requires no configuration beyond having a screenshot provider plugin enabled (e.g., screenshotone, urlbox).
PR-Based Workflow Settings
PR-based submission is controlled by:
- The
autoapprovaloption on the submission call - The user's role in the work (owners/editors default to direct commit)
- The work's
communityPrEnabledsetting (enables external PR processing)
Item Slug Generation
If no slug is provided, it is auto-generated from the item name using slugifyText(). Slugs must be unique within a work -- the service checks for existing item works before creating.
Dependencies
| Dependency | Purpose |
|---|---|
@ever-works/agent/facades | GitFacadeService for repository operations, ScreenshotFacadeService for auto-capture |
@ever-works/agent/generators | DataRepository for item file I/O |
@ever-works/agent/utils | slugifyText for slug generation |
isomorphic-git | Local git clone, commit, push operations |
Usage Examples
Submitting a New Item
import { ItemSubmissionService } from '@ever-works/agent/items-generator';
const result = await submissionService.submitItem(
work,
user,
{
name: 'VS Code',
description: 'A powerful code editor by Microsoft',
source_url: 'https://code.visualstudio.com',
category: 'developer-tools',
tags: ['editor', 'open-source', 'microsoft']
},
{ autoapproval: true }
);
console.log(`Item created: ${result.slug}`); // 'vs-code'
Removing an Item
await submissionService.removeItem(work, user, 'vs-code', {
autoapproval: true
});
Submitting via Pull Request
const result = await submissionService.submitItem(
work,
user,
{
name: 'New Tool',
description: 'A new tool to add',
source_url: 'https://newtool.dev'
},
{
autoapproval: false,
prTitle: 'Add New Tool to work',
prBody: 'This tool provides...'
}
);
console.log(`PR created: ${result.prUrl}`);
Updating Item Metadata
await submissionService.updateItem(work, user, 'vs-code', {
featured: true,
order: 1
});