opencode-immune 1.0.75 → 1.0.76
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/plugin/server.js +117 -2
- package/package.json +1 -1
package/dist/plugin/server.js
CHANGED
|
@@ -3777,7 +3777,7 @@ import { fileURLToPath } from "url";
|
|
|
3777
3777
|
import { createHash } from "crypto";
|
|
3778
3778
|
import { tmpdir } from "os";
|
|
3779
3779
|
import { execFile } from "child_process";
|
|
3780
|
-
var PLUGIN_VERSION = "1.0.
|
|
3780
|
+
var PLUGIN_VERSION = "1.0.76";
|
|
3781
3781
|
var PLUGIN_PACKAGE_NAME = "opencode-immune";
|
|
3782
3782
|
var PLUGIN_DIRNAME = dirname(fileURLToPath(import.meta.url));
|
|
3783
3783
|
function getServerAuthHeaders() {
|
|
@@ -5110,6 +5110,104 @@ async function fileHash(filePath) {
|
|
|
5110
5110
|
return "";
|
|
5111
5111
|
}
|
|
5112
5112
|
}
|
|
5113
|
+
function parseImmunePluginSpec(value) {
|
|
5114
|
+
const trimmed = value.trim();
|
|
5115
|
+
const match = trimmed.match(/^opencode-immune(?:@(.+))?$/);
|
|
5116
|
+
if (!match) return null;
|
|
5117
|
+
return {
|
|
5118
|
+
spec: trimmed,
|
|
5119
|
+
version: match[1] ?? null
|
|
5120
|
+
};
|
|
5121
|
+
}
|
|
5122
|
+
async function readProjectImmunePluginSpec(directory) {
|
|
5123
|
+
try {
|
|
5124
|
+
const raw = await readFile(join(directory, "opencode.json"), "utf-8");
|
|
5125
|
+
const config = JSON.parse(raw);
|
|
5126
|
+
const plugins = Array.isArray(config.plugin) ? config.plugin : [];
|
|
5127
|
+
for (let index = plugins.length - 1; index >= 0; index--) {
|
|
5128
|
+
const value = plugins[index];
|
|
5129
|
+
if (typeof value !== "string") continue;
|
|
5130
|
+
const parsed = parseImmunePluginSpec(value);
|
|
5131
|
+
if (parsed) return parsed;
|
|
5132
|
+
}
|
|
5133
|
+
} catch {
|
|
5134
|
+
}
|
|
5135
|
+
return null;
|
|
5136
|
+
}
|
|
5137
|
+
function execFileAsync(command, args, options) {
|
|
5138
|
+
return new Promise((resolve, reject) => {
|
|
5139
|
+
execFile(command, args, options ?? {}, (err, stdout, stderr) => {
|
|
5140
|
+
if (err) {
|
|
5141
|
+
reject(err);
|
|
5142
|
+
return;
|
|
5143
|
+
}
|
|
5144
|
+
resolve({ stdout, stderr });
|
|
5145
|
+
});
|
|
5146
|
+
});
|
|
5147
|
+
}
|
|
5148
|
+
async function clearProjectPluginOverride(directory) {
|
|
5149
|
+
const overridePath = join(directory, ".opencode", "opencode.json");
|
|
5150
|
+
try {
|
|
5151
|
+
const raw = await readFile(overridePath, "utf-8");
|
|
5152
|
+
const config = JSON.parse(raw);
|
|
5153
|
+
const keys = Object.keys(config ?? {});
|
|
5154
|
+
const plugins = Array.isArray(config.plugin) ? config.plugin : [];
|
|
5155
|
+
const isGeneratedVersionPin = plugins.length === 1 && typeof plugins[0] === "string" && /^opencode-immune@.+$/.test(plugins[0]) && keys.every((key) => key === "plugin" || key === "$schema");
|
|
5156
|
+
if (!isGeneratedVersionPin) {
|
|
5157
|
+
return false;
|
|
5158
|
+
}
|
|
5159
|
+
await unlink(overridePath);
|
|
5160
|
+
return true;
|
|
5161
|
+
} catch {
|
|
5162
|
+
return false;
|
|
5163
|
+
}
|
|
5164
|
+
}
|
|
5165
|
+
async function installPinnedProjectPlugin(state, pluginSpec) {
|
|
5166
|
+
if (!pluginSpec.version) return false;
|
|
5167
|
+
const currentVersion = await getPluginVersion();
|
|
5168
|
+
if (pluginSpec.version === currentVersion) {
|
|
5169
|
+
const overrideRemoved = await clearProjectPluginOverride(state.input.directory);
|
|
5170
|
+
if (overrideRemoved) {
|
|
5171
|
+
pluginLog.info(
|
|
5172
|
+
`[opencode-immune] Harness sync: removed stale local plugin override after confirming ${pluginSpec.spec}.`
|
|
5173
|
+
);
|
|
5174
|
+
}
|
|
5175
|
+
return false;
|
|
5176
|
+
}
|
|
5177
|
+
try {
|
|
5178
|
+
pluginLog.info(
|
|
5179
|
+
`[opencode-immune] Harness sync: installing ${pluginSpec.spec} in ${state.input.directory}`
|
|
5180
|
+
);
|
|
5181
|
+
await execFileAsync("opencode", ["plugin", pluginSpec.spec, "--force"], {
|
|
5182
|
+
cwd: state.input.directory,
|
|
5183
|
+
env: process.env
|
|
5184
|
+
});
|
|
5185
|
+
const overrideRemoved = await clearProjectPluginOverride(state.input.directory);
|
|
5186
|
+
if (overrideRemoved) {
|
|
5187
|
+
pluginLog.info(
|
|
5188
|
+
`[opencode-immune] Harness sync: removed local plugin override after installing ${pluginSpec.spec}.`
|
|
5189
|
+
);
|
|
5190
|
+
}
|
|
5191
|
+
state.pluginUpdateMessage = `[PLUGIN UPDATE] Harness synced this project to ${pluginSpec.spec}. Restart opencode to load the new plugin version.`;
|
|
5192
|
+
await writeDiagnosticLog(state, "harness-sync:plugin-install", {
|
|
5193
|
+
pluginSpec: pluginSpec.spec,
|
|
5194
|
+
status: "installed"
|
|
5195
|
+
});
|
|
5196
|
+
return true;
|
|
5197
|
+
} catch (err) {
|
|
5198
|
+
pluginLog.warn(
|
|
5199
|
+
`[opencode-immune] Harness sync: automatic install failed for ${pluginSpec.spec}.`,
|
|
5200
|
+
err instanceof Error ? err.message : String(err)
|
|
5201
|
+
);
|
|
5202
|
+
state.pluginUpdateMessage = `[PLUGIN UPDATE] Harness synced this project to ${pluginSpec.spec}, but automatic install failed. Run \`opencode plugin ${pluginSpec.spec} --force\` in this project, then restart opencode.`;
|
|
5203
|
+
await writeDiagnosticLog(state, "harness-sync:plugin-install", {
|
|
5204
|
+
pluginSpec: pluginSpec.spec,
|
|
5205
|
+
status: "failed",
|
|
5206
|
+
error: err instanceof Error ? err.message : String(err)
|
|
5207
|
+
});
|
|
5208
|
+
return false;
|
|
5209
|
+
}
|
|
5210
|
+
}
|
|
5113
5211
|
async function syncHarness(state) {
|
|
5114
5212
|
const token = await resolveEnvValue(state.input.directory, HARNESS_TOKEN_ENV);
|
|
5115
5213
|
if (!token) {
|
|
@@ -5160,19 +5258,36 @@ async function syncHarness(state) {
|
|
|
5160
5258
|
release.tagName + "\n",
|
|
5161
5259
|
"utf-8"
|
|
5162
5260
|
);
|
|
5261
|
+
const projectPluginSpec = await readProjectImmunePluginSpec(state.input.directory);
|
|
5262
|
+
const pluginInstalled = projectPluginSpec ? await installPinnedProjectPlugin(state, projectPluginSpec) : false;
|
|
5263
|
+
if (!projectPluginSpec) {
|
|
5264
|
+
const overrideRemoved = await clearProjectPluginOverride(state.input.directory);
|
|
5265
|
+
if (overrideRemoved) {
|
|
5266
|
+
pluginLog.info(
|
|
5267
|
+
`[opencode-immune] Harness sync: removed local plugin override to keep project config authoritative.`
|
|
5268
|
+
);
|
|
5269
|
+
}
|
|
5270
|
+
}
|
|
5163
5271
|
const hashAfter = await fileHash(configPath);
|
|
5164
5272
|
if (hashBefore && hashAfter && hashBefore !== hashAfter) {
|
|
5165
5273
|
pluginLog.warn(
|
|
5166
5274
|
`[opencode-immune] \u26A0 Harness sync: opencode.json was updated. Please restart opencode for the new agent configuration to take effect.`
|
|
5167
5275
|
);
|
|
5168
5276
|
}
|
|
5277
|
+
if (pluginInstalled) {
|
|
5278
|
+
pluginLog.warn(
|
|
5279
|
+
`[opencode-immune] \u26A0 Harness sync: installed updated plugin from project config. Restart opencode to load the new plugin code.`
|
|
5280
|
+
);
|
|
5281
|
+
}
|
|
5169
5282
|
pluginLog.info(
|
|
5170
5283
|
`[opencode-immune] Harness sync: successfully updated to ${release.tagName}`
|
|
5171
5284
|
);
|
|
5172
5285
|
await writeDiagnosticLog(state, "harness-sync:success", {
|
|
5173
5286
|
from: localVersion,
|
|
5174
5287
|
to: release.tagName,
|
|
5175
|
-
configChanged: hashBefore !== hashAfter
|
|
5288
|
+
configChanged: hashBefore !== hashAfter,
|
|
5289
|
+
pluginSpec: projectPluginSpec?.spec ?? null,
|
|
5290
|
+
pluginInstalled
|
|
5176
5291
|
});
|
|
5177
5292
|
} finally {
|
|
5178
5293
|
try {
|