mirror of
https://github.com/sdwolf4103/opencode-working-memory.git
synced 2026-06-01 22:11:08 +02:00
Initial commit: OpenCode Working Memory Plugin v1.0.0
- Four-tier memory architecture (Core, Working, Pruning, Pressure) - Phase 1: Core Memory blocks (goal/progress/context) - Phase 2: Smart Pruning with adaptive thresholds - Phase 3: Working Memory with slots + pool decay - Phase 4: Pressure monitoring with interventions - Phase 4.5: Storage governance (session cleanup + cache sweep) - Complete documentation (README, AGENTS, installation, architecture, configuration) - MIT licensed
This commit is contained in:
+42
@@ -0,0 +1,42 @@
|
|||||||
|
# Dependencies
|
||||||
|
node_modules/
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
||||||
|
|
||||||
|
# Build outputs
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
*.tsbuildinfo
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Testing
|
||||||
|
coverage/
|
||||||
|
.nyc_output/
|
||||||
|
|
||||||
|
# Environment
|
||||||
|
.env
|
||||||
|
.env.local
|
||||||
|
.env.*.local
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
logs/
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
tmp/
|
||||||
|
temp/
|
||||||
|
*.tmp
|
||||||
|
|
||||||
|
# Package files
|
||||||
|
*.tgz
|
||||||
|
package-lock.json
|
||||||
|
yarn.lock
|
||||||
|
pnpm-lock.yaml
|
||||||
@@ -0,0 +1,340 @@
|
|||||||
|
# AGENTS.md - OpenCode Working Memory Plugin Development Guide
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
The **OpenCode Working Memory Plugin** provides a four-tier memory architecture for AI agents:
|
||||||
|
- **Core Memory** - Persistent blocks (goal/progress/context) that survive compaction
|
||||||
|
- **Working Memory** - Session-scoped context with slots (error/decision/todo/dependency) and memory pool
|
||||||
|
- **Smart Pruning** - Automatic filtering of tool outputs before adding to context
|
||||||
|
- **Pressure Monitoring** - Tracks context usage and triggers interventions at thresholds
|
||||||
|
|
||||||
|
Written in **TypeScript** for the OpenCode agent environment.
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# For development
|
||||||
|
git clone https://github.com/yourusername/opencode-working-memory.git
|
||||||
|
cd opencode-working-memory
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# For usage (see README.md)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Build & Development Commands
|
||||||
|
|
||||||
|
### Type Checking
|
||||||
|
```bash
|
||||||
|
# TypeScript strict mode - fix all type errors before committing
|
||||||
|
npx tsc --noEmit
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
Tests are manually verified through OpenCode sessions:
|
||||||
|
```bash
|
||||||
|
# 1. Load plugin in OpenCode session
|
||||||
|
# 2. Run commands that trigger hooks (e.g., tool execution, compaction)
|
||||||
|
# 3. Inspect .opencode/memory-core/ and .opencode/memory-working/
|
||||||
|
# 4. Verify memory blocks appear in system prompts
|
||||||
|
```
|
||||||
|
|
||||||
|
### File Structure
|
||||||
|
```
|
||||||
|
opencode-working-memory/
|
||||||
|
├── index.ts # Main plugin (1700+ lines)
|
||||||
|
├── package.json # Plugin manifest
|
||||||
|
├── tsconfig.json # TypeScript config
|
||||||
|
├── LICENSE # MIT license
|
||||||
|
├── README.md # User documentation
|
||||||
|
├── AGENTS.md # This file (developer guide)
|
||||||
|
└── docs/ # Detailed documentation
|
||||||
|
├── installation.md
|
||||||
|
├── architecture.md
|
||||||
|
└── configuration.md
|
||||||
|
```
|
||||||
|
|
||||||
|
## Code Style Guidelines
|
||||||
|
|
||||||
|
### TypeScript Strict Mode
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// ✅ REQUIRED: Full type annotations, no implicit any
|
||||||
|
async function loadCoreMemory(
|
||||||
|
directory: string,
|
||||||
|
sessionID: string
|
||||||
|
): Promise<CoreMemory | null>
|
||||||
|
|
||||||
|
// ❌ AVOID: Implicit any types
|
||||||
|
async function loadCoreMemory(directory, sessionID) { }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Type Definitions
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// ✅ REQUIRED: Define types at module top
|
||||||
|
type CoreMemory = {
|
||||||
|
sessionID: string;
|
||||||
|
blocks: {
|
||||||
|
goal: CoreBlock;
|
||||||
|
progress: CoreBlock;
|
||||||
|
context: CoreBlock;
|
||||||
|
};
|
||||||
|
updatedAt: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
// ✅ USE: Union types for variants (not enums)
|
||||||
|
type PressureLevel = "safe" | "moderate" | "high" | "critical";
|
||||||
|
|
||||||
|
// ✅ USE: Record<> for keyed configs
|
||||||
|
const SLOT_CONFIG: Record<SlotType, number> = {
|
||||||
|
error: 3,
|
||||||
|
decision: 5,
|
||||||
|
todo: 3,
|
||||||
|
dependency: 3,
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
### Imports & Module Organization
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// ✅ REQUIRED: Group and order imports
|
||||||
|
// 1. Node.js built-ins
|
||||||
|
import { existsSync } from "fs";
|
||||||
|
import { mkdir, readFile, writeFile } from "fs/promises";
|
||||||
|
import { join } from "path";
|
||||||
|
|
||||||
|
// 2. Third-party (OpenCode SDK)
|
||||||
|
import type { Plugin } from "@opencode-ai/plugin";
|
||||||
|
import { tool } from "@opencode-ai/plugin";
|
||||||
|
|
||||||
|
// 3. Local modules (if any)
|
||||||
|
// (none currently)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Naming Conventions
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// ✅ REQUIRED: camelCase for variables & functions
|
||||||
|
const maxItems = 50;
|
||||||
|
async function loadCoreMemory() { }
|
||||||
|
|
||||||
|
// ✅ REQUIRED: SCREAMING_SNAKE_CASE for constants
|
||||||
|
const CORE_MEMORY_LIMITS = { goal: 1000, progress: 2000, context: 1500 };
|
||||||
|
const SLOT_CONFIG = { error: 3, decision: 5, todo: 3, dependency: 3 };
|
||||||
|
|
||||||
|
// ✅ REQUIRED: PascalCase for types
|
||||||
|
type CoreMemory = { ... };
|
||||||
|
type WorkingMemoryItem = { ... };
|
||||||
|
|
||||||
|
// ✅ REQUIRED: get*/set*/load*/save* naming for file operations
|
||||||
|
function getCoreMemoryPath(directory: string, sessionID: string): string { }
|
||||||
|
async function loadCoreMemory(directory: string, sessionID: string): Promise<CoreMemory | null> { }
|
||||||
|
async function saveCoreMemory(directory: string, memory: CoreMemory): Promise<void> { }
|
||||||
|
|
||||||
|
// ✅ REQUIRED: ensure*/validate* for pre-checks
|
||||||
|
async function ensureCoreMemoryDir(directory: string): Promise<void> { }
|
||||||
|
|
||||||
|
// ✅ REQUIRED: Prefix private/internal functions with _
|
||||||
|
function _compressPath(filePath: string): string { }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Function Signatures & Organization
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// ✅ REQUIRED: Parameters on separate lines if > 80 chars
|
||||||
|
async function loadWorkingMemory(
|
||||||
|
directory: string,
|
||||||
|
sessionID: string
|
||||||
|
): Promise<WorkingMemory | null> {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ REQUIRED: Explicit return types (no inference)
|
||||||
|
function getCompactionLogPath(directory: string, sessionID: string): string {
|
||||||
|
return join(directory, ".opencode", "memory-working", `${sessionID}_compaction.json`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ REQUIRED: Async for file/network I/O
|
||||||
|
async function saveCoreMemory(directory: string, memory: CoreMemory): Promise<void> {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Error Handling
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// ✅ REQUIRED: Try-catch with descriptive console.error
|
||||||
|
async function loadCoreMemory(directory: string, sessionID: string): Promise<CoreMemory | null> {
|
||||||
|
const path = getCoreMemoryPath(directory, sessionID);
|
||||||
|
if (!existsSync(path)) return null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
const content = await readFile(path, "utf-8");
|
||||||
|
return JSON.parse(content) as CoreMemory;
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to load core memory:", error);
|
||||||
|
return null; // Graceful degradation
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ REQUIRED: Type guards for runtime safety
|
||||||
|
if (!existsSync(path)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ REQUIRED: Validate JSON before use
|
||||||
|
const data = JSON.parse(content);
|
||||||
|
const typedData = data as CoreMemory; // Explicit cast after validation
|
||||||
|
```
|
||||||
|
|
||||||
|
### Comments & Documentation
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// ✅ REQUIRED: Section headers for major sections
|
||||||
|
// ============================================================================
|
||||||
|
// Phase 1: Core Memory Foundation
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
// ✅ REQUIRED: Block comments for complex logic
|
||||||
|
// Migration: Convert old format (items array) to new format (slots + pool)
|
||||||
|
if (data.items && !data.slots) {
|
||||||
|
// ... migration logic
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ USE: Inline comments sparingly
|
||||||
|
const gamma = 0.85; // Exponential decay rate (15% per event)
|
||||||
|
|
||||||
|
// ✅ AVOID: Over-commenting obvious code
|
||||||
|
const name = "test"; // Set name to test ❌ (obvious)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Code Organization
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// ✅ REQUIRED: Organize plugin file by phase/feature
|
||||||
|
// 1. Header & module documentation
|
||||||
|
// 2. Imports
|
||||||
|
// 3. Types & schemas (grouped by phase)
|
||||||
|
// 4. Constants & configs
|
||||||
|
// 5. Helper functions (private first, public after)
|
||||||
|
// 6. Main plugin export
|
||||||
|
// 7. Hook implementations
|
||||||
|
|
||||||
|
export default {
|
||||||
|
// Plugin definition
|
||||||
|
} as Plugin;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Working with OpenCode Plugin SDK
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// ✅ REQUIRED: Use proper hook signatures
|
||||||
|
import { tool, type Plugin } from "@opencode-ai/plugin";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
id: "working-memory",
|
||||||
|
name: "Working Memory Plugin",
|
||||||
|
|
||||||
|
// ✅ Core hooks
|
||||||
|
hooks: {
|
||||||
|
"tool.execute.after": async (ctx) => {
|
||||||
|
// Tool just executed
|
||||||
|
},
|
||||||
|
"experimental.chat.system.transform": async (ctx) => {
|
||||||
|
// Transform system prompt before sending
|
||||||
|
},
|
||||||
|
"experimental.session.compacting": async (ctx) => {
|
||||||
|
// Session is being compacted (clearing old messages)
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
// ✅ Exposed tools
|
||||||
|
tools: [
|
||||||
|
tool({
|
||||||
|
id: "core_memory_update",
|
||||||
|
name: "Update Core Memory",
|
||||||
|
description: "Update goal/progress/context blocks",
|
||||||
|
// ... schema & execute
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
} as Plugin;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Key Implementation Details
|
||||||
|
|
||||||
|
### Core Memory Files
|
||||||
|
- Location: `.opencode/memory-core/<sessionID>.json`
|
||||||
|
- Schema: `{ sessionID, blocks: { goal, progress, context }, updatedAt }`
|
||||||
|
- Limits: goal (1000 chars), progress (2000 chars), context (1500 chars)
|
||||||
|
|
||||||
|
### Working Memory Files
|
||||||
|
- Location: `.opencode/memory-working/<sessionID>.json`
|
||||||
|
- Schema: `{ sessionID, slots, pool, eventCounter, updatedAt }`
|
||||||
|
- Slot limits: error (3), decision (5), todo (3), dependency (3)
|
||||||
|
- Pool decay: γ=0.85 per event
|
||||||
|
|
||||||
|
### Pressure Monitoring
|
||||||
|
- Triggers at: 70% (safe→moderate), 85% (moderate→high), 95% (high→critical)
|
||||||
|
- Files: `.opencode/memory-working/<sessionID>_pressure.json`
|
||||||
|
- Intervention: Sends `promptAsync()` with complete visible prompt
|
||||||
|
|
||||||
|
### Storage Governance (Layer 1 & 2)
|
||||||
|
- **Layer 1**: Session deletion cleanup - removes orphaned memory files
|
||||||
|
- **Layer 2**: Tool output cache sweep - maintains 300 most recent files, 7-day TTL
|
||||||
|
- Triggered at `eventCounter % 500 === 0` (automatic maintenance)
|
||||||
|
|
||||||
|
## Debugging & Testing
|
||||||
|
|
||||||
|
### Manual Testing Steps
|
||||||
|
1. **Phase 1 (Core Memory)**: Check `.opencode/memory-core/` after `core_memory_update`
|
||||||
|
2. **Phase 2 (Smart Pruning)**: Verify tool outputs are filtered before context injection
|
||||||
|
3. **Phase 3 (Working Memory)**: Check `.opencode/memory-working/` for slot/pool items
|
||||||
|
4. **Phase 4 (Pressure Monitoring)**: Monitor pressure % in system prompts, verify interventions
|
||||||
|
5. **Phase 4.5 (Storage Governance)**: Run 500+ events, check sweep logs
|
||||||
|
|
||||||
|
### Common Issues
|
||||||
|
- **File not found**: Ensure `.opencode/` directory exists and is writable
|
||||||
|
- **Type errors**: Check all imports use `import type { ... }` for types
|
||||||
|
- **Lost memory**: Verify `.opencode/memory-*/` is in `.gitignore` (not committed)
|
||||||
|
- **Sweep not running**: Check `eventCounter` in `<sessionID>.json`, should trigger at multiples of 500
|
||||||
|
|
||||||
|
## Performance Considerations
|
||||||
|
|
||||||
|
- **Memory budgets**: Core (5.5k chars total), Working (1.6k chars for system prompt)
|
||||||
|
- **Pruning**: Hyper-aggressive mode activates at ≥85% pressure
|
||||||
|
- **Compaction**: Preserves most recent 10 items when space-constrained
|
||||||
|
- **Decay**: Pool items scored by exponential decay (γ=0.85) + mention count
|
||||||
|
- **Storage sweep**: Limits cache to 300 files, removes files older than 7 days
|
||||||
|
|
||||||
|
## File Path References
|
||||||
|
|
||||||
|
When referencing code locations in documentation/comments, use:
|
||||||
|
```
|
||||||
|
path/to/file.ts:L123 or path/to/file.ts:Line 123
|
||||||
|
```
|
||||||
|
|
||||||
|
Example: `Function sendPressureInterventionMessage() @ index.ts:L1286`
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
1. Fork the repository
|
||||||
|
2. Create a feature branch: `git checkout -b feature/my-feature`
|
||||||
|
3. Make changes following the code style guidelines above
|
||||||
|
4. Test manually in OpenCode session
|
||||||
|
5. Commit with descriptive message: `git commit -m "Add feature: ..."`
|
||||||
|
6. Push to your fork: `git push origin feature/my-feature`
|
||||||
|
7. Open a pull request
|
||||||
|
|
||||||
|
## Architecture Documentation
|
||||||
|
|
||||||
|
See `docs/architecture.md` for detailed technical documentation including:
|
||||||
|
- Memory tier hierarchy
|
||||||
|
- Pruning algorithms
|
||||||
|
- Decay formulas
|
||||||
|
- Pressure monitoring logic
|
||||||
|
- Storage governance policies
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Last Updated**: February 2026
|
||||||
|
**Plugin Status**: Production (Phases 1-4.5 complete)
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2026 OpenCode Working Memory Contributors
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
@@ -0,0 +1,242 @@
|
|||||||
|
# OpenCode Working Memory Plugin
|
||||||
|
|
||||||
|
[](https://www.npmjs.com/package/opencode-working-memory)
|
||||||
|
[](LICENSE)
|
||||||
|
|
||||||
|
**Advanced four-tier memory architecture that keeps your AI agent sharp, focused, and never forgets what matters.**
|
||||||
|
|
||||||
|
Stop losing context across compactions. Stop watching your agent repeat the same mistakes. This plugin gives your OpenCode agent a professional-grade memory system that scales with your project complexity.
|
||||||
|
|
||||||
|
## What You Get
|
||||||
|
|
||||||
|
- 🧠 **Core Memory** - Persistent goal/progress/context blocks that survive compaction
|
||||||
|
- 💡 **Working Memory** - Smart slot-based system (errors, decisions, todos, dependencies)
|
||||||
|
- 🎯 **Memory Pressure Monitoring** - Real-time token tracking with automatic interventions
|
||||||
|
- 🧹 **Auto Storage Governance** - Prevents unbounded disk growth (300 files/session, 7-day TTL)
|
||||||
|
- 📊 **Smart Pruning** - Pressure-aware tool output compression
|
||||||
|
- ⚡ **Zero Configuration** - Works out of the box, highly customizable
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
### For Humans
|
||||||
|
|
||||||
|
**Option A: Let an LLM do it**
|
||||||
|
|
||||||
|
Paste this into Claude Code, Cursor, or any AI agent:
|
||||||
|
|
||||||
|
```
|
||||||
|
Install opencode-working-memory plugin by following:
|
||||||
|
https://raw.githubusercontent.com/yourusername/opencode-working-memory/main/docs/installation.md
|
||||||
|
```
|
||||||
|
|
||||||
|
**Option B: Manual setup**
|
||||||
|
|
||||||
|
1. Add to your `~/.config/opencode/opencode.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"plugin": ["opencode-working-memory"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Restart OpenCode
|
||||||
|
|
||||||
|
That's it! The plugin is now active.
|
||||||
|
|
||||||
|
### For LLM Agents
|
||||||
|
|
||||||
|
1. Read the OpenCode configuration file at `~/.config/opencode/opencode.json`
|
||||||
|
2. Add `"opencode-working-memory"` to the `plugin` array
|
||||||
|
3. Verify installation by checking the config file
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
The plugin works automatically once installed. No configuration needed.
|
||||||
|
|
||||||
|
**Use the tools:**
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Update persistent memory
|
||||||
|
opencode run "use core_memory_update to set my goal"
|
||||||
|
|
||||||
|
# Read current memory state
|
||||||
|
opencode run "use core_memory_read to show me what you remember"
|
||||||
|
|
||||||
|
# Add important items to working memory
|
||||||
|
opencode run "use working_memory_add to remember this file path"
|
||||||
|
```
|
||||||
|
|
||||||
|
**The agent will automatically:**
|
||||||
|
- Track memory pressure and warn when approaching compaction
|
||||||
|
- Preserve important context during compaction
|
||||||
|
- Clean up old tool-output cache files every 20 tool calls
|
||||||
|
- Remove artifacts when sessions are deleted
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
### 🧠 Core Memory (Phase 1)
|
||||||
|
|
||||||
|
Persistent blocks that survive conversation resets:
|
||||||
|
|
||||||
|
- **goal** (1000 chars) - Current task/objective
|
||||||
|
- **progress** (2000 chars) - What's done, in-progress, next steps
|
||||||
|
- **context** (1500 chars) - Key file paths, conventions, patterns
|
||||||
|
|
||||||
|
### 💡 Working Memory (Phase 3)
|
||||||
|
|
||||||
|
Auto-extracts and ranks important information:
|
||||||
|
|
||||||
|
- **Slots** (guaranteed visibility): errors, decisions, todos, dependencies
|
||||||
|
- **Pool** (ranked by relevance): file paths, recent activity
|
||||||
|
- Exponential decay keeps memory fresh
|
||||||
|
- FIFO limits prevent bloat
|
||||||
|
|
||||||
|
### 🎯 Memory Pressure Monitoring (Phase 4)
|
||||||
|
|
||||||
|
Real-time token tracking from session database:
|
||||||
|
|
||||||
|
- Monitors context window usage (75% → 90% → 95% thresholds)
|
||||||
|
- Proactive intervention messages when pressure is high
|
||||||
|
- Pressure-aware smart pruning (adapts compression based on pressure)
|
||||||
|
|
||||||
|
### 🧹 Storage Governance (Phase 5)
|
||||||
|
|
||||||
|
Prevents unbounded disk growth:
|
||||||
|
|
||||||
|
- **Layer 1**: Auto-cleanup on session deletion (all artifacts removed)
|
||||||
|
- **Layer 2**: Active cache management (max 300 files/session, 7-day TTL)
|
||||||
|
- Triggers every 20 tool calls
|
||||||
|
- Silent background operation
|
||||||
|
|
||||||
|
### 📊 Smart Pruning (Phase 2)
|
||||||
|
|
||||||
|
Intelligent tool output compression:
|
||||||
|
|
||||||
|
- Per-tool strategies (keep-all, keep-ends, keep-last, discard)
|
||||||
|
- Pressure-aware limits (2k/5k/10k lines based on memory pressure)
|
||||||
|
- Preserves important context while reducing noise
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
- [Installation Guide](docs/installation.md) - Detailed setup instructions
|
||||||
|
- [Architecture Overview](docs/architecture.md) - How it works under the hood
|
||||||
|
- [Configuration](docs/configuration.md) - Customization options
|
||||||
|
- [Agent Developer Guide](AGENTS.md) - For plugin developers
|
||||||
|
|
||||||
|
## Tools Provided
|
||||||
|
|
||||||
|
The plugin exposes these tools to your OpenCode agent:
|
||||||
|
|
||||||
|
- `core_memory_update` - Update goal/progress/context blocks
|
||||||
|
- `core_memory_read` - Read current memory state
|
||||||
|
- `working_memory_add` - Manually add important items
|
||||||
|
- `working_memory_clear` - Clear all working memory
|
||||||
|
- `working_memory_clear_slot` - Clear specific slot (errors/decisions)
|
||||||
|
- `working_memory_remove` - Remove specific item by content
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ Core Memory (Always Visible) │
|
||||||
|
│ ┌─────────┬──────────┬──────────┐ │
|
||||||
|
│ │ Goal │ Progress │ Context │ │
|
||||||
|
│ └─────────┴──────────┴──────────┘ │
|
||||||
|
└─────────────────────────────────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ Working Memory (Auto-Extracted) │
|
||||||
|
│ ┌──────────────────┬──────────────────┐ │
|
||||||
|
│ │ Slots (FIFO) │ Pool (Ranked) │ │
|
||||||
|
│ │ • errors │ • file-paths │ │
|
||||||
|
│ │ • decisions │ • recent │ │
|
||||||
|
│ │ • todos │ • mentions │ │
|
||||||
|
│ │ • dependencies │ • decay score │ │
|
||||||
|
│ └──────────────────┴──────────────────┘ │
|
||||||
|
└─────────────────────────────────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ Memory Pressure Monitor │
|
||||||
|
│ • Tracks tokens from session DB │
|
||||||
|
│ • Warns at 75% / 90% / 95% │
|
||||||
|
│ • Sends proactive interventions │
|
||||||
|
│ • Adjusts pruning aggressiveness │
|
||||||
|
└─────────────────────────────────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────────────────────┐
|
||||||
|
│ Storage Governance │
|
||||||
|
│ • Session deletion → cleanup all artifacts │
|
||||||
|
│ • Every 20 calls → sweep old cache (300 max, 7d TTL) │
|
||||||
|
│ • Silent background operation │
|
||||||
|
└─────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Why This Plugin?
|
||||||
|
|
||||||
|
**Without this plugin:**
|
||||||
|
- 🔴 Agent forgets context after compaction
|
||||||
|
- 🔴 Repeats resolved errors
|
||||||
|
- 🔴 Loses track of project structure
|
||||||
|
- 🔴 Context window fills up uncontrollably
|
||||||
|
- 🔴 Disk space grows unbounded
|
||||||
|
|
||||||
|
**With this plugin:**
|
||||||
|
- ✅ Persistent memory across compactions
|
||||||
|
- ✅ Smart auto-extraction of important info
|
||||||
|
- ✅ Real-time pressure monitoring with interventions
|
||||||
|
- ✅ Automatic storage cleanup
|
||||||
|
- ✅ Pressure-aware compression
|
||||||
|
- ✅ Zero configuration, works immediately
|
||||||
|
|
||||||
|
## Configuration (Optional)
|
||||||
|
|
||||||
|
The plugin works great with zero configuration. But if you want to customize:
|
||||||
|
|
||||||
|
Create `~/.config/opencode/working-memory.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"storage_governance": {
|
||||||
|
"tool_output_max_files": 300,
|
||||||
|
"tool_output_max_age_ms": 604800000,
|
||||||
|
"sweep_interval": 20
|
||||||
|
},
|
||||||
|
"memory_pressure": {
|
||||||
|
"thresholds": {
|
||||||
|
"moderate": 0.75,
|
||||||
|
"high": 0.90,
|
||||||
|
"critical": 0.95
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
See [Configuration Guide](docs/configuration.md) for all options.
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- OpenCode >= 1.0.0
|
||||||
|
- Node.js >= 18.0.0
|
||||||
|
- `@opencode-ai/plugin` >= 1.2.0
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT License - see [LICENSE](LICENSE) file for details.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
Contributions welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) first.
|
||||||
|
|
||||||
|
## Support
|
||||||
|
|
||||||
|
- 📖 [Documentation](docs/)
|
||||||
|
- 🐛 [Report Issues](https://github.com/yourusername/opencode-working-memory/issues)
|
||||||
|
- 💬 [Discussions](https://github.com/yourusername/opencode-working-memory/discussions)
|
||||||
|
|
||||||
|
## Credits
|
||||||
|
|
||||||
|
Inspired by the needs of real-world OpenCode usage and built to solve actual pain points in AI-assisted development.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Made with ❤️ for the OpenCode community**
|
||||||
@@ -0,0 +1,376 @@
|
|||||||
|
# Architecture Documentation
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The Working Memory Plugin implements a **four-tier memory architecture** designed to maximize context efficiency for AI agents in OpenCode sessions.
|
||||||
|
|
||||||
|
```
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ TIER 1: CORE MEMORY │
|
||||||
|
│ Persistent blocks: goal (1000) | progress (2000) | context (1500) │
|
||||||
|
│ Survives compaction, always visible in system prompt │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ TIER 2: WORKING MEMORY │
|
||||||
|
│ Session-scoped slots + memory pool │
|
||||||
|
│ Slots: error(3) | decision(5) | todo(3) | dependency(3) │
|
||||||
|
│ Pool: Exponential decay (γ=0.85) + mention tracking │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ TIER 3: SMART PRUNING │
|
||||||
|
│ Filters tool outputs before adding to conversation │
|
||||||
|
│ Removes: file lists, verbose logs, repetitive content │
|
||||||
|
│ Modes: normal → aggressive → hyper-aggressive │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
↓
|
||||||
|
┌─────────────────────────────────────────────────────────────┐
|
||||||
|
│ TIER 4: PRESSURE MONITORING │
|
||||||
|
│ Tracks context usage: safe → moderate → high → critical │
|
||||||
|
│ Thresholds: 70% | 85% | 95% │
|
||||||
|
│ Intervention: Sends promptAsync() with full visible prompt │
|
||||||
|
└─────────────────────────────────────────────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## Phase 1: Core Memory Foundation
|
||||||
|
|
||||||
|
### Purpose
|
||||||
|
Provide persistent memory blocks that survive conversation compaction and are always injected into the system prompt.
|
||||||
|
|
||||||
|
### Storage
|
||||||
|
- **Location**: `.opencode/memory-core/<sessionID>.json`
|
||||||
|
- **Schema**:
|
||||||
|
```typescript
|
||||||
|
{
|
||||||
|
sessionID: string;
|
||||||
|
blocks: {
|
||||||
|
goal: { content: string; chars: number; maxChars: 1000; updatedAt: string };
|
||||||
|
progress: { content: string; chars: number; maxChars: 2000; updatedAt: string };
|
||||||
|
context: { content: string; chars: number; maxChars: 1500; updatedAt: string };
|
||||||
|
};
|
||||||
|
updatedAt: string;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Character Limits
|
||||||
|
- **goal**: 1000 chars (ONE specific task)
|
||||||
|
- **progress**: 2000 chars (done/in-progress/blocked checklist)
|
||||||
|
- **context**: 1500 chars (current working files + key patterns)
|
||||||
|
|
||||||
|
### Operations
|
||||||
|
- **replace**: Completely replace block content
|
||||||
|
- **append**: Add content to end (auto-adds newline)
|
||||||
|
|
||||||
|
### Tools
|
||||||
|
- `core_memory_update`: Update or append to blocks
|
||||||
|
- `core_memory_read`: Read current state of all blocks
|
||||||
|
|
||||||
|
### System Prompt Injection
|
||||||
|
Blocks are injected into every agent message as:
|
||||||
|
```
|
||||||
|
<core_memory>
|
||||||
|
<goal chars="87/1000">...</goal>
|
||||||
|
<progress chars="560/2000">...</progress>
|
||||||
|
<context chars="479/1500">...</context>
|
||||||
|
</core_memory>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Phase 2: Smart Pruning
|
||||||
|
|
||||||
|
### Purpose
|
||||||
|
Reduce context bloat by filtering tool outputs before they enter the conversation history.
|
||||||
|
|
||||||
|
### Pruning Modes
|
||||||
|
|
||||||
|
#### Normal Mode (Pressure < 85%)
|
||||||
|
- Remove file/directory listings > 50 lines
|
||||||
|
- Truncate verbose tool outputs
|
||||||
|
- Keep first/last 30 lines of long outputs
|
||||||
|
- Preserve error messages and key information
|
||||||
|
|
||||||
|
#### Aggressive Mode (85% ≤ Pressure < 95%)
|
||||||
|
- Threshold drops to 30 lines
|
||||||
|
- More aggressive truncation (first/last 20 lines)
|
||||||
|
- Filter repetitive content
|
||||||
|
|
||||||
|
#### Hyper-Aggressive Mode (Pressure ≥ 95%)
|
||||||
|
- Threshold drops to 15 lines
|
||||||
|
- Keep only first/last 10 lines
|
||||||
|
- Maximum compression
|
||||||
|
|
||||||
|
### Pruning Heuristics
|
||||||
|
|
||||||
|
1. **File Listings**: Detect `ls`, `find`, `glob` outputs
|
||||||
|
2. **Directory Trees**: Detect tree-like structures with `/`
|
||||||
|
3. **Log Files**: Detect timestamp patterns, stack traces
|
||||||
|
4. **Repetitive Content**: Detect similar consecutive lines
|
||||||
|
5. **Synthetic Content**: Preserve `synthetic: true` markers
|
||||||
|
|
||||||
|
### Implementation
|
||||||
|
Pruning happens in `tool.execute.after` hook before tool output enters conversation.
|
||||||
|
|
||||||
|
## Phase 3: Working Memory
|
||||||
|
|
||||||
|
### Purpose
|
||||||
|
Provide session-scoped memory with structured slots and a general-purpose pool with intelligent decay.
|
||||||
|
|
||||||
|
### Storage
|
||||||
|
- **Location**: `.opencode/memory-working/<sessionID>.json`
|
||||||
|
- **Schema**:
|
||||||
|
```typescript
|
||||||
|
{
|
||||||
|
sessionID: string;
|
||||||
|
slots: {
|
||||||
|
error: Array<WorkingMemoryItem>; // Max 3
|
||||||
|
decision: Array<WorkingMemoryItem>; // Max 5
|
||||||
|
todo: Array<WorkingMemoryItem>; // Max 3
|
||||||
|
dependency: Array<WorkingMemoryItem>; // Max 3
|
||||||
|
};
|
||||||
|
pool: Array<WorkingMemoryItem>;
|
||||||
|
eventCounter: number;
|
||||||
|
updatedAt: string;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Slot Types
|
||||||
|
|
||||||
|
| Slot | Max Items | Purpose |
|
||||||
|
|------|-----------|---------|
|
||||||
|
| **error** | 3 | Recent errors that need fixing |
|
||||||
|
| **decision** | 5 | Important decisions made |
|
||||||
|
| **todo** | 3 | Current task checklist |
|
||||||
|
| **dependency** | 3 | File/package dependencies |
|
||||||
|
|
||||||
|
### Memory Pool
|
||||||
|
|
||||||
|
General-purpose storage with **exponential decay**:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
score = exp(-γ * age) + mentionCount
|
||||||
|
```
|
||||||
|
|
||||||
|
Where:
|
||||||
|
- `γ = 0.85` (decay rate, 15% per event)
|
||||||
|
- `age = eventCounter - item.eventNumber`
|
||||||
|
- `mentionCount`: Number of times item mentioned in conversation
|
||||||
|
|
||||||
|
Items with `score < 0.01` are pruned.
|
||||||
|
|
||||||
|
### Auto-Extraction
|
||||||
|
|
||||||
|
Working memory items are **automatically extracted** from:
|
||||||
|
- Tool outputs (file paths, errors, dependencies)
|
||||||
|
- User messages (decisions, todos)
|
||||||
|
- Assistant responses (key information)
|
||||||
|
|
||||||
|
### Manual Management
|
||||||
|
|
||||||
|
Tools:
|
||||||
|
- `working_memory_add`: Manually add item
|
||||||
|
- `working_memory_clear`: Clear all items
|
||||||
|
- `working_memory_clear_slot`: Clear specific slot (e.g., after fixing all errors)
|
||||||
|
- `working_memory_remove`: Remove specific item by content match
|
||||||
|
|
||||||
|
### System Prompt Injection
|
||||||
|
|
||||||
|
```
|
||||||
|
<working_memory>
|
||||||
|
Recent session context (auto-managed, sorted by relevance):
|
||||||
|
|
||||||
|
⚠️ Errors:
|
||||||
|
- TypeError at line 42 in utils.ts
|
||||||
|
- Missing import in index.ts
|
||||||
|
|
||||||
|
📁 Key Files:
|
||||||
|
- src/components/Button.tsx
|
||||||
|
- src/utils/helpers.ts
|
||||||
|
|
||||||
|
(15 items shown, updated: 9:46:47 AM)
|
||||||
|
</working_memory>
|
||||||
|
```
|
||||||
|
|
||||||
|
## Phase 4: Pressure Monitoring
|
||||||
|
|
||||||
|
### Purpose
|
||||||
|
Track conversation context usage and trigger interventions when approaching limits.
|
||||||
|
|
||||||
|
### Pressure Calculation
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
pressure = (visiblePromptChars / estimatedContextLimit) * 100
|
||||||
|
```
|
||||||
|
|
||||||
|
Where:
|
||||||
|
- `visiblePromptChars`: Total characters in system prompt + tool outputs
|
||||||
|
- `estimatedContextLimit`: ~180,000 chars (conservative estimate)
|
||||||
|
|
||||||
|
### Pressure Levels
|
||||||
|
|
||||||
|
| Level | Threshold | Behavior |
|
||||||
|
|-------|-----------|----------|
|
||||||
|
| **safe** | < 70% | Normal operation |
|
||||||
|
| **moderate** | 70-84% | Warning in system prompt |
|
||||||
|
| **high** | 85-94% | Aggressive pruning + warning |
|
||||||
|
| **critical** | ≥ 95% | Hyper-aggressive pruning + intervention |
|
||||||
|
|
||||||
|
### Pressure Storage
|
||||||
|
|
||||||
|
- **Location**: `.opencode/memory-working/<sessionID>_pressure.json`
|
||||||
|
- **Schema**:
|
||||||
|
```typescript
|
||||||
|
{
|
||||||
|
sessionID: string;
|
||||||
|
level: "safe" | "moderate" | "high" | "critical";
|
||||||
|
percentage: number;
|
||||||
|
visiblePromptChars: number;
|
||||||
|
estimatedLimit: 180000;
|
||||||
|
lastChecked: string;
|
||||||
|
interventionsSent: number;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Intervention Mechanism
|
||||||
|
|
||||||
|
When pressure reaches **critical** (≥95%):
|
||||||
|
1. Plugin sends `promptAsync()` message to agent
|
||||||
|
2. Message includes full visible prompt for review
|
||||||
|
3. Agent can compress core memory, clear working memory, or continue
|
||||||
|
4. Intervention tracked in `interventionsSent` counter
|
||||||
|
|
||||||
|
### System Prompt Injection
|
||||||
|
|
||||||
|
```
|
||||||
|
[Memory Pressure: 87% (high) - 156,600/180,000 chars]
|
||||||
|
⚠️ High memory pressure detected. Consider:
|
||||||
|
- Compressing core_memory blocks (use core_memory_update)
|
||||||
|
- Clearing resolved errors (use working_memory_clear_slot)
|
||||||
|
- Removing old pool items (auto-pruned at score < 0.01)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Phase 4.5: Storage Governance
|
||||||
|
|
||||||
|
### Purpose
|
||||||
|
Prevent `.opencode/` directory bloat from accumulating tool output caches and orphaned memory files.
|
||||||
|
|
||||||
|
### Layer 1: Session Deletion Cleanup
|
||||||
|
|
||||||
|
**Trigger**: `experimental.session.deleted` hook
|
||||||
|
|
||||||
|
**Actions**:
|
||||||
|
1. Remove `.opencode/memory-core/<sessionID>.json`
|
||||||
|
2. Remove `.opencode/memory-working/<sessionID>.json`
|
||||||
|
3. Remove `.opencode/memory-working/<sessionID>_pressure.json`
|
||||||
|
4. Remove `.opencode/memory-working/<sessionID>_compaction.json`
|
||||||
|
|
||||||
|
### Layer 2: Tool Output Cache Sweep
|
||||||
|
|
||||||
|
**Trigger**: Every 500 events (`eventCounter % 500 === 0`)
|
||||||
|
|
||||||
|
**Target**: `.opencode/cache/tool-outputs/` directory
|
||||||
|
|
||||||
|
**Policy**:
|
||||||
|
- Keep most recent **300 files** (sorted by mtime)
|
||||||
|
- Delete files older than **7 days** (TTL policy)
|
||||||
|
|
||||||
|
**Logging**: Write sweep results to `.opencode/memory-working/<sessionID>_sweep.json`
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
{
|
||||||
|
sessionID: string;
|
||||||
|
timestamp: string;
|
||||||
|
eventCounter: number;
|
||||||
|
results: {
|
||||||
|
filesScanned: number;
|
||||||
|
filesDeleted: number;
|
||||||
|
bytesReclaimed: number;
|
||||||
|
errors: Array<string>;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Performance Considerations
|
||||||
|
|
||||||
|
### Memory Budgets
|
||||||
|
- **Core Memory**: 4,500 chars (injected every message)
|
||||||
|
- **Working Memory**: ~1,600 chars (injected every message)
|
||||||
|
- **Total Overhead**: ~6,100 chars per message
|
||||||
|
|
||||||
|
### Compaction Behavior
|
||||||
|
When OpenCode compacts conversation (clears old messages):
|
||||||
|
- Core memory: **Preserved** (persistent across compactions)
|
||||||
|
- Working memory: **Preserved** (session-scoped, cleared on session end)
|
||||||
|
- Pressure state: **Preserved** (tracks across compaction)
|
||||||
|
- Compaction log: Saved to `<sessionID>_compaction.json`
|
||||||
|
|
||||||
|
### Storage Footprint
|
||||||
|
- Each session: 4 JSON files (~5-20 KB total)
|
||||||
|
- Tool output cache: Max 300 files (~10-50 MB depending on outputs)
|
||||||
|
- Sweep every 500 events keeps storage bounded
|
||||||
|
|
||||||
|
## Extension Points
|
||||||
|
|
||||||
|
### Custom Slot Types
|
||||||
|
To add new slot types:
|
||||||
|
1. Update `SlotType` union in types
|
||||||
|
2. Add to `SLOT_CONFIG` with max items
|
||||||
|
3. Update `formatWorkingMemoryForPrompt()` for display
|
||||||
|
4. Update extraction heuristics in `tool.execute.after`
|
||||||
|
|
||||||
|
### Custom Pruning Rules
|
||||||
|
To add pruning heuristics:
|
||||||
|
1. Update `shouldPrune()` with new detection logic
|
||||||
|
2. Add to `pruneToolOutput()` with filtering rules
|
||||||
|
3. Test with representative tool outputs
|
||||||
|
|
||||||
|
### Custom Pressure Thresholds
|
||||||
|
Adjust in constants:
|
||||||
|
```typescript
|
||||||
|
const PRESSURE_THRESHOLDS = {
|
||||||
|
moderate: 70,
|
||||||
|
high: 85,
|
||||||
|
critical: 95,
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
## Migration & Compatibility
|
||||||
|
|
||||||
|
### Old Format → New Format
|
||||||
|
Plugin automatically migrates from old format:
|
||||||
|
```typescript
|
||||||
|
// Old format (pre-Phase 3)
|
||||||
|
{ items: Array<Item> }
|
||||||
|
|
||||||
|
// New format (Phase 3+)
|
||||||
|
{ slots: Record<SlotType, Array<Item>>, pool: Array<Item> }
|
||||||
|
```
|
||||||
|
|
||||||
|
Migration happens on first load of old format files.
|
||||||
|
|
||||||
|
## File System Layout
|
||||||
|
|
||||||
|
```
|
||||||
|
.opencode/
|
||||||
|
├── memory-core/
|
||||||
|
│ └── <sessionID>.json # Core memory blocks
|
||||||
|
├── memory-working/
|
||||||
|
│ ├── <sessionID>.json # Working memory (slots + pool)
|
||||||
|
│ ├── <sessionID>_pressure.json # Pressure monitoring state
|
||||||
|
│ ├── <sessionID>_compaction.json # Compaction event log
|
||||||
|
│ └── <sessionID>_sweep.json # Storage sweep log
|
||||||
|
└── cache/
|
||||||
|
└── tool-outputs/
|
||||||
|
└── *.json # Tool output cache (auto-swept)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
- All files written with `0644` permissions (owner read/write, group/others read)
|
||||||
|
- Directories created with `0755` permissions (owner rwx, group/others rx)
|
||||||
|
- No sensitive data should be stored in memory blocks (user responsibility)
|
||||||
|
- Session IDs are opaque identifiers, not derived from sensitive data
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Last Updated**: February 2026
|
||||||
|
**Implementation**: `index.ts` (1700+ lines)
|
||||||
@@ -0,0 +1,376 @@
|
|||||||
|
# Configuration Guide
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The Working Memory Plugin works out-of-the-box with sensible defaults. Advanced users can customize behavior by modifying constants in `index.ts`.
|
||||||
|
|
||||||
|
## Core Memory Limits
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const CORE_MEMORY_LIMITS = {
|
||||||
|
goal: 1000, // ONE specific task (not project-wide goals)
|
||||||
|
progress: 2000, // Checklist format (✅ done, ⏳ in-progress, ❌ blocked)
|
||||||
|
context: 1500, // Current working files + key patterns
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**Recommendations**:
|
||||||
|
- Keep **goal** focused on current task (clear when completed)
|
||||||
|
- Use **progress** for checklists (avoid line numbers, commit hashes, API signatures)
|
||||||
|
- Use **context** for files you're actively editing (avoid type definitions, function signatures)
|
||||||
|
|
||||||
|
## Working Memory Configuration
|
||||||
|
|
||||||
|
### Slot Limits
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const SLOT_CONFIG: Record<SlotType, number> = {
|
||||||
|
error: 3, // Recent errors needing fixes
|
||||||
|
decision: 5, // Important decisions made
|
||||||
|
todo: 3, // Current task checklist
|
||||||
|
dependency: 3, // File/package dependencies
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**Tuning**:
|
||||||
|
- Increase slot limits if you need more items tracked
|
||||||
|
- Decrease for stricter memory budgets
|
||||||
|
- Total overhead: ~100-200 chars per item
|
||||||
|
|
||||||
|
### Memory Pool Decay
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const POOL_DECAY_GAMMA = 0.85; // Exponential decay rate (15% per event)
|
||||||
|
const POOL_MIN_SCORE = 0.01; // Items below this score are pruned
|
||||||
|
```
|
||||||
|
|
||||||
|
**Formula**: `score = exp(-γ * age) + mentionCount`
|
||||||
|
|
||||||
|
**Tuning**:
|
||||||
|
- Lower `γ` (e.g., 0.75) → faster decay, more aggressive pruning
|
||||||
|
- Higher `γ` (e.g., 0.90) → slower decay, items stay longer
|
||||||
|
- Lower `POOL_MIN_SCORE` (e.g., 0.005) → more items retained
|
||||||
|
|
||||||
|
### Pool Size Limits
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const POOL_MAX_ITEMS = 50; // Hard limit on pool size
|
||||||
|
```
|
||||||
|
|
||||||
|
**Tuning**:
|
||||||
|
- Increase for longer sessions with more context
|
||||||
|
- Decrease for stricter memory budgets
|
||||||
|
- Each item adds ~50-150 chars to system prompt
|
||||||
|
|
||||||
|
## Pressure Monitoring
|
||||||
|
|
||||||
|
### Thresholds
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const PRESSURE_THRESHOLDS = {
|
||||||
|
moderate: 70, // Warning appears in system prompt
|
||||||
|
high: 85, // Aggressive pruning activates
|
||||||
|
critical: 95, // Intervention sent to agent
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
**Tuning**:
|
||||||
|
- Increase thresholds for more relaxed monitoring
|
||||||
|
- Decrease for earlier warnings and interventions
|
||||||
|
|
||||||
|
### Context Limit Estimate
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const ESTIMATED_CONTEXT_LIMIT = 180000; // Conservative estimate (chars)
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note**: OpenCode actual limit varies by model. Adjust based on your observations.
|
||||||
|
|
||||||
|
## Smart Pruning
|
||||||
|
|
||||||
|
### Line Thresholds
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Normal mode (pressure < 85%)
|
||||||
|
const PRUNE_THRESHOLD_NORMAL = 50;
|
||||||
|
|
||||||
|
// Aggressive mode (85% ≤ pressure < 95%)
|
||||||
|
const PRUNE_THRESHOLD_AGGRESSIVE = 30;
|
||||||
|
|
||||||
|
// Hyper-aggressive mode (pressure ≥ 95%)
|
||||||
|
const PRUNE_THRESHOLD_HYPER = 15;
|
||||||
|
```
|
||||||
|
|
||||||
|
**Tuning**:
|
||||||
|
- Increase thresholds to keep more tool output
|
||||||
|
- Decrease for more aggressive pruning
|
||||||
|
|
||||||
|
### Keep Lines
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Normal mode
|
||||||
|
const KEEP_LINES_NORMAL = 30; // Keep first/last 30 lines
|
||||||
|
|
||||||
|
// Aggressive mode
|
||||||
|
const KEEP_LINES_AGGRESSIVE = 20; // Keep first/last 20 lines
|
||||||
|
|
||||||
|
// Hyper-aggressive mode
|
||||||
|
const KEEP_LINES_HYPER = 10; // Keep first/last 10 lines
|
||||||
|
```
|
||||||
|
|
||||||
|
**Tuning**:
|
||||||
|
- Increase to preserve more context from tool outputs
|
||||||
|
- Decrease for stricter truncation
|
||||||
|
|
||||||
|
## Storage Governance
|
||||||
|
|
||||||
|
### Session Cleanup
|
||||||
|
|
||||||
|
Automatically triggered on `experimental.session.deleted` hook. No configuration needed.
|
||||||
|
|
||||||
|
### Tool Output Cache Sweep
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const SWEEP_INTERVAL = 500; // Trigger every N events
|
||||||
|
const SWEEP_MAX_FILES = 300; // Keep most recent N files
|
||||||
|
const SWEEP_TTL_DAYS = 7; // Delete files older than N days
|
||||||
|
```
|
||||||
|
|
||||||
|
**Tuning**:
|
||||||
|
- Increase `SWEEP_INTERVAL` for less frequent sweeps (lower overhead)
|
||||||
|
- Increase `SWEEP_MAX_FILES` to cache more tool outputs (more disk usage)
|
||||||
|
- Increase `SWEEP_TTL_DAYS` to keep older files longer
|
||||||
|
|
||||||
|
## Compaction Behavior
|
||||||
|
|
||||||
|
### Item Preservation
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const COMPACTION_KEEP_ITEMS = 10; // Preserve N most recent items on compaction
|
||||||
|
```
|
||||||
|
|
||||||
|
**Tuning**:
|
||||||
|
- Increase to preserve more working memory across compactions
|
||||||
|
- Decrease for stricter memory reset on compaction
|
||||||
|
|
||||||
|
## System Prompt Injection
|
||||||
|
|
||||||
|
### Core Memory Format
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Injected as:
|
||||||
|
<core_memory>
|
||||||
|
<goal chars="87/1000">...</goal>
|
||||||
|
<progress chars="560/2000">...</progress>
|
||||||
|
<context chars="479/1500">...</context>
|
||||||
|
</core_memory>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Customization**: Modify `formatCoreMemoryForPrompt()` in `index.ts` to change format.
|
||||||
|
|
||||||
|
### Working Memory Format
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Injected as:
|
||||||
|
<working_memory>
|
||||||
|
Recent session context (auto-managed, sorted by relevance):
|
||||||
|
|
||||||
|
⚠️ Errors:
|
||||||
|
- item content
|
||||||
|
|
||||||
|
📁 Key Files:
|
||||||
|
- file path
|
||||||
|
|
||||||
|
(N items shown, updated: HH:MM:SS AM)
|
||||||
|
</working_memory>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Customization**: Modify `formatWorkingMemoryForPrompt()` in `index.ts` to change:
|
||||||
|
- Section emoji/icons
|
||||||
|
- Display format
|
||||||
|
- Item ordering
|
||||||
|
|
||||||
|
### Pressure Warning Format
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Injected as:
|
||||||
|
[Memory Pressure: 87% (high) - 156,600/180,000 chars]
|
||||||
|
⚠️ High memory pressure detected. Consider:
|
||||||
|
- Action item 1
|
||||||
|
- Action item 2
|
||||||
|
```
|
||||||
|
|
||||||
|
**Customization**: Modify `formatPressureWarning()` in `index.ts`.
|
||||||
|
|
||||||
|
## Auto-Extraction Heuristics
|
||||||
|
|
||||||
|
### File Path Detection
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Detects:
|
||||||
|
- Absolute paths: /users/name/project/file.ts
|
||||||
|
- Relative paths: src/components/Button.tsx
|
||||||
|
- Dot paths: ./utils/helpers.ts
|
||||||
|
- Tilde paths: ~/project/file.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
**Customization**: Modify regex in `extractFilePaths()`.
|
||||||
|
|
||||||
|
### Error Detection
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Detects:
|
||||||
|
- "Error:", "ERROR:", "error:"
|
||||||
|
- Stack traces with "at " prefix
|
||||||
|
- TypeScript errors with "TS####:"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Customization**: Modify `extractErrors()` heuristics.
|
||||||
|
|
||||||
|
### Decision Detection
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Detects:
|
||||||
|
- "decided to...", "decision:", "chose to..."
|
||||||
|
- "using X instead of Y"
|
||||||
|
- "will use X approach"
|
||||||
|
```
|
||||||
|
|
||||||
|
**Customization**: Modify `extractDecisions()` heuristics.
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
Currently, the plugin does not support environment variables. All configuration is done via constants in `index.ts`.
|
||||||
|
|
||||||
|
**Future Enhancement**: Consider adding `.env` support for:
|
||||||
|
```
|
||||||
|
OPENCODE_WM_CORE_GOAL_LIMIT=1000
|
||||||
|
OPENCODE_WM_POOL_DECAY_GAMMA=0.85
|
||||||
|
OPENCODE_WM_SWEEP_INTERVAL=500
|
||||||
|
```
|
||||||
|
|
||||||
|
## Performance Tuning
|
||||||
|
|
||||||
|
### High-Frequency Sessions (500+ messages)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Aggressive pruning
|
||||||
|
const PRUNE_THRESHOLD_NORMAL = 30;
|
||||||
|
const PRUNE_THRESHOLD_AGGRESSIVE = 20;
|
||||||
|
|
||||||
|
// Faster decay
|
||||||
|
const POOL_DECAY_GAMMA = 0.75;
|
||||||
|
|
||||||
|
// More frequent sweeps
|
||||||
|
const SWEEP_INTERVAL = 250;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Long-Running Sessions (Multi-day)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Preserve more context
|
||||||
|
const POOL_MAX_ITEMS = 100;
|
||||||
|
const COMPACTION_KEEP_ITEMS = 20;
|
||||||
|
|
||||||
|
// Slower decay
|
||||||
|
const POOL_DECAY_GAMMA = 0.90;
|
||||||
|
|
||||||
|
// Longer TTL
|
||||||
|
const SWEEP_TTL_DAYS = 14;
|
||||||
|
```
|
||||||
|
|
||||||
|
### Memory-Constrained Environments
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Strict limits
|
||||||
|
const CORE_MEMORY_LIMITS = {
|
||||||
|
goal: 500,
|
||||||
|
progress: 1000,
|
||||||
|
context: 800,
|
||||||
|
};
|
||||||
|
|
||||||
|
const POOL_MAX_ITEMS = 20;
|
||||||
|
|
||||||
|
// Aggressive pruning
|
||||||
|
const PRUNE_THRESHOLD_NORMAL = 20;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Debugging Configuration
|
||||||
|
|
||||||
|
### Enable Verbose Logging
|
||||||
|
|
||||||
|
Add `console.log()` statements in key functions:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// In loadCoreMemory()
|
||||||
|
console.log("[Core Memory] Loaded:", memory);
|
||||||
|
|
||||||
|
// In applyDecay()
|
||||||
|
console.log("[Pool Decay] Pruned items:", prunedCount);
|
||||||
|
|
||||||
|
// In sweepToolOutputCache()
|
||||||
|
console.log("[Sweep] Deleted files:", deletedCount);
|
||||||
|
```
|
||||||
|
|
||||||
|
### Inspect Memory Files
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Core memory
|
||||||
|
cat .opencode/memory-core/<sessionID>.json | jq
|
||||||
|
|
||||||
|
# Working memory
|
||||||
|
cat .opencode/memory-working/<sessionID>.json | jq
|
||||||
|
|
||||||
|
# Pressure state
|
||||||
|
cat .opencode/memory-working/<sessionID>_pressure.json | jq
|
||||||
|
|
||||||
|
# Sweep log
|
||||||
|
cat .opencode/memory-working/<sessionID>_sweep.json | jq
|
||||||
|
```
|
||||||
|
|
||||||
|
## Migration Notes
|
||||||
|
|
||||||
|
### Upgrading from Pre-Phase 3
|
||||||
|
|
||||||
|
Old format files are automatically migrated:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Old format
|
||||||
|
{ items: Array<Item> }
|
||||||
|
|
||||||
|
// New format (auto-migrated)
|
||||||
|
{ slots: { error: [], decision: [], ... }, pool: [...] }
|
||||||
|
```
|
||||||
|
|
||||||
|
No manual intervention required.
|
||||||
|
|
||||||
|
### Upgrading from Phase 3 to Phase 4.5
|
||||||
|
|
||||||
|
Storage governance is backward compatible. No migration needed.
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. **Core Memory Discipline**:
|
||||||
|
- Clear `goal` immediately after task completion
|
||||||
|
- Keep `progress` concise (use checklist format)
|
||||||
|
- Only put actively edited files in `context`
|
||||||
|
|
||||||
|
2. **Working Memory Hygiene**:
|
||||||
|
- Clear `error` slot after fixing all errors (`working_memory_clear_slot`)
|
||||||
|
- Let pool decay naturally (avoid manual removal unless necessary)
|
||||||
|
- Review working memory periodically (use `working_memory_read`)
|
||||||
|
|
||||||
|
3. **Pressure Management**:
|
||||||
|
- Respond to "moderate" warnings proactively
|
||||||
|
- Compress core memory at "high" pressure
|
||||||
|
- Clear working memory at "critical" pressure
|
||||||
|
|
||||||
|
4. **Storage Maintenance**:
|
||||||
|
- Let sweep run automatically (no manual intervention)
|
||||||
|
- Delete old session files manually if needed
|
||||||
|
- Monitor `.opencode/` directory size periodically
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Last Updated**: February 2026
|
||||||
|
**Configuration File**: `index.ts` (constants section)
|
||||||
@@ -0,0 +1,131 @@
|
|||||||
|
# Installation Guide
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- **OpenCode** 1.0.0 or higher
|
||||||
|
- **Node.js** 18+ (for development only)
|
||||||
|
|
||||||
|
## Quick Install (For Users)
|
||||||
|
|
||||||
|
### Option 1: Install from npm (Recommended)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install opencode-working-memory
|
||||||
|
```
|
||||||
|
|
||||||
|
Then add to your `.opencode/package.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
"opencode-working-memory"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option 2: Install from GitHub
|
||||||
|
|
||||||
|
Add to your `.opencode/package.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"opencode-working-memory": "github:yourusername/opencode-working-memory"
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
"opencode-working-memory"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Then run:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd .opencode
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
### Option 3: Local Development Install
|
||||||
|
|
||||||
|
Clone the repository:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/yourusername/opencode-working-memory.git
|
||||||
|
cd opencode-working-memory
|
||||||
|
npm install
|
||||||
|
```
|
||||||
|
|
||||||
|
Link to your OpenCode project:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /path/to/your/project/.opencode
|
||||||
|
npm link /path/to/opencode-working-memory
|
||||||
|
```
|
||||||
|
|
||||||
|
Add to `.opencode/package.json`:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
"opencode-working-memory"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
After installation, start an OpenCode session and run:
|
||||||
|
|
||||||
|
```
|
||||||
|
core_memory_update goal "Test installation"
|
||||||
|
```
|
||||||
|
|
||||||
|
You should see a success message. Check `.opencode/memory-core/` for the session file.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
The plugin works out-of-the-box with sensible defaults. For advanced configuration, see [configuration.md](./configuration.md).
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Plugin Not Loading
|
||||||
|
|
||||||
|
**Symptom**: No `core_memory_update` tool available
|
||||||
|
|
||||||
|
**Solution**:
|
||||||
|
1. Check `.opencode/package.json` includes plugin in `"plugins": []` array
|
||||||
|
2. Verify `npm install` completed successfully
|
||||||
|
3. Restart OpenCode session
|
||||||
|
|
||||||
|
### Memory Files Not Created
|
||||||
|
|
||||||
|
**Symptom**: No `.opencode/memory-core/` or `.opencode/memory-working/` directories
|
||||||
|
|
||||||
|
**Solution**:
|
||||||
|
1. Ensure OpenCode has write permissions in project directory
|
||||||
|
2. Check plugin hooks are registered (look for "Working Memory Plugin" in session logs)
|
||||||
|
3. Trigger memory operations (e.g., use `core_memory_update` tool)
|
||||||
|
|
||||||
|
### Type Errors During Development
|
||||||
|
|
||||||
|
**Symptom**: TypeScript errors when modifying plugin
|
||||||
|
|
||||||
|
**Solution**:
|
||||||
|
1. Ensure `@opencode-ai/plugin` is installed: `npm install @opencode-ai/plugin`
|
||||||
|
2. Run type checking: `npx tsc --noEmit`
|
||||||
|
3. See [AGENTS.md](../AGENTS.md) for code style guidelines
|
||||||
|
|
||||||
|
## Uninstallation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd .opencode
|
||||||
|
npm uninstall opencode-working-memory
|
||||||
|
```
|
||||||
|
|
||||||
|
Remove from `.opencode/package.json` plugins array. Memory files in `.opencode/memory-*` will persist unless manually deleted.
|
||||||
|
|
||||||
|
## Next Steps
|
||||||
|
|
||||||
|
- Read [Architecture Documentation](./architecture.md) to understand how memory tiers work
|
||||||
|
- See [Configuration Guide](./configuration.md) for customization options
|
||||||
|
- Check [AGENTS.md](../AGENTS.md) for development guidelines
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"name": "opencode-working-memory",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Advanced four-tier memory architecture for OpenCode with intelligent pressure monitoring and auto-storage governance",
|
||||||
|
"type": "module",
|
||||||
|
"main": "index.ts",
|
||||||
|
"keywords": [
|
||||||
|
"opencode",
|
||||||
|
"plugin",
|
||||||
|
"memory",
|
||||||
|
"context-management",
|
||||||
|
"ai-agent",
|
||||||
|
"llm"
|
||||||
|
],
|
||||||
|
"author": "Your Name <your.email@example.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://github.com/yourusername/opencode-working-memory.git"
|
||||||
|
},
|
||||||
|
"bugs": {
|
||||||
|
"url": "https://github.com/yourusername/opencode-working-memory/issues"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/yourusername/opencode-working-memory#readme",
|
||||||
|
"peerDependencies": {
|
||||||
|
"@opencode-ai/plugin": "^1.2.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.0.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2022",
|
||||||
|
"module": "ESNext",
|
||||||
|
"lib": ["ES2022"],
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"strict": true,
|
||||||
|
"noImplicitAny": true,
|
||||||
|
"strictNullChecks": true,
|
||||||
|
"strictFunctionTypes": true,
|
||||||
|
"strictBindCallApply": true,
|
||||||
|
"strictPropertyInitialization": true,
|
||||||
|
"noImplicitThis": true,
|
||||||
|
"alwaysStrict": true,
|
||||||
|
"noUnusedLocals": true,
|
||||||
|
"noUnusedParameters": true,
|
||||||
|
"noImplicitReturns": true,
|
||||||
|
"noFallthroughCasesInSwitch": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"allowSyntheticDefaultImports": true
|
||||||
|
},
|
||||||
|
"include": ["index.ts"],
|
||||||
|
"exclude": ["node_modules", "dist"]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user