coding-friend-cli 1.17.4 → 1.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -3
- package/dist/chunk-7CAIGH2Y.js +365 -0
- package/dist/{chunk-UWQPMVJY.js → chunk-IRPW2BMP.js} +3 -1
- package/dist/{chunk-YC6MBHCT.js → chunk-JFGLNTZI.js} +13 -0
- package/dist/{chunk-DVMWMXDZ.js → chunk-NEQZP5D4.js} +31 -6
- package/dist/{chunk-KTX4MGMR.js → chunk-QMD7P67N.js} +24 -4
- package/dist/chunk-WEMDLEK5.js +331 -0
- package/dist/{config-HVWEV2K6.js → config-UQXY45DN.js} +85 -244
- package/dist/{dev-AZSOM775.js → dev-7DLYIXBO.js} +2 -2
- package/dist/{disable-R6K5YJN4.js → disable-XYZRE3TD.js} +1 -1
- package/dist/{enable-HF4PYVJN.js → enable-3NZBQWLQ.js} +1 -1
- package/dist/{host-SYZH3FVC.js → host-QDWBFJB2.js} +1 -1
- package/dist/index.js +42 -30
- package/dist/{init-73ECEDU7.js → init-ONUC6QMM.js} +220 -35
- package/dist/{install-USFLRCS5.js → install-HLCVBOXO.js} +3 -3
- package/dist/{mcp-TBEDYELW.js → mcp-GFIOFXOL.js} +1 -1
- package/dist/{memory-BQK2R7BV.js → memory-BL37DXPU.js} +141 -21
- package/dist/{permission-L2QQR5PO.js → permission-Z3LOBJ4X.js} +72 -11
- package/dist/postinstall.js +1 -1
- package/dist/{session-H4XW2WXH.js → session-JGRF5SNX.js} +1 -1
- package/dist/status-V324NM64.js +223 -0
- package/dist/{uninstall-QSNKGNHR.js → uninstall-NNCEKPIE.js} +2 -2
- package/dist/{update-PNHTIB6M.js → update-EVOGWLKX.js} +6 -2
- package/package.json +1 -1
- package/dist/chunk-56U7US6J.js +0 -198
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getLibPath
|
|
3
|
+
} from "./chunk-RZRT7NGT.js";
|
|
4
|
+
import {
|
|
5
|
+
BACK,
|
|
6
|
+
askScope,
|
|
7
|
+
formatScopeLabel,
|
|
8
|
+
injectBackChoice
|
|
9
|
+
} from "./chunk-C5LYVVEI.js";
|
|
10
|
+
import {
|
|
11
|
+
globalConfigPath,
|
|
12
|
+
localConfigPath,
|
|
13
|
+
mergeJson,
|
|
14
|
+
readJson
|
|
15
|
+
} from "./chunk-RWUTFVRB.js";
|
|
16
|
+
import {
|
|
17
|
+
log
|
|
18
|
+
} from "./chunk-W5CD7WTX.js";
|
|
19
|
+
|
|
20
|
+
// src/lib/memory-prompts.ts
|
|
21
|
+
import { confirm, input, select } from "@inquirer/prompts";
|
|
22
|
+
import { join } from "path";
|
|
23
|
+
function getMemoryFieldScope(field, globalCfg, localCfg) {
|
|
24
|
+
const globalSection = globalCfg?.memory;
|
|
25
|
+
const localSection = localCfg?.memory;
|
|
26
|
+
const inGlobal = globalSection?.[field] !== void 0;
|
|
27
|
+
const inLocal = localSection?.[field] !== void 0;
|
|
28
|
+
if (inGlobal && inLocal) return "both";
|
|
29
|
+
if (inGlobal) return "global";
|
|
30
|
+
if (inLocal) return "local";
|
|
31
|
+
return "-";
|
|
32
|
+
}
|
|
33
|
+
function getMergedMemoryValue(field, globalCfg, localCfg) {
|
|
34
|
+
const localSection = localCfg?.memory;
|
|
35
|
+
if (localSection?.[field] !== void 0) return localSection[field];
|
|
36
|
+
const globalSection = globalCfg?.memory;
|
|
37
|
+
return globalSection?.[field];
|
|
38
|
+
}
|
|
39
|
+
function writeMemoryField(scope, field, value) {
|
|
40
|
+
const targetPath = scope === "global" ? globalConfigPath() : localConfigPath();
|
|
41
|
+
const existingConfig = readJson(targetPath);
|
|
42
|
+
const existingSection = existingConfig?.memory ?? {};
|
|
43
|
+
const updated = { ...existingSection, [field]: value };
|
|
44
|
+
mergeJson(targetPath, { memory: updated });
|
|
45
|
+
log.success(`Saved to ${targetPath}`);
|
|
46
|
+
}
|
|
47
|
+
async function editMemoryTier(globalCfg, localCfg) {
|
|
48
|
+
const currentValue = getMergedMemoryValue("tier", globalCfg, localCfg);
|
|
49
|
+
if (currentValue) {
|
|
50
|
+
log.dim(`Current: ${currentValue}`);
|
|
51
|
+
}
|
|
52
|
+
const choice = await select({
|
|
53
|
+
message: "Memory search tier:",
|
|
54
|
+
choices: injectBackChoice(
|
|
55
|
+
[
|
|
56
|
+
{
|
|
57
|
+
name: "auto \u2014 detect best available (recommended)",
|
|
58
|
+
value: "auto"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
name: "full \u2014 SQLite + FTS5 + vector embeddings (Tier 1)",
|
|
62
|
+
value: "full"
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
name: "lite \u2014 MiniSearch daemon, in-memory BM25 + fuzzy (Tier 2)",
|
|
66
|
+
value: "lite"
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
name: "markdown \u2014 file-based substring search (Tier 3)",
|
|
70
|
+
value: "markdown"
|
|
71
|
+
}
|
|
72
|
+
],
|
|
73
|
+
"Back"
|
|
74
|
+
)
|
|
75
|
+
});
|
|
76
|
+
if (choice === BACK) return;
|
|
77
|
+
const scope = await askScope();
|
|
78
|
+
if (scope === "back") return;
|
|
79
|
+
writeMemoryField(scope, "tier", choice);
|
|
80
|
+
}
|
|
81
|
+
async function editMemoryAutoCapture(globalCfg, localCfg) {
|
|
82
|
+
const currentValue = getMergedMemoryValue(
|
|
83
|
+
"autoCapture",
|
|
84
|
+
globalCfg,
|
|
85
|
+
localCfg
|
|
86
|
+
);
|
|
87
|
+
if (currentValue !== void 0) {
|
|
88
|
+
log.dim(`Current: ${currentValue}`);
|
|
89
|
+
}
|
|
90
|
+
const value = await confirm({
|
|
91
|
+
message: "Auto-capture session context to memory on PreCompact (context window compression)?",
|
|
92
|
+
default: currentValue ?? false
|
|
93
|
+
});
|
|
94
|
+
const scope = await askScope();
|
|
95
|
+
if (scope === "back") return;
|
|
96
|
+
writeMemoryField(scope, "autoCapture", value);
|
|
97
|
+
}
|
|
98
|
+
async function editMemoryAutoStart(globalCfg, localCfg) {
|
|
99
|
+
const currentValue = getMergedMemoryValue(
|
|
100
|
+
"autoStart",
|
|
101
|
+
globalCfg,
|
|
102
|
+
localCfg
|
|
103
|
+
);
|
|
104
|
+
if (currentValue !== void 0) {
|
|
105
|
+
log.dim(`Current: ${currentValue}`);
|
|
106
|
+
}
|
|
107
|
+
const value = await confirm({
|
|
108
|
+
message: "Auto-start memory daemon when MCP server connects?",
|
|
109
|
+
default: currentValue ?? false
|
|
110
|
+
});
|
|
111
|
+
const scope = await askScope();
|
|
112
|
+
if (scope === "back") return;
|
|
113
|
+
writeMemoryField(scope, "autoStart", value);
|
|
114
|
+
}
|
|
115
|
+
async function editMemoryEmbedding(globalCfg, localCfg) {
|
|
116
|
+
const currentEmbedding = getMergedMemoryValue(
|
|
117
|
+
"embedding",
|
|
118
|
+
globalCfg,
|
|
119
|
+
localCfg
|
|
120
|
+
);
|
|
121
|
+
if (currentEmbedding) {
|
|
122
|
+
const parts = [`provider: ${currentEmbedding.provider ?? "transformers"}`];
|
|
123
|
+
if (currentEmbedding.model) parts.push(`model: ${currentEmbedding.model}`);
|
|
124
|
+
if (currentEmbedding.ollamaUrl)
|
|
125
|
+
parts.push(`url: ${currentEmbedding.ollamaUrl}`);
|
|
126
|
+
log.dim(`Current: ${parts.join(", ")}`);
|
|
127
|
+
}
|
|
128
|
+
const provider = await select({
|
|
129
|
+
message: "Embedding provider:",
|
|
130
|
+
choices: injectBackChoice(
|
|
131
|
+
[
|
|
132
|
+
{
|
|
133
|
+
name: "transformers \u2014 Transformers.js, runs in-process (no external deps)",
|
|
134
|
+
value: "transformers"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
name: "ollama \u2014 Local Ollama server (faster, GPU support, wider model selection)",
|
|
138
|
+
value: "ollama"
|
|
139
|
+
}
|
|
140
|
+
],
|
|
141
|
+
"Back"
|
|
142
|
+
)
|
|
143
|
+
});
|
|
144
|
+
if (provider === BACK) return;
|
|
145
|
+
let model;
|
|
146
|
+
let ollamaUrl;
|
|
147
|
+
if (provider === "ollama") {
|
|
148
|
+
ollamaUrl = await input({
|
|
149
|
+
message: "Ollama server URL:",
|
|
150
|
+
default: currentEmbedding?.ollamaUrl ?? "http://localhost:11434"
|
|
151
|
+
});
|
|
152
|
+
if (ollamaUrl === "http://localhost:11434") ollamaUrl = void 0;
|
|
153
|
+
const mcpDir = getLibPath("cf-memory");
|
|
154
|
+
try {
|
|
155
|
+
const { isOllamaRunning, hasOllamaEmbeddingModel } = await import(join(mcpDir, "dist/lib/ollama.js"));
|
|
156
|
+
const url = ollamaUrl ?? "http://localhost:11434";
|
|
157
|
+
const running = await isOllamaRunning(url);
|
|
158
|
+
if (!running) {
|
|
159
|
+
console.log();
|
|
160
|
+
log.warn("Ollama is not running at " + url);
|
|
161
|
+
log.dim(
|
|
162
|
+
"Install Ollama: https://ollama.ai \xB7 Docs: https://cf.dinhanhthi.com/cli/cf-memory"
|
|
163
|
+
);
|
|
164
|
+
console.log();
|
|
165
|
+
const fallback = await confirm({
|
|
166
|
+
message: "Fall back to Transformers.js instead?",
|
|
167
|
+
default: true
|
|
168
|
+
});
|
|
169
|
+
if (fallback) {
|
|
170
|
+
const scope2 = await askScope();
|
|
171
|
+
if (scope2 === "back") return;
|
|
172
|
+
writeMemoryField(scope2, "embedding", { provider: "transformers" });
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
model = await input({
|
|
177
|
+
message: "Ollama model name:",
|
|
178
|
+
default: currentEmbedding?.model ?? "all-minilm:l6-v2"
|
|
179
|
+
});
|
|
180
|
+
const hasModel = await hasOllamaEmbeddingModel(model, url);
|
|
181
|
+
if (!hasModel) {
|
|
182
|
+
console.log();
|
|
183
|
+
log.warn(`Model "${model}" not found in Ollama.`);
|
|
184
|
+
log.dim(`Pull it with: ollama pull ${model}`);
|
|
185
|
+
console.log();
|
|
186
|
+
const proceed = await confirm({
|
|
187
|
+
message: "Save this config anyway? (you can pull the model later)",
|
|
188
|
+
default: true
|
|
189
|
+
});
|
|
190
|
+
if (!proceed) return;
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
} catch {
|
|
194
|
+
model = await input({
|
|
195
|
+
message: "Ollama model name:",
|
|
196
|
+
default: currentEmbedding?.model ?? "all-minilm:l6-v2"
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
} else {
|
|
200
|
+
model = await input({
|
|
201
|
+
message: "Transformers.js model:",
|
|
202
|
+
default: currentEmbedding?.model ?? "Xenova/all-MiniLM-L6-v2"
|
|
203
|
+
});
|
|
204
|
+
if (model === "Xenova/all-MiniLM-L6-v2") model = void 0;
|
|
205
|
+
}
|
|
206
|
+
const scope = await askScope();
|
|
207
|
+
if (scope === "back") return;
|
|
208
|
+
const embedding = { provider };
|
|
209
|
+
if (model) embedding.model = model;
|
|
210
|
+
if (ollamaUrl) embedding.ollamaUrl = ollamaUrl;
|
|
211
|
+
writeMemoryField(scope, "embedding", embedding);
|
|
212
|
+
}
|
|
213
|
+
async function editMemoryDaemonTimeout(globalCfg, localCfg) {
|
|
214
|
+
const currentDaemon = getMergedMemoryValue("daemon", globalCfg, localCfg);
|
|
215
|
+
const currentMs = currentDaemon?.idleTimeout;
|
|
216
|
+
const currentMin = currentMs ? currentMs / 6e4 : void 0;
|
|
217
|
+
if (currentMin !== void 0) {
|
|
218
|
+
log.dim(`Current: ${currentMin} minutes`);
|
|
219
|
+
}
|
|
220
|
+
const value = await input({
|
|
221
|
+
message: "Daemon idle timeout (minutes):",
|
|
222
|
+
default: String(currentMin ?? 30),
|
|
223
|
+
validate: (val) => {
|
|
224
|
+
const n = Number(val);
|
|
225
|
+
if (isNaN(n) || n < 1) return "Must be a positive number";
|
|
226
|
+
return true;
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
const scope = await askScope();
|
|
230
|
+
if (scope === "back") return;
|
|
231
|
+
writeMemoryField(scope, "daemon", {
|
|
232
|
+
...currentDaemon,
|
|
233
|
+
idleTimeout: Number(value) * 6e4
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
async function memoryConfigMenu(opts) {
|
|
237
|
+
while (true) {
|
|
238
|
+
const globalCfg = readJson(globalConfigPath());
|
|
239
|
+
const localCfg = readJson(localConfigPath());
|
|
240
|
+
const tierScope = getMemoryFieldScope("tier", globalCfg, localCfg);
|
|
241
|
+
const tierVal = getMergedMemoryValue("tier", globalCfg, localCfg);
|
|
242
|
+
const autoCaptureScope = getMemoryFieldScope(
|
|
243
|
+
"autoCapture",
|
|
244
|
+
globalCfg,
|
|
245
|
+
localCfg
|
|
246
|
+
);
|
|
247
|
+
const autoCaptureVal = getMergedMemoryValue(
|
|
248
|
+
"autoCapture",
|
|
249
|
+
globalCfg,
|
|
250
|
+
localCfg
|
|
251
|
+
);
|
|
252
|
+
const autoStartScope = getMemoryFieldScope(
|
|
253
|
+
"autoStart",
|
|
254
|
+
globalCfg,
|
|
255
|
+
localCfg
|
|
256
|
+
);
|
|
257
|
+
const autoStartVal = getMergedMemoryValue(
|
|
258
|
+
"autoStart",
|
|
259
|
+
globalCfg,
|
|
260
|
+
localCfg
|
|
261
|
+
);
|
|
262
|
+
const embeddingScope = getMemoryFieldScope(
|
|
263
|
+
"embedding",
|
|
264
|
+
globalCfg,
|
|
265
|
+
localCfg
|
|
266
|
+
);
|
|
267
|
+
const embeddingVal = getMergedMemoryValue(
|
|
268
|
+
"embedding",
|
|
269
|
+
globalCfg,
|
|
270
|
+
localCfg
|
|
271
|
+
);
|
|
272
|
+
const daemonScope = getMemoryFieldScope("daemon", globalCfg, localCfg);
|
|
273
|
+
const daemonVal = getMergedMemoryValue("daemon", globalCfg, localCfg);
|
|
274
|
+
const embeddingLabel = embeddingVal?.provider ? embeddingVal.model ? `${embeddingVal.model} (${embeddingVal.provider})` : embeddingVal.provider : "";
|
|
275
|
+
const choice = await select({
|
|
276
|
+
message: "Memory settings:",
|
|
277
|
+
choices: injectBackChoice(
|
|
278
|
+
[
|
|
279
|
+
{
|
|
280
|
+
name: `Tier ${formatScopeLabel(tierScope)}${tierVal ? ` (${tierVal})` : ""}`,
|
|
281
|
+
value: "tier"
|
|
282
|
+
},
|
|
283
|
+
{
|
|
284
|
+
name: `Auto-capture ${formatScopeLabel(autoCaptureScope)}${autoCaptureVal !== void 0 ? ` (${autoCaptureVal})` : ""}`,
|
|
285
|
+
value: "autoCapture"
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
name: `Auto-start daemon ${formatScopeLabel(autoStartScope)}${autoStartVal !== void 0 ? ` (${autoStartVal})` : ""}`,
|
|
289
|
+
value: "autoStart"
|
|
290
|
+
},
|
|
291
|
+
{
|
|
292
|
+
name: `Embedding ${formatScopeLabel(embeddingScope)}${embeddingLabel ? ` (${embeddingLabel})` : ""}`,
|
|
293
|
+
value: "embedding"
|
|
294
|
+
},
|
|
295
|
+
{
|
|
296
|
+
name: `Daemon timeout ${formatScopeLabel(daemonScope)}${daemonVal?.idleTimeout ? ` (${daemonVal.idleTimeout / 6e4}min)` : ""}`,
|
|
297
|
+
value: "daemon"
|
|
298
|
+
}
|
|
299
|
+
],
|
|
300
|
+
opts?.exitLabel ?? "Back"
|
|
301
|
+
)
|
|
302
|
+
});
|
|
303
|
+
if (choice === BACK) return;
|
|
304
|
+
switch (choice) {
|
|
305
|
+
case "tier":
|
|
306
|
+
await editMemoryTier(globalCfg, localCfg);
|
|
307
|
+
break;
|
|
308
|
+
case "autoCapture":
|
|
309
|
+
await editMemoryAutoCapture(globalCfg, localCfg);
|
|
310
|
+
break;
|
|
311
|
+
case "autoStart":
|
|
312
|
+
await editMemoryAutoStart(globalCfg, localCfg);
|
|
313
|
+
break;
|
|
314
|
+
case "embedding":
|
|
315
|
+
await editMemoryEmbedding(globalCfg, localCfg);
|
|
316
|
+
break;
|
|
317
|
+
case "daemon":
|
|
318
|
+
await editMemoryDaemonTimeout(globalCfg, localCfg);
|
|
319
|
+
break;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export {
|
|
325
|
+
editMemoryTier,
|
|
326
|
+
editMemoryAutoCapture,
|
|
327
|
+
editMemoryAutoStart,
|
|
328
|
+
editMemoryEmbedding,
|
|
329
|
+
editMemoryDaemonTimeout,
|
|
330
|
+
memoryConfigMenu
|
|
331
|
+
};
|