nia-opencode 0.1.6 → 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 -48
  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,72 +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).trim();
99
- let config;
100
- try {
101
- config = jsonContent ? JSON.parse(jsonContent) : {};
102
- } catch {
103
- console.error(" Failed to parse config file. Is it valid JSON?");
104
- console.error(" Try: echo '{}' > " + configPath);
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
+ `));
105
146
  return false;
106
147
  }
107
- const plugins = config.plugin || [];
108
- plugins.push(PLUGIN_NAME);
109
- config.plugin = plugins;
110
- if (configPath.endsWith(".jsonc")) {
111
- if (content.includes('"plugin"')) {
112
- const newContent = content.replace(/("plugin"\s*:\s*\[)([^\]]*?)(\])/, (_match, start, middle, end) => {
113
- const trimmed = middle.trim();
114
- if (trimmed === "") {
115
- return `${start}
116
- "${PLUGIN_NAME}"
117
- ${end}`;
118
- }
119
- return `${start}${middle.trimEnd()},
120
- "${PLUGIN_NAME}"
121
- ${end}`;
122
- });
123
- writeFileSync(configPath, newContent);
124
- } else {
125
- const newContent = content.replace(/^(\s*\{)/, `$1
126
- "plugin": ["${PLUGIN_NAME}"],`);
127
- writeFileSync(configPath, newContent);
128
- }
129
- } else {
130
- writeFileSync(configPath, JSON.stringify(config, null, 2));
131
- }
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);
132
155
  console.log(` Added plugin to ${configPath}`);
133
156
  return true;
134
157
  } catch (err) {
135
158
  console.error(" Failed to update config:", err);
159
+ console.error(" " + getManualInstallInstructions(apiKey).split(`
160
+ `).join(`
161
+ `));
136
162
  return false;
137
163
  }
138
164
  }
139
165
  function addMcpServerToConfig(configPath, apiKey) {
140
166
  try {
141
167
  const content = readFileSync(configPath, "utf-8");
142
- const jsonContent = stripJsoncComments(content).trim();
143
- let config;
144
- try {
145
- config = jsonContent ? JSON.parse(jsonContent) : {};
146
- } catch {
147
- console.error(" Failed to parse config file. Is it valid JSON?");
148
- console.error(" Try: echo '{}' > " + configPath);
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
+ `));
149
175
  return false;
150
176
  }
151
- const mcp = config.mcp || {};
177
+ const mcp = config?.mcp || {};
152
178
  if (mcp.nia) {
153
179
  console.log(" MCP server 'nia' already configured");
154
180
  return true;
155
181
  }
156
- mcp.nia = {
182
+ const niaMcpConfig = {
157
183
  type: "remote",
158
184
  url: "https://apigcp.trynia.ai/mcp",
159
185
  headers: {
@@ -161,12 +187,18 @@ function addMcpServerToConfig(configPath, apiKey) {
161
187
  },
162
188
  oauth: false
163
189
  };
164
- config.mcp = mcp;
165
- 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);
166
195
  console.log(" Added MCP server 'nia' to config");
167
196
  return true;
168
197
  } catch (err) {
169
198
  console.error(" Failed to add MCP server:", err);
199
+ console.error(" " + getManualInstallInstructions(apiKey).split(`
200
+ `).join(`
201
+ `));
170
202
  return false;
171
203
  }
172
204
  }
@@ -264,7 +296,7 @@ Step 3: Configure OpenCode`);
264
296
  if (options.tui && rl) {
265
297
  const shouldModify = await confirm(rl, `Modify ${configPath}?`);
266
298
  if (shouldModify) {
267
- addPluginToConfig(configPath);
299
+ addPluginToConfig(configPath, apiKey);
268
300
  if (apiKey) {
269
301
  addMcpServerToConfig(configPath, apiKey);
270
302
  }
@@ -272,7 +304,7 @@ Step 3: Configure OpenCode`);
272
304
  console.log(" Skipped.");
273
305
  }
274
306
  } else {
275
- addPluginToConfig(configPath);
307
+ addPluginToConfig(configPath, apiKey);
276
308
  if (apiKey) {
277
309
  addMcpServerToConfig(configPath, apiKey);
278
310
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nia-opencode",
3
- "version": "0.1.6",
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",