cmdr-agent 2.1.1 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin/cmdr.js +4 -0
- package/dist/bin/cmdr.js.map +1 -1
- package/dist/package.json +69 -0
- package/dist/src/cli/args.d.ts +4 -0
- package/dist/src/cli/args.d.ts.map +1 -1
- package/dist/src/cli/args.js +15 -0
- package/dist/src/cli/args.js.map +1 -1
- package/dist/src/cli/commands.js +20 -0
- package/dist/src/cli/commands.js.map +1 -1
- package/dist/src/cli/ink/App.d.ts.map +1 -1
- package/dist/src/cli/ink/App.js +15 -0
- package/dist/src/cli/ink/App.js.map +1 -1
- package/dist/src/cli/repl.d.ts +4 -0
- package/dist/src/cli/repl.d.ts.map +1 -1
- package/dist/src/cli/repl.js +48 -19
- package/dist/src/cli/repl.js.map +1 -1
- package/dist/src/core/agent-runner.d.ts +5 -0
- package/dist/src/core/agent-runner.d.ts.map +1 -1
- package/dist/src/core/agent-runner.js +12 -2
- package/dist/src/core/agent-runner.js.map +1 -1
- package/dist/src/core/agent.d.ts +2 -1
- package/dist/src/core/agent.d.ts.map +1 -1
- package/dist/src/core/agent.js +5 -1
- package/dist/src/core/agent.js.map +1 -1
- package/dist/src/core/content-replacement.d.ts +44 -0
- package/dist/src/core/content-replacement.d.ts.map +1 -0
- package/dist/src/core/content-replacement.js +67 -0
- package/dist/src/core/content-replacement.js.map +1 -0
- package/dist/src/core/event-bus.d.ts +129 -0
- package/dist/src/core/event-bus.d.ts.map +1 -0
- package/dist/src/core/event-bus.js +103 -0
- package/dist/src/core/event-bus.js.map +1 -0
- package/dist/src/core/orchestrator.d.ts +17 -1
- package/dist/src/core/orchestrator.d.ts.map +1 -1
- package/dist/src/core/orchestrator.js +95 -1
- package/dist/src/core/orchestrator.js.map +1 -1
- package/dist/src/core/permissions.d.ts +31 -3
- package/dist/src/core/permissions.d.ts.map +1 -1
- package/dist/src/core/permissions.js +122 -11
- package/dist/src/core/permissions.js.map +1 -1
- package/dist/src/core/presets.d.ts.map +1 -1
- package/dist/src/core/presets.js +1 -0
- package/dist/src/core/presets.js.map +1 -1
- package/dist/src/core/types.d.ts +17 -1
- package/dist/src/core/types.d.ts.map +1 -1
- package/dist/src/llm/anthropic.d.ts +27 -0
- package/dist/src/llm/anthropic.d.ts.map +1 -0
- package/dist/src/llm/anthropic.js +269 -0
- package/dist/src/llm/anthropic.js.map +1 -0
- package/dist/src/llm/ollama.d.ts.map +1 -1
- package/dist/src/llm/ollama.js +16 -4
- package/dist/src/llm/ollama.js.map +1 -1
- package/dist/src/llm/openai.d.ts +25 -0
- package/dist/src/llm/openai.d.ts.map +1 -0
- package/dist/src/llm/openai.js +299 -0
- package/dist/src/llm/openai.js.map +1 -0
- package/dist/src/llm/provider-factory.d.ts +35 -0
- package/dist/src/llm/provider-factory.d.ts.map +1 -0
- package/dist/src/llm/provider-factory.js +73 -0
- package/dist/src/llm/provider-factory.js.map +1 -0
- package/dist/src/memory/consolidation.d.ts +37 -0
- package/dist/src/memory/consolidation.d.ts.map +1 -0
- package/dist/src/memory/consolidation.js +148 -0
- package/dist/src/memory/consolidation.js.map +1 -0
- package/dist/src/memory/memory-manager.d.ts +39 -0
- package/dist/src/memory/memory-manager.d.ts.map +1 -0
- package/dist/src/memory/memory-manager.js +96 -0
- package/dist/src/memory/memory-manager.js.map +1 -0
- package/dist/src/plugins/mcp-client.d.ts +14 -5
- package/dist/src/plugins/mcp-client.d.ts.map +1 -1
- package/dist/src/plugins/mcp-client.js +197 -43
- package/dist/src/plugins/mcp-client.js.map +1 -1
- package/dist/src/scheduling/task-scheduler.d.ts +51 -0
- package/dist/src/scheduling/task-scheduler.d.ts.map +1 -0
- package/dist/src/scheduling/task-scheduler.js +127 -0
- package/dist/src/scheduling/task-scheduler.js.map +1 -0
- package/dist/src/session/prompt-builder.d.ts +6 -0
- package/dist/src/session/prompt-builder.d.ts.map +1 -1
- package/dist/src/session/prompt-builder.js +21 -2
- package/dist/src/session/prompt-builder.js.map +1 -1
- package/dist/src/session/prompt-cache.d.ts +33 -0
- package/dist/src/session/prompt-cache.d.ts.map +1 -0
- package/dist/src/session/prompt-cache.js +54 -0
- package/dist/src/session/prompt-cache.js.map +1 -0
- package/dist/src/tools/built-in/diagnostics.d.ts +12 -0
- package/dist/src/tools/built-in/diagnostics.d.ts.map +1 -0
- package/dist/src/tools/built-in/diagnostics.js +119 -0
- package/dist/src/tools/built-in/diagnostics.js.map +1 -0
- package/dist/src/tools/built-in/git-worktree.d.ts +13 -0
- package/dist/src/tools/built-in/git-worktree.d.ts.map +1 -0
- package/dist/src/tools/built-in/git-worktree.js +75 -0
- package/dist/src/tools/built-in/git-worktree.js.map +1 -0
- package/dist/src/tools/built-in/index.d.ts +5 -1
- package/dist/src/tools/built-in/index.d.ts.map +1 -1
- package/dist/src/tools/built-in/index.js +8 -2
- package/dist/src/tools/built-in/index.js.map +1 -1
- package/dist/src/tools/built-in/memory.d.ts +15 -0
- package/dist/src/tools/built-in/memory.d.ts.map +1 -0
- package/dist/src/tools/built-in/memory.js +58 -0
- package/dist/src/tools/built-in/memory.js.map +1 -0
- package/dist/src/tools/built-in/notebook.d.ts +22 -0
- package/dist/src/tools/built-in/notebook.d.ts.map +1 -0
- package/dist/src/tools/built-in/notebook.js +207 -0
- package/dist/src/tools/built-in/notebook.js.map +1 -0
- package/package.json +2 -2
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Consolidation — the "auto-dream" system for cmdr.
|
|
3
|
+
*
|
|
4
|
+
* After a session ends, consolidation reviews the conversation to extract
|
|
5
|
+
* learnings and update MEMORY.md files. This follows a 4-stage pipeline:
|
|
6
|
+
*
|
|
7
|
+
* 1. Orient — Identify what the session was about (project, topic, scope)
|
|
8
|
+
* 2. Gather — Extract actionable learnings from the conversation
|
|
9
|
+
* 3. Consolidate — Merge new learnings with existing memory, dedup
|
|
10
|
+
* 4. Prune — Remove stale or contradicted entries, enforce size budget
|
|
11
|
+
*
|
|
12
|
+
* Triggered automatically at session end or via /compact command.
|
|
13
|
+
*/
|
|
14
|
+
import type { LLMAdapter, LLMMessage } from '../core/types.js';
|
|
15
|
+
import type { MemoryManager } from './memory-manager.js';
|
|
16
|
+
interface ConsolidationResult {
|
|
17
|
+
learningsFound: number;
|
|
18
|
+
memoryUpdated: boolean;
|
|
19
|
+
scope: 'project' | 'user';
|
|
20
|
+
}
|
|
21
|
+
export declare class MemoryConsolidator {
|
|
22
|
+
private readonly memoryManager;
|
|
23
|
+
private readonly adapter;
|
|
24
|
+
private readonly model;
|
|
25
|
+
constructor(memoryManager: MemoryManager, adapter: LLMAdapter, model: string);
|
|
26
|
+
/**
|
|
27
|
+
* Run the full consolidation pipeline on a completed session's messages.
|
|
28
|
+
* Returns info about what was updated.
|
|
29
|
+
*/
|
|
30
|
+
consolidate(messages: LLMMessage[], scope?: 'project' | 'user'): Promise<ConsolidationResult>;
|
|
31
|
+
/** Stage 2: Extract learnings from conversation messages. */
|
|
32
|
+
private gatherLearnings;
|
|
33
|
+
/** Stage 3 & 4: Merge new learnings with existing memory. */
|
|
34
|
+
private consolidateMemory;
|
|
35
|
+
}
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=consolidation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consolidation.d.ts","sourceRoot":"","sources":["../../../src/memory/consolidation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAA6B,MAAM,kBAAkB,CAAA;AACzF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AA+BxD,UAAU,mBAAmB;IAC3B,cAAc,EAAE,MAAM,CAAA;IACtB,aAAa,EAAE,OAAO,CAAA;IACtB,KAAK,EAAE,SAAS,GAAG,MAAM,CAAA;CAC1B;AAED,qBAAa,kBAAkB;IAE3B,OAAO,CAAC,QAAQ,CAAC,aAAa;IAC9B,OAAO,CAAC,QAAQ,CAAC,OAAO;IACxB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAFL,aAAa,EAAE,aAAa,EAC5B,OAAO,EAAE,UAAU,EACnB,KAAK,EAAE,MAAM;IAGhC;;;OAGG;IACG,WAAW,CACf,QAAQ,EAAE,UAAU,EAAE,EACtB,KAAK,GAAE,SAAS,GAAG,MAAkB,GACpC,OAAO,CAAC,mBAAmB,CAAC;IAgC/B,6DAA6D;YAC/C,eAAe;IAyC7B,6DAA6D;YAC/C,iBAAiB;CA+BhC"}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory Consolidation — the "auto-dream" system for cmdr.
|
|
3
|
+
*
|
|
4
|
+
* After a session ends, consolidation reviews the conversation to extract
|
|
5
|
+
* learnings and update MEMORY.md files. This follows a 4-stage pipeline:
|
|
6
|
+
*
|
|
7
|
+
* 1. Orient — Identify what the session was about (project, topic, scope)
|
|
8
|
+
* 2. Gather — Extract actionable learnings from the conversation
|
|
9
|
+
* 3. Consolidate — Merge new learnings with existing memory, dedup
|
|
10
|
+
* 4. Prune — Remove stale or contradicted entries, enforce size budget
|
|
11
|
+
*
|
|
12
|
+
* Triggered automatically at session end or via /compact command.
|
|
13
|
+
*/
|
|
14
|
+
const GATHER_PROMPT = `You are a memory consolidation agent. Analyze this conversation and extract key learnings.
|
|
15
|
+
|
|
16
|
+
Focus on:
|
|
17
|
+
- Project conventions discovered (naming, structure, patterns)
|
|
18
|
+
- User preferences observed (style, tools, workflow)
|
|
19
|
+
- Technical decisions made and their rationale
|
|
20
|
+
- Bugs found and solutions applied
|
|
21
|
+
- Common patterns that should be remembered
|
|
22
|
+
|
|
23
|
+
Output a bulleted list of concise, actionable learnings. Each item should be self-contained.
|
|
24
|
+
Do NOT include conversation-specific details that won't be useful in future sessions.
|
|
25
|
+
Do NOT include transient information (file paths of temporary files, specific error messages that were fixed).
|
|
26
|
+
|
|
27
|
+
If there are no meaningful learnings to extract, output exactly: NO_LEARNINGS`;
|
|
28
|
+
const CONSOLIDATE_PROMPT = `You are a memory manager. Given existing memory and new learnings, produce a consolidated MEMORY.md.
|
|
29
|
+
|
|
30
|
+
Rules:
|
|
31
|
+
- Merge duplicates: if a new learning matches an existing entry, keep the more specific/recent one
|
|
32
|
+
- Remove contradictions: if a new learning contradicts an old one, keep the new one
|
|
33
|
+
- Group by topic: use ## headers (preferences, conventions, patterns, decisions)
|
|
34
|
+
- Keep each entry as a concise bullet point
|
|
35
|
+
- Stay under {MAX_LINES} lines total
|
|
36
|
+
- Preserve date annotations where useful
|
|
37
|
+
|
|
38
|
+
Output the final consolidated markdown content. No preamble, just the content.`;
|
|
39
|
+
const MAX_MEMORY_LINES = 150;
|
|
40
|
+
export class MemoryConsolidator {
|
|
41
|
+
memoryManager;
|
|
42
|
+
adapter;
|
|
43
|
+
model;
|
|
44
|
+
constructor(memoryManager, adapter, model) {
|
|
45
|
+
this.memoryManager = memoryManager;
|
|
46
|
+
this.adapter = adapter;
|
|
47
|
+
this.model = model;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Run the full consolidation pipeline on a completed session's messages.
|
|
51
|
+
* Returns info about what was updated.
|
|
52
|
+
*/
|
|
53
|
+
async consolidate(messages, scope = 'project') {
|
|
54
|
+
// Skip tiny sessions — not enough to learn from
|
|
55
|
+
if (messages.length < 4) {
|
|
56
|
+
return { learningsFound: 0, memoryUpdated: false, scope };
|
|
57
|
+
}
|
|
58
|
+
// Stage 1 & 2: Gather learnings from conversation
|
|
59
|
+
const learnings = await this.gatherLearnings(messages);
|
|
60
|
+
if (!learnings || learnings === 'NO_LEARNINGS') {
|
|
61
|
+
return { learningsFound: 0, memoryUpdated: false, scope };
|
|
62
|
+
}
|
|
63
|
+
const learningsList = learnings.split('\n').filter(l => l.trim().startsWith('-') || l.trim().startsWith('*'));
|
|
64
|
+
if (learningsList.length === 0) {
|
|
65
|
+
return { learningsFound: 0, memoryUpdated: false, scope };
|
|
66
|
+
}
|
|
67
|
+
// Stage 3 & 4: Consolidate with existing memory
|
|
68
|
+
const existingMemory = await this.memoryManager.read(scope);
|
|
69
|
+
const consolidated = await this.consolidateMemory(existingMemory, learnings);
|
|
70
|
+
if (consolidated && consolidated.trim()) {
|
|
71
|
+
await this.memoryManager.write(scope, consolidated);
|
|
72
|
+
}
|
|
73
|
+
return {
|
|
74
|
+
learningsFound: learningsList.length,
|
|
75
|
+
memoryUpdated: true,
|
|
76
|
+
scope,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/** Stage 2: Extract learnings from conversation messages. */
|
|
80
|
+
async gatherLearnings(messages) {
|
|
81
|
+
// Build a condensed transcript for the LLM
|
|
82
|
+
const transcript = messages
|
|
83
|
+
.filter(m => !m.isMeta && !m.isVisibleInTranscriptOnly)
|
|
84
|
+
.map(m => {
|
|
85
|
+
const texts = m.content
|
|
86
|
+
.filter((b) => b.type === 'text')
|
|
87
|
+
.map(b => b.text)
|
|
88
|
+
.join('');
|
|
89
|
+
return `[${m.role}]: ${texts.slice(0, 2000)}`;
|
|
90
|
+
})
|
|
91
|
+
.join('\n\n');
|
|
92
|
+
// Limit transcript size for the LLM call
|
|
93
|
+
const truncated = transcript.length > 12_000
|
|
94
|
+
? transcript.slice(0, 6000) + '\n\n...(middle omitted)...\n\n' + transcript.slice(-6000)
|
|
95
|
+
: transcript;
|
|
96
|
+
const chatMessages = [
|
|
97
|
+
{ role: 'user', content: [{ type: 'text', text: `Here is the conversation to analyze:\n\n${truncated}` }] },
|
|
98
|
+
];
|
|
99
|
+
const options = {
|
|
100
|
+
model: this.model,
|
|
101
|
+
systemPrompt: GATHER_PROMPT,
|
|
102
|
+
maxTokens: 1024,
|
|
103
|
+
temperature: 0.3,
|
|
104
|
+
};
|
|
105
|
+
try {
|
|
106
|
+
const response = await this.adapter.chat(chatMessages, options);
|
|
107
|
+
const text = response.content
|
|
108
|
+
.filter((b) => b.type === 'text')
|
|
109
|
+
.map(b => b.text)
|
|
110
|
+
.join('');
|
|
111
|
+
return text.trim();
|
|
112
|
+
}
|
|
113
|
+
catch {
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/** Stage 3 & 4: Merge new learnings with existing memory. */
|
|
118
|
+
async consolidateMemory(existing, newLearnings) {
|
|
119
|
+
const prompt = CONSOLIDATE_PROMPT.replace('{MAX_LINES}', String(MAX_MEMORY_LINES));
|
|
120
|
+
const chatMessages = [
|
|
121
|
+
{
|
|
122
|
+
role: 'user',
|
|
123
|
+
content: [{
|
|
124
|
+
type: 'text',
|
|
125
|
+
text: `## Existing Memory\n\n${existing || '(empty — first session)'}\n\n## New Learnings\n\n${newLearnings}`,
|
|
126
|
+
}],
|
|
127
|
+
},
|
|
128
|
+
];
|
|
129
|
+
const options = {
|
|
130
|
+
model: this.model,
|
|
131
|
+
systemPrompt: prompt,
|
|
132
|
+
maxTokens: 2048,
|
|
133
|
+
temperature: 0.2,
|
|
134
|
+
};
|
|
135
|
+
try {
|
|
136
|
+
const response = await this.adapter.chat(chatMessages, options);
|
|
137
|
+
const text = response.content
|
|
138
|
+
.filter((b) => b.type === 'text')
|
|
139
|
+
.map(b => b.text)
|
|
140
|
+
.join('');
|
|
141
|
+
return text.trim();
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=consolidation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consolidation.js","sourceRoot":"","sources":["../../../src/memory/consolidation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MemoryManager — persistent cross-session learning for cmdr.
|
|
3
|
+
*
|
|
4
|
+
* Manages MEMORY.md files at two scopes:
|
|
5
|
+
* - Project: .cmdr/MEMORY.md (per-repo knowledge)
|
|
6
|
+
* - User: ~/.cmdr/MEMORY.md (global patterns, preferences)
|
|
7
|
+
*
|
|
8
|
+
* Memory is injected into the system prompt each session so the agent
|
|
9
|
+
* retains learned patterns, project conventions, and user preferences.
|
|
10
|
+
*/
|
|
11
|
+
export interface MemoryScope {
|
|
12
|
+
readonly scope: 'project' | 'user';
|
|
13
|
+
readonly path: string;
|
|
14
|
+
content: string;
|
|
15
|
+
}
|
|
16
|
+
export declare class MemoryManager {
|
|
17
|
+
private projectDir;
|
|
18
|
+
private caches;
|
|
19
|
+
constructor(projectDir: string);
|
|
20
|
+
/** Path to the project-level memory file. */
|
|
21
|
+
get projectMemoryPath(): string;
|
|
22
|
+
/** Path to the user-level memory file. */
|
|
23
|
+
get userMemoryPath(): string;
|
|
24
|
+
/** Read a memory file, returning empty string if not found. */
|
|
25
|
+
private readMemoryFile;
|
|
26
|
+
/** Write content to a memory file, creating directories as needed. */
|
|
27
|
+
private writeMemoryFile;
|
|
28
|
+
/** Load all memory scopes. */
|
|
29
|
+
loadAll(): Promise<MemoryScope[]>;
|
|
30
|
+
/** Get combined memory as a prompt-injectable string. */
|
|
31
|
+
getMemoryPrompt(): Promise<string>;
|
|
32
|
+
/** Read memory for a given scope. */
|
|
33
|
+
read(scope: 'project' | 'user'): Promise<string>;
|
|
34
|
+
/** Write (overwrite) memory for a given scope. */
|
|
35
|
+
write(scope: 'project' | 'user', content: string): Promise<void>;
|
|
36
|
+
/** Append to memory for a given scope (most common operation). */
|
|
37
|
+
append(scope: 'project' | 'user', entry: string): Promise<void>;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=memory-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-manager.d.ts","sourceRoot":"","sources":["../../../src/memory/memory-manager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,CAAA;IAClC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;CAChB;AAID,qBAAa,aAAa;IACxB,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,MAAM,CAAiC;gBAEnC,UAAU,EAAE,MAAM;IAI9B,6CAA6C;IAC7C,IAAI,iBAAiB,IAAI,MAAM,CAE9B;IAED,0CAA0C;IAC1C,IAAI,cAAc,IAAI,MAAM,CAE3B;IAED,+DAA+D;YACjD,cAAc;IAU5B,sEAAsE;YACxD,eAAe;IAU7B,8BAA8B;IACxB,OAAO,IAAI,OAAO,CAAC,WAAW,EAAE,CAAC;IAYvC,yDAAyD;IACnD,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC;IAaxC,qCAAqC;IAC/B,IAAI,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAKtD,kDAAkD;IAC5C,KAAK,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAKtE,kEAAkE;IAC5D,MAAM,CAAC,KAAK,EAAE,SAAS,GAAG,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAQtE"}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MemoryManager — persistent cross-session learning for cmdr.
|
|
3
|
+
*
|
|
4
|
+
* Manages MEMORY.md files at two scopes:
|
|
5
|
+
* - Project: .cmdr/MEMORY.md (per-repo knowledge)
|
|
6
|
+
* - User: ~/.cmdr/MEMORY.md (global patterns, preferences)
|
|
7
|
+
*
|
|
8
|
+
* Memory is injected into the system prompt each session so the agent
|
|
9
|
+
* retains learned patterns, project conventions, and user preferences.
|
|
10
|
+
*/
|
|
11
|
+
import { readFile, writeFile, mkdir } from 'fs/promises';
|
|
12
|
+
import { join, dirname } from 'path';
|
|
13
|
+
import { homedir } from 'os';
|
|
14
|
+
const MAX_MEMORY_SIZE = 8192; // chars — prevent context bloat
|
|
15
|
+
export class MemoryManager {
|
|
16
|
+
projectDir;
|
|
17
|
+
caches = new Map();
|
|
18
|
+
constructor(projectDir) {
|
|
19
|
+
this.projectDir = projectDir;
|
|
20
|
+
}
|
|
21
|
+
/** Path to the project-level memory file. */
|
|
22
|
+
get projectMemoryPath() {
|
|
23
|
+
return join(this.projectDir, '.cmdr', 'MEMORY.md');
|
|
24
|
+
}
|
|
25
|
+
/** Path to the user-level memory file. */
|
|
26
|
+
get userMemoryPath() {
|
|
27
|
+
return join(homedir(), '.cmdr', 'MEMORY.md');
|
|
28
|
+
}
|
|
29
|
+
/** Read a memory file, returning empty string if not found. */
|
|
30
|
+
async readMemoryFile(path) {
|
|
31
|
+
try {
|
|
32
|
+
const content = await readFile(path, 'utf-8');
|
|
33
|
+
this.caches.set(path, content);
|
|
34
|
+
return content;
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return '';
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/** Write content to a memory file, creating directories as needed. */
|
|
41
|
+
async writeMemoryFile(path, content) {
|
|
42
|
+
// Enforce size limit
|
|
43
|
+
const trimmed = content.length > MAX_MEMORY_SIZE
|
|
44
|
+
? content.slice(0, MAX_MEMORY_SIZE) + '\n\n<!-- Memory truncated at 8KB limit -->\n'
|
|
45
|
+
: content;
|
|
46
|
+
await mkdir(dirname(path), { recursive: true });
|
|
47
|
+
await writeFile(path, trimmed, 'utf-8');
|
|
48
|
+
this.caches.set(path, trimmed);
|
|
49
|
+
}
|
|
50
|
+
/** Load all memory scopes. */
|
|
51
|
+
async loadAll() {
|
|
52
|
+
const [project, user] = await Promise.all([
|
|
53
|
+
this.readMemoryFile(this.projectMemoryPath),
|
|
54
|
+
this.readMemoryFile(this.userMemoryPath),
|
|
55
|
+
]);
|
|
56
|
+
const scopes = [];
|
|
57
|
+
if (user)
|
|
58
|
+
scopes.push({ scope: 'user', path: this.userMemoryPath, content: user });
|
|
59
|
+
if (project)
|
|
60
|
+
scopes.push({ scope: 'project', path: this.projectMemoryPath, content: project });
|
|
61
|
+
return scopes;
|
|
62
|
+
}
|
|
63
|
+
/** Get combined memory as a prompt-injectable string. */
|
|
64
|
+
async getMemoryPrompt() {
|
|
65
|
+
const scopes = await this.loadAll();
|
|
66
|
+
if (scopes.length === 0)
|
|
67
|
+
return '';
|
|
68
|
+
const parts = [];
|
|
69
|
+
for (const scope of scopes) {
|
|
70
|
+
if (scope.content.trim()) {
|
|
71
|
+
parts.push(`<memory scope="${scope.scope}">\n${scope.content.trim()}\n</memory>`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return parts.join('\n\n');
|
|
75
|
+
}
|
|
76
|
+
/** Read memory for a given scope. */
|
|
77
|
+
async read(scope) {
|
|
78
|
+
const path = scope === 'project' ? this.projectMemoryPath : this.userMemoryPath;
|
|
79
|
+
return this.readMemoryFile(path);
|
|
80
|
+
}
|
|
81
|
+
/** Write (overwrite) memory for a given scope. */
|
|
82
|
+
async write(scope, content) {
|
|
83
|
+
const path = scope === 'project' ? this.projectMemoryPath : this.userMemoryPath;
|
|
84
|
+
await this.writeMemoryFile(path, content);
|
|
85
|
+
}
|
|
86
|
+
/** Append to memory for a given scope (most common operation). */
|
|
87
|
+
async append(scope, entry) {
|
|
88
|
+
const existing = await this.read(scope);
|
|
89
|
+
const timestamp = new Date().toISOString().split('T')[0];
|
|
90
|
+
const newContent = existing
|
|
91
|
+
? `${existing.trimEnd()}\n\n## ${timestamp}\n${entry.trim()}\n`
|
|
92
|
+
: `# CMDR Memory\n\n## ${timestamp}\n${entry.trim()}\n`;
|
|
93
|
+
await this.write(scope, newContent);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
//# sourceMappingURL=memory-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-manager.js","sourceRoot":"","sources":["../../../src/memory/memory-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* MCP Client — connects to external Model Context Protocol servers for tool expansion.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Supports multiple transports:
|
|
5
|
+
* - HTTP REST: GET /tools, POST /tools/{name}
|
|
6
|
+
* - stdio: Spawn a child process, communicate via JSON-RPC over stdin/stdout
|
|
7
|
+
* - SSE: Server-Sent Events for streaming tool discovery and execution
|
|
6
8
|
*/
|
|
7
9
|
import type { McpServerConfig, ToolResult } from '../core/types.js';
|
|
8
10
|
import type { ToolRegistry } from '../tools/registry.js';
|
|
@@ -13,18 +15,25 @@ interface McpTool {
|
|
|
13
15
|
}
|
|
14
16
|
export declare class McpClient {
|
|
15
17
|
private connections;
|
|
16
|
-
/** Connect to an MCP server
|
|
18
|
+
/** Connect to an MCP server. Auto-detects transport from config. */
|
|
17
19
|
connect(config: McpServerConfig): Promise<McpTool[]>;
|
|
20
|
+
private connectHttp;
|
|
21
|
+
private callToolHttp;
|
|
22
|
+
private connectStdio;
|
|
23
|
+
private callToolStdio;
|
|
24
|
+
private connectSse;
|
|
25
|
+
private callToolSse;
|
|
18
26
|
/** Disconnect from an MCP server. */
|
|
19
27
|
disconnect(name: string): boolean;
|
|
20
28
|
/** List connected MCP servers. */
|
|
21
29
|
listConnections(): Array<{
|
|
22
30
|
name: string;
|
|
23
|
-
url: string;
|
|
31
|
+
url: string | undefined;
|
|
24
32
|
tools: number;
|
|
25
33
|
connected: boolean;
|
|
34
|
+
transport: string;
|
|
26
35
|
}>;
|
|
27
|
-
/** Call a tool on an MCP server. */
|
|
36
|
+
/** Call a tool on an MCP server. Dispatches to the appropriate transport. */
|
|
28
37
|
callTool(serverName: string, toolName: string, input: Record<string, unknown>): Promise<ToolResult>;
|
|
29
38
|
/**
|
|
30
39
|
* Register all tools from connected MCP servers into a ToolRegistry.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"mcp-client.d.ts","sourceRoot":"","sources":["../../../src/plugins/mcp-client.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"mcp-client.d.ts","sourceRoot":"","sources":["../../../src/plugins/mcp-client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAkB,UAAU,EAAkB,MAAM,kBAAkB,CAAA;AACnG,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAA;AAKxD,UAAU,OAAO;IACf,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACrC;AA8BD,qBAAa,SAAS;IACpB,OAAO,CAAC,WAAW,CAAmC;IAEtD,oEAAoE;IAC9D,OAAO,CAAC,MAAM,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;YAY5C,WAAW;YAgBX,YAAY;YAuBZ,YAAY;YAmEZ,aAAa;YAuCb,UAAU;YAkCV,WAAW;IAKzB,qCAAqC;IACrC,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAUjC,kCAAkC;IAClC,eAAe,IAAI,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAUzH,6EAA6E;IACvE,QAAQ,CACZ,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC7B,OAAO,CAAC,UAAU,CAAC;IAgBtB;;;OAGG;IACH,aAAa,CAAC,QAAQ,EAAE,YAAY,GAAG,MAAM;IAyB7C,0CAA0C;IAC1C,IAAI,cAAc,IAAI,OAAO,CAE5B;CACF"}
|