@mechanai/deepreview 2.1.2 → 2.1.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.
Files changed (2) hide show
  1. package/dist/setup.mjs +115 -0
  2. package/package.json +4 -1
package/dist/setup.mjs ADDED
@@ -0,0 +1,115 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/setup.ts
4
+ import {
5
+ existsSync,
6
+ lstatSync,
7
+ mkdirSync,
8
+ readdirSync,
9
+ symlinkSync,
10
+ unlinkSync,
11
+ readFileSync,
12
+ writeFileSync
13
+ } from "node:fs";
14
+ import path from "node:path";
15
+ import os from "node:os";
16
+ import { applyEdits, modify, parse as parseJsonc } from "jsonc-parser";
17
+ var PACKAGE_NAME = "@mechanai/deepreview";
18
+ var local = process.argv.includes("--local");
19
+ var cwd = process.cwd();
20
+ var globalConfigDir = path.join(process.env.XDG_CONFIG_HOME ?? path.join(os.homedir(), ".config"), "opencode");
21
+ var targetDir = local ? path.join(cwd, ".opencode") : globalConfigDir;
22
+ var packageDir = path.resolve(import.meta.dirname, "..");
23
+ var packageOpencode = path.join(packageDir, ".opencode");
24
+ function ensurePluginInConfig() {
25
+ const configFiles = ["opencode.jsonc", "opencode.json"];
26
+ const searchDir = local ? cwd : globalConfigDir;
27
+ let configPath;
28
+ for (const file of configFiles) {
29
+ const candidate = path.join(searchDir, file);
30
+ if (existsSync(candidate)) {
31
+ configPath = candidate;
32
+ break;
33
+ }
34
+ }
35
+ if (configPath === undefined) {
36
+ configPath = path.join(searchDir, "opencode.json");
37
+ mkdirSync(searchDir, { recursive: true });
38
+ writeFileSync(configPath, JSON.stringify({ plugin: [PACKAGE_NAME] }, null, 2) + `
39
+ `);
40
+ console.log(`Created ${configPath} with plugin entry.`);
41
+ return;
42
+ }
43
+ const raw = readFileSync(configPath, "utf-8");
44
+ let config;
45
+ try {
46
+ const parsed = parseJsonc(raw);
47
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
48
+ throw new Error("not an object");
49
+ }
50
+ config = parsed;
51
+ } catch {
52
+ console.error(`Could not parse ${configPath}. Add the plugin manually:`);
53
+ console.error(` "plugin": ["${PACKAGE_NAME}"]`);
54
+ process.exitCode = 1;
55
+ return;
56
+ }
57
+ const pluginArray = Array.isArray(config.plugin) ? config.plugin : [];
58
+ const plugins = pluginArray.filter((p) => typeof p === "string");
59
+ if (plugins.includes(PACKAGE_NAME)) {
60
+ console.log(`Plugin already registered in ${configPath}.`);
61
+ return;
62
+ }
63
+ const formatting = { formattingOptions: { insertSpaces: true, tabSize: 2 } };
64
+ const edits = Array.isArray(config.plugin) ? modify(raw, ["plugin", pluginArray.length], PACKAGE_NAME, formatting) : modify(raw, ["plugin"], [PACKAGE_NAME], formatting);
65
+ writeFileSync(configPath, applyEdits(raw, edits));
66
+ console.log(`Added "${PACKAGE_NAME}" to plugin array in ${configPath}.`);
67
+ }
68
+ function symlinkDirectory(kind) {
69
+ const sourceDir = path.join(packageOpencode, kind);
70
+ if (!existsSync(sourceDir))
71
+ return;
72
+ const destDir = path.join(targetDir, kind);
73
+ mkdirSync(destDir, { recursive: true });
74
+ const sourceFiles = new Set(readdirSync(sourceDir).filter((f) => f.endsWith(".md")));
75
+ let created = 0;
76
+ for (const file of readdirSync(destDir)) {
77
+ if (!file.startsWith("deepreview-") && !file.startsWith("_deepreview-"))
78
+ continue;
79
+ const dest = path.join(destDir, file);
80
+ try {
81
+ if (lstatSync(dest).isSymbolicLink() && !sourceFiles.has(file)) {
82
+ unlinkSync(dest);
83
+ }
84
+ } catch (err) {
85
+ if (err instanceof Error && !(("code" in err) && err.code === "ENOENT")) {
86
+ console.warn(`Could not check ${dest}: ${err.message}`);
87
+ }
88
+ }
89
+ }
90
+ for (const file of sourceFiles) {
91
+ const dest = path.join(destDir, file);
92
+ const source = path.relative(destDir, path.join(sourceDir, file));
93
+ try {
94
+ const stat = lstatSync(dest);
95
+ if (!stat.isSymbolicLink()) {
96
+ console.warn(`Skipping ${dest}: not a symlink (would overwrite regular file)`);
97
+ continue;
98
+ }
99
+ unlinkSync(dest);
100
+ } catch (err) {
101
+ if (err instanceof Error && "code" in err && err.code !== "ENOENT") {
102
+ throw err;
103
+ }
104
+ }
105
+ symlinkSync(source, dest);
106
+ created++;
107
+ }
108
+ const label = local ? `.opencode/${kind}/` : path.join(targetDir, kind) + "/";
109
+ console.log(`Linked ${created} ${kind} into ${label}`);
110
+ }
111
+ ensurePluginInConfig();
112
+ symlinkDirectory("agents");
113
+ symlinkDirectory("commands");
114
+ var scope = local ? "project" : "global";
115
+ console.log(`Done (${scope}). Run opencode to use /deepreview commands.`);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mechanai/deepreview",
3
- "version": "2.1.2",
3
+ "version": "2.1.3",
4
4
  "description": "Multi-agent parallel code/spec review for OpenCode",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -25,6 +25,9 @@
25
25
  "publishConfig": {
26
26
  "access": "public"
27
27
  },
28
+ "scripts": {
29
+ "prepare": "mise run build"
30
+ },
28
31
  "dependencies": {
29
32
  "gray-matter": "4.0.3",
30
33
  "js-yaml": "4.1.0",