Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions .changeset/thick-dragons-beg.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
"roo-cline": minor
---

Added Context Memory System to enhance AI-human collaboration through persistent, mode-aware state management. This feature:

- Implements different memory limits per mode (Code/Architect/Ask)
- Tracks and learns from common coding patterns
- Maintains task progress and technical context
- Records mistakes for improved accuracy
- Integrates with VSCode's global state
- Configurable through the Prompts tab
85 changes: 84 additions & 1 deletion .clinerules
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# Code Quality Rules

1. Test Coverage:
- Your Dev prefers that functionality be user-test
- Before attempting completion, always make sure that any code changes have test coverage
- Ensure all tests pass before submitting changes

Expand All @@ -12,4 +13,86 @@

# Adding a New Setting

To add a new setting that persists its state, follow the steps in cline_docs/settings.md
To add a new setting that persists its state, follow the steps in cline_docs/settings.md

# Current Project

# AI Code Collaboration Framework Requirements

## Purpose
We are supporting Roo-Cline open source. As a supporting DEV I want to create a structured approach for human-AI pair programming that optimizes AI language model interactions by understanding and working with their fundamental characteristics:
- Pattern-based responses
- Stateless nature
- Probability-driven outputs
- Context window limitations

## Core Problem Statement
AI code assistants operate on pattern recognition and probability distributions but currently lack:
1. Persistent memory between interactions
2. True causal understanding
3. Ability to maintain context over long sessions
4. Consistent constraint adherence without reminders

## Solution Requirements

### 1. Context Management
```typescript
// Each interaction needs to be self-contained and explicit
interface DevelopmentContext {
// What are we working on right now?
currentTask: {
scope: string; // Single, focused objective
stage: string; // Where we are in implementation
};

// What patterns should the AI follow?
technicalContext: {
framework: string; // e.g., "Vitest", "Jest"
language: string; // e.g., "TypeScript"
patterns: string[]; // Expected code patterns
};

// What are the boundaries?
constraints: {
size: string; // e.g., "Single test case"
style: string[]; // e.g., ["Functional", "Immutable"]
dependencies: string[] // Required imports/tools
};
}
```

### 2. Interaction Protocol
Must support:
- One task at a time
- Explicit context setting
- Clear constraints
- Pattern reinforcement
- Regular verification points

### 3. Development Flow
Each feature development should:
1. Start with smallest testable unit
2. Provide minimal but sufficient context
3. Verify output matches expected patterns
4. Explicitly progress to next step

## Success Criteria
1. Reduced pattern mixing (e.g., Jest patterns in Vitest code)
2. Consistent adherence to specified constraints
3. Manageable, focused outputs
4. Clear progression through development tasks

## Implementation Priorities
1. Context Template Structure
2. Interaction Protocol Definition
3. Pattern Library
4. Development Flow Management

## First Development Task
Create the base context template structure that will:
- Define minimal required context for AI interaction
- Validate context completeness
- Support single-task focus
- Enable pattern enforcement

## Contributions, we are contributing to a larger project, please match current design patterns and ask the user to provide more information when encountering a broader distribution
11 changes: 3 additions & 8 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,15 @@
"type": "extensionHost",
"request": "launch",
"runtimeExecutable": "${execPath}",
"args": [
"--extensionDevelopmentPath=${workspaceFolder}",
],
"args": ["--extensionDevelopmentPath=${workspaceFolder}"],
"sourceMaps": true,
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"preLaunchTask": "compile",
"env": {
"NODE_ENV": "development",
"VSCODE_DEBUG_MODE": "true"
},
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
]
},
"resolveSourceMapLocations": ["${workspaceFolder}/**", "!**/node_modules/**"]
}
]
}
2 changes: 1 addition & 1 deletion jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ module.exports = {
transformIgnorePatterns: [
"node_modules/(?!(@modelcontextprotocol|delay|p-wait-for|globby|serialize-error|strip-ansi|default-shell|os-name)/)",
],
modulePathIgnorePatterns: [".vscode-test"],
modulePathIgnorePatterns: [".vscode-test", "out"],
reporters: [["jest-simple-dot-reporter", {}]],
setupFiles: [],
}
5 changes: 5 additions & 0 deletions src/__mocks__/vscode.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
const vscode = {
ExtensionMode: {
Production: 1,
Development: 2,
Test: 3,
},
window: {
showInformationMessage: jest.fn(),
showErrorMessage: jest.fn(),
Expand Down
71 changes: 71 additions & 0 deletions src/core/Cline.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ import { AssistantMessageContent, parseAssistantMessage, ToolParamName, ToolUseN
import { formatResponse } from "./prompts/responses"
import { SYSTEM_PROMPT } from "./prompts/system"
import { modes, defaultModeSlug, getModeBySlug } from "../shared/modes"
import { ContextManager } from "./context/ContextManager"
import { truncateHalfConversation } from "./sliding-window"
import { ClineProvider, GlobalFileNames } from "./webview/ClineProvider"
import { detectCodeOmission } from "../integrations/editor/detect-omission"
Expand Down Expand Up @@ -80,6 +81,7 @@ export class Cline {
diffStrategy?: DiffStrategy
diffEnabled: boolean = false
fuzzyMatchThreshold: number = 1.0
private contextManager: ContextManager

apiConversationHistory: (Anthropic.MessageParam & { ts?: number })[] = []
clineMessages: ClineMessage[] = []
Expand Down Expand Up @@ -131,6 +133,7 @@ export class Cline {
this.fuzzyMatchThreshold = fuzzyMatchThreshold ?? 1.0
this.providerRef = new WeakRef(provider)
this.diffViewProvider = new DiffViewProvider(cwd)
this.contextManager = new ContextManager({ context: provider.context })

if (historyItem) {
this.taskId = historyItem.id
Expand Down Expand Up @@ -435,6 +438,9 @@ export class Cline {
this.apiConversationHistory = []
await this.providerRef.deref()?.postStateToWebview()

// Initialize task context
await this.contextManager.initializeTaskContext(this.taskId, task || "")

await this.say("text", task, images)

let imageBlocks: Anthropic.ImageBlockParam[] = formatResponse.imageBlocks(images)
Expand Down Expand Up @@ -780,6 +786,14 @@ export class Cline {
]
}

// Record command in history and update task progress
await this.contextManager.addCommandToHistory(command)
await this.contextManager.updateTaskProgress(
completed ? "command_completed" : "command_running",
completed ? [command] : [],
completed ? [] : [command],
)

if (completed) {
return [false, `Command executed.${result.length > 0 ? `\nOutput:\n${result}` : ""}`]
} else {
Expand Down Expand Up @@ -1337,7 +1351,20 @@ export class Cline {
pushToolResult(
`The content was successfully saved to ${relPath.toPosix()}.${newProblemsMessage}`,
)
// Record successful file write pattern
await this.contextManager.recordPattern("write_to_file:success")
}

// Update technical context with the modified file
await this.contextManager.updateTechnicalContext({
lastAnalyzedFiles: [relPath],
projectStructure: {
root: cwd,
mainFiles: [relPath],
dependencies: [],
},
})

await this.diffViewProvider.reset()
break
}
Expand Down Expand Up @@ -1463,6 +1490,17 @@ export class Cline {
`Changes successfully applied to ${relPath.toPosix()}:\n\n${newProblemsMessage}`,
)
}

// Update technical context with the modified file
await this.contextManager.updateTechnicalContext({
lastAnalyzedFiles: [relPath],
projectStructure: {
root: cwd,
mainFiles: [relPath],
dependencies: [],
},
})

await this.diffViewProvider.reset()
break
}
Expand Down Expand Up @@ -1504,6 +1542,25 @@ export class Cline {
}
// now execute the tool like normal
const content = await extractTextFromFile(absolutePath)

// Update technical context with analyzed file
await this.contextManager.updateTechnicalContext({
lastAnalyzedFiles: [relPath],
projectStructure: {
root: cwd,
mainFiles: this.contextManager
.getContext()
.technical.projectStructure.mainFiles.includes(relPath)
? this.contextManager.getContext().technical.projectStructure.mainFiles
: [
...this.contextManager.getContext().technical.projectStructure
.mainFiles,
relPath,
],
dependencies: [],
},
})

pushToolResult(content)
break
}
Expand Down Expand Up @@ -1764,6 +1821,12 @@ export class Cline {
case "scroll_down":
case "scroll_up":
await this.say("browser_action_result", JSON.stringify(browserActionResult))

// Record successful browser action pattern
await this.contextManager.recordPattern(
`browser_action_result:${action}:executed`,
)

pushToolResult(
formatResponse.toolResult(
`The browser action has been executed. The console logs and screenshot have been captured for your analysis.\n\nConsole logs:\n${
Expand Down Expand Up @@ -1910,6 +1973,10 @@ export class Cline {
.filter(Boolean)
.join("\n\n") || "(No response)"
await this.say("mcp_server_response", toolResultPretty)

// Record successful MCP tool execution pattern
await this.contextManager.recordPattern(`mcp_tool:${server_name}:${tool_name}:executed`)

pushToolResult(formatResponse.toolResult(toolResultPretty))
break
}
Expand Down Expand Up @@ -1971,6 +2038,10 @@ export class Cline {
.filter(Boolean)
.join("\n\n") || "(Empty response)"
await this.say("mcp_server_response", resourceResultPretty)

// Record successful MCP resource access pattern
await this.contextManager.recordPattern(`mcp_resource:${server_name}:used`)

pushToolResult(formatResponse.toolResult(resourceResultPretty))
break
}
Expand Down
48 changes: 48 additions & 0 deletions src/core/config/ContextMemorySchema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { z } from "zod"

// Schema for mode-specific settings
const ModeSettingsSchema = z.object({
maxHistoryItems: z.number().min(1, "Must keep at least 1 history item"),
maxPatterns: z.number().min(1, "Must track at least 1 pattern"),
maxMistakes: z.number().min(1, "Must track at least 1 mistake"),
})

// Schema for the entire context memory settings file
export const ContextMemorySettingsSchema = z.object({
enabled: z.boolean(),
modeSettings: z.record(z.string(), ModeSettingsSchema),
})

export type ContextMemorySettings = z.infer<typeof ContextMemorySettingsSchema>

/**
* Default settings to use when none are configured
*/
export const DEFAULT_MEMORY_SETTINGS: ContextMemorySettings = {
enabled: true,
modeSettings: {
code: {
maxHistoryItems: 50,
maxPatterns: 20,
maxMistakes: 10,
},
architect: {
maxHistoryItems: 30,
maxPatterns: 15,
maxMistakes: 5,
},
ask: {
maxHistoryItems: 20,
maxPatterns: 10,
maxMistakes: 3,
},
},
}

/**
* Validates context memory settings against the schema
* @throws {z.ZodError} if validation fails
*/
export function validateContextMemorySettings(settings: unknown): asserts settings is ContextMemorySettings {
ContextMemorySettingsSchema.parse(settings)
}
Loading
Loading