oc-tweaks 0.11.1 → 0.11.3
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/cli/init.js +138 -3
- package/dist/index.js +4 -1
- package/package.json +1 -1
package/dist/cli/init.js
CHANGED
|
@@ -2,8 +2,8 @@
|
|
|
2
2
|
// @bun
|
|
3
3
|
|
|
4
4
|
// src/cli/init.ts
|
|
5
|
-
import { mkdir } from "fs/promises";
|
|
6
|
-
import { dirname } from "path";
|
|
5
|
+
import { mkdir as mkdir2 } from "fs/promises";
|
|
6
|
+
import { dirname as dirname2 } from "path";
|
|
7
7
|
|
|
8
8
|
// src/plugins/auto-memory/diag.ts
|
|
9
9
|
import { statSync } from "node:fs";
|
|
@@ -103,6 +103,33 @@ function parseFrontmatter(raw) {
|
|
|
103
103
|
};
|
|
104
104
|
return { meta, body };
|
|
105
105
|
}
|
|
106
|
+
function serializeFrontmatter(meta, body) {
|
|
107
|
+
const lines = ["---"];
|
|
108
|
+
if (meta.id)
|
|
109
|
+
lines.push(`id: ${meta.id}`);
|
|
110
|
+
lines.push(`scope: ${meta.scope}`);
|
|
111
|
+
if (meta.type)
|
|
112
|
+
lines.push(`type: ${meta.type}`);
|
|
113
|
+
if (meta.source)
|
|
114
|
+
lines.push(`source: ${meta.source}`);
|
|
115
|
+
if (meta.created_at)
|
|
116
|
+
lines.push(`created_at: ${meta.created_at}`);
|
|
117
|
+
if (meta.updated_at)
|
|
118
|
+
lines.push(`updated_at: ${meta.updated_at}`);
|
|
119
|
+
lines.push(`trusted_as_instruction: false`);
|
|
120
|
+
if (meta.summary !== undefined)
|
|
121
|
+
lines.push(`summary: "${meta.summary}"`);
|
|
122
|
+
if (meta.disabled !== undefined)
|
|
123
|
+
lines.push(`disabled: ${meta.disabled ? "true" : "false"}`);
|
|
124
|
+
if (meta.usage_count !== undefined)
|
|
125
|
+
lines.push(`usage_count: ${meta.usage_count}`);
|
|
126
|
+
if (meta.last_usage !== undefined)
|
|
127
|
+
lines.push(`last_usage: ${meta.last_usage}`);
|
|
128
|
+
lines.push("---");
|
|
129
|
+
lines.push(body);
|
|
130
|
+
return lines.join(`
|
|
131
|
+
`);
|
|
132
|
+
}
|
|
106
133
|
|
|
107
134
|
// src/plugins/auto-memory/registry.ts
|
|
108
135
|
var SKIP_PATTERNS = [
|
|
@@ -169,6 +196,8 @@ function scanDir(dir, scope) {
|
|
|
169
196
|
continue;
|
|
170
197
|
}
|
|
171
198
|
const { meta, body } = parseFrontmatter(partial);
|
|
199
|
+
if (meta.disabled === true)
|
|
200
|
+
continue;
|
|
172
201
|
const summary = extractSummary(meta, body);
|
|
173
202
|
const tokenEstimate = Math.ceil((summary.length + JSON.stringify(meta).length) / 4);
|
|
174
203
|
const entry = {
|
|
@@ -279,6 +308,90 @@ function formatDiagReport(report) {
|
|
|
279
308
|
}
|
|
280
309
|
if (false) {}
|
|
281
310
|
|
|
311
|
+
// src/plugins/auto-memory/migrate.ts
|
|
312
|
+
import { mkdir, open, readdir, readFile, rename, unlink } from "node:fs/promises";
|
|
313
|
+
import { dirname, join as join3, resolve } from "node:path";
|
|
314
|
+
function detectScope(absRoot, override) {
|
|
315
|
+
if (override)
|
|
316
|
+
return override;
|
|
317
|
+
return absRoot.includes(`.opencode${"/"}memory`) || absRoot.includes(`.opencode${"\\"}memory`) ? "project" : "global";
|
|
318
|
+
}
|
|
319
|
+
function slugifyFilename(filename) {
|
|
320
|
+
return filename.replace(/\.md$/i, "").toLowerCase().replace(/[\s_]+/g, "-");
|
|
321
|
+
}
|
|
322
|
+
async function atomicWrite(absPath, content) {
|
|
323
|
+
const tmpfile = `${absPath}.tmp.${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
324
|
+
let tmpfileCreated = false;
|
|
325
|
+
try {
|
|
326
|
+
await mkdir(dirname(absPath), { recursive: true });
|
|
327
|
+
const handle = await open(tmpfile, "w");
|
|
328
|
+
try {
|
|
329
|
+
await handle.writeFile(content, "utf8");
|
|
330
|
+
await handle.sync();
|
|
331
|
+
} finally {
|
|
332
|
+
await handle.close();
|
|
333
|
+
}
|
|
334
|
+
tmpfileCreated = true;
|
|
335
|
+
await rename(tmpfile, absPath);
|
|
336
|
+
tmpfileCreated = false;
|
|
337
|
+
} finally {
|
|
338
|
+
if (tmpfileCreated) {
|
|
339
|
+
await unlink(tmpfile).catch(() => {});
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
async function migrate(opts) {
|
|
344
|
+
const absRoot = resolve(opts.root);
|
|
345
|
+
const scope = detectScope(absRoot, opts.scope);
|
|
346
|
+
const result = { migrated: [], skipped: [], errored: [] };
|
|
347
|
+
let filenames;
|
|
348
|
+
try {
|
|
349
|
+
filenames = await readdir(absRoot);
|
|
350
|
+
} catch {
|
|
351
|
+
return result;
|
|
352
|
+
}
|
|
353
|
+
for (const filename of filenames) {
|
|
354
|
+
if (!filename.endsWith(".md"))
|
|
355
|
+
continue;
|
|
356
|
+
const absPath = join3(absRoot, filename);
|
|
357
|
+
let raw;
|
|
358
|
+
try {
|
|
359
|
+
raw = await readFile(absPath, "utf8");
|
|
360
|
+
} catch (err) {
|
|
361
|
+
console.error(`[migrate] error reading ${filename}: ${err.message}`);
|
|
362
|
+
result.errored.push(filename);
|
|
363
|
+
continue;
|
|
364
|
+
}
|
|
365
|
+
const stripped = raw.startsWith("\uFEFF") ? raw.slice(1) : raw;
|
|
366
|
+
if (stripped.startsWith("---")) {
|
|
367
|
+
console.log(`[migrate] skip (has frontmatter): ${filename}`);
|
|
368
|
+
result.skipped.push(filename);
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
const now = new Date().toISOString();
|
|
372
|
+
const meta = {
|
|
373
|
+
id: slugifyFilename(filename),
|
|
374
|
+
scope,
|
|
375
|
+
type: "note",
|
|
376
|
+
source: "migrate",
|
|
377
|
+
created_at: now,
|
|
378
|
+
updated_at: now,
|
|
379
|
+
trusted_as_instruction: false
|
|
380
|
+
};
|
|
381
|
+
const newContent = serializeFrontmatter(meta, raw);
|
|
382
|
+
try {
|
|
383
|
+
await atomicWrite(absPath, newContent);
|
|
384
|
+
console.log(`[migrate] migrated: ${filename}`);
|
|
385
|
+
result.migrated.push(filename);
|
|
386
|
+
} catch (err) {
|
|
387
|
+
console.error(`[migrate] error writing ${filename}: ${err.message}`);
|
|
388
|
+
result.errored.push(filename);
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
return result;
|
|
392
|
+
}
|
|
393
|
+
if (false) {}
|
|
394
|
+
|
|
282
395
|
// src/cli/init.ts
|
|
283
396
|
var DEFAULT_CONFIG = {
|
|
284
397
|
notify: { enabled: true },
|
|
@@ -296,7 +409,7 @@ async function initConfig() {
|
|
|
296
409
|
return { created: false, path: configPath };
|
|
297
410
|
}
|
|
298
411
|
const json = JSON.stringify(DEFAULT_CONFIG, null, 2);
|
|
299
|
-
await
|
|
412
|
+
await mkdir2(dirname2(configPath), { recursive: true });
|
|
300
413
|
await Bun.write(configPath, json + `
|
|
301
414
|
`);
|
|
302
415
|
return { created: true, path: configPath };
|
|
@@ -308,6 +421,9 @@ function parseCliArgs(argv) {
|
|
|
308
421
|
if (args[0] === "memory" && args[1] === "diag") {
|
|
309
422
|
return { command: "memory-diag", opts: parseDiagOpts(args.slice(2)) };
|
|
310
423
|
}
|
|
424
|
+
if (args[0] === "memory" && args[1] === "migrate") {
|
|
425
|
+
return { command: "memory-migrate", opts: parseMigrateOpts(args.slice(2)) };
|
|
426
|
+
}
|
|
311
427
|
return { command: "init" };
|
|
312
428
|
}
|
|
313
429
|
function parseDiagOpts(args) {
|
|
@@ -323,12 +439,31 @@ function parseDiagOpts(args) {
|
|
|
323
439
|
}
|
|
324
440
|
return opts;
|
|
325
441
|
}
|
|
442
|
+
function parseMigrateOpts(args) {
|
|
443
|
+
const opts = { root: "" };
|
|
444
|
+
for (let i = 0;i < args.length; i++) {
|
|
445
|
+
const arg = args[i];
|
|
446
|
+
if (arg === "--root" && args[i + 1])
|
|
447
|
+
opts.root = args[++i];
|
|
448
|
+
else if (arg === "--scope" && args[i + 1]) {
|
|
449
|
+
const scope = args[++i];
|
|
450
|
+
if (scope === "global" || scope === "project")
|
|
451
|
+
opts.scope = scope;
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
return opts;
|
|
455
|
+
}
|
|
326
456
|
var isMain = typeof Bun !== "undefined" && Bun.main === import.meta.path;
|
|
327
457
|
if (isMain) {
|
|
328
458
|
const parsed = parseCliArgs(process.argv.slice(2));
|
|
329
459
|
if (parsed.command === "memory-diag") {
|
|
330
460
|
const report = await runDiag(parsed.opts);
|
|
331
461
|
console.log(formatDiagReport(report));
|
|
462
|
+
} else if (parsed.command === "memory-migrate") {
|
|
463
|
+
if (!parsed.opts.root)
|
|
464
|
+
throw new Error("--root <dir> is required");
|
|
465
|
+
const result = await migrate(parsed.opts);
|
|
466
|
+
console.log(`Summary: migrated=${result.migrated.length}, skipped=${result.skipped.length}, errored=${result.errored.length}`);
|
|
332
467
|
} else {
|
|
333
468
|
const result = await initConfig();
|
|
334
469
|
if (result.created) {
|
package/dist/index.js
CHANGED
|
@@ -931,7 +931,8 @@ async function recallMemory(query, registry, opts = {}) {
|
|
|
931
931
|
if (query.length === 0) {
|
|
932
932
|
return [{ id: NO_MATCH_SENTINEL_ID, content: NO_MATCH_SENTINEL_CONTENT }];
|
|
933
933
|
}
|
|
934
|
-
const
|
|
934
|
+
const enabledEntries = registry.filter((entry) => entry.meta.disabled !== true);
|
|
935
|
+
const typeCandidates = opts.filterType ? enabledEntries.filter((e) => e.meta.type === opts.filterType) : enabledEntries;
|
|
935
936
|
const candidates = opts.filterTags?.length ? typeCandidates.filter((entry) => {
|
|
936
937
|
const tags = entry.meta.tags;
|
|
937
938
|
return !tags || tags.some((tag) => opts.filterTags?.includes(tag));
|
|
@@ -1028,6 +1029,8 @@ function scanDir(dir, scope) {
|
|
|
1028
1029
|
continue;
|
|
1029
1030
|
}
|
|
1030
1031
|
const { meta, body } = parseFrontmatter(partial);
|
|
1032
|
+
if (meta.disabled === true)
|
|
1033
|
+
continue;
|
|
1031
1034
|
const summary = extractSummary(meta, body);
|
|
1032
1035
|
const tokenEstimate = Math.ceil((summary.length + JSON.stringify(meta).length) / 4);
|
|
1033
1036
|
const entry = {
|