oc-tweaks 0.11.2 → 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 +136 -3
- 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 = [
|
|
@@ -281,6 +308,90 @@ function formatDiagReport(report) {
|
|
|
281
308
|
}
|
|
282
309
|
if (false) {}
|
|
283
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
|
+
|
|
284
395
|
// src/cli/init.ts
|
|
285
396
|
var DEFAULT_CONFIG = {
|
|
286
397
|
notify: { enabled: true },
|
|
@@ -298,7 +409,7 @@ async function initConfig() {
|
|
|
298
409
|
return { created: false, path: configPath };
|
|
299
410
|
}
|
|
300
411
|
const json = JSON.stringify(DEFAULT_CONFIG, null, 2);
|
|
301
|
-
await
|
|
412
|
+
await mkdir2(dirname2(configPath), { recursive: true });
|
|
302
413
|
await Bun.write(configPath, json + `
|
|
303
414
|
`);
|
|
304
415
|
return { created: true, path: configPath };
|
|
@@ -310,6 +421,9 @@ function parseCliArgs(argv) {
|
|
|
310
421
|
if (args[0] === "memory" && args[1] === "diag") {
|
|
311
422
|
return { command: "memory-diag", opts: parseDiagOpts(args.slice(2)) };
|
|
312
423
|
}
|
|
424
|
+
if (args[0] === "memory" && args[1] === "migrate") {
|
|
425
|
+
return { command: "memory-migrate", opts: parseMigrateOpts(args.slice(2)) };
|
|
426
|
+
}
|
|
313
427
|
return { command: "init" };
|
|
314
428
|
}
|
|
315
429
|
function parseDiagOpts(args) {
|
|
@@ -325,12 +439,31 @@ function parseDiagOpts(args) {
|
|
|
325
439
|
}
|
|
326
440
|
return opts;
|
|
327
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
|
+
}
|
|
328
456
|
var isMain = typeof Bun !== "undefined" && Bun.main === import.meta.path;
|
|
329
457
|
if (isMain) {
|
|
330
458
|
const parsed = parseCliArgs(process.argv.slice(2));
|
|
331
459
|
if (parsed.command === "memory-diag") {
|
|
332
460
|
const report = await runDiag(parsed.opts);
|
|
333
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}`);
|
|
334
467
|
} else {
|
|
335
468
|
const result = await initConfig();
|
|
336
469
|
if (result.created) {
|