nia-opencode 0.1.5 → 0.1.7

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/cli.js +80 -46
  2. package/package.json +4 -3
package/dist/cli.js CHANGED
@@ -5,6 +5,7 @@ import { mkdirSync, writeFileSync, readFileSync, existsSync } from "node:fs";
5
5
  import { join } from "node:path";
6
6
  import { homedir } from "node:os";
7
7
  import * as readline from "node:readline";
8
+ import * as jsonc from "jsonc-parser";
8
9
  var OPENCODE_CONFIG_DIR = join(homedir(), ".config", "opencode");
9
10
  var NIA_CONFIG_PATH = join(OPENCODE_CONFIG_DIR, "nia.json");
10
11
  var AGENTS_MD_PATH = join(OPENCODE_CONFIG_DIR, "AGENTS.md");
@@ -53,8 +54,48 @@ Before ANY WebFetch or WebSearch call, verify:
53
54
  - [ ] Confirmed no indexed source covers this information
54
55
  - [ ] For GitHub/npm/PyPI URLs: These should ALWAYS be indexed, not fetched
55
56
  `;
56
- function stripJsoncComments(content) {
57
- return content.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "");
57
+ function getManualInstallInstructions(apiKey) {
58
+ const sanitizedKey = apiKey || "nk_YOUR_API_KEY_HERE";
59
+ return `
60
+ Manual Installation Instructions
61
+ ================================
62
+
63
+ Add the following to your ~/.config/opencode/opencode.json (or opencode.jsonc):
64
+
65
+ 1. Plugin registration:
66
+ {
67
+ "plugin": ["nia-opencode@latest"]
68
+ }
69
+
70
+ 2. MCP server config:
71
+ {
72
+ "mcp": {
73
+ "nia": {
74
+ "type": "remote",
75
+ "url": "https://apigcp.trynia.ai/mcp",
76
+ "headers": {
77
+ "Authorization": "Bearer ${sanitizedKey}"
78
+ },
79
+ "oauth": false
80
+ }
81
+ }
82
+ }
83
+
84
+ Combined example (merge into your existing config):
85
+ {
86
+ "plugin": ["nia-opencode@latest"],
87
+ "mcp": {
88
+ "nia": {
89
+ "type": "remote",
90
+ "url": "https://apigcp.trynia.ai/mcp",
91
+ "headers": {
92
+ "Authorization": "Bearer ${sanitizedKey}"
93
+ },
94
+ "oauth": false
95
+ }
96
+ }
97
+ }
98
+ `;
58
99
  }
59
100
  function createReadline() {
60
101
  return readline.createInterface({
@@ -88,70 +129,57 @@ function findOpencodeConfig() {
88
129
  }
89
130
  return null;
90
131
  }
91
- function addPluginToConfig(configPath) {
132
+ function addPluginToConfig(configPath, apiKey) {
92
133
  try {
93
134
  const content = readFileSync(configPath, "utf-8");
94
135
  if (content.includes("nia-opencode")) {
95
136
  console.log(" Plugin already registered in config");
96
137
  return true;
97
138
  }
98
- const jsonContent = stripJsoncComments(content);
99
- let config;
100
- try {
101
- config = JSON.parse(jsonContent);
102
- } catch {
103
- console.error(" Failed to parse config file");
139
+ const errors = [];
140
+ const config = jsonc.parse(content, errors, { allowTrailingComma: true });
141
+ if (errors.length > 0) {
142
+ console.error(" Failed to parse config file (JSONC parse error).");
143
+ console.error(" " + getManualInstallInstructions(apiKey).split(`
144
+ `).join(`
145
+ `));
104
146
  return false;
105
147
  }
106
- const plugins = config.plugin || [];
107
- plugins.push(PLUGIN_NAME);
108
- config.plugin = plugins;
109
- if (configPath.endsWith(".jsonc")) {
110
- if (content.includes('"plugin"')) {
111
- const newContent = content.replace(/("plugin"\s*:\s*\[)([^\]]*?)(\])/, (_match, start, middle, end) => {
112
- const trimmed = middle.trim();
113
- if (trimmed === "") {
114
- return `${start}
115
- "${PLUGIN_NAME}"
116
- ${end}`;
117
- }
118
- return `${start}${middle.trimEnd()},
119
- "${PLUGIN_NAME}"
120
- ${end}`;
121
- });
122
- writeFileSync(configPath, newContent);
123
- } else {
124
- const newContent = content.replace(/^(\s*\{)/, `$1
125
- "plugin": ["${PLUGIN_NAME}"],`);
126
- writeFileSync(configPath, newContent);
127
- }
128
- } else {
129
- writeFileSync(configPath, JSON.stringify(config, null, 2));
130
- }
148
+ const plugins = config?.plugin || [];
149
+ const newPlugins = [...plugins, PLUGIN_NAME];
150
+ const edits = jsonc.modify(content, ["plugin"], newPlugins, {
151
+ formattingOptions: { tabSize: 2, insertSpaces: true }
152
+ });
153
+ const newContent = jsonc.applyEdits(content, edits);
154
+ writeFileSync(configPath, newContent);
131
155
  console.log(` Added plugin to ${configPath}`);
132
156
  return true;
133
157
  } catch (err) {
134
158
  console.error(" Failed to update config:", err);
159
+ console.error(" " + getManualInstallInstructions(apiKey).split(`
160
+ `).join(`
161
+ `));
135
162
  return false;
136
163
  }
137
164
  }
138
165
  function addMcpServerToConfig(configPath, apiKey) {
139
166
  try {
140
167
  const content = readFileSync(configPath, "utf-8");
141
- const jsonContent = stripJsoncComments(content);
142
- let config;
143
- try {
144
- config = JSON.parse(jsonContent);
145
- } catch {
146
- console.error(" Failed to parse config file");
168
+ const errors = [];
169
+ const config = jsonc.parse(content, errors, { allowTrailingComma: true });
170
+ if (errors.length > 0) {
171
+ console.error(" Failed to parse config file (JSONC parse error).");
172
+ console.error(" " + getManualInstallInstructions(apiKey).split(`
173
+ `).join(`
174
+ `));
147
175
  return false;
148
176
  }
149
- const mcp = config.mcp || {};
177
+ const mcp = config?.mcp || {};
150
178
  if (mcp.nia) {
151
179
  console.log(" MCP server 'nia' already configured");
152
180
  return true;
153
181
  }
154
- mcp.nia = {
182
+ const niaMcpConfig = {
155
183
  type: "remote",
156
184
  url: "https://apigcp.trynia.ai/mcp",
157
185
  headers: {
@@ -159,12 +187,18 @@ function addMcpServerToConfig(configPath, apiKey) {
159
187
  },
160
188
  oauth: false
161
189
  };
162
- config.mcp = mcp;
163
- writeFileSync(configPath, JSON.stringify(config, null, 2));
190
+ const edits = jsonc.modify(content, ["mcp", "nia"], niaMcpConfig, {
191
+ formattingOptions: { tabSize: 2, insertSpaces: true }
192
+ });
193
+ const newContent = jsonc.applyEdits(content, edits);
194
+ writeFileSync(configPath, newContent);
164
195
  console.log(" Added MCP server 'nia' to config");
165
196
  return true;
166
197
  } catch (err) {
167
198
  console.error(" Failed to add MCP server:", err);
199
+ console.error(" " + getManualInstallInstructions(apiKey).split(`
200
+ `).join(`
201
+ `));
168
202
  return false;
169
203
  }
170
204
  }
@@ -262,7 +296,7 @@ Step 3: Configure OpenCode`);
262
296
  if (options.tui && rl) {
263
297
  const shouldModify = await confirm(rl, `Modify ${configPath}?`);
264
298
  if (shouldModify) {
265
- addPluginToConfig(configPath);
299
+ addPluginToConfig(configPath, apiKey);
266
300
  if (apiKey) {
267
301
  addMcpServerToConfig(configPath, apiKey);
268
302
  }
@@ -270,7 +304,7 @@ Step 3: Configure OpenCode`);
270
304
  console.log(" Skipped.");
271
305
  }
272
306
  } else {
273
- addPluginToConfig(configPath);
307
+ addPluginToConfig(configPath, apiKey);
274
308
  if (apiKey) {
275
309
  addMcpServerToConfig(configPath, apiKey);
276
310
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nia-opencode",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "OpenCode plugin that integrates Nia Knowledge Agent for research and documentation",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -9,7 +9,7 @@
9
9
  "nia-opencode": "./dist/cli.js"
10
10
  },
11
11
  "scripts": {
12
- "build": "bun build ./src/index.ts --outdir ./dist --target node && bun build ./src/cli.ts --outfile ./dist/cli.js --target node && tsc --emitDeclarationOnly",
12
+ "build": "bun build ./src/index.ts --outdir ./dist --target node && bun build ./src/cli.ts --outfile ./dist/cli.js --target node --external jsonc-parser && tsc --emitDeclarationOnly",
13
13
  "dev": "tsc --watch",
14
14
  "typecheck": "tsc --noEmit"
15
15
  },
@@ -30,7 +30,8 @@
30
30
  "url": "https://github.com/nozomio-labs/nia-opencode"
31
31
  },
32
32
  "dependencies": {
33
- "@opencode-ai/plugin": "^1.0.162"
33
+ "@opencode-ai/plugin": "^1.0.162",
34
+ "jsonc-parser": "^3.3.1"
34
35
  },
35
36
  "devDependencies": {
36
37
  "@types/bun": "latest",