harnesstrim 0.0.3 → 0.0.4
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/cli.mjs +185 -80
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -22681,40 +22681,45 @@ function checkSkills(dir, findings) {
|
|
|
22681
22681
|
}
|
|
22682
22682
|
}
|
|
22683
22683
|
function checkOpenCode(dir, findings) {
|
|
22684
|
-
const
|
|
22685
|
-
if (
|
|
22684
|
+
const hasOpencodeProject = readIfExists(path.join(dir, "opencode.json")) !== null || fs.existsSync(path.join(dir, ".opencode"));
|
|
22685
|
+
if (!hasOpencodeProject) {
|
|
22686
22686
|
findings.push({
|
|
22687
22687
|
severity: "info",
|
|
22688
|
-
title: "No
|
|
22689
|
-
detail: "No
|
|
22688
|
+
title: "No OpenCode project config found",
|
|
22689
|
+
detail: "No opencode.json or .opencode/ in this directory."
|
|
22690
22690
|
});
|
|
22691
22691
|
return;
|
|
22692
22692
|
}
|
|
22693
|
-
|
|
22694
|
-
|
|
22695
|
-
|
|
22696
|
-
|
|
22697
|
-
|
|
22698
|
-
|
|
22699
|
-
|
|
22700
|
-
|
|
22701
|
-
}
|
|
22702
|
-
return;
|
|
22693
|
+
const wrapper = path.join(dir, ".opencode", "plugin", "harnesstrim.ts");
|
|
22694
|
+
const wrapperPresent = fs.existsSync(wrapper);
|
|
22695
|
+
const raw = readIfExists(path.join(dir, "opencode.json"));
|
|
22696
|
+
let staleEntry = false;
|
|
22697
|
+
if (raw !== null) {
|
|
22698
|
+
try {
|
|
22699
|
+
staleEntry = extractPluginNames(JSON.parse(raw)).some((p) => p.includes("@harnesstrim/adapter-opencode"));
|
|
22700
|
+
} catch {
|
|
22701
|
+
}
|
|
22703
22702
|
}
|
|
22704
|
-
|
|
22705
|
-
const installed = plugins.some((p) => p.includes("@harnesstrim/adapter-opencode"));
|
|
22706
|
-
if (installed) {
|
|
22703
|
+
if (wrapperPresent) {
|
|
22707
22704
|
findings.push({
|
|
22708
22705
|
severity: "ok",
|
|
22709
|
-
title: "HarnessTrim OpenCode adapter is
|
|
22710
|
-
detail: "
|
|
22706
|
+
title: "HarnessTrim OpenCode adapter is installed",
|
|
22707
|
+
detail: ".opencode/plugin/harnesstrim.ts loads the adapter (OpenCode auto-loads it)."
|
|
22711
22708
|
});
|
|
22712
22709
|
} else {
|
|
22713
22710
|
findings.push({
|
|
22714
22711
|
severity: "warn",
|
|
22715
|
-
title: "HarnessTrim adapter not installed
|
|
22712
|
+
title: "HarnessTrim adapter not installed for OpenCode",
|
|
22716
22713
|
detail: "The OpenCode adapter would slim tool output automatically.",
|
|
22717
|
-
suggestion: "Run `harnesstrim install opencode` to
|
|
22714
|
+
suggestion: "Run `harnesstrim install opencode --apply` to install the local plugin."
|
|
22715
|
+
});
|
|
22716
|
+
}
|
|
22717
|
+
if (staleEntry && !wrapperPresent) {
|
|
22718
|
+
findings.push({
|
|
22719
|
+
severity: "warn",
|
|
22720
|
+
title: "Stale adapter entry in opencode.json",
|
|
22721
|
+
detail: "opencode.json lists @harnesstrim/adapter-opencode, but OpenCode's plugin field is a string array and ignores option tuples \u2014 this entry never loaded.",
|
|
22722
|
+
suggestion: "Run `harnesstrim install opencode --apply` to migrate to the local plugin wrapper."
|
|
22718
22723
|
});
|
|
22719
22724
|
}
|
|
22720
22725
|
}
|
|
@@ -22741,70 +22746,151 @@ function inspect(dir) {
|
|
|
22741
22746
|
init_src();
|
|
22742
22747
|
import fs2 from "node:fs";
|
|
22743
22748
|
import path2 from "node:path";
|
|
22749
|
+
import { spawnSync } from "node:child_process";
|
|
22744
22750
|
var OPENCODE_PLUGIN_NAME = "@harnesstrim/adapter-opencode";
|
|
22745
|
-
|
|
22746
|
-
|
|
22747
|
-
|
|
22748
|
-
|
|
22751
|
+
var OPENCODE_ADAPTER_VERSION = "^0.0.2";
|
|
22752
|
+
var DEFAULT_OPENCODE_ADAPTER_CONFIG = {
|
|
22753
|
+
mode: "active",
|
|
22754
|
+
telemetry: true,
|
|
22755
|
+
telemetryPath: ".harnesstrim/metrics.jsonl"
|
|
22756
|
+
};
|
|
22757
|
+
var WRAPPER_REL = path2.join(".opencode", "plugin", "harnesstrim.ts");
|
|
22758
|
+
var PKG_REL = path2.join(".opencode", "package.json");
|
|
22759
|
+
var OPENCODE_JSON = "opencode.json";
|
|
22760
|
+
function buildOpencodeWrapper(adapterConfig) {
|
|
22761
|
+
const opts = JSON.stringify(adapterConfig, null, 2).replace(/\n/g, "\n ");
|
|
22762
|
+
return `// Generated by \`harnesstrim install opencode\`. Do not reference this plugin from
|
|
22763
|
+
// opencode.json \u2014 OpenCode's \`plugin\` field is a string array and cannot pass options,
|
|
22764
|
+
// so HarnessTrim options live here and OpenCode auto-loads this file from .opencode/plugin/.
|
|
22765
|
+
// The dependency is declared in ../package.json. Edit the options below freely.
|
|
22766
|
+
import { HarnessTrim } from "${OPENCODE_PLUGIN_NAME}";
|
|
22767
|
+
|
|
22768
|
+
export const HarnessTrimPlugin = async (input) =>
|
|
22769
|
+
HarnessTrim(input, ${opts});
|
|
22770
|
+
`;
|
|
22749
22771
|
}
|
|
22750
|
-
function
|
|
22751
|
-
|
|
22752
|
-
|
|
22753
|
-
|
|
22772
|
+
function buildOpencodePackageJson(existing) {
|
|
22773
|
+
let base = {};
|
|
22774
|
+
if (existing) {
|
|
22775
|
+
try {
|
|
22776
|
+
const parsed = JSON.parse(existing);
|
|
22777
|
+
if (parsed && typeof parsed === "object") base = parsed;
|
|
22778
|
+
} catch {
|
|
22779
|
+
}
|
|
22780
|
+
}
|
|
22781
|
+
const deps = { ...base.dependencies };
|
|
22782
|
+
deps[OPENCODE_PLUGIN_NAME] = OPENCODE_ADAPTER_VERSION;
|
|
22783
|
+
return JSON.stringify({ ...base, dependencies: deps }, null, 2) + "\n";
|
|
22784
|
+
}
|
|
22785
|
+
function opencodeJsonReferencesAdapter(config2) {
|
|
22786
|
+
const plugin = config2.plugin;
|
|
22787
|
+
if (!Array.isArray(plugin)) return false;
|
|
22788
|
+
return plugin.some((e) => {
|
|
22789
|
+
if (typeof e === "string") return e.includes(OPENCODE_PLUGIN_NAME);
|
|
22790
|
+
if (Array.isArray(e)) return typeof e[0] === "string" && e[0].includes(OPENCODE_PLUGIN_NAME);
|
|
22791
|
+
if (e && typeof e === "object") {
|
|
22792
|
+
const name = e.name;
|
|
22793
|
+
return typeof name === "string" && name.includes(OPENCODE_PLUGIN_NAME);
|
|
22794
|
+
}
|
|
22795
|
+
return false;
|
|
22796
|
+
});
|
|
22754
22797
|
}
|
|
22755
|
-
function
|
|
22756
|
-
|
|
22757
|
-
|
|
22758
|
-
|
|
22759
|
-
|
|
22760
|
-
|
|
22761
|
-
|
|
22762
|
-
|
|
22763
|
-
|
|
22764
|
-
|
|
22765
|
-
|
|
22766
|
-
|
|
22767
|
-
|
|
22768
|
-
|
|
22769
|
-
|
|
22770
|
-
|
|
22771
|
-
|
|
22772
|
-
|
|
22773
|
-
|
|
22774
|
-
|
|
22775
|
-
return {
|
|
22776
|
-
}
|
|
22777
|
-
function
|
|
22798
|
+
function cleanOpencodeJson(existing) {
|
|
22799
|
+
let config2;
|
|
22800
|
+
try {
|
|
22801
|
+
config2 = JSON.parse(existing);
|
|
22802
|
+
} catch {
|
|
22803
|
+
throw new Error(`${OPENCODE_JSON} exists but is not valid JSON`);
|
|
22804
|
+
}
|
|
22805
|
+
if (!opencodeJsonReferencesAdapter(config2)) return null;
|
|
22806
|
+
const plugin = config2.plugin.filter((e) => {
|
|
22807
|
+
if (typeof e === "string") return !e.includes(OPENCODE_PLUGIN_NAME);
|
|
22808
|
+
if (Array.isArray(e)) return !(typeof e[0] === "string" && e[0].includes(OPENCODE_PLUGIN_NAME));
|
|
22809
|
+
if (e && typeof e === "object") {
|
|
22810
|
+
const name = e.name;
|
|
22811
|
+
return !(typeof name === "string" && name.includes(OPENCODE_PLUGIN_NAME));
|
|
22812
|
+
}
|
|
22813
|
+
return true;
|
|
22814
|
+
});
|
|
22815
|
+
const next = { ...config2 };
|
|
22816
|
+
if (plugin.length === 0) delete next.plugin;
|
|
22817
|
+
else next.plugin = plugin;
|
|
22818
|
+
return { content: JSON.stringify(next, null, 2) + "\n" };
|
|
22819
|
+
}
|
|
22820
|
+
function planOpencodeInstall(input) {
|
|
22821
|
+
const adapterConfig = input.adapterConfig ?? DEFAULT_OPENCODE_ADAPTER_CONFIG;
|
|
22822
|
+
const wrapperContent = buildOpencodeWrapper(adapterConfig);
|
|
22823
|
+
const packageJsonContent = buildOpencodePackageJson(input.existingPackageJson);
|
|
22824
|
+
const opencodeClean = input.existingOpencodeJson ? cleanOpencodeJson(input.existingOpencodeJson) : null;
|
|
22825
|
+
const opencodeJsonContent = opencodeClean?.content ?? null;
|
|
22826
|
+
const wrapperChanged = input.existingWrapper !== wrapperContent;
|
|
22827
|
+
const pkgChanged = input.existingPackageJson !== packageJsonContent;
|
|
22828
|
+
const opencodeChanged = opencodeJsonContent !== null;
|
|
22829
|
+
const alreadyInstalled = input.existingWrapper !== null;
|
|
22830
|
+
const changed = wrapperChanged || pkgChanged || opencodeChanged;
|
|
22831
|
+
return { wrapperContent, packageJsonContent, opencodeJsonContent, alreadyInstalled, changed };
|
|
22832
|
+
}
|
|
22833
|
+
function runInstallOpencode(dir, apply, presetName, installDeps = true) {
|
|
22778
22834
|
let preset;
|
|
22779
|
-
let adapterConfig;
|
|
22835
|
+
let adapterConfig = { ...DEFAULT_OPENCODE_ADAPTER_CONFIG };
|
|
22780
22836
|
if (presetName) {
|
|
22781
22837
|
preset = getPreset(presetName);
|
|
22782
22838
|
if (!preset) throw new Error(`Unknown preset: ${presetName}`);
|
|
22783
|
-
adapterConfig = { ...preset.adapter };
|
|
22839
|
+
adapterConfig = { ...adapterConfig, ...preset.adapter };
|
|
22784
22840
|
}
|
|
22785
|
-
const
|
|
22786
|
-
|
|
22787
|
-
|
|
22788
|
-
|
|
22789
|
-
} catch {
|
|
22790
|
-
raw = null;
|
|
22791
|
-
}
|
|
22792
|
-
const existed = raw !== null;
|
|
22793
|
-
let config2 = {};
|
|
22794
|
-
if (raw !== null) {
|
|
22841
|
+
const wrapperPath = path2.join(dir, WRAPPER_REL);
|
|
22842
|
+
const packageJsonPath = path2.join(dir, PKG_REL);
|
|
22843
|
+
const opencodeJsonPath = path2.join(dir, OPENCODE_JSON);
|
|
22844
|
+
const readOrNull = (p) => {
|
|
22795
22845
|
try {
|
|
22796
|
-
|
|
22846
|
+
return fs2.readFileSync(p, "utf8");
|
|
22797
22847
|
} catch {
|
|
22798
|
-
|
|
22848
|
+
return null;
|
|
22799
22849
|
}
|
|
22800
|
-
}
|
|
22801
|
-
const
|
|
22850
|
+
};
|
|
22851
|
+
const existingWrapper = readOrNull(wrapperPath);
|
|
22852
|
+
const existingPackageJson = readOrNull(packageJsonPath);
|
|
22853
|
+
const existingOpencodeJson = readOrNull(opencodeJsonPath);
|
|
22854
|
+
const plan = planOpencodeInstall({
|
|
22855
|
+
existingWrapper,
|
|
22856
|
+
existingPackageJson,
|
|
22857
|
+
existingOpencodeJson,
|
|
22858
|
+
adapterConfig
|
|
22859
|
+
});
|
|
22802
22860
|
let applied = false;
|
|
22861
|
+
let depsInstalled = null;
|
|
22862
|
+
let depsMessage;
|
|
22803
22863
|
if (apply && plan.changed) {
|
|
22804
|
-
fs2.
|
|
22864
|
+
fs2.mkdirSync(path2.dirname(wrapperPath), { recursive: true });
|
|
22865
|
+
fs2.writeFileSync(wrapperPath, plan.wrapperContent);
|
|
22866
|
+
fs2.writeFileSync(packageJsonPath, plan.packageJsonContent);
|
|
22867
|
+
if (plan.opencodeJsonContent !== null) fs2.writeFileSync(opencodeJsonPath, plan.opencodeJsonContent);
|
|
22805
22868
|
applied = true;
|
|
22869
|
+
if (installDeps) {
|
|
22870
|
+
const npm = process.platform === "win32" ? "npm.cmd" : "npm";
|
|
22871
|
+
const res = spawnSync(npm, ["install", "--silent"], {
|
|
22872
|
+
cwd: path2.dirname(packageJsonPath),
|
|
22873
|
+
encoding: "utf8"
|
|
22874
|
+
});
|
|
22875
|
+
if (res.error || res.status !== 0) {
|
|
22876
|
+
depsInstalled = false;
|
|
22877
|
+
depsMessage = `Could not auto-install the adapter; run \`npm install\` in ${path2.dirname(packageJsonPath)}.`;
|
|
22878
|
+
} else {
|
|
22879
|
+
depsInstalled = true;
|
|
22880
|
+
}
|
|
22881
|
+
}
|
|
22806
22882
|
}
|
|
22807
|
-
return {
|
|
22883
|
+
return {
|
|
22884
|
+
...plan,
|
|
22885
|
+
wrapperPath,
|
|
22886
|
+
packageJsonPath,
|
|
22887
|
+
opencodeJsonPath,
|
|
22888
|
+
existed: existingWrapper !== null,
|
|
22889
|
+
applied,
|
|
22890
|
+
depsInstalled,
|
|
22891
|
+
depsMessage,
|
|
22892
|
+
preset
|
|
22893
|
+
};
|
|
22808
22894
|
}
|
|
22809
22895
|
|
|
22810
22896
|
// src/install-codex.ts
|
|
@@ -23256,7 +23342,7 @@ function runInstallPi(installDir, apply) {
|
|
|
23256
23342
|
// src/install-hermes.ts
|
|
23257
23343
|
import fs8 from "node:fs";
|
|
23258
23344
|
import path12 from "node:path";
|
|
23259
|
-
import { spawnSync } from "node:child_process";
|
|
23345
|
+
import { spawnSync as spawnSync2 } from "node:child_process";
|
|
23260
23346
|
|
|
23261
23347
|
// ../adapter-hermes/src/index.ts
|
|
23262
23348
|
import path11 from "node:path";
|
|
@@ -23323,7 +23409,7 @@ function runInstallHermes(installDir, apply) {
|
|
|
23323
23409
|
fs8.writeFileSync(path12.join(pluginDest, ".installed"), markerFileContent2());
|
|
23324
23410
|
copiedFiles.push(".installed");
|
|
23325
23411
|
applied = true;
|
|
23326
|
-
const enable =
|
|
23412
|
+
const enable = spawnSync2("hermes", ["plugins", "enable", HERMES_PLUGIN_NAME], {
|
|
23327
23413
|
encoding: "utf8"
|
|
23328
23414
|
});
|
|
23329
23415
|
if (enable.error) {
|
|
@@ -23389,19 +23475,38 @@ function renderDoctor(report) {
|
|
|
23389
23475
|
}
|
|
23390
23476
|
function renderInstall(result, apply) {
|
|
23391
23477
|
const lines = [];
|
|
23392
|
-
|
|
23393
|
-
|
|
23478
|
+
const wrapper = result.wrapperPath;
|
|
23479
|
+
const pkg = result.packageJsonPath;
|
|
23480
|
+
if (!result.changed) {
|
|
23481
|
+
lines.push(`Already installed and up to date: ${wrapper} loads the HarnessTrim adapter.`);
|
|
23482
|
+
if (result.preset) {
|
|
23483
|
+
lines.push("");
|
|
23484
|
+
lines.push(renderPresetAdvisory(result.preset));
|
|
23485
|
+
}
|
|
23394
23486
|
return lines.join("\n");
|
|
23395
23487
|
}
|
|
23396
23488
|
if (apply) {
|
|
23397
|
-
lines.push(`
|
|
23398
|
-
lines.push(
|
|
23399
|
-
}
|
|
23400
|
-
|
|
23489
|
+
lines.push(`Installed the OpenCode adapter as a local plugin:`);
|
|
23490
|
+
lines.push(` \u2022 wrote ${wrapper} (auto-loaded by OpenCode from .opencode/plugin/)`);
|
|
23491
|
+
lines.push(` \u2022 wrote ${pkg} (declares @harnesstrim/adapter-opencode)`);
|
|
23492
|
+
if (result.opencodeJsonContent !== null) {
|
|
23493
|
+
lines.push(` \u2022 cleaned the adapter entry out of ${result.opencodeJsonPath} (options live in the wrapper now)`);
|
|
23494
|
+
}
|
|
23495
|
+
if (result.depsInstalled === true) lines.push(` \u2022 installed the .opencode dependency`);
|
|
23496
|
+
else if (result.depsInstalled === false) lines.push(` ! ${result.depsMessage}`);
|
|
23401
23497
|
lines.push("");
|
|
23402
|
-
lines.push(
|
|
23498
|
+
lines.push("Reduction is active; telemetry writes to .harnesstrim/metrics.jsonl.");
|
|
23499
|
+
lines.push("Reload OpenCode so it loads the plugin, then check `harnesstrim metrics`.");
|
|
23500
|
+
} else {
|
|
23501
|
+
lines.push(`Dry run \u2014 no files changed. \`--apply\` would:`);
|
|
23502
|
+
lines.push(` \u2022 write ${wrapper} (local plugin wrapper with the adapter options)`);
|
|
23503
|
+
lines.push(` \u2022 write ${pkg} (declare @harnesstrim/adapter-opencode) and install it`);
|
|
23504
|
+
if (result.opencodeJsonContent !== null) {
|
|
23505
|
+
lines.push(` \u2022 remove the stale adapter entry from ${result.opencodeJsonPath}`);
|
|
23506
|
+
}
|
|
23403
23507
|
lines.push("");
|
|
23404
|
-
lines.push("
|
|
23508
|
+
lines.push("OpenCode's `plugin` config can't pass options, so the adapter is installed as a");
|
|
23509
|
+
lines.push("local plugin file instead. Re-run with `--apply` to write it.");
|
|
23405
23510
|
}
|
|
23406
23511
|
if (result.preset) {
|
|
23407
23512
|
lines.push("");
|