opencode-orchestrator 1.2.17 → 1.2.21

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.
@@ -1,7 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // scripts/postinstall.ts
4
- import { existsSync, mkdirSync, readFileSync, writeFileSync, appendFileSync } from "fs";
4
+ import { existsSync, mkdirSync, readFileSync, writeFileSync, appendFileSync, readdirSync } from "fs";
5
5
  import { homedir, tmpdir } from "os";
6
6
  import { join } from "path";
7
7
  var LOG_FILE = join(tmpdir(), "opencode-orchestrator.log");
@@ -57,74 +57,170 @@ function getConfigPaths() {
57
57
  }
58
58
  return paths;
59
59
  }
60
+ function createBackup(configFile) {
61
+ try {
62
+ if (!existsSync(configFile)) return true;
63
+ const backupFile = `${configFile}.backup.${Date.now()}`;
64
+ const content = readFileSync(configFile, "utf-8");
65
+ writeFileSync(backupFile, content);
66
+ log("Backup created", { backupFile });
67
+ return true;
68
+ } catch (err) {
69
+ log("Backup creation failed", { error: String(err) });
70
+ return false;
71
+ }
72
+ }
60
73
  function registerInConfig(configDir) {
61
74
  const configFile = join(configDir, "opencode.json");
62
75
  try {
63
76
  if (!existsSync(configDir)) {
64
77
  mkdirSync(configDir, { recursive: true });
78
+ log("Config directory created", { configDir });
65
79
  }
66
80
  let config = {};
81
+ let isNewFile = false;
67
82
  if (existsSync(configFile)) {
68
83
  try {
69
- config = JSON.parse(readFileSync(configFile, "utf-8"));
70
- } catch {
84
+ const content = readFileSync(configFile, "utf-8").trim();
85
+ if (!content) {
86
+ config = {};
87
+ log("Empty config file detected, creating new config");
88
+ } else {
89
+ config = JSON.parse(content);
90
+ log("Existing config loaded", { keys: Object.keys(config) });
91
+ }
92
+ } catch (parseErr) {
93
+ log("Config parse error, creating backup", { error: String(parseErr) });
94
+ createBackup(configFile);
71
95
  config = {};
72
96
  }
97
+ } else {
98
+ isNewFile = true;
99
+ log("No config file found, creating new");
73
100
  }
74
101
  if (!config.plugin) {
75
102
  config.plugin = [];
76
103
  }
77
- const hasPlugin = config.plugin.some(
78
- (p) => p.includes(PLUGIN_NAME)
79
- );
80
- if (!hasPlugin) {
81
- config.plugin.push(PLUGIN_NAME);
82
- writeFileSync(configFile, JSON.stringify(config, null, 2) + "\n");
83
- return true;
104
+ if (!Array.isArray(config.plugin)) {
105
+ log("Invalid plugin field (not array), resetting", { current: config.plugin });
106
+ config.plugin = [];
84
107
  }
85
- return false;
86
- } catch {
108
+ const hasPlugin = config.plugin.some((p) => {
109
+ if (typeof p !== "string") return false;
110
+ return p === PLUGIN_NAME || p.includes(PLUGIN_NAME);
111
+ });
112
+ if (hasPlugin) {
113
+ log("Plugin already registered", { plugins: config.plugin });
114
+ return false;
115
+ }
116
+ config.plugin.push(PLUGIN_NAME);
117
+ if (!config.$schema) {
118
+ config.$schema = "https://opencode.ai/config.json";
119
+ }
120
+ if (!isNewFile) {
121
+ createBackup(configFile);
122
+ }
123
+ const configContent = JSON.stringify(config, null, 2) + "\n";
124
+ writeFileSync(configFile, configContent, { encoding: "utf-8", mode: 420 });
125
+ log("Config written successfully", {
126
+ configFile,
127
+ isNewFile,
128
+ plugins: config.plugin,
129
+ allKeys: Object.keys(config)
130
+ });
131
+ return true;
132
+ } catch (err) {
133
+ log("registerInConfig failed", {
134
+ error: String(err),
135
+ code: err.code
136
+ });
87
137
  return false;
88
138
  }
89
139
  }
90
140
  try {
91
141
  console.log("\u{1F3AF} OpenCode Orchestrator - Installing...");
92
- log("Installation started", { platform: process.platform });
142
+ console.log("");
143
+ log("Installation started", { platform: process.platform, node: process.version });
93
144
  const configPaths = getConfigPaths();
94
145
  log("Config paths to check", configPaths);
95
146
  let registered = false;
96
147
  let alreadyRegistered = false;
148
+ let configsChecked = 0;
149
+ let registeredPath = "";
97
150
  for (const configDir of configPaths) {
98
151
  const configFile = join(configDir, "opencode.json");
152
+ configsChecked++;
99
153
  if (existsSync(configFile)) {
100
154
  try {
101
- const config = JSON.parse(readFileSync(configFile, "utf-8"));
102
- if (config.plugin?.some((p) => p.includes(PLUGIN_NAME))) {
103
- alreadyRegistered = true;
104
- continue;
155
+ const content = readFileSync(configFile, "utf-8").trim();
156
+ if (content) {
157
+ const config = JSON.parse(content);
158
+ if (config.plugin?.some((p) => p.includes(PLUGIN_NAME))) {
159
+ console.log(`\u2705 Already registered in: ${configFile}`);
160
+ log("Already registered", { configFile });
161
+ alreadyRegistered = true;
162
+ registeredPath = configFile;
163
+ continue;
164
+ }
105
165
  }
106
- } catch {
166
+ } catch (err) {
167
+ log("Parse error checking existing config", { configFile, error: String(err) });
107
168
  }
108
169
  }
109
170
  if (registerInConfig(configDir)) {
110
- console.log(`\u2705 Plugin registered: ${configFile}`);
171
+ console.log(`\u2705 Plugin registered in: ${configFile}`);
172
+ console.log(" \u{1F4DD} Your existing settings have been preserved");
173
+ try {
174
+ const files = readdirSync(configDir);
175
+ const hasBackup = files.some((f) => f.startsWith("opencode.json.backup."));
176
+ if (hasBackup) {
177
+ console.log(" \u{1F4BE} Backup created for safety");
178
+ }
179
+ } catch {
180
+ }
111
181
  log("Plugin registered successfully", { configFile });
112
182
  registered = true;
183
+ registeredPath = configFile;
184
+ break;
113
185
  }
114
186
  }
115
- if (!registered && alreadyRegistered) {
116
- console.log("\u2705 Plugin already registered.");
117
- log("Plugin was already registered");
118
- } else if (!registered) {
119
- console.log("\u26A0\uFE0F Could not register plugin in any config location.");
120
- log("Failed to register plugin in any location");
187
+ console.log("");
188
+ if (registered) {
189
+ console.log("\u2705 Installation successful!");
190
+ console.log(` Config file: ${registeredPath}`);
191
+ } else if (alreadyRegistered) {
192
+ console.log("\u2705 Plugin already installed!");
193
+ console.log(` Config file: ${registeredPath}`);
194
+ } else {
195
+ console.log("\u26A0\uFE0F Could not register plugin automatically.");
196
+ console.log("");
197
+ console.log(" Please manually add to your OpenCode config:");
198
+ console.log(` ${configPaths[0]}/opencode.json`);
199
+ console.log("");
200
+ console.log(" Add this line:");
201
+ console.log(` "plugin": ["${PLUGIN_NAME}"]`);
202
+ console.log("");
203
+ log("Failed to register plugin in any location", { configsChecked, paths: configPaths });
121
204
  }
122
205
  console.log("");
123
- console.log("\u{1F680} Ready! Restart OpenCode to use.");
206
+ console.log("\u{1F680} Next steps:");
207
+ console.log(" 1. Restart OpenCode");
208
+ console.log(" 2. Try /task command in your project");
124
209
  console.log("");
125
- log("Installation completed", { registered, alreadyRegistered });
210
+ log("Installation completed", {
211
+ registered,
212
+ alreadyRegistered,
213
+ configsChecked,
214
+ registeredPath
215
+ });
126
216
  } catch (error) {
127
- log("Installation error", { error: String(error) });
128
- console.error(formatError(error, "register plugin"));
217
+ console.log("");
218
+ console.error("\u274C Installation error:");
219
+ console.error(" " + formatError(error, "register plugin"));
220
+ console.log("");
221
+ console.log(" Please report this issue at:");
222
+ console.log(" https://github.com/agnusdei1207/opencode-orchestrator/issues");
223
+ console.log("");
224
+ log("Installation error", { error: String(error), stack: error instanceof Error ? error.stack : void 0 });
129
225
  process.exit(0);
130
226
  }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Hook events
3
+ */
4
+ export declare const HOOK_EVENTS: {
5
+ readonly PRE_TOOL: "hook.pre_tool";
6
+ readonly POST_TOOL: "hook.post_tool";
7
+ readonly CHAT: "hook.chat";
8
+ readonly DONE: "hook.done";
9
+ };
@@ -2,6 +2,10 @@
2
2
  * Combined Event Constants
3
3
  */
4
4
  export declare const EVENT_TYPES: {
5
+ readonly PRE_TOOL: "hook.pre_tool";
6
+ readonly POST_TOOL: "hook.post_tool";
7
+ readonly CHAT: "hook.chat";
8
+ readonly DONE: "hook.done";
5
9
  readonly WILDCARD: "*";
6
10
  readonly UPDATED: "message.updated";
7
11
  readonly COMPLETE: "mission.complete";
@@ -26,3 +30,4 @@ export * from "./document-events.js";
26
30
  export * from "./mission-events.js";
27
31
  export * from "./message-events.js";
28
32
  export * from "./special-events.js";
33
+ export * from "./hook-events.js";
@@ -27,14 +27,15 @@ export declare const PARALLEL_TASK: {
27
27
  * Worker and Reviewer are terminal nodes by design.
28
28
  */
29
29
  readonly TERMINAL_DEPTH: 2;
30
- readonly DEFAULT_CONCURRENCY: 3;
30
+ readonly CONCURRENCY: 5;
31
+ readonly DEFAULT_CONCURRENCY: 5;
31
32
  readonly MAX_CONCURRENCY: 5;
32
33
  readonly SYNC_TIMEOUT_MS: number;
33
- readonly POLL_INTERVAL_MS: 5000;
34
+ readonly POLL_INTERVAL_MS: 3000;
34
35
  readonly MIN_IDLE_TIME_MS: number;
35
36
  readonly MIN_STABILITY_MS: number;
36
37
  readonly STABLE_POLLS_REQUIRED: 2;
37
- readonly MAX_POLL_COUNT: 150;
38
+ readonly MAX_POLL_COUNT: 600;
38
39
  readonly SESSION_TITLE_PREFIX: "Parallel";
39
40
  readonly LABEL: "parallel";
40
41
  readonly GROUP_PREFIX: "parallel:";
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "opencode-orchestrator",
3
3
  "displayName": "OpenCode Orchestrator",
4
4
  "description": "Distributed Cognitive Architecture for OpenCode. Turns simple prompts into specialized multi-agent workflows (Planner, Coder, Reviewer).",
5
- "version": "1.2.17",
5
+ "version": "1.2.21",
6
6
  "author": "agnusdei1207",
7
7
  "license": "MIT",
8
8
  "repository": {