cckb 0.1.6 → 0.1.9
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/cckb.js +4 -4
- package/dist/{chunk-FEXOQA6H.js → chunk-AJ2AVV5V.js} +3 -3
- package/dist/{chunk-2USUMNE7.js → chunk-EXDIJANL.js} +2 -2
- package/dist/{chunk-V6LRQYKA.js → chunk-I4GLPRZ2.js} +3 -3
- package/dist/chunk-I4GLPRZ2.js.map +1 -0
- package/dist/{chunk-CGTH2E5W.js → chunk-JTHQRYKF.js} +3 -3
- package/dist/{chunk-D753AA36.js → chunk-NEHPNFRM.js} +2 -2
- package/dist/{chunk-C7H3GIXY.js → chunk-OZQVYSKC.js} +6 -3
- package/dist/chunk-OZQVYSKC.js.map +1 -0
- package/dist/hooks/notification.js +2 -2
- package/dist/hooks/post-tool-use.js +2 -2
- package/dist/hooks/session-start.js +3 -3
- package/dist/hooks/stop.js +44 -25
- package/dist/hooks/stop.js.map +1 -1
- package/dist/hooks/user-prompt.js +2 -2
- package/dist/index.js +6 -6
- package/package.json +1 -1
- package/dist/chunk-C7H3GIXY.js.map +0 -1
- package/dist/chunk-V6LRQYKA.js.map +0 -1
- /package/dist/{chunk-FEXOQA6H.js.map → chunk-AJ2AVV5V.js.map} +0 -0
- /package/dist/{chunk-2USUMNE7.js.map → chunk-EXDIJANL.js.map} +0 -0
- /package/dist/{chunk-CGTH2E5W.js.map → chunk-JTHQRYKF.js.map} +0 -0
- /package/dist/{chunk-D753AA36.js.map → chunk-NEHPNFRM.js.map} +0 -0
package/dist/bin/cckb.js
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import {
|
|
3
3
|
discover,
|
|
4
4
|
install
|
|
5
|
-
} from "../chunk-
|
|
6
|
-
import "../chunk-
|
|
7
|
-
import "../chunk-
|
|
8
|
-
import "../chunk-
|
|
5
|
+
} from "../chunk-JTHQRYKF.js";
|
|
6
|
+
import "../chunk-AJ2AVV5V.js";
|
|
7
|
+
import "../chunk-NEHPNFRM.js";
|
|
8
|
+
import "../chunk-I4GLPRZ2.js";
|
|
9
9
|
|
|
10
10
|
// src/bin/cckb.ts
|
|
11
11
|
var args = process.argv.slice(2);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import {
|
|
2
2
|
IndexManager
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-NEHPNFRM.js";
|
|
4
4
|
import {
|
|
5
5
|
appendToFile,
|
|
6
6
|
ensureDir,
|
|
7
7
|
fileExists,
|
|
8
8
|
readTextFile,
|
|
9
9
|
writeTextFile
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-I4GLPRZ2.js";
|
|
11
11
|
|
|
12
12
|
// src/core/entity-detector.ts
|
|
13
13
|
var EntityDetector = class {
|
|
@@ -355,4 +355,4 @@ export {
|
|
|
355
355
|
spawnClaudeAgent,
|
|
356
356
|
isClaudeAvailable
|
|
357
357
|
};
|
|
358
|
-
//# sourceMappingURL=chunk-
|
|
358
|
+
//# sourceMappingURL=chunk-AJ2AVV5V.js.map
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
readTextFile,
|
|
14
14
|
writeJSON,
|
|
15
15
|
writeTextFile
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-I4GLPRZ2.js";
|
|
17
17
|
|
|
18
18
|
// src/core/conversation-manager.ts
|
|
19
19
|
import * as path from "path";
|
|
@@ -236,4 +236,4 @@ ${entry.content}
|
|
|
236
236
|
export {
|
|
237
237
|
ConversationManager
|
|
238
238
|
};
|
|
239
|
-
//# sourceMappingURL=chunk-
|
|
239
|
+
//# sourceMappingURL=chunk-EXDIJANL.js.map
|
|
@@ -88,8 +88,8 @@ var DEFAULT_CONFIG = {
|
|
|
88
88
|
},
|
|
89
89
|
discover: {
|
|
90
90
|
maxFiles: 100,
|
|
91
|
-
maxChunkSize:
|
|
92
|
-
// ~
|
|
91
|
+
maxChunkSize: 15e3,
|
|
92
|
+
// ~3750 tokens, creates ~10 smaller chunks
|
|
93
93
|
excludePatterns: [
|
|
94
94
|
"*.min.js",
|
|
95
95
|
"*.bundle.js",
|
|
@@ -152,4 +152,4 @@ export {
|
|
|
152
152
|
getVaultPath,
|
|
153
153
|
getStatePath
|
|
154
154
|
};
|
|
155
|
-
//# sourceMappingURL=chunk-
|
|
155
|
+
//# sourceMappingURL=chunk-I4GLPRZ2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/file-utils.ts","../src/utils/config.ts"],"sourcesContent":["import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\n\nexport async function ensureDir(dirPath: string): Promise<void> {\n await fs.mkdir(dirPath, { recursive: true });\n}\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function readJSON<T>(filePath: string): Promise<T | null> {\n try {\n const content = await fs.readFile(filePath, \"utf-8\");\n return JSON.parse(content) as T;\n } catch {\n return null;\n }\n}\n\nexport async function writeJSON(\n filePath: string,\n data: unknown,\n pretty = true\n): Promise<void> {\n await ensureDir(path.dirname(filePath));\n const content = pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data);\n await fs.writeFile(filePath, content);\n}\n\nexport async function appendToFile(\n filePath: string,\n content: string\n): Promise<void> {\n await ensureDir(path.dirname(filePath));\n await fs.appendFile(filePath, content);\n}\n\nexport async function readTextFile(filePath: string): Promise<string | null> {\n try {\n return await fs.readFile(filePath, \"utf-8\");\n } catch {\n return null;\n }\n}\n\nexport async function writeTextFile(\n filePath: string,\n content: string\n): Promise<void> {\n await ensureDir(path.dirname(filePath));\n await fs.writeFile(filePath, content);\n}\n\nexport async function copyFile(src: string, dest: string): Promise<void> {\n await ensureDir(path.dirname(dest));\n await fs.copyFile(src, dest);\n}\n\nexport async function listDir(dirPath: string): Promise<string[]> {\n try {\n return await fs.readdir(dirPath);\n } catch {\n return [];\n }\n}\n\nexport async function getFileSize(filePath: string): Promise<number> {\n try {\n const stats = await fs.stat(filePath);\n return stats.size;\n } catch {\n return 0;\n }\n}\n\nexport function generateSessionId(): string {\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).substring(2, 8);\n return `${timestamp}-${random}`;\n}\n\nexport function getCurrentTimestamp(): string {\n return new Date().toISOString();\n}\n","import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\n\nexport interface CCKBConfig {\n compaction: {\n trigger: \"session_end\" | \"size\" | \"messages\" | \"manual\";\n sizeThresholdKB: number;\n messageThreshold: number;\n cleanupAfterSummary: \"keep\" | \"archive\" | \"delete\";\n };\n capture: {\n tools: string[];\n maxContentLength: number;\n };\n vault: {\n autoIntegrate: boolean;\n maxDepth: number;\n };\n feedback: {\n enabled: boolean;\n contextDepth: number;\n };\n discover: {\n maxFiles: number;\n maxChunkSize: number;\n excludePatterns: string[];\n priorityPatterns: string[];\n supportedLanguages: string[];\n };\n}\n\nexport const DEFAULT_CONFIG: CCKBConfig = {\n compaction: {\n trigger: \"session_end\",\n sizeThresholdKB: 50,\n messageThreshold: 100,\n cleanupAfterSummary: \"keep\",\n },\n capture: {\n tools: [\"Write\", \"Edit\", \"MultiEdit\", \"Bash\", \"Task\"],\n maxContentLength: 500,\n },\n vault: {\n autoIntegrate: true,\n maxDepth: 5,\n },\n feedback: {\n enabled: true,\n contextDepth: 2,\n },\n discover: {\n maxFiles: 100,\n maxChunkSize: 15000, // ~3750 tokens, creates ~10 smaller chunks\n excludePatterns: [\n \"*.min.js\",\n \"*.bundle.js\",\n \"*.map\",\n \"coverage/**\",\n \".next/**\",\n \"build/**\",\n \"dist/**\",\n ],\n priorityPatterns: [\n \"**/index.{ts,js,tsx,jsx}\",\n \"**/main.{ts,js,py,go,rs}\",\n \"**/app.{ts,js,py}\",\n \"**/models/**\",\n \"**/entities/**\",\n \"**/services/**\",\n ],\n supportedLanguages: [\"typescript\", \"javascript\", \"python\", \"go\", \"rust\"],\n },\n};\n\nexport async function loadConfig(projectPath: string): Promise<CCKBConfig> {\n const configPath = path.join(\n projectPath,\n \"cc-knowledge-base\",\n \".cckb-config.json\"\n );\n\n try {\n const content = await fs.readFile(configPath, \"utf-8\");\n const userConfig = JSON.parse(content);\n return { ...DEFAULT_CONFIG, ...userConfig };\n } catch {\n return DEFAULT_CONFIG;\n }\n}\n\nexport async function saveConfig(\n projectPath: string,\n config: CCKBConfig\n): Promise<void> {\n const configPath = path.join(\n projectPath,\n \"cc-knowledge-base\",\n \".cckb-config.json\"\n );\n\n await fs.writeFile(configPath, JSON.stringify(config, null, 2));\n}\n\nexport function getKnowledgeBasePath(projectPath: string): string {\n return path.join(projectPath, \"cc-knowledge-base\");\n}\n\nexport function getConversationsPath(projectPath: string): string {\n return path.join(projectPath, \"cc-knowledge-base\", \"conversations\");\n}\n\nexport function getVaultPath(projectPath: string): string {\n return path.join(projectPath, \"cc-knowledge-base\", \"vault\");\n}\n\nexport function getStatePath(projectPath: string): string {\n return path.join(projectPath, \"cc-knowledge-base\", \".cckb-state\");\n}\n"],"mappings":"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","names":["fs","path"]}
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
VaultIntegrator,
|
|
3
3
|
isClaudeAvailable,
|
|
4
4
|
spawnClaudeAgent
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-AJ2AVV5V.js";
|
|
6
6
|
import {
|
|
7
7
|
DEFAULT_CONFIG,
|
|
8
8
|
ensureDir,
|
|
@@ -12,7 +12,7 @@ import {
|
|
|
12
12
|
readTextFile,
|
|
13
13
|
writeJSON,
|
|
14
14
|
writeTextFile
|
|
15
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-I4GLPRZ2.js";
|
|
16
16
|
|
|
17
17
|
// src/cli/install.ts
|
|
18
18
|
import * as fs from "fs/promises";
|
|
@@ -969,4 +969,4 @@ export {
|
|
|
969
969
|
AutoDiscover,
|
|
970
970
|
discover
|
|
971
971
|
};
|
|
972
|
-
//# sourceMappingURL=chunk-
|
|
972
|
+
//# sourceMappingURL=chunk-JTHQRYKF.js.map
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
listDir,
|
|
5
5
|
readTextFile,
|
|
6
6
|
writeTextFile
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-I4GLPRZ2.js";
|
|
8
8
|
|
|
9
9
|
// src/core/index-manager.ts
|
|
10
10
|
import * as path from "path";
|
|
@@ -146,4 +146,4 @@ _Last updated: ${(/* @__PURE__ */ new Date()).toISOString()}_
|
|
|
146
146
|
export {
|
|
147
147
|
IndexManager
|
|
148
148
|
};
|
|
149
|
-
//# sourceMappingURL=chunk-
|
|
149
|
+
//# sourceMappingURL=chunk-NEHPNFRM.js.map
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
spawnClaudeAgent
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-AJ2AVV5V.js";
|
|
4
4
|
import {
|
|
5
5
|
getConversationsPath,
|
|
6
6
|
loadConfig,
|
|
7
7
|
readTextFile,
|
|
8
8
|
writeTextFile
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-I4GLPRZ2.js";
|
|
10
10
|
|
|
11
11
|
// src/core/compaction-engine.ts
|
|
12
12
|
import * as path from "path";
|
|
@@ -71,9 +71,12 @@ var CompactionEngine = class {
|
|
|
71
71
|
async generateSummary(conversation) {
|
|
72
72
|
const prompt = SUMMARIZATION_PROMPT + conversation;
|
|
73
73
|
try {
|
|
74
|
+
console.error("[CCKB] Calling Claude for summarization...");
|
|
74
75
|
const result = await spawnClaudeAgent(prompt);
|
|
76
|
+
console.error("[CCKB] Claude summarization complete");
|
|
75
77
|
return result;
|
|
76
78
|
} catch (error) {
|
|
79
|
+
console.error("[CCKB] Claude failed, using fallback:", error);
|
|
77
80
|
return this.fallbackExtraction(conversation);
|
|
78
81
|
}
|
|
79
82
|
}
|
|
@@ -273,4 +276,4 @@ ${content}`);
|
|
|
273
276
|
export {
|
|
274
277
|
CompactionEngine
|
|
275
278
|
};
|
|
276
|
-
//# sourceMappingURL=chunk-
|
|
279
|
+
//# sourceMappingURL=chunk-OZQVYSKC.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/core/compaction-engine.ts"],"sourcesContent":["import * as path from \"node:path\";\nimport * as fs from \"node:fs/promises\";\nimport * as zlib from \"node:zlib\";\nimport { promisify } from \"node:util\";\nimport { writeTextFile, readTextFile } from \"../utils/file-utils.js\";\nimport { getConversationsPath, loadConfig } from \"../utils/config.js\";\nimport { spawnClaudeAgent } from \"../utils/claude-sdk.js\";\n\nconst gzip = promisify(zlib.gzip);\n\nconst SUMMARIZATION_PROMPT = `You are a technical knowledge extractor. Analyze this conversation log and extract key information for a project knowledge base.\n\nExtract and format the following:\n\n## Entities\nFor each domain entity (data model, type, class) created or modified:\n- **Name**: Entity name\n- **Location**: File path\n- **Attributes**: Key fields/properties\n- **Relations**: Related entities\n\n## Architecture\nFor each architectural pattern or design decision:\n- **Pattern**: Name of pattern\n- **Description**: Brief explanation\n- **Affected Files**: Relevant file paths\n\n## Services\nFor each service or component created:\n- **Name**: Service name\n- **Location**: File path\n- **Purpose**: Brief description\n- **Methods**: Key methods/functions\n\n## Knowledge\nFor each convention, rule, or important context:\n- **Topic**: What it's about\n- **Details**: The actual information\n\nOnly include sections that have content. Be concise but complete.\nUse file paths exactly as shown in the conversation.\n\nCONVERSATION LOG:\n`;\n\nexport interface Summary {\n sessionId: string;\n content: string;\n entities: ExtractedEntity[];\n architecture: ArchitectureItem[];\n services: ServiceItem[];\n knowledge: KnowledgeItem[];\n}\n\nexport interface ExtractedEntity {\n name: string;\n location?: string;\n attributes: string[];\n relations: string[];\n}\n\nexport interface ArchitectureItem {\n pattern: string;\n description: string;\n affectedFiles: string[];\n}\n\nexport interface ServiceItem {\n name: string;\n location?: string;\n purpose: string;\n methods: string[];\n}\n\nexport interface KnowledgeItem {\n topic: string;\n details: string;\n}\n\nexport class CompactionEngine {\n private projectPath: string;\n\n constructor(projectPath: string) {\n this.projectPath = projectPath;\n }\n\n async compact(sessionId: string, conversation: string): Promise<Summary | null> {\n try {\n // Use Claude SDK to generate summary\n const summaryContent = await this.generateSummary(conversation);\n\n if (!summaryContent) {\n return null;\n }\n\n // Parse the summary to extract structured data\n const summary = this.parseSummary(sessionId, summaryContent);\n\n // Write summary to conversation folder\n await this.writeSummary(sessionId, summaryContent);\n\n // Cleanup original conversation files based on config\n await this.cleanupConversationFiles(sessionId);\n\n return summary;\n } catch (error) {\n console.error(\"Compaction failed:\", error);\n return null;\n }\n }\n\n private async generateSummary(conversation: string): Promise<string | null> {\n const prompt = SUMMARIZATION_PROMPT + conversation;\n\n try {\n console.error(\"[CCKB] Calling Claude for summarization...\");\n const result = await spawnClaudeAgent(prompt);\n console.error(\"[CCKB] Claude summarization complete\");\n return result;\n } catch (error) {\n console.error(\"[CCKB] Claude failed, using fallback:\", error);\n return this.fallbackExtraction(conversation);\n }\n }\n\n private fallbackExtraction(conversation: string): string {\n // Basic extraction without AI - just capture file paths and actions\n const lines = conversation.split(\"\\n\");\n const files: string[] = [];\n const actions: string[] = [];\n\n for (const line of lines) {\n // Extract file paths\n const fileMatch = line.match(/(?:Created|Modified|Edited).*?:\\s*(.+\\.(?:ts|js|tsx|jsx|md))/i);\n if (fileMatch) {\n files.push(fileMatch[1]);\n }\n\n // Extract tool actions\n if (line.includes(\"[TOOL:\")) {\n actions.push(line);\n }\n }\n\n let summary = \"# Session Summary\\n\\n\";\n\n if (files.length > 0) {\n summary += \"## Files Modified\\n\";\n for (const file of [...new Set(files)]) {\n summary += `- ${file}\\n`;\n }\n summary += \"\\n\";\n }\n\n if (actions.length > 0) {\n summary += \"## Actions\\n\";\n for (const action of actions.slice(0, 20)) {\n summary += `- ${action}\\n`;\n }\n }\n\n return summary;\n }\n\n private parseSummary(sessionId: string, content: string): Summary {\n const summary: Summary = {\n sessionId,\n content,\n entities: [],\n architecture: [],\n services: [],\n knowledge: [],\n };\n\n // Parse entities section\n const entitiesMatch = content.match(/## Entities\\n([\\s\\S]*?)(?=\\n## |$)/);\n if (entitiesMatch) {\n summary.entities = this.parseEntities(entitiesMatch[1]);\n }\n\n // Parse architecture section\n const archMatch = content.match(/## Architecture\\n([\\s\\S]*?)(?=\\n## |$)/);\n if (archMatch) {\n summary.architecture = this.parseArchitecture(archMatch[1]);\n }\n\n // Parse services section\n const servicesMatch = content.match(/## Services\\n([\\s\\S]*?)(?=\\n## |$)/);\n if (servicesMatch) {\n summary.services = this.parseServices(servicesMatch[1]);\n }\n\n // Parse knowledge section\n const knowledgeMatch = content.match(/## Knowledge\\n([\\s\\S]*?)(?=\\n## |$)/);\n if (knowledgeMatch) {\n summary.knowledge = this.parseKnowledge(knowledgeMatch[1]);\n }\n\n return summary;\n }\n\n private parseEntities(section: string): ExtractedEntity[] {\n const entities: ExtractedEntity[] = [];\n const blocks = section.split(/\\n(?=- \\*\\*Name\\*\\*:)/);\n\n for (const block of blocks) {\n if (!block.trim()) continue;\n\n const nameMatch = block.match(/\\*\\*Name\\*\\*:\\s*(.+)/);\n const locationMatch = block.match(/\\*\\*Location\\*\\*:\\s*(.+)/);\n const attributesMatch = block.match(/\\*\\*Attributes\\*\\*:\\s*(.+)/);\n const relationsMatch = block.match(/\\*\\*Relations\\*\\*:\\s*(.+)/);\n\n if (nameMatch) {\n entities.push({\n name: nameMatch[1].trim(),\n location: locationMatch?.[1].trim(),\n attributes: attributesMatch?.[1].split(\",\").map((a) => a.trim()) || [],\n relations: relationsMatch?.[1].split(\",\").map((r) => r.trim()) || [],\n });\n }\n }\n\n return entities;\n }\n\n private parseArchitecture(section: string): ArchitectureItem[] {\n const items: ArchitectureItem[] = [];\n const blocks = section.split(/\\n(?=- \\*\\*Pattern\\*\\*:)/);\n\n for (const block of blocks) {\n if (!block.trim()) continue;\n\n const patternMatch = block.match(/\\*\\*Pattern\\*\\*:\\s*(.+)/);\n const descMatch = block.match(/\\*\\*Description\\*\\*:\\s*(.+)/);\n const filesMatch = block.match(/\\*\\*Affected Files\\*\\*:\\s*(.+)/);\n\n if (patternMatch) {\n items.push({\n pattern: patternMatch[1].trim(),\n description: descMatch?.[1].trim() || \"\",\n affectedFiles: filesMatch?.[1].split(\",\").map((f) => f.trim()) || [],\n });\n }\n }\n\n return items;\n }\n\n private parseServices(section: string): ServiceItem[] {\n const items: ServiceItem[] = [];\n const blocks = section.split(/\\n(?=- \\*\\*Name\\*\\*:)/);\n\n for (const block of blocks) {\n if (!block.trim()) continue;\n\n const nameMatch = block.match(/\\*\\*Name\\*\\*:\\s*(.+)/);\n const locationMatch = block.match(/\\*\\*Location\\*\\*:\\s*(.+)/);\n const purposeMatch = block.match(/\\*\\*Purpose\\*\\*:\\s*(.+)/);\n const methodsMatch = block.match(/\\*\\*Methods\\*\\*:\\s*(.+)/);\n\n if (nameMatch) {\n items.push({\n name: nameMatch[1].trim(),\n location: locationMatch?.[1].trim(),\n purpose: purposeMatch?.[1].trim() || \"\",\n methods: methodsMatch?.[1].split(\",\").map((m) => m.trim()) || [],\n });\n }\n }\n\n return items;\n }\n\n private parseKnowledge(section: string): KnowledgeItem[] {\n const items: KnowledgeItem[] = [];\n const blocks = section.split(/\\n(?=- \\*\\*Topic\\*\\*:)/);\n\n for (const block of blocks) {\n if (!block.trim()) continue;\n\n const topicMatch = block.match(/\\*\\*Topic\\*\\*:\\s*(.+)/);\n const detailsMatch = block.match(/\\*\\*Details\\*\\*:\\s*(.+)/);\n\n if (topicMatch) {\n items.push({\n topic: topicMatch[1].trim(),\n details: detailsMatch?.[1].trim() || \"\",\n });\n }\n }\n\n return items;\n }\n\n private async writeSummary(sessionId: string, content: string): Promise<void> {\n const conversationsPath = getConversationsPath(this.projectPath);\n const summaryPath = path.join(conversationsPath, sessionId, \"summary.md\");\n\n const fullContent = `# Session Summary: ${sessionId}\nGenerated: ${new Date().toISOString()}\n\n${content}\n`;\n\n await writeTextFile(summaryPath, fullContent);\n }\n\n private async cleanupConversationFiles(sessionId: string): Promise<void> {\n const config = await loadConfig(this.projectPath);\n const cleanupMode = config.compaction.cleanupAfterSummary;\n\n if (cleanupMode === \"keep\") {\n return; // Nothing to do\n }\n\n const conversationsPath = getConversationsPath(this.projectPath);\n const sessionPath = path.join(conversationsPath, sessionId);\n\n // Get all conversation files (numbered .txt files)\n const files = await fs.readdir(sessionPath);\n const conversationFiles = files.filter(\n (f) => /^\\d+\\.txt$/.test(f)\n );\n\n if (conversationFiles.length === 0) {\n return;\n }\n\n if (cleanupMode === \"archive\") {\n await this.archiveConversationFiles(sessionPath, conversationFiles);\n } else if (cleanupMode === \"delete\") {\n await this.deleteConversationFiles(sessionPath, conversationFiles);\n }\n }\n\n private async archiveConversationFiles(\n sessionPath: string,\n files: string[]\n ): Promise<void> {\n try {\n // Combine all conversation files into one archive\n const contents: string[] = [];\n\n for (const file of files.sort()) {\n const filePath = path.join(sessionPath, file);\n const content = await readTextFile(filePath);\n if (content) {\n contents.push(`=== ${file} ===\\n${content}`);\n }\n }\n\n const combined = contents.join(\"\\n\\n\");\n const compressed = await gzip(Buffer.from(combined, \"utf-8\"));\n\n // Write archive\n const archivePath = path.join(sessionPath, \"raw.txt.gz\");\n await fs.writeFile(archivePath, compressed);\n\n // Delete original files\n await this.deleteConversationFiles(sessionPath, files);\n } catch (error) {\n console.error(\"Failed to archive conversation files:\", error);\n // Don't delete originals if archive fails\n }\n }\n\n private async deleteConversationFiles(\n sessionPath: string,\n files: string[]\n ): Promise<void> {\n for (const file of files) {\n try {\n await fs.unlink(path.join(sessionPath, file));\n } catch {\n // Ignore deletion errors\n }\n }\n }\n}\n"],"mappings":"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","names":["gzip"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
IndexManager
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-NEHPNFRM.js";
|
|
4
4
|
import {
|
|
5
5
|
fileExists,
|
|
6
6
|
getStatePath,
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
loadConfig,
|
|
9
9
|
readJSON,
|
|
10
10
|
writeJSON
|
|
11
|
-
} from "../chunk-
|
|
11
|
+
} from "../chunk-I4GLPRZ2.js";
|
|
12
12
|
|
|
13
13
|
// src/hooks/notification.ts
|
|
14
14
|
import * as path from "path";
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ConversationManager
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-EXDIJANL.js";
|
|
4
4
|
import {
|
|
5
5
|
IndexManager
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-NEHPNFRM.js";
|
|
7
7
|
import {
|
|
8
8
|
getVaultPath
|
|
9
|
-
} from "../chunk-
|
|
9
|
+
} from "../chunk-I4GLPRZ2.js";
|
|
10
10
|
|
|
11
11
|
// src/hooks/session-start.ts
|
|
12
12
|
async function handleSessionStart() {
|
package/dist/hooks/stop.js
CHANGED
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CompactionEngine
|
|
3
|
-
} from "../chunk-
|
|
3
|
+
} from "../chunk-OZQVYSKC.js";
|
|
4
4
|
import {
|
|
5
5
|
VaultIntegrator
|
|
6
|
-
} from "../chunk-
|
|
6
|
+
} from "../chunk-AJ2AVV5V.js";
|
|
7
7
|
import {
|
|
8
8
|
ConversationManager
|
|
9
|
-
} from "../chunk-
|
|
10
|
-
import "../chunk-
|
|
9
|
+
} from "../chunk-EXDIJANL.js";
|
|
10
|
+
import "../chunk-NEHPNFRM.js";
|
|
11
11
|
import {
|
|
12
12
|
getVaultPath,
|
|
13
13
|
loadConfig
|
|
14
|
-
} from "../chunk-
|
|
14
|
+
} from "../chunk-I4GLPRZ2.js";
|
|
15
15
|
|
|
16
16
|
// src/hooks/stop.ts
|
|
17
17
|
async function handleStop() {
|
|
@@ -19,42 +19,61 @@ async function handleStop() {
|
|
|
19
19
|
const input = await readStdin();
|
|
20
20
|
const data = input ? JSON.parse(input) : {};
|
|
21
21
|
const projectPath = data.cwd || process.cwd();
|
|
22
|
+
console.error(`[CCKB] Stop hook triggered for: ${projectPath}`);
|
|
22
23
|
const manager = new ConversationManager(projectPath);
|
|
23
24
|
const sessionId = await manager.getActiveSessionId();
|
|
24
25
|
if (!sessionId) {
|
|
26
|
+
console.error("[CCKB] No active session found, skipping compaction");
|
|
25
27
|
console.log(JSON.stringify({ continue: true, suppressOutput: true }));
|
|
26
28
|
return;
|
|
27
29
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
+
console.error(`[CCKB] Starting compaction for session: ${sessionId}`);
|
|
31
|
+
try {
|
|
32
|
+
await runCompactionAsync(projectPath, sessionId);
|
|
33
|
+
console.error("[CCKB] Compaction complete");
|
|
34
|
+
} catch (error) {
|
|
35
|
+
console.error("[CCKB] Compaction failed:", error);
|
|
36
|
+
}
|
|
30
37
|
const output = {
|
|
31
38
|
continue: true,
|
|
32
39
|
suppressOutput: true
|
|
33
40
|
};
|
|
34
41
|
console.log(JSON.stringify(output));
|
|
35
42
|
} catch (error) {
|
|
43
|
+
console.error("[CCKB] Stop hook error:", error);
|
|
36
44
|
console.log(JSON.stringify({ continue: true, suppressOutput: true }));
|
|
37
45
|
}
|
|
38
46
|
}
|
|
39
47
|
async function runCompactionAsync(projectPath, sessionId) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
48
|
+
try {
|
|
49
|
+
const config = await loadConfig(projectPath);
|
|
50
|
+
if (config.compaction.trigger !== "session_end") {
|
|
51
|
+
console.error(`[CCKB] Skipping - trigger is "${config.compaction.trigger}"`);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
54
|
+
const manager = new ConversationManager(projectPath);
|
|
55
|
+
const conversation = await manager.getFullConversation(sessionId);
|
|
56
|
+
if (!conversation || conversation.length < 100) {
|
|
57
|
+
console.error(`[CCKB] Skipping - conversation too short (${conversation?.length || 0} chars)`);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
console.error(`[CCKB] Compacting ${conversation.length} chars...`);
|
|
61
|
+
const compactionEngine = new CompactionEngine(projectPath);
|
|
62
|
+
const summary = await compactionEngine.compact(sessionId, conversation);
|
|
63
|
+
if (!summary) {
|
|
64
|
+
console.error("[CCKB] Compaction returned null");
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
console.error(`[CCKB] Summary created: ${summary.entities.length} entities`);
|
|
68
|
+
if (config.vault.autoIntegrate) {
|
|
69
|
+
const vaultPath = getVaultPath(projectPath);
|
|
70
|
+
const integrator = new VaultIntegrator(vaultPath);
|
|
71
|
+
await integrator.integrate(summary);
|
|
72
|
+
console.error("[CCKB] Vault updated");
|
|
73
|
+
}
|
|
74
|
+
} catch (error) {
|
|
75
|
+
console.error("[CCKB] runCompactionAsync error:", error);
|
|
76
|
+
throw error;
|
|
58
77
|
}
|
|
59
78
|
}
|
|
60
79
|
async function readStdin() {
|
package/dist/hooks/stop.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hooks/stop.ts"],"sourcesContent":["import { ConversationManager } from \"../core/conversation-manager.js\";\nimport { CompactionEngine } from \"../core/compaction-engine.js\";\nimport { VaultIntegrator } from \"../core/vault-integrator.js\";\nimport { loadConfig, getVaultPath } from \"../utils/config.js\";\n\ninterface StopInput {\n cwd?: string;\n}\n\ninterface HookOutput {\n continue: boolean;\n suppressOutput?: boolean;\n}\n\nexport async function handleStop(): Promise<void> {\n try {\n // Read input from stdin\n const input = await readStdin();\n const data: StopInput = input ? JSON.parse(input) : {};\n\n const projectPath = data.cwd || process.cwd();\n\n // Get active session\n const manager = new ConversationManager(projectPath);\n const sessionId = await manager.getActiveSessionId();\n\n if (!sessionId) {\n console.log(JSON.stringify({ continue: true, suppressOutput: true }));\n return;\n }\n\n // Run compaction
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/stop.ts"],"sourcesContent":["import { ConversationManager } from \"../core/conversation-manager.js\";\nimport { CompactionEngine } from \"../core/compaction-engine.js\";\nimport { VaultIntegrator } from \"../core/vault-integrator.js\";\nimport { loadConfig, getVaultPath } from \"../utils/config.js\";\n\ninterface StopInput {\n cwd?: string;\n}\n\ninterface HookOutput {\n continue: boolean;\n suppressOutput?: boolean;\n}\n\nexport async function handleStop(): Promise<void> {\n try {\n // Read input from stdin\n const input = await readStdin();\n const data: StopInput = input ? JSON.parse(input) : {};\n\n const projectPath = data.cwd || process.cwd();\n\n // Log to stderr for debugging (stdout is for hook protocol)\n console.error(`[CCKB] Stop hook triggered for: ${projectPath}`);\n\n // Get active session\n const manager = new ConversationManager(projectPath);\n const sessionId = await manager.getActiveSessionId();\n\n if (!sessionId) {\n console.error(\"[CCKB] No active session found, skipping compaction\");\n console.log(JSON.stringify({ continue: true, suppressOutput: true }));\n return;\n }\n\n console.error(`[CCKB] Starting compaction for session: ${sessionId}`);\n\n // Run compaction and wait for it to complete before exiting\n try {\n await runCompactionAsync(projectPath, sessionId);\n console.error(\"[CCKB] Compaction complete\");\n } catch (error) {\n console.error(\"[CCKB] Compaction failed:\", error);\n }\n\n const output: HookOutput = {\n continue: true,\n suppressOutput: true,\n };\n\n console.log(JSON.stringify(output));\n } catch (error) {\n console.error(\"[CCKB] Stop hook error:\", error);\n console.log(JSON.stringify({ continue: true, suppressOutput: true }));\n }\n}\n\nasync function runCompactionAsync(\n projectPath: string,\n sessionId: string\n): Promise<void> {\n try {\n const config = await loadConfig(projectPath);\n\n if (config.compaction.trigger !== \"session_end\") {\n console.error(`[CCKB] Skipping - trigger is \"${config.compaction.trigger}\"`);\n return;\n }\n\n const manager = new ConversationManager(projectPath);\n const conversation = await manager.getFullConversation(sessionId);\n\n if (!conversation || conversation.length < 100) {\n console.error(`[CCKB] Skipping - conversation too short (${conversation?.length || 0} chars)`);\n return;\n }\n\n console.error(`[CCKB] Compacting ${conversation.length} chars...`);\n\n const compactionEngine = new CompactionEngine(projectPath);\n const summary = await compactionEngine.compact(sessionId, conversation);\n\n if (!summary) {\n console.error(\"[CCKB] Compaction returned null\");\n return;\n }\n\n console.error(`[CCKB] Summary created: ${summary.entities.length} entities`);\n\n if (config.vault.autoIntegrate) {\n const vaultPath = getVaultPath(projectPath);\n const integrator = new VaultIntegrator(vaultPath);\n await integrator.integrate(summary);\n console.error(\"[CCKB] Vault updated\");\n }\n } catch (error) {\n console.error(\"[CCKB] runCompactionAsync error:\", error);\n throw error;\n }\n}\n\nasync function readStdin(): Promise<string> {\n return new Promise((resolve) => {\n let data = \"\";\n\n if (process.stdin.isTTY) {\n resolve(\"\");\n return;\n }\n\n process.stdin.setEncoding(\"utf8\");\n process.stdin.on(\"data\", (chunk) => {\n data += chunk;\n });\n process.stdin.on(\"end\", () => {\n resolve(data.trim());\n });\n\n setTimeout(() => {\n resolve(data.trim());\n }, 1000);\n });\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAcA,eAAsB,aAA4B;AAChD,MAAI;AAEF,UAAM,QAAQ,MAAM,UAAU;AAC9B,UAAM,OAAkB,QAAQ,KAAK,MAAM,KAAK,IAAI,CAAC;AAErD,UAAM,cAAc,KAAK,OAAO,QAAQ,IAAI;AAG5C,YAAQ,MAAM,mCAAmC,WAAW,EAAE;AAG9D,UAAM,UAAU,IAAI,oBAAoB,WAAW;AACnD,UAAM,YAAY,MAAM,QAAQ,mBAAmB;AAEnD,QAAI,CAAC,WAAW;AACd,cAAQ,MAAM,qDAAqD;AACnE,cAAQ,IAAI,KAAK,UAAU,EAAE,UAAU,MAAM,gBAAgB,KAAK,CAAC,CAAC;AACpE;AAAA,IACF;AAEA,YAAQ,MAAM,2CAA2C,SAAS,EAAE;AAGpE,QAAI;AACF,YAAM,mBAAmB,aAAa,SAAS;AAC/C,cAAQ,MAAM,4BAA4B;AAAA,IAC5C,SAAS,OAAO;AACd,cAAQ,MAAM,6BAA6B,KAAK;AAAA,IAClD;AAEA,UAAM,SAAqB;AAAA,MACzB,UAAU;AAAA,MACV,gBAAgB;AAAA,IAClB;AAEA,YAAQ,IAAI,KAAK,UAAU,MAAM,CAAC;AAAA,EACpC,SAAS,OAAO;AACd,YAAQ,MAAM,2BAA2B,KAAK;AAC9C,YAAQ,IAAI,KAAK,UAAU,EAAE,UAAU,MAAM,gBAAgB,KAAK,CAAC,CAAC;AAAA,EACtE;AACF;AAEA,eAAe,mBACb,aACA,WACe;AACf,MAAI;AACF,UAAM,SAAS,MAAM,WAAW,WAAW;AAE3C,QAAI,OAAO,WAAW,YAAY,eAAe;AAC/C,cAAQ,MAAM,iCAAiC,OAAO,WAAW,OAAO,GAAG;AAC3E;AAAA,IACF;AAEA,UAAM,UAAU,IAAI,oBAAoB,WAAW;AACnD,UAAM,eAAe,MAAM,QAAQ,oBAAoB,SAAS;AAEhE,QAAI,CAAC,gBAAgB,aAAa,SAAS,KAAK;AAC9C,cAAQ,MAAM,6CAA6C,cAAc,UAAU,CAAC,SAAS;AAC7F;AAAA,IACF;AAEA,YAAQ,MAAM,qBAAqB,aAAa,MAAM,WAAW;AAEjE,UAAM,mBAAmB,IAAI,iBAAiB,WAAW;AACzD,UAAM,UAAU,MAAM,iBAAiB,QAAQ,WAAW,YAAY;AAEtE,QAAI,CAAC,SAAS;AACZ,cAAQ,MAAM,iCAAiC;AAC/C;AAAA,IACF;AAEA,YAAQ,MAAM,2BAA2B,QAAQ,SAAS,MAAM,WAAW;AAE3E,QAAI,OAAO,MAAM,eAAe;AAC9B,YAAM,YAAY,aAAa,WAAW;AAC1C,YAAM,aAAa,IAAI,gBAAgB,SAAS;AAChD,YAAM,WAAW,UAAU,OAAO;AAClC,cAAQ,MAAM,sBAAsB;AAAA,IACtC;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,oCAAoC,KAAK;AACvD,UAAM;AAAA,EACR;AACF;AAEA,eAAe,YAA6B;AAC1C,SAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,QAAI,OAAO;AAEX,QAAI,QAAQ,MAAM,OAAO;AACvB,cAAQ,EAAE;AACV;AAAA,IACF;AAEA,YAAQ,MAAM,YAAY,MAAM;AAChC,YAAQ,MAAM,GAAG,QAAQ,CAAC,UAAU;AAClC,cAAQ;AAAA,IACV,CAAC;AACD,YAAQ,MAAM,GAAG,OAAO,MAAM;AAC5B,cAAQ,KAAK,KAAK,CAAC;AAAA,IACrB,CAAC;AAED,eAAW,MAAM;AACf,cAAQ,KAAK,KAAK,CAAC;AAAA,IACrB,GAAG,GAAI;AAAA,EACT,CAAC;AACH;","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -4,21 +4,21 @@ import {
|
|
|
4
4
|
FileCollector,
|
|
5
5
|
discover,
|
|
6
6
|
install
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-JTHQRYKF.js";
|
|
8
8
|
import {
|
|
9
9
|
CompactionEngine
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-OZQVYSKC.js";
|
|
11
11
|
import {
|
|
12
12
|
EntityDetector,
|
|
13
13
|
VaultIntegrator
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-AJ2AVV5V.js";
|
|
15
15
|
import {
|
|
16
16
|
ConversationManager
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-EXDIJANL.js";
|
|
18
18
|
import {
|
|
19
19
|
IndexManager
|
|
20
|
-
} from "./chunk-
|
|
21
|
-
import "./chunk-
|
|
20
|
+
} from "./chunk-NEHPNFRM.js";
|
|
21
|
+
import "./chunk-I4GLPRZ2.js";
|
|
22
22
|
export {
|
|
23
23
|
AutoDiscover,
|
|
24
24
|
ChunkManager,
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/core/compaction-engine.ts"],"sourcesContent":["import * as path from \"node:path\";\nimport * as fs from \"node:fs/promises\";\nimport * as zlib from \"node:zlib\";\nimport { promisify } from \"node:util\";\nimport { writeTextFile, readTextFile } from \"../utils/file-utils.js\";\nimport { getConversationsPath, loadConfig } from \"../utils/config.js\";\nimport { spawnClaudeAgent } from \"../utils/claude-sdk.js\";\n\nconst gzip = promisify(zlib.gzip);\n\nconst SUMMARIZATION_PROMPT = `You are a technical knowledge extractor. Analyze this conversation log and extract key information for a project knowledge base.\n\nExtract and format the following:\n\n## Entities\nFor each domain entity (data model, type, class) created or modified:\n- **Name**: Entity name\n- **Location**: File path\n- **Attributes**: Key fields/properties\n- **Relations**: Related entities\n\n## Architecture\nFor each architectural pattern or design decision:\n- **Pattern**: Name of pattern\n- **Description**: Brief explanation\n- **Affected Files**: Relevant file paths\n\n## Services\nFor each service or component created:\n- **Name**: Service name\n- **Location**: File path\n- **Purpose**: Brief description\n- **Methods**: Key methods/functions\n\n## Knowledge\nFor each convention, rule, or important context:\n- **Topic**: What it's about\n- **Details**: The actual information\n\nOnly include sections that have content. Be concise but complete.\nUse file paths exactly as shown in the conversation.\n\nCONVERSATION LOG:\n`;\n\nexport interface Summary {\n sessionId: string;\n content: string;\n entities: ExtractedEntity[];\n architecture: ArchitectureItem[];\n services: ServiceItem[];\n knowledge: KnowledgeItem[];\n}\n\nexport interface ExtractedEntity {\n name: string;\n location?: string;\n attributes: string[];\n relations: string[];\n}\n\nexport interface ArchitectureItem {\n pattern: string;\n description: string;\n affectedFiles: string[];\n}\n\nexport interface ServiceItem {\n name: string;\n location?: string;\n purpose: string;\n methods: string[];\n}\n\nexport interface KnowledgeItem {\n topic: string;\n details: string;\n}\n\nexport class CompactionEngine {\n private projectPath: string;\n\n constructor(projectPath: string) {\n this.projectPath = projectPath;\n }\n\n async compact(sessionId: string, conversation: string): Promise<Summary | null> {\n try {\n // Use Claude SDK to generate summary\n const summaryContent = await this.generateSummary(conversation);\n\n if (!summaryContent) {\n return null;\n }\n\n // Parse the summary to extract structured data\n const summary = this.parseSummary(sessionId, summaryContent);\n\n // Write summary to conversation folder\n await this.writeSummary(sessionId, summaryContent);\n\n // Cleanup original conversation files based on config\n await this.cleanupConversationFiles(sessionId);\n\n return summary;\n } catch (error) {\n console.error(\"Compaction failed:\", error);\n return null;\n }\n }\n\n private async generateSummary(conversation: string): Promise<string | null> {\n const prompt = SUMMARIZATION_PROMPT + conversation;\n\n try {\n const result = await spawnClaudeAgent(prompt);\n return result;\n } catch (error) {\n // Fallback to basic extraction if Claude SDK fails\n return this.fallbackExtraction(conversation);\n }\n }\n\n private fallbackExtraction(conversation: string): string {\n // Basic extraction without AI - just capture file paths and actions\n const lines = conversation.split(\"\\n\");\n const files: string[] = [];\n const actions: string[] = [];\n\n for (const line of lines) {\n // Extract file paths\n const fileMatch = line.match(/(?:Created|Modified|Edited).*?:\\s*(.+\\.(?:ts|js|tsx|jsx|md))/i);\n if (fileMatch) {\n files.push(fileMatch[1]);\n }\n\n // Extract tool actions\n if (line.includes(\"[TOOL:\")) {\n actions.push(line);\n }\n }\n\n let summary = \"# Session Summary\\n\\n\";\n\n if (files.length > 0) {\n summary += \"## Files Modified\\n\";\n for (const file of [...new Set(files)]) {\n summary += `- ${file}\\n`;\n }\n summary += \"\\n\";\n }\n\n if (actions.length > 0) {\n summary += \"## Actions\\n\";\n for (const action of actions.slice(0, 20)) {\n summary += `- ${action}\\n`;\n }\n }\n\n return summary;\n }\n\n private parseSummary(sessionId: string, content: string): Summary {\n const summary: Summary = {\n sessionId,\n content,\n entities: [],\n architecture: [],\n services: [],\n knowledge: [],\n };\n\n // Parse entities section\n const entitiesMatch = content.match(/## Entities\\n([\\s\\S]*?)(?=\\n## |$)/);\n if (entitiesMatch) {\n summary.entities = this.parseEntities(entitiesMatch[1]);\n }\n\n // Parse architecture section\n const archMatch = content.match(/## Architecture\\n([\\s\\S]*?)(?=\\n## |$)/);\n if (archMatch) {\n summary.architecture = this.parseArchitecture(archMatch[1]);\n }\n\n // Parse services section\n const servicesMatch = content.match(/## Services\\n([\\s\\S]*?)(?=\\n## |$)/);\n if (servicesMatch) {\n summary.services = this.parseServices(servicesMatch[1]);\n }\n\n // Parse knowledge section\n const knowledgeMatch = content.match(/## Knowledge\\n([\\s\\S]*?)(?=\\n## |$)/);\n if (knowledgeMatch) {\n summary.knowledge = this.parseKnowledge(knowledgeMatch[1]);\n }\n\n return summary;\n }\n\n private parseEntities(section: string): ExtractedEntity[] {\n const entities: ExtractedEntity[] = [];\n const blocks = section.split(/\\n(?=- \\*\\*Name\\*\\*:)/);\n\n for (const block of blocks) {\n if (!block.trim()) continue;\n\n const nameMatch = block.match(/\\*\\*Name\\*\\*:\\s*(.+)/);\n const locationMatch = block.match(/\\*\\*Location\\*\\*:\\s*(.+)/);\n const attributesMatch = block.match(/\\*\\*Attributes\\*\\*:\\s*(.+)/);\n const relationsMatch = block.match(/\\*\\*Relations\\*\\*:\\s*(.+)/);\n\n if (nameMatch) {\n entities.push({\n name: nameMatch[1].trim(),\n location: locationMatch?.[1].trim(),\n attributes: attributesMatch?.[1].split(\",\").map((a) => a.trim()) || [],\n relations: relationsMatch?.[1].split(\",\").map((r) => r.trim()) || [],\n });\n }\n }\n\n return entities;\n }\n\n private parseArchitecture(section: string): ArchitectureItem[] {\n const items: ArchitectureItem[] = [];\n const blocks = section.split(/\\n(?=- \\*\\*Pattern\\*\\*:)/);\n\n for (const block of blocks) {\n if (!block.trim()) continue;\n\n const patternMatch = block.match(/\\*\\*Pattern\\*\\*:\\s*(.+)/);\n const descMatch = block.match(/\\*\\*Description\\*\\*:\\s*(.+)/);\n const filesMatch = block.match(/\\*\\*Affected Files\\*\\*:\\s*(.+)/);\n\n if (patternMatch) {\n items.push({\n pattern: patternMatch[1].trim(),\n description: descMatch?.[1].trim() || \"\",\n affectedFiles: filesMatch?.[1].split(\",\").map((f) => f.trim()) || [],\n });\n }\n }\n\n return items;\n }\n\n private parseServices(section: string): ServiceItem[] {\n const items: ServiceItem[] = [];\n const blocks = section.split(/\\n(?=- \\*\\*Name\\*\\*:)/);\n\n for (const block of blocks) {\n if (!block.trim()) continue;\n\n const nameMatch = block.match(/\\*\\*Name\\*\\*:\\s*(.+)/);\n const locationMatch = block.match(/\\*\\*Location\\*\\*:\\s*(.+)/);\n const purposeMatch = block.match(/\\*\\*Purpose\\*\\*:\\s*(.+)/);\n const methodsMatch = block.match(/\\*\\*Methods\\*\\*:\\s*(.+)/);\n\n if (nameMatch) {\n items.push({\n name: nameMatch[1].trim(),\n location: locationMatch?.[1].trim(),\n purpose: purposeMatch?.[1].trim() || \"\",\n methods: methodsMatch?.[1].split(\",\").map((m) => m.trim()) || [],\n });\n }\n }\n\n return items;\n }\n\n private parseKnowledge(section: string): KnowledgeItem[] {\n const items: KnowledgeItem[] = [];\n const blocks = section.split(/\\n(?=- \\*\\*Topic\\*\\*:)/);\n\n for (const block of blocks) {\n if (!block.trim()) continue;\n\n const topicMatch = block.match(/\\*\\*Topic\\*\\*:\\s*(.+)/);\n const detailsMatch = block.match(/\\*\\*Details\\*\\*:\\s*(.+)/);\n\n if (topicMatch) {\n items.push({\n topic: topicMatch[1].trim(),\n details: detailsMatch?.[1].trim() || \"\",\n });\n }\n }\n\n return items;\n }\n\n private async writeSummary(sessionId: string, content: string): Promise<void> {\n const conversationsPath = getConversationsPath(this.projectPath);\n const summaryPath = path.join(conversationsPath, sessionId, \"summary.md\");\n\n const fullContent = `# Session Summary: ${sessionId}\nGenerated: ${new Date().toISOString()}\n\n${content}\n`;\n\n await writeTextFile(summaryPath, fullContent);\n }\n\n private async cleanupConversationFiles(sessionId: string): Promise<void> {\n const config = await loadConfig(this.projectPath);\n const cleanupMode = config.compaction.cleanupAfterSummary;\n\n if (cleanupMode === \"keep\") {\n return; // Nothing to do\n }\n\n const conversationsPath = getConversationsPath(this.projectPath);\n const sessionPath = path.join(conversationsPath, sessionId);\n\n // Get all conversation files (numbered .txt files)\n const files = await fs.readdir(sessionPath);\n const conversationFiles = files.filter(\n (f) => /^\\d+\\.txt$/.test(f)\n );\n\n if (conversationFiles.length === 0) {\n return;\n }\n\n if (cleanupMode === \"archive\") {\n await this.archiveConversationFiles(sessionPath, conversationFiles);\n } else if (cleanupMode === \"delete\") {\n await this.deleteConversationFiles(sessionPath, conversationFiles);\n }\n }\n\n private async archiveConversationFiles(\n sessionPath: string,\n files: string[]\n ): Promise<void> {\n try {\n // Combine all conversation files into one archive\n const contents: string[] = [];\n\n for (const file of files.sort()) {\n const filePath = path.join(sessionPath, file);\n const content = await readTextFile(filePath);\n if (content) {\n contents.push(`=== ${file} ===\\n${content}`);\n }\n }\n\n const combined = contents.join(\"\\n\\n\");\n const compressed = await gzip(Buffer.from(combined, \"utf-8\"));\n\n // Write archive\n const archivePath = path.join(sessionPath, \"raw.txt.gz\");\n await fs.writeFile(archivePath, compressed);\n\n // Delete original files\n await this.deleteConversationFiles(sessionPath, files);\n } catch (error) {\n console.error(\"Failed to archive conversation files:\", error);\n // Don't delete originals if archive fails\n }\n }\n\n private async deleteConversationFiles(\n sessionPath: string,\n files: string[]\n ): Promise<void> {\n for (const file of files) {\n try {\n await fs.unlink(path.join(sessionPath, file));\n } catch {\n // Ignore deletion errors\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;;AAAA,YAAY,UAAU;AACtB,YAAY,QAAQ;AACpB,YAAY,UAAU;AACtB,SAAS,iBAAiB;AAK1B,IAAMA,QAAO,UAAe,SAAI;AAEhC,IAAM,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqEtB,IAAM,mBAAN,MAAuB;AAAA,EACpB;AAAA,EAER,YAAY,aAAqB;AAC/B,SAAK,cAAc;AAAA,EACrB;AAAA,EAEA,MAAM,QAAQ,WAAmB,cAA+C;AAC9E,QAAI;AAEF,YAAM,iBAAiB,MAAM,KAAK,gBAAgB,YAAY;AAE9D,UAAI,CAAC,gBAAgB;AACnB,eAAO;AAAA,MACT;AAGA,YAAM,UAAU,KAAK,aAAa,WAAW,cAAc;AAG3D,YAAM,KAAK,aAAa,WAAW,cAAc;AAGjD,YAAM,KAAK,yBAAyB,SAAS;AAE7C,aAAO;AAAA,IACT,SAAS,OAAO;AACd,cAAQ,MAAM,sBAAsB,KAAK;AACzC,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EAEA,MAAc,gBAAgB,cAA8C;AAC1E,UAAM,SAAS,uBAAuB;AAEtC,QAAI;AACF,YAAM,SAAS,MAAM,iBAAiB,MAAM;AAC5C,aAAO;AAAA,IACT,SAAS,OAAO;AAEd,aAAO,KAAK,mBAAmB,YAAY;AAAA,IAC7C;AAAA,EACF;AAAA,EAEQ,mBAAmB,cAA8B;AAEvD,UAAM,QAAQ,aAAa,MAAM,IAAI;AACrC,UAAM,QAAkB,CAAC;AACzB,UAAM,UAAoB,CAAC;AAE3B,eAAW,QAAQ,OAAO;AAExB,YAAM,YAAY,KAAK,MAAM,+DAA+D;AAC5F,UAAI,WAAW;AACb,cAAM,KAAK,UAAU,CAAC,CAAC;AAAA,MACzB;AAGA,UAAI,KAAK,SAAS,QAAQ,GAAG;AAC3B,gBAAQ,KAAK,IAAI;AAAA,MACnB;AAAA,IACF;AAEA,QAAI,UAAU;AAEd,QAAI,MAAM,SAAS,GAAG;AACpB,iBAAW;AACX,iBAAW,QAAQ,CAAC,GAAG,IAAI,IAAI,KAAK,CAAC,GAAG;AACtC,mBAAW,KAAK,IAAI;AAAA;AAAA,MACtB;AACA,iBAAW;AAAA,IACb;AAEA,QAAI,QAAQ,SAAS,GAAG;AACtB,iBAAW;AACX,iBAAW,UAAU,QAAQ,MAAM,GAAG,EAAE,GAAG;AACzC,mBAAW,KAAK,MAAM;AAAA;AAAA,MACxB;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,aAAa,WAAmB,SAA0B;AAChE,UAAM,UAAmB;AAAA,MACvB;AAAA,MACA;AAAA,MACA,UAAU,CAAC;AAAA,MACX,cAAc,CAAC;AAAA,MACf,UAAU,CAAC;AAAA,MACX,WAAW,CAAC;AAAA,IACd;AAGA,UAAM,gBAAgB,QAAQ,MAAM,oCAAoC;AACxE,QAAI,eAAe;AACjB,cAAQ,WAAW,KAAK,cAAc,cAAc,CAAC,CAAC;AAAA,IACxD;AAGA,UAAM,YAAY,QAAQ,MAAM,wCAAwC;AACxE,QAAI,WAAW;AACb,cAAQ,eAAe,KAAK,kBAAkB,UAAU,CAAC,CAAC;AAAA,IAC5D;AAGA,UAAM,gBAAgB,QAAQ,MAAM,oCAAoC;AACxE,QAAI,eAAe;AACjB,cAAQ,WAAW,KAAK,cAAc,cAAc,CAAC,CAAC;AAAA,IACxD;AAGA,UAAM,iBAAiB,QAAQ,MAAM,qCAAqC;AAC1E,QAAI,gBAAgB;AAClB,cAAQ,YAAY,KAAK,eAAe,eAAe,CAAC,CAAC;AAAA,IAC3D;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,cAAc,SAAoC;AACxD,UAAM,WAA8B,CAAC;AACrC,UAAM,SAAS,QAAQ,MAAM,uBAAuB;AAEpD,eAAW,SAAS,QAAQ;AAC1B,UAAI,CAAC,MAAM,KAAK,EAAG;AAEnB,YAAM,YAAY,MAAM,MAAM,sBAAsB;AACpD,YAAM,gBAAgB,MAAM,MAAM,0BAA0B;AAC5D,YAAM,kBAAkB,MAAM,MAAM,4BAA4B;AAChE,YAAM,iBAAiB,MAAM,MAAM,2BAA2B;AAE9D,UAAI,WAAW;AACb,iBAAS,KAAK;AAAA,UACZ,MAAM,UAAU,CAAC,EAAE,KAAK;AAAA,UACxB,UAAU,gBAAgB,CAAC,EAAE,KAAK;AAAA,UAClC,YAAY,kBAAkB,CAAC,EAAE,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC;AAAA,UACrE,WAAW,iBAAiB,CAAC,EAAE,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC;AAAA,QACrE,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,kBAAkB,SAAqC;AAC7D,UAAM,QAA4B,CAAC;AACnC,UAAM,SAAS,QAAQ,MAAM,0BAA0B;AAEvD,eAAW,SAAS,QAAQ;AAC1B,UAAI,CAAC,MAAM,KAAK,EAAG;AAEnB,YAAM,eAAe,MAAM,MAAM,yBAAyB;AAC1D,YAAM,YAAY,MAAM,MAAM,6BAA6B;AAC3D,YAAM,aAAa,MAAM,MAAM,gCAAgC;AAE/D,UAAI,cAAc;AAChB,cAAM,KAAK;AAAA,UACT,SAAS,aAAa,CAAC,EAAE,KAAK;AAAA,UAC9B,aAAa,YAAY,CAAC,EAAE,KAAK,KAAK;AAAA,UACtC,eAAe,aAAa,CAAC,EAAE,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC;AAAA,QACrE,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,cAAc,SAAgC;AACpD,UAAM,QAAuB,CAAC;AAC9B,UAAM,SAAS,QAAQ,MAAM,uBAAuB;AAEpD,eAAW,SAAS,QAAQ;AAC1B,UAAI,CAAC,MAAM,KAAK,EAAG;AAEnB,YAAM,YAAY,MAAM,MAAM,sBAAsB;AACpD,YAAM,gBAAgB,MAAM,MAAM,0BAA0B;AAC5D,YAAM,eAAe,MAAM,MAAM,yBAAyB;AAC1D,YAAM,eAAe,MAAM,MAAM,yBAAyB;AAE1D,UAAI,WAAW;AACb,cAAM,KAAK;AAAA,UACT,MAAM,UAAU,CAAC,EAAE,KAAK;AAAA,UACxB,UAAU,gBAAgB,CAAC,EAAE,KAAK;AAAA,UAClC,SAAS,eAAe,CAAC,EAAE,KAAK,KAAK;AAAA,UACrC,SAAS,eAAe,CAAC,EAAE,MAAM,GAAG,EAAE,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC;AAAA,QACjE,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,eAAe,SAAkC;AACvD,UAAM,QAAyB,CAAC;AAChC,UAAM,SAAS,QAAQ,MAAM,wBAAwB;AAErD,eAAW,SAAS,QAAQ;AAC1B,UAAI,CAAC,MAAM,KAAK,EAAG;AAEnB,YAAM,aAAa,MAAM,MAAM,uBAAuB;AACtD,YAAM,eAAe,MAAM,MAAM,yBAAyB;AAE1D,UAAI,YAAY;AACd,cAAM,KAAK;AAAA,UACT,OAAO,WAAW,CAAC,EAAE,KAAK;AAAA,UAC1B,SAAS,eAAe,CAAC,EAAE,KAAK,KAAK;AAAA,QACvC,CAAC;AAAA,MACH;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAc,aAAa,WAAmB,SAAgC;AAC5E,UAAM,oBAAoB,qBAAqB,KAAK,WAAW;AAC/D,UAAM,cAAmB,UAAK,mBAAmB,WAAW,YAAY;AAExE,UAAM,cAAc,sBAAsB,SAAS;AAAA,cAC1C,oBAAI,KAAK,GAAE,YAAY,CAAC;AAAA;AAAA,EAEnC,OAAO;AAAA;AAGL,UAAM,cAAc,aAAa,WAAW;AAAA,EAC9C;AAAA,EAEA,MAAc,yBAAyB,WAAkC;AACvE,UAAM,SAAS,MAAM,WAAW,KAAK,WAAW;AAChD,UAAM,cAAc,OAAO,WAAW;AAEtC,QAAI,gBAAgB,QAAQ;AAC1B;AAAA,IACF;AAEA,UAAM,oBAAoB,qBAAqB,KAAK,WAAW;AAC/D,UAAM,cAAmB,UAAK,mBAAmB,SAAS;AAG1D,UAAM,QAAQ,MAAS,WAAQ,WAAW;AAC1C,UAAM,oBAAoB,MAAM;AAAA,MAC9B,CAAC,MAAM,aAAa,KAAK,CAAC;AAAA,IAC5B;AAEA,QAAI,kBAAkB,WAAW,GAAG;AAClC;AAAA,IACF;AAEA,QAAI,gBAAgB,WAAW;AAC7B,YAAM,KAAK,yBAAyB,aAAa,iBAAiB;AAAA,IACpE,WAAW,gBAAgB,UAAU;AACnC,YAAM,KAAK,wBAAwB,aAAa,iBAAiB;AAAA,IACnE;AAAA,EACF;AAAA,EAEA,MAAc,yBACZ,aACA,OACe;AACf,QAAI;AAEF,YAAM,WAAqB,CAAC;AAE5B,iBAAW,QAAQ,MAAM,KAAK,GAAG;AAC/B,cAAM,WAAgB,UAAK,aAAa,IAAI;AAC5C,cAAM,UAAU,MAAM,aAAa,QAAQ;AAC3C,YAAI,SAAS;AACX,mBAAS,KAAK,OAAO,IAAI;AAAA,EAAS,OAAO,EAAE;AAAA,QAC7C;AAAA,MACF;AAEA,YAAM,WAAW,SAAS,KAAK,MAAM;AACrC,YAAM,aAAa,MAAMA,MAAK,OAAO,KAAK,UAAU,OAAO,CAAC;AAG5D,YAAM,cAAmB,UAAK,aAAa,YAAY;AACvD,YAAS,aAAU,aAAa,UAAU;AAG1C,YAAM,KAAK,wBAAwB,aAAa,KAAK;AAAA,IACvD,SAAS,OAAO;AACd,cAAQ,MAAM,yCAAyC,KAAK;AAAA,IAE9D;AAAA,EACF;AAAA,EAEA,MAAc,wBACZ,aACA,OACe;AACf,eAAW,QAAQ,OAAO;AACxB,UAAI;AACF,cAAS,UAAY,UAAK,aAAa,IAAI,CAAC;AAAA,MAC9C,QAAQ;AAAA,MAER;AAAA,IACF;AAAA,EACF;AACF;","names":["gzip"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/utils/file-utils.ts","../src/utils/config.ts"],"sourcesContent":["import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\n\nexport async function ensureDir(dirPath: string): Promise<void> {\n await fs.mkdir(dirPath, { recursive: true });\n}\n\nexport async function fileExists(filePath: string): Promise<boolean> {\n try {\n await fs.access(filePath);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function readJSON<T>(filePath: string): Promise<T | null> {\n try {\n const content = await fs.readFile(filePath, \"utf-8\");\n return JSON.parse(content) as T;\n } catch {\n return null;\n }\n}\n\nexport async function writeJSON(\n filePath: string,\n data: unknown,\n pretty = true\n): Promise<void> {\n await ensureDir(path.dirname(filePath));\n const content = pretty ? JSON.stringify(data, null, 2) : JSON.stringify(data);\n await fs.writeFile(filePath, content);\n}\n\nexport async function appendToFile(\n filePath: string,\n content: string\n): Promise<void> {\n await ensureDir(path.dirname(filePath));\n await fs.appendFile(filePath, content);\n}\n\nexport async function readTextFile(filePath: string): Promise<string | null> {\n try {\n return await fs.readFile(filePath, \"utf-8\");\n } catch {\n return null;\n }\n}\n\nexport async function writeTextFile(\n filePath: string,\n content: string\n): Promise<void> {\n await ensureDir(path.dirname(filePath));\n await fs.writeFile(filePath, content);\n}\n\nexport async function copyFile(src: string, dest: string): Promise<void> {\n await ensureDir(path.dirname(dest));\n await fs.copyFile(src, dest);\n}\n\nexport async function listDir(dirPath: string): Promise<string[]> {\n try {\n return await fs.readdir(dirPath);\n } catch {\n return [];\n }\n}\n\nexport async function getFileSize(filePath: string): Promise<number> {\n try {\n const stats = await fs.stat(filePath);\n return stats.size;\n } catch {\n return 0;\n }\n}\n\nexport function generateSessionId(): string {\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).substring(2, 8);\n return `${timestamp}-${random}`;\n}\n\nexport function getCurrentTimestamp(): string {\n return new Date().toISOString();\n}\n","import * as fs from \"node:fs/promises\";\nimport * as path from \"node:path\";\n\nexport interface CCKBConfig {\n compaction: {\n trigger: \"session_end\" | \"size\" | \"messages\" | \"manual\";\n sizeThresholdKB: number;\n messageThreshold: number;\n cleanupAfterSummary: \"keep\" | \"archive\" | \"delete\";\n };\n capture: {\n tools: string[];\n maxContentLength: number;\n };\n vault: {\n autoIntegrate: boolean;\n maxDepth: number;\n };\n feedback: {\n enabled: boolean;\n contextDepth: number;\n };\n discover: {\n maxFiles: number;\n maxChunkSize: number;\n excludePatterns: string[];\n priorityPatterns: string[];\n supportedLanguages: string[];\n };\n}\n\nexport const DEFAULT_CONFIG: CCKBConfig = {\n compaction: {\n trigger: \"session_end\",\n sizeThresholdKB: 50,\n messageThreshold: 100,\n cleanupAfterSummary: \"keep\",\n },\n capture: {\n tools: [\"Write\", \"Edit\", \"MultiEdit\", \"Bash\", \"Task\"],\n maxContentLength: 500,\n },\n vault: {\n autoIntegrate: true,\n maxDepth: 5,\n },\n feedback: {\n enabled: true,\n contextDepth: 2,\n },\n discover: {\n maxFiles: 100,\n maxChunkSize: 30000, // ~7500 tokens, safer for Claude\n excludePatterns: [\n \"*.min.js\",\n \"*.bundle.js\",\n \"*.map\",\n \"coverage/**\",\n \".next/**\",\n \"build/**\",\n \"dist/**\",\n ],\n priorityPatterns: [\n \"**/index.{ts,js,tsx,jsx}\",\n \"**/main.{ts,js,py,go,rs}\",\n \"**/app.{ts,js,py}\",\n \"**/models/**\",\n \"**/entities/**\",\n \"**/services/**\",\n ],\n supportedLanguages: [\"typescript\", \"javascript\", \"python\", \"go\", \"rust\"],\n },\n};\n\nexport async function loadConfig(projectPath: string): Promise<CCKBConfig> {\n const configPath = path.join(\n projectPath,\n \"cc-knowledge-base\",\n \".cckb-config.json\"\n );\n\n try {\n const content = await fs.readFile(configPath, \"utf-8\");\n const userConfig = JSON.parse(content);\n return { ...DEFAULT_CONFIG, ...userConfig };\n } catch {\n return DEFAULT_CONFIG;\n }\n}\n\nexport async function saveConfig(\n projectPath: string,\n config: CCKBConfig\n): Promise<void> {\n const configPath = path.join(\n projectPath,\n \"cc-knowledge-base\",\n \".cckb-config.json\"\n );\n\n await fs.writeFile(configPath, JSON.stringify(config, null, 2));\n}\n\nexport function getKnowledgeBasePath(projectPath: string): string {\n return path.join(projectPath, \"cc-knowledge-base\");\n}\n\nexport function getConversationsPath(projectPath: string): string {\n return path.join(projectPath, \"cc-knowledge-base\", \"conversations\");\n}\n\nexport function getVaultPath(projectPath: string): string {\n return path.join(projectPath, \"cc-knowledge-base\", \"vault\");\n}\n\nexport function getStatePath(projectPath: string): string {\n return path.join(projectPath, \"cc-knowledge-base\", \".cckb-state\");\n}\n"],"mappings":"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","names":["fs","path"]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|