# History Management System in Prompt-Optimizer: Architecture and Implementation

> Explore the prompt-optimizer history management system architecture. Discover its three-layer design, API, business logic, and adapter implementation for efficient prompt optimization.

- Repository: [且炼时光/prompt-optimizer](https://github.com/linshenkx/prompt-optimizer)
- Tags: architecture
- Published: 2026-02-23

---

**The prompt-optimizer history management system uses a three-layer architecture consisting of an interface/API layer exposing CRUD operations, a business logic layer handling validation and chain management, and platform-specific adapters for browser and Electron environments.**

The **history management system** in the `linshenkx/prompt-optimizer` repository provides a robust framework for storing, versioning, and retrieving prompt optimization records across web and desktop platforms. Implemented within the `packages/core` package, this subsystem tracks every prompt iteration as an immutable record while maintaining logical grouping through versioned chains. The architecture abstracts storage concerns through a provider pattern, enabling seamless operation across browser storage APIs and Electron's IPC-based filesystem access.

## Three-Layer Architecture Overview

The history subsystem organizes functionality into distinct layers that separate concerns between interface definition, business logic, and platform adaptation.

| Layer | Responsibility | Key File |
|-------|---------------|----------|
| **API / Service** | Defines public contracts via `IHistoryManager` and `IImportExportable` interfaces | [`packages/core/src/services/history/types.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/services/history/types.ts) |
| **Business Logic** | Validates records, enforces storage limits, builds chains, and coordinates storage | [`packages/core/src/services/history/manager.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/services/history/manager.ts) |
| **Platform Adapters** | Browser-side direct storage vs. Electron IPC proxy for main process communication | [`packages/core/src/services/history/electron-proxy.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/services/history/electron-proxy.ts) |

All data persistence flows through the **storage abstraction** (`StorageAdapter` → `IStorageProvider`). The system maintains a default limit of **50 records** and organizes entries into **chains**, where each chain represents a series of iterations for a single prompt optimization session.

## Core Components and Data Models

### Type Definitions and Interfaces (types.ts)

The foundation of the system resides in [`packages/core/src/services/history/types.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/services/history/types.ts), which defines the shape of historical data and the manager contract.

```typescript
export interface PromptRecord {
  id: string;
  chainId: string;
  version: number;
  originalPrompt: string;
  optimizedPrompt: string;
  type: 'optimize' | 'iterate';
  timestamp: number;
  modelKey: string;
  modelName?: string;
  templateId: string;
  iterationNote?: string;
}

export interface PromptRecordChain {
  chainId: string;
  rootRecord: PromptRecord;
  currentRecord: PromptRecord;
  versions: PromptRecord[];
}

export interface IHistoryManager extends IImportExportable {
  addRecord(record: PromptRecord): Promise<void>;
  getRecords(): Promise<PromptRecord[]>;
  createNewChain(record: Omit<PromptRecord, 'chainId' | 'version'>): Promise<PromptRecord>;
  addIteration(chainId: string, record: Omit<PromptRecord, 'chainId' | 'version'>): Promise<PromptRecord>;
  getChain(chainId: string): Promise<PromptRecordChain | null>;
  getAllChains(): Promise<PromptRecordChain[]>;
  deleteChain(chainId: string): Promise<void>;
}

```

The `IImportExportable` interface enables backup and migration capabilities through standardized `importData` and `exportData` methods.

### The HistoryManager Business Logic (manager.ts)

The `HistoryManager` class in [`packages/core/src/services/history/manager.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/services/history/manager.ts) implements the core business rules and state management.

```typescript
export class HistoryManager implements IHistoryManager {
  private readonly storageKey = CORE_SERVICE_KEYS.PROMPT_HISTORY;
  private readonly maxRecords = 50;
  private readonly storage: StorageAdapter;
  private readonly modelManager: IModelManager;
  
  constructor(storageProvider: IStorageProvider, modelManager: IModelManager) {
    this.storage = new StorageAdapter(storageProvider);
    this.modelManager = modelManager;
  }
}

```

**Key responsibilities include:**

- **`addRecord`** – Validates incoming `PromptRecord` objects, auto-populates `modelName` via `ModelManager.getModelNameByKey()` if missing, and inserts records at the head of the storage array while maintaining the 50-record limit through truncation.
- **`createNewChain`** – Generates a UUID for `chainId`, assigns version `1`, and persists the root record.
- **`addIteration`** – Retrieves the target chain, increments the version counter, sets type to `iterate`, and appends the new record to the chain.
- **`getChain` / `getAllChains`** – Filters records by `chainId`, sorts by version ascending, and constructs `PromptRecordChain` objects containing root, current, and full version history.
- **`deleteChain`** – Removes all records sharing a common `chainId`.
- **Import/Export** – Implements `IImportExportable` to clear existing data and bulk-import records while preserving original IDs and validating payload structure.

All storage operations wrap low-level errors in domain-specific exceptions (`HistoryStorageError`, `RecordNotFoundError`, `RecordValidationError`) defined in [`packages/core/src/services/history/errors.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/services/history/errors.ts).

### Electron IPC Proxy (electron-proxy.ts)

When running in the Electron desktop environment, the renderer process cannot access the filesystem directly. The `ElectronHistoryManagerProxy` class in [`packages/core/src/services/history/electron-proxy.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/services/history/electron-proxy.ts) implements `IHistoryManager` while forwarding calls to the main process via `window.electronAPI.history`.

```typescript
export class ElectronHistoryManagerProxy implements IHistoryManager {
  async addRecord(record: PromptRecord): Promise<void> {
    const safeRecord = safeSerializeForIPC(record);
    return this.electronAPI.history.addRecord(safeRecord);
  }
  // ... other methods follow same pattern
}

```

The `safeSerializeForIPC` utility (from [`packages/core/src/utils/ipc-serialization.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/utils/ipc-serialization.ts)) strips Vue reactivity proxies and other non-serializable properties to ensure valid JSON payloads across the IPC boundary.

### Error Handling Strategy (errors.ts)

The system employs a hierarchical error model in [`packages/core/src/services/history/errors.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/services/history/errors.ts) that extends base `HistoryError` classes with specific error codes from [`packages/core/src/constants/error-codes.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/constants/error-codes.ts). This architecture enables the UI layer to map technical failures to localized user messages based on structured error codes.

## Chain-Based Versioning System

The **PromptRecordChain** concept organizes history into logical sequences. Each chain originates with a root record (version 1) created via `createNewChain`. Subsequent optimizations or edits create iteration records with incrementing version numbers via `addIteration`.

This design maintains immutable snapshots of every prompt state while providing efficient access to the current version and full audit history. The chain structure supports branching visualization and rollback capabilities in the UI layer.

## Implementation Examples

### Creating a New History Chain

```typescript
import { createHistoryManager } from '@prompt-optimizer/core';
import { MemoryStorageProvider } from '@prompt-optimizer/core/src/services/storage/memory';
import { ModelManager } from '@prompt-optimizer/core/src/services/model/manager';

const storage = new MemoryStorageProvider();
const modelMgr = new ModelManager();
const history = createHistoryManager(storage, modelMgr);

const rootRecord = await history.createNewChain({
  id: crypto.randomUUID(),
  originalPrompt: 'Write a haiku about sunrise',
  optimizedPrompt: 'Compose a haiku describing sunrise',
  type: 'optimize',
  modelKey: 'gpt-4',
  templateId: 'default',
});

```

### Adding Iterations to Existing Chains

```typescript
const chainId = rootRecord.chainId;

await history.addIteration({
  chainId,
  originalPrompt: 'Compose a haiku describing sunrise',
  optimizedPrompt: 'Sun climbs, sky blushes – a fleeting gold kiss',
  modelKey: 'gpt-4',
  templateId: 'default',
  iterationNote: 'Made tone more vivid',
});

```

### Retrieving Chain History

```typescript
const chain = await history.getChain(chainId);
console.log('Root prompt:', chain.rootRecord.originalPrompt);
console.log('Current version:', chain.currentRecord.version);
console.log('Total iterations:', chain.versions.length);

```

### Exporting and Importing Data

```typescript
// Export for backup
const backupData = await history.exportData();
localStorage.setItem('history_backup', JSON.stringify(backupData));

// Import to restore or migrate
const importedData = JSON.parse(localStorage.getItem('history_backup'));
await history.importData(importedData);

```

### Electron Environment Setup

```typescript
import { ElectronHistoryManagerProxy } from '@prompt-optimizer/core';

const history = new ElectronHistoryManagerProxy();

// API identical to browser implementation
await history.addRecord({
  id: crypto.randomUUID(),
  originalPrompt: 'Explain quantum computing',
  optimizedPrompt: 'Explain quantum computing to a high school student',
  type: 'optimize',
  chainId: 'chain-xyz',
  version: 1,
  timestamp: Date.now(),
  modelKey: 'gpt-4',
  templateId: 'default',
});

```

## Summary

- The **history management system in prompt-optimizer** employs a strict three-layer architecture separating interfaces, business logic, and platform adapters.
- **PromptRecord** objects are immutable snapshots stored in versioned **PromptRecordChain** groupings with a default limit of 50 total records.
- **HistoryManager** in [`packages/core/src/services/history/manager.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/services/history/manager.ts) handles validation, model name resolution, and chain construction.
- **ElectronHistoryManagerProxy** enables desktop operation by serializing calls over IPC using `safeSerializeForIPC` to handle Vue reactivity wrappers.
- The **IImportExportable** interface provides portable backup and migration capabilities across storage backends.
- Domain-specific errors in [`packages/core/src/services/history/errors.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/services/history/errors.ts) provide structured error codes for UI localization.

## Frequently Asked Questions

### What is the maximum number of history records stored in prompt-optimizer?

The system enforces a default limit of **50 records**, defined by the `maxRecords` constant in [`packages/core/src/services/history/manager.ts`](https://github.com/linshenkx/prompt-optimizer/blob/main/packages/core/src/services/history/manager.ts). When adding new records via `addRecord`, the manager automatically truncates the oldest entries to maintain this limit, preventing unbounded storage growth in browser and desktop environments.

### How does prompt-optimizer handle model name resolution in history records?

When a `PromptRecord` is saved without an explicit `modelName`, the `HistoryManager` performs lazy resolution by querying the injected `IModelManager` instance via `getModelNameByKey()`. This lookup occurs during the `addRecord` validation phase, ensuring the stored record contains the human-readable display name required for UI rendering while maintaining the `modelKey` for technical references.

### Can history data be migrated between different storage backends?

Yes. The `IHistoryManager` interface extends `IImportExportable`, which exposes `exportData()` and `importData()` methods. These methods serialize the entire history collection to a plain JSON array of `PromptRecord` objects, allowing users to backup data from browser LocalStorage and restore it into Electron's filesystem storage or vice versa without losing chain relationships or version history.

### How does the Electron app access history storage?

In Electron environments, the renderer process instantiates `ElectronHistoryManagerProxy` instead of the direct `HistoryManager`. This proxy class implements the same interface but forwards all method calls to the main process via `window.electronAPI.history`. Before transmission, records pass through `safeSerializeForIPC` to remove framework-specific proxies, ensuring the IPC payload contains only vanilla JavaScript objects compatible with Electron's structured clone algorithm.