Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
20 changes: 11 additions & 9 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -333,12 +333,12 @@ export const OpenCodeMemPlugin: Plugin = async (ctx: PluginInput) => {
commands: [
{
command: "add",
description: `Store new memory (MATCH USER LANGUAGE: ${langName})`,
description: "Store new memory",
args: ["content", "type?", "tags?"],
},
{
command: "search",
description: `Search memories via keywords (MATCH USER LANGUAGE: ${langName})`,
description: "Search memories via keywords",
args: ["query"],
},
{
Expand Down Expand Up @@ -622,15 +622,17 @@ function formatSearchResults(query: string, results: any, limit?: number): strin
}

function formatMemoriesForCompaction(memories: any[]): string {
let output = `## Restored Session Memory\n\n`;
const sections: string[] = ["## Restored Session Memory\n"];

memories.forEach((m, i) => {
output += `### Memory ${i + 1}\n`;
output += `${m.memory}\n\n`;
for (let i = 0; i < memories.length; i++) {
const m = memories[i];
sections.push(`### Memory ${i + 1}`);
sections.push(m.memory);
if (m.tags && m.tags.length > 0) {
output += `Tags: ${m.tags.join(", ")}\n\n`;
sections.push(`Tags: ${m.tags.join(", ")}`);
}
});
sections.push("");
}

return output;
return sections.join("\n");
}
85 changes: 34 additions & 51 deletions src/services/auto-capture.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,32 @@ interface ToolCallInfo {

const MAX_TOOL_INPUT_LENGTH = 100;

const AUTO_CAPTURE_SYSTEM_PROMPT_TEMPLATE = (
langName: string
) => `You are a technical memory recorder for a software development project.

RULES:
1. ONLY capture technical work (code, bugs, features, architecture, config)
2. SKIP non-technical by returning type="skip"
3. NO meta-commentary or behavior analysis
4. Include specific file names, functions, technical details
5. Generate 2-4 technical tags (e.g., "react", "auth", "bug-fix")
6. You MUST write the summary in ${langName}.

FORMAT:
## Request
[1-2 sentences: what was requested, in ${langName}]

## Outcome
[1-2 sentences: what was done, include files/functions, in ${langName}]

SKIP if: greetings, casual chat, no code/decisions made
CAPTURE if: code changed, bug fixed, feature added, decision made`;

const AUTO_CAPTURE_ANALYSIS_PROMPT = (context: string) => `${context}

Analyze this conversation. If it contains technical work (code, bugs, features, decisions), create a concise summary and relevant tags. If it's non-technical (greetings, casual chat, incomplete requests), return type="skip" with empty summary.`;

let isCaptureRunning = false;

export async function performAutoCapture(
Expand Down Expand Up @@ -260,30 +286,6 @@ async function generateSummary(
: CONFIG.autoCaptureLanguage;
const langName = getLanguageName(targetLang);

const systemPrompt = `You are a technical memory recorder for a software development project.

RULES:
1. ONLY capture technical work (code, bugs, features, architecture, config)
2. SKIP non-technical by returning type="skip"
3. NO meta-commentary or behavior analysis
4. Include specific file names, functions, technical details
5. Generate 2-4 technical tags (e.g., "react", "auth", "bug-fix")
6. You MUST write the summary in ${langName}.

FORMAT:
## Request
[1-2 sentences: what was requested, in ${langName}]

## Outcome
[1-2 sentences: what was done, include files/functions, in ${langName}]

SKIP if: greetings, casual chat, no code/decisions made
CAPTURE if: code changed, bug fixed, feature added, decision made`;

const aiPrompt = `${context}

Analyze this conversation. If it contains technical work (code, bugs, features, decisions), create a concise summary and relevant tags. If it's non-technical (greetings, casual chat, incomplete requests), return type="skip" with empty summary.`;

const { z } = await import("zod");
const schema = z.object({
summary: z.string(),
Expand All @@ -295,8 +297,8 @@ Analyze this conversation. If it contains technical work (code, bugs, features,
providerName: CONFIG.opencodeProvider,
modelId: CONFIG.opencodeModel,
statePath: getStatePath(),
systemPrompt,
userPrompt: aiPrompt,
systemPrompt: AUTO_CAPTURE_SYSTEM_PROMPT_TEMPLATE(langName),
userPrompt: AUTO_CAPTURE_ANALYSIS_PROMPT(context),
schema,
temperature:
CONFIG.memoryTemperature === false ? undefined : (CONFIG.memoryTemperature ?? 0.3),
Expand Down Expand Up @@ -329,30 +331,6 @@ Analyze this conversation. If it contains technical work (code, bugs, features,

const langName = getLanguageName(targetLang);

const systemPrompt = `You are a technical memory recorder for a software development project.

RULES:
1. ONLY capture technical work (code, bugs, features, architecture, config)
2. SKIP non-technical by returning type="skip"
3. NO meta-commentary or behavior analysis
4. Include specific file names, functions, technical details
5. Generate 2-4 technical tags (e.g., "react", "auth", "bug-fix")
6. You MUST write the summary in ${langName}.

FORMAT:
## Request
[1-2 sentences: what was requested, in ${langName}]

## Outcome
[1-2 sentences: what was done, include files/functions, in ${langName}]

SKIP if: greetings, casual chat, no code/decisions made
CAPTURE if: code changed, bug fixed, feature added, decision made`;

const aiPrompt = `${context}

Analyze this conversation. If it contains technical work (code, bugs, features, decisions), create a concise summary and relevant tags. If it's non-technical (greetings, casual chat, incomplete requests), return type="skip" with empty summary.`;

const toolSchema = {
type: "function" as const,
function: {
Expand Down Expand Up @@ -381,7 +359,12 @@ Analyze this conversation. If it contains technical work (code, bugs, features,
},
};

const result = await provider.executeToolCall(systemPrompt, aiPrompt, toolSchema, sessionID);
const result = await provider.executeToolCall(
AUTO_CAPTURE_SYSTEM_PROMPT_TEMPLATE(langName),
AUTO_CAPTURE_ANALYSIS_PROMPT(context),
toolSchema,
sessionID
);

if (!result.success || !result.data) {
throw new Error(result.error || "Failed to generate summary");
Expand Down
30 changes: 12 additions & 18 deletions src/services/user-memory-learning.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,16 @@ import type { UserPrompt } from "./user-prompt/user-prompt-manager.js";
import { userProfileManager } from "./user-profile/user-profile-manager.js";
import type { UserProfile, UserProfileData } from "./user-profile/types.js";

const USER_PROFILE_SYSTEM_PROMPT = (
existingProfile: boolean
) => `You are a user behavior analyst for a coding assistant.

Your task is to analyze user prompts and ${existingProfile ? "update" : "create"} a comprehensive user profile.

CRITICAL: Detect the language used by the user in their prompts. You MUST output all descriptions, categories, and text in the SAME language as the user's prompts.

Use the update_user_profile tool to save the ${existingProfile ? "updated" : "new"} profile.`;

let isLearningRunning = false;

export async function performUserProfileLearning(
Expand Down Expand Up @@ -159,14 +169,6 @@ async function analyzeUserProfile(
);
}

const systemPrompt = `You are a user behavior analyst for a coding assistant.

Your task is to analyze user prompts and ${existingProfile ? "update" : "create"} a comprehensive user profile.

CRITICAL: Detect the language used by the user in their prompts. You MUST output all descriptions, categories, and text in the SAME language as the user's prompts.

Use the update_user_profile tool to save the ${existingProfile ? "updated" : "new"} profile.`;

const { z } = await import("zod");
const schema = z.object({
preferences: z.array(
Expand Down Expand Up @@ -195,7 +197,7 @@ Use the update_user_profile tool to save the ${existingProfile ? "updated" : "ne
providerName: CONFIG.opencodeProvider,
modelId: CONFIG.opencodeModel,
statePath: getStatePath(),
systemPrompt,
systemPrompt: USER_PROFILE_SYSTEM_PROMPT(!!existingProfile),
userPrompt: context,
schema,
temperature:
Expand Down Expand Up @@ -228,14 +230,6 @@ Use the update_user_profile tool to save the ${existingProfile ? "updated" : "ne

const provider = AIProviderFactory.createProvider(CONFIG.memoryProvider, providerConfig);

const systemPrompt = `You are a user behavior analyst for a coding assistant.

Your task is to analyze user prompts and ${existingProfile ? "update" : "create"} a comprehensive user profile.

CRITICAL: Detect the language used by the user in their prompts. You MUST output all descriptions, categories, and text in the SAME language as the user's prompts.

Use the update_user_profile tool to save the ${existingProfile ? "updated" : "new"} profile.`;

const toolSchema = {
type: "function" as const,
function: {
Expand Down Expand Up @@ -288,7 +282,7 @@ Use the update_user_profile tool to save the ${existingProfile ? "updated" : "ne
};

const result = await provider.executeToolCall(
systemPrompt,
USER_PROFILE_SYSTEM_PROMPT(!!existingProfile),
context,
toolSchema,
`user-profile-${Date.now()}`
Expand Down
Loading
Loading