@luckydraw/cumulus 0.5.1
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/README.md +148 -0
- package/dist/cli/cumulus.d.ts +3 -0
- package/dist/cli/cumulus.d.ts.map +1 -0
- package/dist/cli/cumulus.js +233 -0
- package/dist/cli/cumulus.js.map +1 -0
- package/dist/index.d.ts +33 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +43 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/config.d.ts +86 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +241 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/content-detector.d.ts +46 -0
- package/dist/lib/content-detector.d.ts.map +1 -0
- package/dist/lib/content-detector.js +359 -0
- package/dist/lib/content-detector.js.map +1 -0
- package/dist/lib/content-store.d.ts +255 -0
- package/dist/lib/content-store.d.ts.map +1 -0
- package/dist/lib/content-store.js +955 -0
- package/dist/lib/content-store.js.map +1 -0
- package/dist/lib/context-budget.d.ts +83 -0
- package/dist/lib/context-budget.d.ts.map +1 -0
- package/dist/lib/context-budget.js +101 -0
- package/dist/lib/context-budget.js.map +1 -0
- package/dist/lib/embeddings.d.ts +64 -0
- package/dist/lib/embeddings.d.ts.map +1 -0
- package/dist/lib/embeddings.js +176 -0
- package/dist/lib/embeddings.js.map +1 -0
- package/dist/lib/history.d.ts +120 -0
- package/dist/lib/history.d.ts.map +1 -0
- package/dist/lib/history.js +205 -0
- package/dist/lib/history.js.map +1 -0
- package/dist/lib/image-utils.d.ts +41 -0
- package/dist/lib/image-utils.d.ts.map +1 -0
- package/dist/lib/image-utils.js +288 -0
- package/dist/lib/image-utils.js.map +1 -0
- package/dist/lib/migrate.d.ts +35 -0
- package/dist/lib/migrate.d.ts.map +1 -0
- package/dist/lib/migrate.js +196 -0
- package/dist/lib/migrate.js.map +1 -0
- package/dist/lib/retriever.d.ts +56 -0
- package/dist/lib/retriever.d.ts.map +1 -0
- package/dist/lib/retriever.js +644 -0
- package/dist/lib/retriever.js.map +1 -0
- package/dist/lib/revert.d.ts +23 -0
- package/dist/lib/revert.d.ts.map +1 -0
- package/dist/lib/revert.js +75 -0
- package/dist/lib/revert.js.map +1 -0
- package/dist/lib/session.d.ts +65 -0
- package/dist/lib/session.d.ts.map +1 -0
- package/dist/lib/session.js +289 -0
- package/dist/lib/session.js.map +1 -0
- package/dist/lib/snapshots.d.ts +39 -0
- package/dist/lib/snapshots.d.ts.map +1 -0
- package/dist/lib/snapshots.js +99 -0
- package/dist/lib/snapshots.js.map +1 -0
- package/dist/lib/stream-processor.d.ts +149 -0
- package/dist/lib/stream-processor.d.ts.map +1 -0
- package/dist/lib/stream-processor.js +389 -0
- package/dist/lib/stream-processor.js.map +1 -0
- package/dist/lib/summarizer.d.ts +67 -0
- package/dist/lib/summarizer.d.ts.map +1 -0
- package/dist/lib/summarizer.js +213 -0
- package/dist/lib/summarizer.js.map +1 -0
- package/dist/mcp/index.d.ts +3 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +16 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/proxy.d.ts +19 -0
- package/dist/mcp/proxy.d.ts.map +1 -0
- package/dist/mcp/proxy.js +120 -0
- package/dist/mcp/proxy.js.map +1 -0
- package/dist/mcp/server.d.ts +6 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +29 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/mcp/shared-server.d.ts +21 -0
- package/dist/mcp/shared-server.d.ts.map +1 -0
- package/dist/mcp/shared-server.js +210 -0
- package/dist/mcp/shared-server.js.map +1 -0
- package/dist/mcp/tool-handler.d.ts +20 -0
- package/dist/mcp/tool-handler.d.ts.map +1 -0
- package/dist/mcp/tool-handler.js +1405 -0
- package/dist/mcp/tool-handler.js.map +1 -0
- package/dist/tui/components/App.d.ts +11 -0
- package/dist/tui/components/App.d.ts.map +1 -0
- package/dist/tui/components/App.js +607 -0
- package/dist/tui/components/App.js.map +1 -0
- package/dist/tui/components/DebugContextView.d.ts +13 -0
- package/dist/tui/components/DebugContextView.d.ts.map +1 -0
- package/dist/tui/components/DebugContextView.js +78 -0
- package/dist/tui/components/DebugContextView.js.map +1 -0
- package/dist/tui/components/IncludeMenu.d.ts +12 -0
- package/dist/tui/components/IncludeMenu.d.ts.map +1 -0
- package/dist/tui/components/IncludeMenu.js +127 -0
- package/dist/tui/components/IncludeMenu.js.map +1 -0
- package/dist/tui/components/InputArea.d.ts +27 -0
- package/dist/tui/components/InputArea.d.ts.map +1 -0
- package/dist/tui/components/InputArea.js +366 -0
- package/dist/tui/components/InputArea.js.map +1 -0
- package/dist/tui/components/MarkdownText.d.ts +38 -0
- package/dist/tui/components/MarkdownText.d.ts.map +1 -0
- package/dist/tui/components/MarkdownText.js +234 -0
- package/dist/tui/components/MarkdownText.js.map +1 -0
- package/dist/tui/components/MessageBubble.d.ts +11 -0
- package/dist/tui/components/MessageBubble.d.ts.map +1 -0
- package/dist/tui/components/MessageBubble.js +16 -0
- package/dist/tui/components/MessageBubble.js.map +1 -0
- package/dist/tui/components/MessageHistory.d.ts +11 -0
- package/dist/tui/components/MessageHistory.d.ts.map +1 -0
- package/dist/tui/components/MessageHistory.js +12 -0
- package/dist/tui/components/MessageHistory.js.map +1 -0
- package/dist/tui/components/RevertMenu.d.ts +17 -0
- package/dist/tui/components/RevertMenu.d.ts.map +1 -0
- package/dist/tui/components/RevertMenu.js +144 -0
- package/dist/tui/components/RevertMenu.js.map +1 -0
- package/dist/tui/components/StatusBar.d.ts +14 -0
- package/dist/tui/components/StatusBar.d.ts.map +1 -0
- package/dist/tui/components/StatusBar.js +13 -0
- package/dist/tui/components/StatusBar.js.map +1 -0
- package/dist/tui/components/StreamingResponse.d.ts +15 -0
- package/dist/tui/components/StreamingResponse.d.ts.map +1 -0
- package/dist/tui/components/StreamingResponse.js +52 -0
- package/dist/tui/components/StreamingResponse.js.map +1 -0
- package/dist/tui/hooks/useAppState.d.ts +147 -0
- package/dist/tui/hooks/useAppState.d.ts.map +1 -0
- package/dist/tui/hooks/useAppState.js +110 -0
- package/dist/tui/hooks/useAppState.js.map +1 -0
- package/dist/tui/hooks/useClaudeProcess.d.ts +19 -0
- package/dist/tui/hooks/useClaudeProcess.d.ts.map +1 -0
- package/dist/tui/hooks/useClaudeProcess.js +185 -0
- package/dist/tui/hooks/useClaudeProcess.js.map +1 -0
- package/dist/tui/index.d.ts +10 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +11 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/tui/utils/streamParser.d.ts +31 -0
- package/dist/tui/utils/streamParser.d.ts.map +1 -0
- package/dist/tui/utils/streamParser.js +63 -0
- package/dist/tui/utils/streamParser.js.map +1 -0
- package/package.json +94 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
import { existsSync } from 'fs';
|
|
2
|
+
import * as fs from 'fs/promises';
|
|
3
|
+
// Constants
|
|
4
|
+
const MESSAGE_THRESHOLD = 50;
|
|
5
|
+
const TOKEN_THRESHOLD = 10000;
|
|
6
|
+
const SUMMARY_FILE_SUFFIX = '.summaries.json';
|
|
7
|
+
/**
|
|
8
|
+
* Get the summary file path for a thread.
|
|
9
|
+
*/
|
|
10
|
+
export function getSummaryPath(threadPath) {
|
|
11
|
+
return threadPath.replace('.jsonl', SUMMARY_FILE_SUFFIX);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Load existing summaries for a thread.
|
|
15
|
+
*/
|
|
16
|
+
export async function loadSummaries(threadPath) {
|
|
17
|
+
const summaryPath = getSummaryPath(threadPath);
|
|
18
|
+
if (!existsSync(summaryPath)) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const content = await fs.readFile(summaryPath, 'utf-8');
|
|
23
|
+
return JSON.parse(content);
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Save summaries to file.
|
|
31
|
+
*/
|
|
32
|
+
export async function saveSummaries(summaryFile, threadPath) {
|
|
33
|
+
const summaryPath = getSummaryPath(threadPath);
|
|
34
|
+
await fs.writeFile(summaryPath, JSON.stringify(summaryFile, null, 2), 'utf-8');
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Check if summarization should be triggered.
|
|
38
|
+
*/
|
|
39
|
+
export function shouldSummarize(lastSummaryIndex, currentIndex, estimatedTokens = 0) {
|
|
40
|
+
const messageGap = currentIndex - lastSummaryIndex;
|
|
41
|
+
return messageGap >= MESSAGE_THRESHOLD || estimatedTokens >= TOKEN_THRESHOLD;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Extract topics from summary text using simple pattern matching.
|
|
45
|
+
*/
|
|
46
|
+
function extractTopicsFromSummary(summary) {
|
|
47
|
+
const topicPatterns = [
|
|
48
|
+
/discussed\s+(\w+(?:\s+\w+)?)/gi,
|
|
49
|
+
/implemented\s+(\w+(?:\s+\w+)?)/gi,
|
|
50
|
+
/decided\s+(?:on\s+)?(\w+(?:\s+\w+)?)/gi,
|
|
51
|
+
/working\s+on\s+(\w+(?:\s+\w+)?)/gi,
|
|
52
|
+
/about\s+(\w+(?:\s+\w+)?)/gi,
|
|
53
|
+
];
|
|
54
|
+
const topics = new Set();
|
|
55
|
+
for (const pattern of topicPatterns) {
|
|
56
|
+
const matches = summary.matchAll(pattern);
|
|
57
|
+
for (const match of matches) {
|
|
58
|
+
if (match[1]) {
|
|
59
|
+
topics.add(match[1].toLowerCase());
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return Array.from(topics).slice(0, 10);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Format messages for summarization prompt.
|
|
67
|
+
*/
|
|
68
|
+
function formatMessagesForSummary(messages) {
|
|
69
|
+
return messages
|
|
70
|
+
.map(m => {
|
|
71
|
+
const date = new Date(m.timestamp).toISOString().split('T')[0];
|
|
72
|
+
return `[${date}] ${m.role}: ${m.content}`;
|
|
73
|
+
})
|
|
74
|
+
.join('\n\n');
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Generate a summary for a chunk of messages using sub_query.
|
|
78
|
+
*/
|
|
79
|
+
export async function generateChunkSummary(messages, fromIndex, toIndex, subQueryFn) {
|
|
80
|
+
const context = formatMessagesForSummary(messages);
|
|
81
|
+
const prompt = `Summarize this conversation segment concisely. Include:
|
|
82
|
+
- Key topics discussed
|
|
83
|
+
- Decisions made
|
|
84
|
+
- Technical concepts or code discussed
|
|
85
|
+
- Action items or next steps
|
|
86
|
+
- Important context for future reference
|
|
87
|
+
|
|
88
|
+
Keep the summary focused and under 500 words.`;
|
|
89
|
+
const content = await subQueryFn(prompt, context);
|
|
90
|
+
const topics = extractTopicsFromSummary(content);
|
|
91
|
+
return {
|
|
92
|
+
id: `sum_${Date.now()}_${fromIndex}`,
|
|
93
|
+
fromIndex,
|
|
94
|
+
toIndex,
|
|
95
|
+
generatedAt: Date.now(),
|
|
96
|
+
content,
|
|
97
|
+
topics,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Generate a high-level session summary from multiple chunk summaries.
|
|
102
|
+
*/
|
|
103
|
+
export async function generateSessionSummary(chunks, subQueryFn) {
|
|
104
|
+
if (chunks.length <= 1) {
|
|
105
|
+
return chunks[0]?.content ?? '';
|
|
106
|
+
}
|
|
107
|
+
const context = chunks
|
|
108
|
+
.map(c => `[Messages ${c.fromIndex}-${c.toIndex}]:\n${c.content}`)
|
|
109
|
+
.join('\n\n---\n\n');
|
|
110
|
+
const prompt = `Create a high-level summary combining these conversation segments.
|
|
111
|
+
Focus on the overall narrative, major decisions, and key outcomes.
|
|
112
|
+
Keep it concise but comprehensive.`;
|
|
113
|
+
return await subQueryFn(prompt, context);
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Run summarization for a thread if needed.
|
|
117
|
+
*/
|
|
118
|
+
export async function runSummarization(threadPath, messages, subQueryFn) {
|
|
119
|
+
if (messages.length === 0) {
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
const currentIndex = messages.length - 1;
|
|
123
|
+
let summaryFile = await loadSummaries(threadPath);
|
|
124
|
+
if (!summaryFile) {
|
|
125
|
+
// Extract thread ID from path
|
|
126
|
+
const threadId = threadPath.split('/').pop()?.replace('.jsonl', '') ?? 'unknown';
|
|
127
|
+
summaryFile = {
|
|
128
|
+
threadId,
|
|
129
|
+
lastMessageIndex: -1,
|
|
130
|
+
summaries: [],
|
|
131
|
+
updatedAt: Date.now(),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
const startIndex = summaryFile.lastMessageIndex + 1;
|
|
135
|
+
if (!shouldSummarize(summaryFile.lastMessageIndex, currentIndex)) {
|
|
136
|
+
return; // Not enough new messages
|
|
137
|
+
}
|
|
138
|
+
// Get the chunk of messages to summarize
|
|
139
|
+
const chunk = messages.slice(startIndex, currentIndex + 1);
|
|
140
|
+
// Generate chunk summary
|
|
141
|
+
const summary = await generateChunkSummary(chunk, startIndex, currentIndex, subQueryFn);
|
|
142
|
+
summaryFile.summaries.push(summary);
|
|
143
|
+
summaryFile.lastMessageIndex = currentIndex;
|
|
144
|
+
summaryFile.updatedAt = Date.now();
|
|
145
|
+
// Regenerate session summary if we have multiple chunks
|
|
146
|
+
if (summaryFile.summaries.length > 1) {
|
|
147
|
+
summaryFile.sessionSummary = await generateSessionSummary(summaryFile.summaries, subQueryFn);
|
|
148
|
+
}
|
|
149
|
+
await saveSummaries(summaryFile, threadPath);
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Get summary based on scope.
|
|
153
|
+
*/
|
|
154
|
+
export async function getSummary(threadPath, scope = 'recent', startIndex, endIndex) {
|
|
155
|
+
const summaryFile = await loadSummaries(threadPath);
|
|
156
|
+
if (!summaryFile || summaryFile.summaries.length === 0) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
switch (scope) {
|
|
160
|
+
case 'recent': {
|
|
161
|
+
const latest = summaryFile.summaries[summaryFile.summaries.length - 1];
|
|
162
|
+
if (!latest)
|
|
163
|
+
return null;
|
|
164
|
+
return {
|
|
165
|
+
summary: latest.content,
|
|
166
|
+
coversMessages: { from: latest.fromIndex, to: latest.toIndex },
|
|
167
|
+
topics: latest.topics,
|
|
168
|
+
generatedAt: latest.generatedAt,
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
case 'full': {
|
|
172
|
+
const allTopics = [...new Set(summaryFile.summaries.flatMap(s => s.topics))];
|
|
173
|
+
const firstChunk = summaryFile.summaries[0];
|
|
174
|
+
const lastChunk = summaryFile.summaries[summaryFile.summaries.length - 1];
|
|
175
|
+
if (!firstChunk || !lastChunk)
|
|
176
|
+
return null;
|
|
177
|
+
return {
|
|
178
|
+
summary: summaryFile.sessionSummary ?? lastChunk.content,
|
|
179
|
+
coversMessages: {
|
|
180
|
+
from: firstChunk.fromIndex,
|
|
181
|
+
to: lastChunk.toIndex,
|
|
182
|
+
},
|
|
183
|
+
topics: allTopics,
|
|
184
|
+
generatedAt: summaryFile.updatedAt,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
case 'range': {
|
|
188
|
+
if (startIndex === undefined || endIndex === undefined) {
|
|
189
|
+
throw new Error('startIndex and endIndex required for range scope');
|
|
190
|
+
}
|
|
191
|
+
// Find summaries that overlap with the requested range
|
|
192
|
+
const relevantSummaries = summaryFile.summaries.filter(s => s.toIndex >= startIndex && s.fromIndex <= endIndex);
|
|
193
|
+
if (relevantSummaries.length === 0) {
|
|
194
|
+
return null;
|
|
195
|
+
}
|
|
196
|
+
const combinedTopics = [...new Set(relevantSummaries.flatMap(s => s.topics))];
|
|
197
|
+
const combinedSummary = relevantSummaries.map(s => s.content).join('\n\n');
|
|
198
|
+
const first = relevantSummaries[0];
|
|
199
|
+
const last = relevantSummaries[relevantSummaries.length - 1];
|
|
200
|
+
if (!first || !last)
|
|
201
|
+
return null;
|
|
202
|
+
return {
|
|
203
|
+
summary: combinedSummary,
|
|
204
|
+
coversMessages: {
|
|
205
|
+
from: Math.max(startIndex, first.fromIndex),
|
|
206
|
+
to: Math.min(endIndex, last.toIndex),
|
|
207
|
+
},
|
|
208
|
+
topics: combinedTopics,
|
|
209
|
+
};
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=summarizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"summarizer.js","sourceRoot":"","sources":["../../src/lib/summarizer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { runServer } from './server.js';
|
|
3
|
+
const threadPath = process.env['CUMULUS_THREAD_PATH'];
|
|
4
|
+
const contentPath = process.env['CUMULUS_CONTENT_PATH'];
|
|
5
|
+
const sessionsPath = process.env['CUMULUS_SESSIONS_PATH'];
|
|
6
|
+
const sessionId = process.env['CUMULUS_SESSION_ID'];
|
|
7
|
+
if (!threadPath) {
|
|
8
|
+
console.error('Error: CUMULUS_THREAD_PATH environment variable is required');
|
|
9
|
+
console.error('Usage: CUMULUS_THREAD_PATH=/path/to/thread.jsonl node dist/mcp/index.js');
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
runServer(threadPath, contentPath, sessionsPath, sessionId).catch(error => {
|
|
13
|
+
console.error('MCP server error:', error);
|
|
14
|
+
process.exit(1);
|
|
15
|
+
});
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;AACtD,MAAM,WAAW,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAC;AACxD,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;AAC1D,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;AAEpD,IAAI,CAAC,UAAU,EAAE,CAAC;IAChB,OAAO,CAAC,KAAK,CAAC,6DAA6D,CAAC,CAAC;IAC7E,OAAO,CAAC,KAAK,CAAC,yEAAyE,CAAC,CAAC;IACzF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,SAAS,CAAC,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;IACxE,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;IAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Lightweight stdio↔HTTP proxy for the shared MCP server.
|
|
4
|
+
*
|
|
5
|
+
* Claude CLI spawns this as a normal stdio MCP server.
|
|
6
|
+
* It forwards every JSON-RPC message to the shared HTTP server
|
|
7
|
+
* and pipes responses back over stdout.
|
|
8
|
+
*
|
|
9
|
+
* Environment variables:
|
|
10
|
+
* CUMULUS_SHARED_URL — Base URL of the shared server (e.g. http://127.0.0.1:3456)
|
|
11
|
+
* CUMULUS_THREAD_NAME — Thread name for this agent (e.g. "janus", "puppet")
|
|
12
|
+
*
|
|
13
|
+
* Stdin: newline-delimited JSON-RPC (one JSON object per line)
|
|
14
|
+
* Stdout: newline-delimited JSON-RPC responses
|
|
15
|
+
*
|
|
16
|
+
* Zero heavy deps — only uses Node built-ins (http, readline).
|
|
17
|
+
*/
|
|
18
|
+
export {};
|
|
19
|
+
//# sourceMappingURL=proxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/mcp/proxy.ts"],"names":[],"mappings":";AACA;;;;;;;;;;;;;;;GAeG"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Lightweight stdio↔HTTP proxy for the shared MCP server.
|
|
4
|
+
*
|
|
5
|
+
* Claude CLI spawns this as a normal stdio MCP server.
|
|
6
|
+
* It forwards every JSON-RPC message to the shared HTTP server
|
|
7
|
+
* and pipes responses back over stdout.
|
|
8
|
+
*
|
|
9
|
+
* Environment variables:
|
|
10
|
+
* CUMULUS_SHARED_URL — Base URL of the shared server (e.g. http://127.0.0.1:3456)
|
|
11
|
+
* CUMULUS_THREAD_NAME — Thread name for this agent (e.g. "janus", "puppet")
|
|
12
|
+
*
|
|
13
|
+
* Stdin: newline-delimited JSON-RPC (one JSON object per line)
|
|
14
|
+
* Stdout: newline-delimited JSON-RPC responses
|
|
15
|
+
*
|
|
16
|
+
* Zero heavy deps — only uses Node built-ins (http, readline).
|
|
17
|
+
*/
|
|
18
|
+
import * as http from 'http';
|
|
19
|
+
import * as https from 'https';
|
|
20
|
+
import * as readline from 'readline';
|
|
21
|
+
import { URL } from 'url';
|
|
22
|
+
const sharedUrl = process.env['CUMULUS_SHARED_URL'];
|
|
23
|
+
const threadName = process.env['CUMULUS_THREAD_NAME'];
|
|
24
|
+
if (!sharedUrl || !threadName) {
|
|
25
|
+
process.stderr.write('Error: CUMULUS_SHARED_URL and CUMULUS_THREAD_NAME environment variables are required\n');
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
const rpcUrl = new URL(`/rpc/${encodeURIComponent(threadName)}`, sharedUrl);
|
|
29
|
+
const httpModule = rpcUrl.protocol === 'https:' ? https : http;
|
|
30
|
+
/**
|
|
31
|
+
* POST a JSON-RPC message to the shared server and return the response body.
|
|
32
|
+
* Returns null for 204 (notification acknowledged).
|
|
33
|
+
*/
|
|
34
|
+
function postRpc(body) {
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
const req = httpModule.request(rpcUrl, {
|
|
37
|
+
method: 'POST',
|
|
38
|
+
headers: {
|
|
39
|
+
'Content-Type': 'application/json',
|
|
40
|
+
'Content-Length': Buffer.byteLength(body),
|
|
41
|
+
},
|
|
42
|
+
}, res => {
|
|
43
|
+
if (res.statusCode === 204) {
|
|
44
|
+
res.resume(); // drain
|
|
45
|
+
resolve(null);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const chunks = [];
|
|
49
|
+
res.on('data', (chunk) => chunks.push(chunk));
|
|
50
|
+
res.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));
|
|
51
|
+
res.on('error', reject);
|
|
52
|
+
});
|
|
53
|
+
req.on('error', err => {
|
|
54
|
+
// If the shared server is down, return an error response
|
|
55
|
+
reject(err);
|
|
56
|
+
});
|
|
57
|
+
req.write(body);
|
|
58
|
+
req.end();
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
// ── Main loop ──────────────────────────────────────────
|
|
62
|
+
const rl = readline.createInterface({
|
|
63
|
+
input: process.stdin,
|
|
64
|
+
terminal: false,
|
|
65
|
+
});
|
|
66
|
+
rl.on('line', async (line) => {
|
|
67
|
+
const trimmed = line.trim();
|
|
68
|
+
if (!trimmed)
|
|
69
|
+
return;
|
|
70
|
+
try {
|
|
71
|
+
// Parse to validate it's JSON, then forward the raw string
|
|
72
|
+
const msg = JSON.parse(trimmed);
|
|
73
|
+
const responseBody = await postRpc(trimmed);
|
|
74
|
+
if (responseBody !== null) {
|
|
75
|
+
// Write response as newline-delimited JSON
|
|
76
|
+
process.stdout.write(responseBody + '\n');
|
|
77
|
+
}
|
|
78
|
+
// For notifications (204), no stdout output — Claude doesn't expect a response
|
|
79
|
+
// If this was a notification and it's "cancelled", we could abort in-flight
|
|
80
|
+
// requests in the future. For now, just forward and move on.
|
|
81
|
+
if (msg.method === 'notifications/cancelled') {
|
|
82
|
+
// Future: could track in-flight requests and abort them
|
|
83
|
+
process.stderr.write(`[cumulus-proxy] Received cancellation for request ${msg.params?.requestId}\n`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
// If the shared server is unreachable, return a JSON-RPC error
|
|
88
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
89
|
+
process.stderr.write(`[cumulus-proxy] Error: ${message}\n`);
|
|
90
|
+
// Try to extract the id from the original message for the error response
|
|
91
|
+
let id;
|
|
92
|
+
try {
|
|
93
|
+
id = JSON.parse(trimmed).id;
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
// couldn't parse, leave id undefined
|
|
97
|
+
}
|
|
98
|
+
if (id !== undefined) {
|
|
99
|
+
const errorResponse = {
|
|
100
|
+
jsonrpc: '2.0',
|
|
101
|
+
id,
|
|
102
|
+
error: {
|
|
103
|
+
code: -32603,
|
|
104
|
+
message: `Proxy error: ${message}`,
|
|
105
|
+
},
|
|
106
|
+
};
|
|
107
|
+
process.stdout.write(JSON.stringify(errorResponse) + '\n');
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
rl.on('close', () => {
|
|
112
|
+
// stdin closed — Claude CLI terminated. Exit cleanly.
|
|
113
|
+
process.exit(0);
|
|
114
|
+
});
|
|
115
|
+
// Handle uncaught errors gracefully
|
|
116
|
+
process.on('uncaughtException', err => {
|
|
117
|
+
process.stderr.write(`[cumulus-proxy] Uncaught exception: ${err.message}\n`);
|
|
118
|
+
process.exit(1);
|
|
119
|
+
});
|
|
120
|
+
//# sourceMappingURL=proxy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/mcp/proxy.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import { ContentStore } from '../lib/content-store.js';
|
|
3
|
+
import { HistoryStore } from '../lib/history.js';
|
|
4
|
+
export declare function createMcpServer(historyStore: HistoryStore, contentStore?: ContentStore, sessionsPath?: string, currentSessionId?: string): Server;
|
|
5
|
+
export declare function runServer(threadPath: string, contentPath?: string, sessionsPath?: string, sessionId?: string): Promise<void>;
|
|
6
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AAInE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAIjD,wBAAgB,eAAe,CAC7B,YAAY,EAAE,YAAY,EAC1B,YAAY,CAAC,EAAE,YAAY,EAC3B,YAAY,CAAC,EAAE,MAAM,EACrB,gBAAgB,CAAC,EAAE,MAAM,GACxB,MAAM,CAkBR;AAED,wBAAsB,SAAS,CAC7B,UAAU,EAAE,MAAM,EAClB,WAAW,CAAC,EAAE,MAAM,EACpB,YAAY,CAAC,EAAE,MAAM,EACrB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,IAAI,CAAC,CASf"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { Server } from '@modelcontextprotocol/sdk/server/index.js';
|
|
2
|
+
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
3
|
+
import { CallToolRequestSchema, ListToolsRequestSchema } from '@modelcontextprotocol/sdk/types.js';
|
|
4
|
+
import { ContentStore } from '../lib/content-store.js';
|
|
5
|
+
import { HistoryStore } from '../lib/history.js';
|
|
6
|
+
import { getToolDefinitions, handleToolCall } from './tool-handler.js';
|
|
7
|
+
export function createMcpServer(historyStore, contentStore, sessionsPath, currentSessionId) {
|
|
8
|
+
const ctx = { historyStore, contentStore, sessionsPath, currentSessionId };
|
|
9
|
+
const server = new Server({ name: 'cumulus-history', version: '1.0.0' }, { capabilities: { tools: {} } });
|
|
10
|
+
server.setRequestHandler(ListToolsRequestSchema, async () => ({
|
|
11
|
+
tools: getToolDefinitions(),
|
|
12
|
+
}));
|
|
13
|
+
server.setRequestHandler(CallToolRequestSchema, async (request) => {
|
|
14
|
+
const { name, arguments: args } = request.params;
|
|
15
|
+
return handleToolCall(name, args, ctx);
|
|
16
|
+
});
|
|
17
|
+
return server;
|
|
18
|
+
}
|
|
19
|
+
export async function runServer(threadPath, contentPath, sessionsPath, sessionId) {
|
|
20
|
+
const historyStore = new HistoryStore(threadPath);
|
|
21
|
+
const contentStore = contentPath ? new ContentStore(contentPath) : undefined;
|
|
22
|
+
const server = createMcpServer(historyStore, contentStore, sessionsPath, sessionId);
|
|
23
|
+
const transport = new StdioServerTransport();
|
|
24
|
+
await server.connect(transport);
|
|
25
|
+
await new Promise(resolve => {
|
|
26
|
+
transport.onclose = () => resolve();
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/mcp/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2CAA2C,CAAC;AACnE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,oCAAoC,CAAC;AAEnG,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAe,MAAM,mBAAmB,CAAC;AAEpF,MAAM,UAAU,eAAe,CAC7B,YAA0B,EAC1B,YAA2B,EAC3B,YAAqB,EACrB,gBAAyB;IAEzB,MAAM,GAAG,GAAgB,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,gBAAgB,EAAE,CAAC;IAExF,MAAM,MAAM,GAAG,IAAI,MAAM,CACvB,EAAE,IAAI,EAAE,iBAAiB,EAAE,OAAO,EAAE,OAAO,EAAE,EAC7C,EAAE,YAAY,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,EAAE,CAChC,CAAC;IAEF,MAAM,CAAC,iBAAiB,CAAC,sBAAsB,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC;QAC5D,KAAK,EAAE,kBAAkB,EAAE;KAC5B,CAAC,CAAC,CAAC;IAEJ,MAAM,CAAC,iBAAiB,CAAC,qBAAqB,EAAE,KAAK,EAAC,OAAO,EAAC,EAAE;QAC9D,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;QACjD,OAAO,cAAc,CAAC,IAAI,EAAE,IAA2C,EAAE,GAAG,CAAC,CAAC;IAChF,CAAC,CAAC,CAAC;IAEH,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,UAAkB,EAClB,WAAoB,EACpB,YAAqB,EACrB,SAAkB;IAElB,MAAM,YAAY,GAAG,IAAI,YAAY,CAAC,UAAU,CAAC,CAAC;IAClD,MAAM,YAAY,GAAG,WAAW,CAAC,CAAC,CAAC,IAAI,YAAY,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC7E,MAAM,MAAM,GAAG,eAAe,CAAC,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC;IACpF,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAChC,MAAM,IAAI,OAAO,CAAO,OAAO,CAAC,EAAE;QAChC,SAAS,CAAC,OAAO,GAAG,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;IACtC,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared MCP server — one HTTP process serving multiple threads.
|
|
3
|
+
*
|
|
4
|
+
* Exposes POST /rpc/:threadName which accepts JSON-RPC messages
|
|
5
|
+
* (the same protocol Claude CLI speaks over stdio).
|
|
6
|
+
* Caches HistoryStore/ContentStore per thread so the embeddings
|
|
7
|
+
* model loads once, not once per agent.
|
|
8
|
+
*/
|
|
9
|
+
export interface SharedMcpServerOptions {
|
|
10
|
+
/** Base directory containing thread data (e.g. ~/.cumulus) */
|
|
11
|
+
basePath: string;
|
|
12
|
+
/** Port to listen on. 0 = random available port. */
|
|
13
|
+
port?: number;
|
|
14
|
+
}
|
|
15
|
+
export interface SharedMcpServerHandle {
|
|
16
|
+
port: number;
|
|
17
|
+
url: string;
|
|
18
|
+
close: () => Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
export declare function startSharedMcpServer(options: SharedMcpServerOptions): Promise<SharedMcpServerHandle>;
|
|
21
|
+
//# sourceMappingURL=shared-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shared-server.d.ts","sourceRoot":"","sources":["../../src/mcp/shared-server.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAaH,MAAM,WAAW,sBAAsB;IACrC,8DAA8D;IAC9D,QAAQ,EAAE,MAAM,CAAC;IACjB,oDAAoD;IACpD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AA6LD,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,sBAAsB,GAC9B,OAAO,CAAC,qBAAqB,CAAC,CA0EhC"}
|