ccjk 13.5.2 → 13.5.4
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 +5 -5
- package/dist/chunks/boost.mjs +8 -1
- package/dist/chunks/ccjk-config.mjs +17 -0
- package/dist/chunks/ccr.mjs +2 -2
- package/dist/chunks/check-updates.mjs +1 -1
- package/dist/chunks/codex-config-switch.mjs +1 -1
- package/dist/chunks/codex-provider-manager.mjs +1 -1
- package/dist/chunks/codex.mjs +2 -2
- package/dist/chunks/completion.mjs +1 -1
- package/dist/chunks/config-switch.mjs +1 -1
- package/dist/chunks/context.mjs +316 -1
- package/dist/chunks/features.mjs +43 -14
- package/dist/chunks/index4.mjs +8 -1
- package/dist/chunks/init.mjs +2 -2
- package/dist/chunks/mcp-cli.mjs +3 -3
- package/dist/chunks/mcp.mjs +177 -35
- package/dist/{shared/ccjk.Crd_nEfj.mjs → chunks/memory-check.mjs} +18 -424
- package/dist/chunks/memory-paths.mjs +259 -0
- package/dist/chunks/memory-sync.mjs +209 -0
- package/dist/chunks/memory.mjs +140 -17
- package/dist/chunks/menu-hierarchical.mjs +2 -2
- package/dist/chunks/menu.mjs +1 -1
- package/dist/chunks/onboarding-wizard.mjs +8 -1
- package/dist/chunks/package.mjs +1 -1
- package/dist/chunks/quick-actions.mjs +8 -1
- package/dist/chunks/quick-setup.mjs +1 -1
- package/dist/chunks/smart-defaults.mjs +1 -20
- package/dist/chunks/status.mjs +8 -1
- package/dist/chunks/update.mjs +2 -2
- package/dist/cli.mjs +16 -4
- package/dist/shared/{ccjk.LTONy3IS.mjs → ccjk.BOfPON0N.mjs} +1 -1
- package/dist/shared/{ccjk.0aJQmVxS.mjs → ccjk.miT0g_vA.mjs} +3 -160
- package/dist/shared/ccjk.xkKNsC02.mjs +421 -0
- package/package.json +1 -1
- package/dist/chunks/auto-memory-bridge.mjs +0 -221
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import { resolve } from 'node:path';
|
|
2
|
+
import { CCJK_CONFIG_FILE, SUPPORTED_LANGS, DEFAULT_CODE_TOOL_TYPE, CCJK_CONFIG_DIR, CLAUDE_DIR } from './constants.mjs';
|
|
3
|
+
import { p as parse } from '../shared/ccjk.BBtCGd_g.mjs';
|
|
4
|
+
import { stringify } from './index6.mjs';
|
|
5
|
+
import { exists, readFile, ensureDir, writeFileAtomic } from './fs-operations.mjs';
|
|
6
|
+
import { d as dirname, j as join } from '../shared/ccjk.bQ7Dh1g4.mjs';
|
|
7
|
+
import 'node:os';
|
|
8
|
+
import './index5.mjs';
|
|
9
|
+
import 'node:fs';
|
|
10
|
+
import 'node:process';
|
|
11
|
+
import 'node:url';
|
|
12
|
+
import 'node:crypto';
|
|
13
|
+
import 'node:fs/promises';
|
|
14
|
+
|
|
15
|
+
const DEFAULT_CONFIG_VERSION = "4.0.0";
|
|
16
|
+
function createDefaultCcjkConfig(preferredLang = "en", claudeCodeInstallType = "global") {
|
|
17
|
+
return {
|
|
18
|
+
version: DEFAULT_CONFIG_VERSION,
|
|
19
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
20
|
+
general: {
|
|
21
|
+
preferredLang,
|
|
22
|
+
templateLang: preferredLang,
|
|
23
|
+
aiOutputLang: preferredLang === "zh-CN" ? "zh-CN" : void 0,
|
|
24
|
+
currentTool: DEFAULT_CODE_TOOL_TYPE
|
|
25
|
+
},
|
|
26
|
+
tools: {
|
|
27
|
+
claudeCode: {
|
|
28
|
+
enabled: true,
|
|
29
|
+
installType: claudeCodeInstallType,
|
|
30
|
+
outputStyles: ["speed-coder", "senior-architect", "pair-programmer"],
|
|
31
|
+
defaultOutputStyle: "senior-architect",
|
|
32
|
+
currentProfile: "",
|
|
33
|
+
profiles: {}
|
|
34
|
+
},
|
|
35
|
+
codex: {
|
|
36
|
+
enabled: false,
|
|
37
|
+
systemPromptStyle: "senior-architect"
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
storage: {
|
|
41
|
+
memory: {}
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function readCcjkConfig(configPath = CCJK_CONFIG_FILE) {
|
|
46
|
+
try {
|
|
47
|
+
if (!exists(configPath)) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
const content = readFile(configPath);
|
|
51
|
+
const parsed = parse(content);
|
|
52
|
+
return convertTomlToCcjkConfig(parsed);
|
|
53
|
+
} catch (error) {
|
|
54
|
+
console.error(`Failed to read CCJK config from ${configPath}:`, error);
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function writeCcjkConfig(config, configPath = CCJK_CONFIG_FILE) {
|
|
59
|
+
try {
|
|
60
|
+
const configDir = dirname(configPath);
|
|
61
|
+
ensureDir(configDir);
|
|
62
|
+
config.lastUpdated = (/* @__PURE__ */ new Date()).toISOString();
|
|
63
|
+
const tomlContent = stringify(config);
|
|
64
|
+
writeFileAtomic(configPath, tomlContent);
|
|
65
|
+
} catch (error) {
|
|
66
|
+
console.error(`Failed to write CCJK config to ${configPath}:`, error);
|
|
67
|
+
throw new Error(`Failed to write CCJK config: ${error instanceof Error ? error.message : String(error)}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function updateCcjkConfig(updates, configPath = CCJK_CONFIG_FILE) {
|
|
71
|
+
const existingConfig = readCcjkConfig(configPath) || createDefaultCcjkConfig();
|
|
72
|
+
const updatedConfig = {
|
|
73
|
+
version: updates.version || existingConfig.version,
|
|
74
|
+
lastUpdated: (/* @__PURE__ */ new Date()).toISOString(),
|
|
75
|
+
general: {
|
|
76
|
+
...existingConfig.general,
|
|
77
|
+
...updates.general
|
|
78
|
+
},
|
|
79
|
+
tools: {
|
|
80
|
+
...existingConfig.tools,
|
|
81
|
+
...updates.tools,
|
|
82
|
+
claudeCode: {
|
|
83
|
+
...existingConfig.tools.claudeCode,
|
|
84
|
+
...updates.tools?.claudeCode
|
|
85
|
+
},
|
|
86
|
+
codex: {
|
|
87
|
+
...existingConfig.tools.codex,
|
|
88
|
+
...updates.tools?.codex
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
storage: {
|
|
92
|
+
...existingConfig.storage,
|
|
93
|
+
...updates.storage,
|
|
94
|
+
memory: {
|
|
95
|
+
...existingConfig.storage.memory,
|
|
96
|
+
...updates.storage?.memory
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
writeCcjkConfig(updatedConfig, configPath);
|
|
101
|
+
return updatedConfig;
|
|
102
|
+
}
|
|
103
|
+
function getCcjkConfig(configPath = CCJK_CONFIG_FILE) {
|
|
104
|
+
const config = readCcjkConfig(configPath);
|
|
105
|
+
return config || createDefaultCcjkConfig();
|
|
106
|
+
}
|
|
107
|
+
function validateCcjkConfig(config) {
|
|
108
|
+
const errors = [];
|
|
109
|
+
if (!config || typeof config !== "object") {
|
|
110
|
+
return { valid: false, errors: ["Configuration must be an object"] };
|
|
111
|
+
}
|
|
112
|
+
const cfg = config;
|
|
113
|
+
if (!cfg.version || typeof cfg.version !== "string") {
|
|
114
|
+
errors.push("Invalid or missing version");
|
|
115
|
+
}
|
|
116
|
+
if (!cfg.general || typeof cfg.general !== "object") {
|
|
117
|
+
errors.push("Invalid or missing general section");
|
|
118
|
+
} else {
|
|
119
|
+
if (!cfg.general.preferredLang || !SUPPORTED_LANGS.includes(cfg.general.preferredLang)) {
|
|
120
|
+
errors.push(`Invalid preferredLang: ${cfg.general.preferredLang}`);
|
|
121
|
+
}
|
|
122
|
+
if (cfg.general.templateLang && !SUPPORTED_LANGS.includes(cfg.general.templateLang)) {
|
|
123
|
+
errors.push(`Invalid templateLang: ${cfg.general.templateLang}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (!cfg.tools || typeof cfg.tools !== "object") {
|
|
127
|
+
errors.push("Invalid or missing tools section");
|
|
128
|
+
} else {
|
|
129
|
+
if (!cfg.tools.claudeCode || typeof cfg.tools.claudeCode !== "object") {
|
|
130
|
+
errors.push("Invalid or missing claudeCode tool config");
|
|
131
|
+
}
|
|
132
|
+
if (!cfg.tools.codex || typeof cfg.tools.codex !== "object") {
|
|
133
|
+
errors.push("Invalid or missing codex tool config");
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
if (!cfg.storage || typeof cfg.storage !== "object") {
|
|
137
|
+
errors.push("Invalid or missing storage section");
|
|
138
|
+
}
|
|
139
|
+
return {
|
|
140
|
+
valid: errors.length === 0,
|
|
141
|
+
errors
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
function convertTomlToCcjkConfig(tomlConfig) {
|
|
145
|
+
if (!tomlConfig) {
|
|
146
|
+
return null;
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
version: tomlConfig.version || DEFAULT_CONFIG_VERSION,
|
|
150
|
+
lastUpdated: tomlConfig.lastUpdated || (/* @__PURE__ */ new Date()).toISOString(),
|
|
151
|
+
general: {
|
|
152
|
+
preferredLang: tomlConfig.general?.preferredLang || "en",
|
|
153
|
+
templateLang: tomlConfig.general?.templateLang,
|
|
154
|
+
aiOutputLang: tomlConfig.general?.aiOutputLang,
|
|
155
|
+
currentTool: tomlConfig.general?.currentTool || DEFAULT_CODE_TOOL_TYPE
|
|
156
|
+
},
|
|
157
|
+
tools: {
|
|
158
|
+
claudeCode: {
|
|
159
|
+
enabled: tomlConfig.claudeCode?.enabled ?? true,
|
|
160
|
+
installType: tomlConfig.claudeCode?.installType || "global",
|
|
161
|
+
installMethod: tomlConfig.claudeCode?.installMethod,
|
|
162
|
+
outputStyles: tomlConfig.claudeCode?.outputStyles || [],
|
|
163
|
+
defaultOutputStyle: tomlConfig.claudeCode?.defaultOutputStyle,
|
|
164
|
+
currentProfile: tomlConfig.claudeCode?.currentProfile || "",
|
|
165
|
+
profiles: tomlConfig.claudeCode?.profiles || {},
|
|
166
|
+
version: tomlConfig.claudeCode?.version
|
|
167
|
+
},
|
|
168
|
+
codex: {
|
|
169
|
+
enabled: tomlConfig.codex?.enabled ?? false,
|
|
170
|
+
systemPromptStyle: tomlConfig.codex?.systemPromptStyle || "senior-architect",
|
|
171
|
+
installMethod: tomlConfig.codex?.installMethod,
|
|
172
|
+
envKeyMigrated: tomlConfig.codex?.envKeyMigrated
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
storage: {
|
|
176
|
+
memory: {
|
|
177
|
+
claudeDir: tomlConfig.storage?.memory?.claudeDir,
|
|
178
|
+
ccjkDir: tomlConfig.storage?.memory?.ccjkDir
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
const config = {
|
|
185
|
+
/**
|
|
186
|
+
* CCJK Configuration (~/.ccjk/config.toml)
|
|
187
|
+
*/
|
|
188
|
+
ccjk: {
|
|
189
|
+
/**
|
|
190
|
+
* Read CCJK configuration
|
|
191
|
+
*/
|
|
192
|
+
read: readCcjkConfig,
|
|
193
|
+
/**
|
|
194
|
+
* Write CCJK configuration
|
|
195
|
+
*/
|
|
196
|
+
write: writeCcjkConfig,
|
|
197
|
+
/**
|
|
198
|
+
* Update CCJK configuration with partial changes
|
|
199
|
+
*/
|
|
200
|
+
update: updateCcjkConfig,
|
|
201
|
+
/**
|
|
202
|
+
* Get or create CCJK configuration (with defaults)
|
|
203
|
+
*/
|
|
204
|
+
get: getCcjkConfig,
|
|
205
|
+
/**
|
|
206
|
+
* Create default CCJK configuration
|
|
207
|
+
*/
|
|
208
|
+
createDefault: createDefaultCcjkConfig,
|
|
209
|
+
/**
|
|
210
|
+
* Validate CCJK configuration
|
|
211
|
+
*/
|
|
212
|
+
validate: validateCcjkConfig
|
|
213
|
+
}};
|
|
214
|
+
|
|
215
|
+
function getMemoryDirectoryOverrides() {
|
|
216
|
+
const ccjkConfig = config.ccjk.read();
|
|
217
|
+
return {
|
|
218
|
+
claudeDir: ccjkConfig?.storage?.memory?.claudeDir,
|
|
219
|
+
ccjkDir: ccjkConfig?.storage?.memory?.ccjkDir
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
function resolveClaudeDir(claudeDir) {
|
|
223
|
+
return normalizeProjectPath(claudeDir || getMemoryDirectoryOverrides().claudeDir || CLAUDE_DIR);
|
|
224
|
+
}
|
|
225
|
+
function resolveCcjkDir(ccjkDir) {
|
|
226
|
+
return normalizeProjectPath(ccjkDir || getMemoryDirectoryOverrides().ccjkDir || CCJK_CONFIG_DIR);
|
|
227
|
+
}
|
|
228
|
+
function normalizeProjectPath(projectPath) {
|
|
229
|
+
return resolve(projectPath).replace(/\\/g, "/");
|
|
230
|
+
}
|
|
231
|
+
function toClaudeProjectDirName(projectPath) {
|
|
232
|
+
const normalizedPath = normalizeProjectPath(projectPath).replace(/^\/+/, "");
|
|
233
|
+
return `-${normalizedPath.replace(/[:/]/g, "-")}`;
|
|
234
|
+
}
|
|
235
|
+
function getClaudeMemoryPath(projectPath, claudeDir) {
|
|
236
|
+
const resolvedClaudeDir = resolveClaudeDir(claudeDir);
|
|
237
|
+
if (projectPath) {
|
|
238
|
+
return join(resolvedClaudeDir, "projects", toClaudeProjectDirName(projectPath), "memory", "MEMORY.md");
|
|
239
|
+
}
|
|
240
|
+
return join(resolvedClaudeDir, "memory", "MEMORY.md");
|
|
241
|
+
}
|
|
242
|
+
function getCcjkMemoryPath(projectPath, ccjkDir) {
|
|
243
|
+
const resolvedCcjkDir = resolveCcjkDir(ccjkDir);
|
|
244
|
+
if (projectPath) {
|
|
245
|
+
return join(resolvedCcjkDir, "memory", "projects", toClaudeProjectDirName(projectPath), "MEMORY.md");
|
|
246
|
+
}
|
|
247
|
+
return join(resolvedCcjkDir, "memory", "global", "MEMORY.md");
|
|
248
|
+
}
|
|
249
|
+
function getClaudeProjectsDir(claudeDir) {
|
|
250
|
+
return join(resolveClaudeDir(claudeDir), "projects");
|
|
251
|
+
}
|
|
252
|
+
function getConfiguredMemoryDirectories() {
|
|
253
|
+
return {
|
|
254
|
+
claudeDir: resolveClaudeDir(),
|
|
255
|
+
ccjkDir: resolveCcjkDir()
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
export { getCcjkMemoryPath, getClaudeMemoryPath, getClaudeProjectsDir, getConfiguredMemoryDirectories, normalizeProjectPath, toClaudeProjectDirName };
|
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
import { readFileSync, existsSync, statSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
import 'node:fs/promises';
|
|
4
|
+
import { normalizeProjectPath, getCcjkMemoryPath, getClaudeMemoryPath } from './memory-paths.mjs';
|
|
5
|
+
import './constants.mjs';
|
|
6
|
+
import 'node:os';
|
|
7
|
+
import './index5.mjs';
|
|
8
|
+
import 'node:process';
|
|
9
|
+
import 'node:url';
|
|
10
|
+
import '../shared/ccjk.bQ7Dh1g4.mjs';
|
|
11
|
+
import '../shared/ccjk.BBtCGd_g.mjs';
|
|
12
|
+
import './index6.mjs';
|
|
13
|
+
import './fs-operations.mjs';
|
|
14
|
+
import 'node:crypto';
|
|
15
|
+
|
|
16
|
+
function parseAutoMemory(content) {
|
|
17
|
+
const lines = content.split("\n");
|
|
18
|
+
const entries = [];
|
|
19
|
+
let currentEntry = null;
|
|
20
|
+
for (const line of lines) {
|
|
21
|
+
const headerMatch = line.match(/^(#{1,6})\s+(.+)$/);
|
|
22
|
+
if (headerMatch) {
|
|
23
|
+
if (currentEntry && currentEntry.content.length > 0) {
|
|
24
|
+
entries.push(currentEntry);
|
|
25
|
+
}
|
|
26
|
+
currentEntry = {
|
|
27
|
+
title: headerMatch[2].trim(),
|
|
28
|
+
content: [],
|
|
29
|
+
level: headerMatch[1].length
|
|
30
|
+
};
|
|
31
|
+
} else if (currentEntry && line.trim()) {
|
|
32
|
+
currentEntry.content.push(line);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (currentEntry && currentEntry.content.length > 0) {
|
|
36
|
+
entries.push(currentEntry);
|
|
37
|
+
}
|
|
38
|
+
return entries;
|
|
39
|
+
}
|
|
40
|
+
function autoMemoryToBrainContext(entries, projectPath) {
|
|
41
|
+
const context = {
|
|
42
|
+
facts: [],
|
|
43
|
+
patterns: [],
|
|
44
|
+
decisions: [],
|
|
45
|
+
metadata: {
|
|
46
|
+
source: "auto-memory",
|
|
47
|
+
projectPath,
|
|
48
|
+
syncedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
for (const entry of entries) {
|
|
52
|
+
const contentText = entry.content.join("\n").trim();
|
|
53
|
+
const titleLower = entry.title.toLowerCase();
|
|
54
|
+
if (titleLower.includes("architecture") || titleLower.includes("pattern") || titleLower.includes("design")) {
|
|
55
|
+
context.patterns.push({
|
|
56
|
+
name: entry.title,
|
|
57
|
+
description: contentText,
|
|
58
|
+
category: "architecture"
|
|
59
|
+
});
|
|
60
|
+
} else if (titleLower.includes("decision") || titleLower.includes("choice") || titleLower.includes("why")) {
|
|
61
|
+
context.decisions.push({
|
|
62
|
+
decision: entry.title,
|
|
63
|
+
rationale: contentText,
|
|
64
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
65
|
+
});
|
|
66
|
+
} else {
|
|
67
|
+
context.facts.push({
|
|
68
|
+
key: entry.title,
|
|
69
|
+
value: contentText,
|
|
70
|
+
confidence: 0.9
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return context;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function readMemorySnapshot(path) {
|
|
78
|
+
if (!existsSync(path)) {
|
|
79
|
+
return {
|
|
80
|
+
path,
|
|
81
|
+
content: "",
|
|
82
|
+
exists: false,
|
|
83
|
+
hasContent: false,
|
|
84
|
+
sizeBytes: 0,
|
|
85
|
+
mtimeMs: 0
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
const stats = statSync(path);
|
|
89
|
+
const content = readFileSync(path, "utf-8");
|
|
90
|
+
return {
|
|
91
|
+
path,
|
|
92
|
+
content,
|
|
93
|
+
exists: true,
|
|
94
|
+
hasContent: content.trim().length > 0,
|
|
95
|
+
sizeBytes: stats.size,
|
|
96
|
+
mtimeMs: stats.mtimeMs
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function writeMemorySnapshot(path, content) {
|
|
100
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
101
|
+
writeFileSync(path, content, "utf-8");
|
|
102
|
+
}
|
|
103
|
+
function summarizeMemoryContent(content, projectPath) {
|
|
104
|
+
if (!content.trim()) {
|
|
105
|
+
return {
|
|
106
|
+
parseMode: "empty",
|
|
107
|
+
entryCount: 0,
|
|
108
|
+
factCount: 0,
|
|
109
|
+
patternCount: 0,
|
|
110
|
+
decisionCount: 0
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
const entries = parseAutoMemory(content);
|
|
114
|
+
if (entries.length === 0) {
|
|
115
|
+
return {
|
|
116
|
+
parseMode: "freeform",
|
|
117
|
+
entryCount: 0,
|
|
118
|
+
factCount: 0,
|
|
119
|
+
patternCount: 0,
|
|
120
|
+
decisionCount: 0
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
const context = autoMemoryToBrainContext(entries, projectPath || "global");
|
|
124
|
+
return {
|
|
125
|
+
parseMode: "structured",
|
|
126
|
+
entryCount: entries.length,
|
|
127
|
+
factCount: context.facts.length,
|
|
128
|
+
patternCount: context.patterns.length,
|
|
129
|
+
decisionCount: context.decisions.length
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
function inspectSnapshots(claudeSnapshot, ccjkSnapshot, projectPath) {
|
|
133
|
+
let source = "none";
|
|
134
|
+
let sourceContent = "";
|
|
135
|
+
let syncState = "empty";
|
|
136
|
+
if (claudeSnapshot.hasContent || ccjkSnapshot.hasContent) {
|
|
137
|
+
if (claudeSnapshot.hasContent && ccjkSnapshot.hasContent && claudeSnapshot.content === ccjkSnapshot.content) {
|
|
138
|
+
source = "already-synced";
|
|
139
|
+
sourceContent = claudeSnapshot.content;
|
|
140
|
+
syncState = "in-sync";
|
|
141
|
+
} else if (claudeSnapshot.hasContent && !ccjkSnapshot.hasContent) {
|
|
142
|
+
source = "claude";
|
|
143
|
+
sourceContent = claudeSnapshot.content;
|
|
144
|
+
syncState = "claude-only";
|
|
145
|
+
} else if (ccjkSnapshot.hasContent && !claudeSnapshot.hasContent) {
|
|
146
|
+
source = "ccjk";
|
|
147
|
+
sourceContent = ccjkSnapshot.content;
|
|
148
|
+
syncState = "ccjk-only";
|
|
149
|
+
} else if (claudeSnapshot.mtimeMs >= ccjkSnapshot.mtimeMs) {
|
|
150
|
+
source = "claude";
|
|
151
|
+
sourceContent = claudeSnapshot.content;
|
|
152
|
+
syncState = "claude-newer";
|
|
153
|
+
} else {
|
|
154
|
+
source = "ccjk";
|
|
155
|
+
sourceContent = ccjkSnapshot.content;
|
|
156
|
+
syncState = "ccjk-newer";
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return {
|
|
160
|
+
source,
|
|
161
|
+
syncState,
|
|
162
|
+
snapshots: {
|
|
163
|
+
claude: {
|
|
164
|
+
exists: claudeSnapshot.exists,
|
|
165
|
+
hasContent: claudeSnapshot.hasContent,
|
|
166
|
+
sizeBytes: claudeSnapshot.sizeBytes,
|
|
167
|
+
mtimeMs: claudeSnapshot.mtimeMs
|
|
168
|
+
},
|
|
169
|
+
ccjk: {
|
|
170
|
+
exists: ccjkSnapshot.exists,
|
|
171
|
+
hasContent: ccjkSnapshot.hasContent,
|
|
172
|
+
sizeBytes: ccjkSnapshot.sizeBytes,
|
|
173
|
+
mtimeMs: ccjkSnapshot.mtimeMs
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
...summarizeMemoryContent(sourceContent, projectPath)
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
function inspectMemoryFiles(options = {}) {
|
|
180
|
+
const projectPath = options.projectPath ? normalizeProjectPath(options.projectPath) : void 0;
|
|
181
|
+
const paths = {
|
|
182
|
+
claude: getClaudeMemoryPath(projectPath, options.claudeDir),
|
|
183
|
+
ccjk: getCcjkMemoryPath(projectPath, options.ccjkDir)
|
|
184
|
+
};
|
|
185
|
+
const claudeSnapshot = readMemorySnapshot(paths.claude);
|
|
186
|
+
const ccjkSnapshot = readMemorySnapshot(paths.ccjk);
|
|
187
|
+
return {
|
|
188
|
+
scope: projectPath ? "project" : "global",
|
|
189
|
+
paths,
|
|
190
|
+
...inspectSnapshots(claudeSnapshot, ccjkSnapshot, projectPath)
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
function syncMemoryFiles(options = {}) {
|
|
194
|
+
const inspection = inspectMemoryFiles(options);
|
|
195
|
+
const updatedTargets = [];
|
|
196
|
+
if (inspection.source === "claude" && inspection.syncState !== "in-sync") {
|
|
197
|
+
writeMemorySnapshot(inspection.paths.ccjk, readFileSync(inspection.paths.claude, "utf-8"));
|
|
198
|
+
updatedTargets.push("ccjk");
|
|
199
|
+
} else if (inspection.source === "ccjk" && inspection.syncState !== "in-sync") {
|
|
200
|
+
writeMemorySnapshot(inspection.paths.claude, readFileSync(inspection.paths.ccjk, "utf-8"));
|
|
201
|
+
updatedTargets.push("claude");
|
|
202
|
+
}
|
|
203
|
+
return {
|
|
204
|
+
...inspection,
|
|
205
|
+
updatedTargets
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export { inspectMemoryFiles, syncMemoryFiles };
|
package/dist/chunks/memory.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { existsSync, readFileSync, mkdirSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { homedir } from 'node:os';
|
|
3
2
|
import a from './index2.mjs';
|
|
4
3
|
import { i as inquirer } from './index3.mjs';
|
|
5
4
|
import { x as K } from './main.mjs';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
5
|
+
import { getClaudeMemoryPath } from './memory-paths.mjs';
|
|
6
|
+
import { memoryCheck } from './memory-check.mjs';
|
|
7
|
+
import { inspectMemoryFiles, syncMemoryFiles } from './memory-sync.mjs';
|
|
8
8
|
import { j as join } from '../shared/ccjk.bQ7Dh1g4.mjs';
|
|
9
9
|
import '../shared/ccjk.BAGoDD49.mjs';
|
|
10
10
|
import 'node:readline';
|
|
@@ -18,26 +18,118 @@ import 'tty';
|
|
|
18
18
|
import 'fs';
|
|
19
19
|
import 'child_process';
|
|
20
20
|
import 'node:path';
|
|
21
|
+
import 'node:os';
|
|
21
22
|
import 'node:crypto';
|
|
22
23
|
import 'buffer';
|
|
23
24
|
import 'string_decoder';
|
|
24
25
|
import 'module';
|
|
25
26
|
import 'node:child_process';
|
|
26
27
|
import 'node:stream';
|
|
27
|
-
import '
|
|
28
|
+
import './constants.mjs';
|
|
28
29
|
import './index5.mjs';
|
|
29
30
|
import 'node:url';
|
|
31
|
+
import '../shared/ccjk.BBtCGd_g.mjs';
|
|
32
|
+
import './index6.mjs';
|
|
33
|
+
import './fs-operations.mjs';
|
|
34
|
+
import 'node:fs/promises';
|
|
35
|
+
import 'constants';
|
|
36
|
+
import 'util';
|
|
37
|
+
import 'assert';
|
|
38
|
+
import 'path';
|
|
30
39
|
|
|
31
|
-
function
|
|
32
|
-
|
|
40
|
+
function formatTimestamp(timestampMs) {
|
|
41
|
+
if (!timestampMs) {
|
|
42
|
+
return "never";
|
|
43
|
+
}
|
|
44
|
+
return new Date(timestampMs).toISOString();
|
|
33
45
|
}
|
|
34
|
-
function
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
46
|
+
function formatSize(sizeBytes) {
|
|
47
|
+
return `${(sizeBytes / 1024).toFixed(2)} KB`;
|
|
48
|
+
}
|
|
49
|
+
function describeSyncState(syncState) {
|
|
50
|
+
switch (syncState) {
|
|
51
|
+
case "in-sync":
|
|
52
|
+
return "Claude and CCJK memory are in sync";
|
|
53
|
+
case "claude-only":
|
|
54
|
+
return "Only Claude memory has content";
|
|
55
|
+
case "ccjk-only":
|
|
56
|
+
return "Only CCJK memory has content";
|
|
57
|
+
case "claude-newer":
|
|
58
|
+
return "Claude memory is newer than the CCJK mirror";
|
|
59
|
+
case "ccjk-newer":
|
|
60
|
+
return "CCJK mirror is newer than Claude memory";
|
|
61
|
+
case "empty":
|
|
62
|
+
return "No memory content found";
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async function showMemoryStatus(projectPath) {
|
|
66
|
+
const result = inspectMemoryFiles({ projectPath });
|
|
67
|
+
console.log(a.cyan.bold("\n\u{1F4CA} Memory Status"));
|
|
68
|
+
console.log(a.gray(`Scope: ${result.scope}`));
|
|
69
|
+
console.log(a.gray(`State: ${describeSyncState(result.syncState)}`));
|
|
70
|
+
console.log(a.gray(`Source: ${result.source}`));
|
|
71
|
+
console.log(a.gray(`Claude: ${result.paths.claude}`));
|
|
72
|
+
console.log(a.gray(`CCJK: ${result.paths.ccjk}`));
|
|
73
|
+
console.log("");
|
|
74
|
+
console.log(a.bold("Claude Memory"));
|
|
75
|
+
console.log(a.gray(` Exists: ${result.snapshots.claude.exists ? "yes" : "no"}`));
|
|
76
|
+
console.log(a.gray(` Content: ${result.snapshots.claude.hasContent ? "yes" : "no"}`));
|
|
77
|
+
console.log(a.gray(` Size: ${formatSize(result.snapshots.claude.sizeBytes)}`));
|
|
78
|
+
console.log(a.gray(` Updated: ${formatTimestamp(result.snapshots.claude.mtimeMs)}`));
|
|
79
|
+
console.log(a.bold("\nCCJK Mirror"));
|
|
80
|
+
console.log(a.gray(` Exists: ${result.snapshots.ccjk.exists ? "yes" : "no"}`));
|
|
81
|
+
console.log(a.gray(` Content: ${result.snapshots.ccjk.hasContent ? "yes" : "no"}`));
|
|
82
|
+
console.log(a.gray(` Size: ${formatSize(result.snapshots.ccjk.sizeBytes)}`));
|
|
83
|
+
console.log(a.gray(` Updated: ${formatTimestamp(result.snapshots.ccjk.mtimeMs)}`));
|
|
84
|
+
if (result.parseMode === "structured") {
|
|
85
|
+
console.log(a.bold("\nStructured Summary"));
|
|
86
|
+
console.log(a.gray(` Entries: ${result.entryCount}`));
|
|
87
|
+
console.log(a.gray(` Facts: ${result.factCount}`));
|
|
88
|
+
console.log(a.gray(` Patterns: ${result.patternCount}`));
|
|
89
|
+
console.log(a.gray(` Decisions: ${result.decisionCount}`));
|
|
90
|
+
} else if (result.parseMode === "freeform") {
|
|
91
|
+
console.log(a.bold("\nStructured Summary"));
|
|
92
|
+
console.log(a.gray(" Freeform notes detected; no structured headings parsed"));
|
|
93
|
+
}
|
|
94
|
+
console.log("");
|
|
95
|
+
}
|
|
96
|
+
async function runMemoryDoctor(projectPath) {
|
|
97
|
+
const result = inspectMemoryFiles({ projectPath });
|
|
98
|
+
const health = await memoryCheck.check();
|
|
99
|
+
console.log(a.cyan.bold("\n\u{1FA7A} Memory Doctor"));
|
|
100
|
+
console.log(a.gray(`Project state: ${describeSyncState(result.syncState)}`));
|
|
101
|
+
console.log(a.gray(`Health score: ${health.score}/100 (${health.status})`));
|
|
102
|
+
console.log(a.gray(`Summary: ${health.message}`));
|
|
103
|
+
if (health.details && health.details.length > 0) {
|
|
104
|
+
console.log(a.bold("\nHealth Details"));
|
|
105
|
+
for (const detail of health.details) {
|
|
106
|
+
console.log(a.gray(` ${detail}`));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
const recommendations = [];
|
|
110
|
+
if (result.syncState === "claude-newer" || result.syncState === "ccjk-newer" || result.syncState === "claude-only" || result.syncState === "ccjk-only") {
|
|
111
|
+
recommendations.push("Run `ccjk memory --sync` to reconcile Claude memory and the CCJK mirror");
|
|
112
|
+
}
|
|
113
|
+
if (result.syncState === "empty") {
|
|
114
|
+
recommendations.push("Add project memory with `ccjk memory --edit` before relying on sync or doctor checks");
|
|
115
|
+
}
|
|
116
|
+
if (health.fix) {
|
|
117
|
+
recommendations.push(health.fix);
|
|
39
118
|
}
|
|
40
|
-
|
|
119
|
+
if (recommendations.length > 0) {
|
|
120
|
+
console.log(a.bold("\nRecommendations"));
|
|
121
|
+
for (const recommendation of recommendations) {
|
|
122
|
+
console.log(a.gray(` - ${recommendation}`));
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (health.command) {
|
|
126
|
+
console.log(a.bold("\nSuggested Command"));
|
|
127
|
+
console.log(a.gray(` ${health.command}`));
|
|
128
|
+
}
|
|
129
|
+
console.log("");
|
|
130
|
+
}
|
|
131
|
+
function getMemoryPath(projectPath) {
|
|
132
|
+
return getClaudeMemoryPath(projectPath);
|
|
41
133
|
}
|
|
42
134
|
function readMemory(memoryPath) {
|
|
43
135
|
if (!existsSync(memoryPath)) {
|
|
@@ -151,20 +243,43 @@ ${formattedContent}` : formattedContent;
|
|
|
151
243
|
console.log(a.green("\u2713 Memory replaced"));
|
|
152
244
|
}
|
|
153
245
|
}
|
|
154
|
-
async function syncMemory(
|
|
246
|
+
async function syncMemory(projectPath) {
|
|
155
247
|
console.log(a.cyan("\nSyncing memory with AutoMemoryBridge..."));
|
|
156
248
|
try {
|
|
157
|
-
const
|
|
158
|
-
|
|
159
|
-
|
|
249
|
+
const result = syncMemoryFiles({ projectPath });
|
|
250
|
+
if (result.source === "none") {
|
|
251
|
+
console.log(a.yellow("\u26A0 No memory content found in Claude or CCJK storage"));
|
|
252
|
+
console.log(a.gray(` Claude: ${result.paths.claude}`));
|
|
253
|
+
console.log(a.gray(` CCJK: ${result.paths.ccjk}`));
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
const sourceLabel = result.source === "already-synced" ? "Claude and CCJK memory" : `${result.source === "claude" ? "Claude" : "CCJK"} memory`;
|
|
257
|
+
const targetLabel = result.updatedTargets.length === 0 ? "already in sync" : `updated ${result.updatedTargets.map((target) => target === "claude" ? "Claude" : "CCJK").join(", ")}`;
|
|
258
|
+
console.log(a.green(`\u2713 Synced ${sourceLabel} (${targetLabel})`));
|
|
259
|
+
console.log(a.gray(` Claude: ${result.paths.claude}`));
|
|
260
|
+
console.log(a.gray(` CCJK: ${result.paths.ccjk}`));
|
|
261
|
+
if (result.parseMode === "structured") {
|
|
262
|
+
console.log(a.gray(
|
|
263
|
+
` Structured entries: ${result.entryCount} (facts ${result.factCount}, patterns ${result.patternCount}, decisions ${result.decisionCount})`
|
|
264
|
+
));
|
|
265
|
+
} else if (result.parseMode === "freeform") {
|
|
266
|
+
console.log(a.gray(" Synced freeform notes (no structured headings detected)"));
|
|
267
|
+
}
|
|
160
268
|
} catch (error) {
|
|
161
269
|
console.error(a.red("Failed to sync memory:"), error);
|
|
162
270
|
throw error;
|
|
163
271
|
}
|
|
164
272
|
}
|
|
165
273
|
async function memoryCommand(options) {
|
|
166
|
-
options.project || process.cwd();
|
|
167
274
|
const memoryPath = getMemoryPath(options.project);
|
|
275
|
+
if (options.status) {
|
|
276
|
+
await showMemoryStatus(options.project);
|
|
277
|
+
return;
|
|
278
|
+
}
|
|
279
|
+
if (options.doctor) {
|
|
280
|
+
await runMemoryDoctor(options.project);
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
168
283
|
if (options.view) {
|
|
169
284
|
const content = readMemory(memoryPath);
|
|
170
285
|
const title = options.project ? `Project Memory: ${options.project}` : "Global Memory";
|
|
@@ -188,6 +303,8 @@ async function memoryCommand(options) {
|
|
|
188
303
|
name: "action",
|
|
189
304
|
message: "What would you like to do?",
|
|
190
305
|
choices: [
|
|
306
|
+
{ name: "\u{1F4CA} Status", value: "status" },
|
|
307
|
+
{ name: "\u{1FA7A} Doctor", value: "doctor" },
|
|
191
308
|
{ name: "\u{1F441}\uFE0F View memory", value: "view" },
|
|
192
309
|
{ name: "\u270F\uFE0F Edit memory", value: "edit" },
|
|
193
310
|
{ name: "\u{1F504} Sync memory (AutoMemoryBridge)", value: "sync" },
|
|
@@ -197,6 +314,12 @@ async function memoryCommand(options) {
|
|
|
197
314
|
}
|
|
198
315
|
]);
|
|
199
316
|
switch (action) {
|
|
317
|
+
case "status":
|
|
318
|
+
await showMemoryStatus(options.project);
|
|
319
|
+
break;
|
|
320
|
+
case "doctor":
|
|
321
|
+
await runMemoryDoctor(options.project);
|
|
322
|
+
break;
|
|
200
323
|
case "view": {
|
|
201
324
|
const content = readMemory(memoryPath);
|
|
202
325
|
const title = options.project ? `Project Memory: ${options.project}` : "Global Memory";
|
|
@@ -21,7 +21,7 @@ import 'string_decoder';
|
|
|
21
21
|
import 'node:fs';
|
|
22
22
|
import 'node:url';
|
|
23
23
|
import '../shared/ccjk.bQ7Dh1g4.mjs';
|
|
24
|
-
import '../shared/ccjk.
|
|
24
|
+
import '../shared/ccjk.miT0g_vA.mjs';
|
|
25
25
|
import 'node:child_process';
|
|
26
26
|
import './constants.mjs';
|
|
27
27
|
import './banner.mjs';
|
|
@@ -81,7 +81,7 @@ import './uninstall.mjs';
|
|
|
81
81
|
import '../shared/ccjk.CvChMYvB.mjs';
|
|
82
82
|
import 'globby';
|
|
83
83
|
import './update.mjs';
|
|
84
|
-
import '../shared/ccjk.
|
|
84
|
+
import '../shared/ccjk.BOfPON0N.mjs';
|
|
85
85
|
|
|
86
86
|
function renderMenuHeader(context, _isZh) {
|
|
87
87
|
const title = context.breadcrumb.join(i18n.t("menu:menu.breadcrumb.separator"));
|