@mutmutco/cli 2.50.0 → 2.51.0
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/main.cjs +221 -13
- package/package.json +1 -1
package/dist/main.cjs
CHANGED
|
@@ -15749,6 +15749,22 @@ function stageRequiredSecrets(stage2, meta) {
|
|
|
15749
15749
|
function stageKey(stage2, key) {
|
|
15750
15750
|
return key.includes("/") ? key : `${stage2}/${key}`;
|
|
15751
15751
|
}
|
|
15752
|
+
function materializedRuntimeSecretName(entry) {
|
|
15753
|
+
return entry.includes(":") ? entry.split(":").pop() : entry;
|
|
15754
|
+
}
|
|
15755
|
+
function runtimeSecretStreamGap(stage2, meta, presentSecrets) {
|
|
15756
|
+
const streamed = new Set(
|
|
15757
|
+
(contractByStage(meta.requiredRuntimeSecrets)[stage2] ?? []).map(materializedRuntimeSecretName)
|
|
15758
|
+
);
|
|
15759
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15760
|
+
const gap = [];
|
|
15761
|
+
for (const name of stageRequiredSecrets(stage2, meta).map(materializedRuntimeSecretName)) {
|
|
15762
|
+
if (seen.has(name)) continue;
|
|
15763
|
+
seen.add(name);
|
|
15764
|
+
if (!streamed.has(name) && presentSecrets.has(stageKey(stage2, name))) gap.push(name);
|
|
15765
|
+
}
|
|
15766
|
+
return gap;
|
|
15767
|
+
}
|
|
15752
15768
|
function hasRuntimeSecretContract(contract) {
|
|
15753
15769
|
if (!contract || typeof contract !== "object" || Array.isArray(contract)) return false;
|
|
15754
15770
|
return ["dev", "rc", "main"].some((stage2) => Array.isArray(contract[stage2]));
|
|
@@ -15990,6 +16006,11 @@ async function buildV2Doctor(repoOrSlug, deps) {
|
|
|
15990
16006
|
const missing = required.filter((key) => !presentSecrets.has(key));
|
|
15991
16007
|
return [stage2, { required, present, missing }];
|
|
15992
16008
|
}));
|
|
16009
|
+
const runtimeSecretStreamWarnings = Object.fromEntries(STAGES.map((stage2) => [
|
|
16010
|
+
stage2,
|
|
16011
|
+
stageInTrack(meta, stage2) ? runtimeSecretStreamGap(stage2, meta, presentSecrets) : []
|
|
16012
|
+
]));
|
|
16013
|
+
const runtimeSecretStreamWarningRows = STAGES.map((stage2) => ({ stage: stage2, names: runtimeSecretStreamWarnings[stage2] })).filter((row) => row.names.length > 0);
|
|
15993
16014
|
const metaMissing = ["class", "projectType", "deployModel", "vaultPath", "kbPointer"].filter((key) => meta[key] === void 0).concat(boardRegistryGaps(meta));
|
|
15994
16015
|
const ok = !secretsError && metaMissing.length === 0 && Object.values(deployCoords).every((v) => v.ok) && Object.values(secrets).every((v) => v.missing.length === 0);
|
|
15995
16016
|
const edgeDomainWarnings = deps.resolveDns ? await probeEdgeDomains(meta, deps.resolveDns) : [];
|
|
@@ -16005,6 +16026,7 @@ async function buildV2Doctor(repoOrSlug, deps) {
|
|
|
16005
16026
|
autoHealAvailable: Object.keys(autoHeal.patch),
|
|
16006
16027
|
appOwnedGaps: autoHeal.appOwnedGaps,
|
|
16007
16028
|
...edgeDomainWarnings.length ? { edgeDomainWarnings } : {},
|
|
16029
|
+
...runtimeSecretStreamWarningRows.length ? { runtimeSecretStreamWarnings: runtimeSecretStreamWarningRows } : {},
|
|
16008
16030
|
appAttested: appAttestationOf(meta) ?? void 0
|
|
16009
16031
|
};
|
|
16010
16032
|
}
|
|
@@ -16035,6 +16057,9 @@ function renderReadinessIssueBody(existingBody, report, opts = {}) {
|
|
|
16035
16057
|
...(report.edgeDomainWarnings ?? []).map(
|
|
16036
16058
|
(w) => `- \u26A0 edge domain does not resolve in DNS (advisory): ${w.stage} \u2192 ${w.host}; verify the registry edgeDomains value against the live public host`
|
|
16037
16059
|
),
|
|
16060
|
+
...(report.runtimeSecretStreamWarnings ?? []).map(
|
|
16061
|
+
(w) => `- \u26A0 required secrets provisioned but not in requiredRuntimeSecrets (advisory): ${w.stage} \u2192 ${w.names.join(", ")}; add them to the registry stream list or they will not be materialized into tenant.env`
|
|
16062
|
+
),
|
|
16038
16063
|
"",
|
|
16039
16064
|
"### Auto-heal applied / available",
|
|
16040
16065
|
...opts.healed?.length ? opts.healed.map((x) => `- ${x}`) : report.autoHealAvailable.map((x) => `- ${x}`),
|
|
@@ -18044,8 +18069,45 @@ var CLAUDE_RECOVERY = `claude plugin marketplace remove ${LEGACY_MMI_MARKETPLACE
|
|
|
18044
18069
|
var CODEX_RECOVERY = `codex plugin marketplace remove ${LEGACY_MMI_MARKETPLACE} && codex plugin marketplace remove mutmutco && codex plugin marketplace add mutmutco/MMI-Hub --ref main && codex plugin add mmi@mutmutco`;
|
|
18045
18070
|
var OPENCODE_PLUGIN_PACKAGE = "@mutmutco/opencode-mmi";
|
|
18046
18071
|
var OPENCODE_PLUGIN_SPEC = `${OPENCODE_PLUGIN_PACKAGE}@latest`;
|
|
18047
|
-
var OPENCODE_PLUGIN_INSTALL_COMMAND = `
|
|
18072
|
+
var OPENCODE_PLUGIN_INSTALL_COMMAND = `mmi-cli doctor --apply`;
|
|
18048
18073
|
var OPENCODE_RECOVERY = `${OPENCODE_PLUGIN_INSTALL_COMMAND} # then restart OpenCode to load MMI commands`;
|
|
18074
|
+
var OPENCODE_WORKFLOW_COMMANDS = [
|
|
18075
|
+
"mmi",
|
|
18076
|
+
"secrets",
|
|
18077
|
+
"stage",
|
|
18078
|
+
"rcand",
|
|
18079
|
+
"release",
|
|
18080
|
+
"hotfix",
|
|
18081
|
+
"bootstrap",
|
|
18082
|
+
"grind",
|
|
18083
|
+
"build",
|
|
18084
|
+
"handoff",
|
|
18085
|
+
"coop",
|
|
18086
|
+
"browser-automation"
|
|
18087
|
+
];
|
|
18088
|
+
function opencodeCommandDescription(command) {
|
|
18089
|
+
if (command === "mmi") return "Run the MMI work-board workflow.";
|
|
18090
|
+
if (command === "browser-automation") return "Run the MMI browser automation workflow.";
|
|
18091
|
+
return `Run the MMI ${command} workflow.`;
|
|
18092
|
+
}
|
|
18093
|
+
function opencodeCommandTemplate(command) {
|
|
18094
|
+
return [
|
|
18095
|
+
`Use the \`${command}\` skill and follow it exactly.`,
|
|
18096
|
+
"",
|
|
18097
|
+
"$ARGUMENTS"
|
|
18098
|
+
].join("\n");
|
|
18099
|
+
}
|
|
18100
|
+
function opencodeCommandMarkdown(command) {
|
|
18101
|
+
return [
|
|
18102
|
+
"---",
|
|
18103
|
+
`description: ${opencodeCommandDescription(command)}`,
|
|
18104
|
+
"agent: build",
|
|
18105
|
+
"---",
|
|
18106
|
+
"",
|
|
18107
|
+
opencodeCommandTemplate(command),
|
|
18108
|
+
""
|
|
18109
|
+
].join("\n");
|
|
18110
|
+
}
|
|
18049
18111
|
var PLUGIN_SURFACE_HEAL = {
|
|
18050
18112
|
claude: {
|
|
18051
18113
|
delivery: "plugin-cli",
|
|
@@ -18239,6 +18301,7 @@ function buildOpencodeVersionCheck(input) {
|
|
|
18239
18301
|
return { ...base, ok: false, installedVersion: input.installedVersion, releasedVersion: input.releasedVersion };
|
|
18240
18302
|
}
|
|
18241
18303
|
var OPENCODE_CONFIG_PLUGIN_LABEL = "OpenCode MMI adapter config wiring";
|
|
18304
|
+
var OPENCODE_SURFACE_ASSETS_LABEL = "OpenCode MMI commands and skills";
|
|
18242
18305
|
function opencodePluginEntryMatches(entry) {
|
|
18243
18306
|
return entry === OPENCODE_PLUGIN_PACKAGE || entry === OPENCODE_PLUGIN_SPEC || Array.isArray(entry) && (entry[0] === OPENCODE_PLUGIN_PACKAGE || entry[0] === OPENCODE_PLUGIN_SPEC);
|
|
18244
18307
|
}
|
|
@@ -18326,6 +18389,23 @@ function buildOpencodeConfigPluginCheck(input) {
|
|
|
18326
18389
|
}
|
|
18327
18390
|
return { ...base, configPath: input.configPath };
|
|
18328
18391
|
}
|
|
18392
|
+
function buildOpencodeSurfaceAssetsCheck(input) {
|
|
18393
|
+
const base = {
|
|
18394
|
+
ok: true,
|
|
18395
|
+
label: OPENCODE_SURFACE_ASSETS_LABEL,
|
|
18396
|
+
fix: OPENCODE_RECOVERY,
|
|
18397
|
+
configPath: input.configPath,
|
|
18398
|
+
commandsDir: input.commandsDir,
|
|
18399
|
+
skillsPath: input.skillsPath
|
|
18400
|
+
};
|
|
18401
|
+
if (!input.isOrgRepo) return base;
|
|
18402
|
+
const existing = new Set(input.existingCommands.map((c) => c.toLowerCase()));
|
|
18403
|
+
const missingCommands = OPENCODE_WORKFLOW_COMMANDS.filter((c) => !existing.has(c));
|
|
18404
|
+
const normalizedSkillsPath = input.skillsPath?.replace(/\\/g, "/");
|
|
18405
|
+
const hasSkillsPath = Boolean(normalizedSkillsPath && input.configuredSkillsPaths?.some((p) => p.replace(/\\/g, "/") === normalizedSkillsPath));
|
|
18406
|
+
if (!missingCommands.length && hasSkillsPath) return { ...base, hasSkillsPath };
|
|
18407
|
+
return { ...base, ok: false, missingCommands, hasSkillsPath };
|
|
18408
|
+
}
|
|
18329
18409
|
var OPENCODE_DESKTOP_BOOTSTRAP_LABEL = "OpenCode Desktop stale project bootstrap";
|
|
18330
18410
|
var OPENCODE_DESKTOP_BOOTSTRAP_FIX = "OpenCode Desktop is bootstrapping a deleted MMI worktree; open an existing checkout in OpenCode, remove/select away from the stale project entry, then restart OpenCode";
|
|
18331
18411
|
function decodeLogUrlDirectory(value) {
|
|
@@ -19084,8 +19164,17 @@ function backupAndWriteInstalledPlugins(records, pluginId) {
|
|
|
19084
19164
|
return false;
|
|
19085
19165
|
}
|
|
19086
19166
|
}
|
|
19167
|
+
function opencodeConfigDir() {
|
|
19168
|
+
return (0, import_node_path22.join)((0, import_node_os5.homedir)(), ".config", "opencode");
|
|
19169
|
+
}
|
|
19087
19170
|
function opencodeConfigPath() {
|
|
19088
|
-
return (0, import_node_path22.join)((
|
|
19171
|
+
return (0, import_node_path22.join)(opencodeConfigDir(), "opencode.jsonc");
|
|
19172
|
+
}
|
|
19173
|
+
function opencodeCommandsDir() {
|
|
19174
|
+
return (0, import_node_path22.join)(opencodeConfigDir(), "commands");
|
|
19175
|
+
}
|
|
19176
|
+
function opencodeSkillsPath() {
|
|
19177
|
+
return (0, import_node_path22.join)(opencodeConfigDir(), "node_modules", "@mutmutco", "opencode-mmi", "skills");
|
|
19089
19178
|
}
|
|
19090
19179
|
function opencodeConfigSnapshot() {
|
|
19091
19180
|
const path2 = opencodeConfigPath();
|
|
@@ -19094,12 +19183,14 @@ function opencodeConfigSnapshot() {
|
|
|
19094
19183
|
const raw = (0, import_node_fs26.readFileSync)(path2, "utf8");
|
|
19095
19184
|
const parsed = JSON.parse(stripJsonc(raw));
|
|
19096
19185
|
const hasPluginField = Object.prototype.hasOwnProperty.call(parsed, "plugin");
|
|
19186
|
+
const skillsPaths = Array.isArray(parsed.skills?.paths) ? parsed.skills.paths.filter((p) => typeof p === "string") : void 0;
|
|
19097
19187
|
return {
|
|
19098
19188
|
path: path2,
|
|
19099
19189
|
hasConfig: true,
|
|
19100
19190
|
hasPluginField,
|
|
19101
19191
|
parseOk: true,
|
|
19102
19192
|
raw,
|
|
19193
|
+
...skillsPaths ? { skillsPaths } : {},
|
|
19103
19194
|
...Array.isArray(parsed.plugin) ? { pluginEntries: parsed.plugin } : parsed.plugin === void 0 ? {} : { pluginEntries: void 0 }
|
|
19104
19195
|
};
|
|
19105
19196
|
} catch {
|
|
@@ -19120,6 +19211,79 @@ function writeOpencodeConfigPlugin(snapshot) {
|
|
|
19120
19211
|
return false;
|
|
19121
19212
|
}
|
|
19122
19213
|
}
|
|
19214
|
+
function writeOpencodeSkillsPath(snapshot, skillsPath) {
|
|
19215
|
+
try {
|
|
19216
|
+
const raw = snapshot.hasConfig ? snapshot.raw : void 0;
|
|
19217
|
+
const parsed = raw ? JSON.parse(stripJsonc(raw)) : { $schema: "https://opencode.ai/config.json" };
|
|
19218
|
+
const skills = parsed.skills && typeof parsed.skills === "object" && !Array.isArray(parsed.skills) ? parsed.skills : {};
|
|
19219
|
+
const paths = Array.isArray(skills.paths) ? skills.paths.filter((p) => typeof p === "string") : [];
|
|
19220
|
+
const normalized = skillsPath.replace(/\\/g, "/");
|
|
19221
|
+
if (!paths.some((p) => p.replace(/\\/g, "/") === normalized)) paths.push(skillsPath.replace(/\\/g, "/"));
|
|
19222
|
+
parsed.skills = { ...skills, paths };
|
|
19223
|
+
(0, import_node_fs26.mkdirSync)((0, import_node_path22.dirname)(snapshot.path), { recursive: true });
|
|
19224
|
+
if (snapshot.hasConfig && (0, import_node_fs26.existsSync)(snapshot.path)) (0, import_node_fs26.copyFileSync)(snapshot.path, `${snapshot.path}.bak`);
|
|
19225
|
+
(0, import_node_fs26.writeFileSync)(snapshot.path, `${JSON.stringify(parsed, null, 2)}
|
|
19226
|
+
`, "utf8");
|
|
19227
|
+
return true;
|
|
19228
|
+
} catch {
|
|
19229
|
+
return false;
|
|
19230
|
+
}
|
|
19231
|
+
}
|
|
19232
|
+
function opencodeExistingCommands() {
|
|
19233
|
+
try {
|
|
19234
|
+
return (0, import_node_fs26.readdirSync)(opencodeCommandsDir(), { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".md")).map((entry) => entry.name.slice(0, -3).toLowerCase());
|
|
19235
|
+
} catch {
|
|
19236
|
+
return [];
|
|
19237
|
+
}
|
|
19238
|
+
}
|
|
19239
|
+
function writeOpencodeCommandFiles() {
|
|
19240
|
+
try {
|
|
19241
|
+
const dir = opencodeCommandsDir();
|
|
19242
|
+
(0, import_node_fs26.mkdirSync)(dir, { recursive: true });
|
|
19243
|
+
for (const command of OPENCODE_WORKFLOW_COMMANDS) {
|
|
19244
|
+
(0, import_node_fs26.writeFileSync)((0, import_node_path22.join)(dir, `${command}.md`), opencodeCommandMarkdown(command), "utf8");
|
|
19245
|
+
}
|
|
19246
|
+
return true;
|
|
19247
|
+
} catch {
|
|
19248
|
+
return false;
|
|
19249
|
+
}
|
|
19250
|
+
}
|
|
19251
|
+
function readOpencodeAdapterDiskVersion() {
|
|
19252
|
+
const candidates = [
|
|
19253
|
+
(0, import_node_path22.join)(opencodeConfigDir(), "node_modules", "@mutmutco", "opencode-mmi", "package.json"),
|
|
19254
|
+
(0, import_node_path22.join)((0, import_node_os5.homedir)(), ".cache", "opencode", "node_modules", "@mutmutco", "opencode-mmi", "package.json")
|
|
19255
|
+
];
|
|
19256
|
+
for (const path2 of candidates) {
|
|
19257
|
+
try {
|
|
19258
|
+
const parsed = JSON.parse((0, import_node_fs26.readFileSync)(path2, "utf8"));
|
|
19259
|
+
if (typeof parsed.version === "string" && parsed.version.trim()) return parsed.version.trim();
|
|
19260
|
+
} catch {
|
|
19261
|
+
continue;
|
|
19262
|
+
}
|
|
19263
|
+
}
|
|
19264
|
+
return void 0;
|
|
19265
|
+
}
|
|
19266
|
+
function opencodeMmiPluginSpecs(snapshot) {
|
|
19267
|
+
const specs = (snapshot.pluginEntries ?? []).map((entry) => Array.isArray(entry) ? entry[0] : entry).filter((entry) => typeof entry === "string").filter((entry) => entry === OPENCODE_PLUGIN_PACKAGE || entry === OPENCODE_PLUGIN_SPEC || entry.startsWith("@mutmutco/"));
|
|
19268
|
+
return Array.from(new Set(specs.length ? specs : [OPENCODE_PLUGIN_SPEC]));
|
|
19269
|
+
}
|
|
19270
|
+
async function forceInstallOpencodeMmiPlugins(snapshot, log) {
|
|
19271
|
+
try {
|
|
19272
|
+
const specs = opencodeMmiPluginSpecs(snapshot);
|
|
19273
|
+
log(` \u21BB force-refreshing OpenCode MMI npm plugin(s): ${specs.join(", ")}\u2026`);
|
|
19274
|
+
(0, import_node_fs26.mkdirSync)(opencodeConfigDir(), { recursive: true });
|
|
19275
|
+
await runHostBin("npm", ["install", "--prefix", opencodeConfigDir(), "--force", ...specs], { timeout: NPM_UPDATE_TIMEOUT_MS });
|
|
19276
|
+
return true;
|
|
19277
|
+
} catch {
|
|
19278
|
+
return false;
|
|
19279
|
+
}
|
|
19280
|
+
}
|
|
19281
|
+
function opencodeInstalledVersionForDoctor() {
|
|
19282
|
+
return process.env.MMI_OPENCODE_PLUGIN_VERSION || readOpencodeAdapterDiskVersion();
|
|
19283
|
+
}
|
|
19284
|
+
function opencodePluginVersionsForReport() {
|
|
19285
|
+
return [process.env.MMI_OPENCODE_PLUGIN_VERSION, readOpencodeAdapterDiskVersion()].filter((v) => Boolean(v));
|
|
19286
|
+
}
|
|
19123
19287
|
function opencodeDesktopLogsRoot() {
|
|
19124
19288
|
if (process.platform === "win32") {
|
|
19125
19289
|
const base = process.env.APPDATA || (0, import_node_path22.join)((0, import_node_os5.homedir)(), "AppData", "Roaming");
|
|
@@ -19598,7 +19762,7 @@ async function runDoctor(opts, io = consoleIo) {
|
|
|
19598
19762
|
}
|
|
19599
19763
|
}
|
|
19600
19764
|
checks.push(installedVersionCheck);
|
|
19601
|
-
|
|
19765
|
+
let openCodeConfigSnapshot = opencodeConfigSnapshot();
|
|
19602
19766
|
const inspectOpenCode = surface === "opencode" || openCodeConfigSnapshot.hasConfig || runExtended;
|
|
19603
19767
|
if (inspectOpenCode) {
|
|
19604
19768
|
let opencodeConfigCheck = buildOpencodeConfigPluginCheck({
|
|
@@ -19611,14 +19775,14 @@ async function runDoctor(opts, io = consoleIo) {
|
|
|
19611
19775
|
});
|
|
19612
19776
|
if (!opencodeConfigCheck.ok && opencodeConfigCheck.reason !== "unreadable-config" && opencodeConfigCheck.reason !== "invalid-plugin-shape" && repairLocal) {
|
|
19613
19777
|
if (writeOpencodeConfigPlugin(openCodeConfigSnapshot)) {
|
|
19614
|
-
|
|
19778
|
+
openCodeConfigSnapshot = opencodeConfigSnapshot();
|
|
19615
19779
|
opencodeConfigCheck = buildOpencodeConfigPluginCheck({
|
|
19616
19780
|
isOrgRepo: Boolean(cfg.sagaApiUrl),
|
|
19617
|
-
configPath:
|
|
19618
|
-
hasConfig:
|
|
19619
|
-
hasPluginField:
|
|
19620
|
-
pluginEntries:
|
|
19621
|
-
parseOk:
|
|
19781
|
+
configPath: openCodeConfigSnapshot.path,
|
|
19782
|
+
hasConfig: openCodeConfigSnapshot.hasConfig,
|
|
19783
|
+
hasPluginField: openCodeConfigSnapshot.hasPluginField,
|
|
19784
|
+
pluginEntries: openCodeConfigSnapshot.pluginEntries,
|
|
19785
|
+
parseOk: openCodeConfigSnapshot.parseOk
|
|
19622
19786
|
});
|
|
19623
19787
|
if (opencodeConfigCheck.ok) {
|
|
19624
19788
|
markPluginReloadRequired();
|
|
@@ -19627,11 +19791,55 @@ async function runDoctor(opts, io = consoleIo) {
|
|
|
19627
19791
|
}
|
|
19628
19792
|
}
|
|
19629
19793
|
checks.push(opencodeConfigCheck);
|
|
19630
|
-
|
|
19794
|
+
let opencodeInstalledVersion = opencodeInstalledVersionForDoctor();
|
|
19795
|
+
let opencodeVersionCheck = buildOpencodeVersionCheck({
|
|
19631
19796
|
isOrgRepo: Boolean(cfg.sagaApiUrl),
|
|
19632
|
-
installedVersion:
|
|
19797
|
+
installedVersion: opencodeInstalledVersion,
|
|
19633
19798
|
releasedVersion
|
|
19634
|
-
})
|
|
19799
|
+
});
|
|
19800
|
+
if (!opencodeVersionCheck.ok && repairFull) {
|
|
19801
|
+
if (await forceInstallOpencodeMmiPlugins(openCodeConfigSnapshot, (m) => io.err(m))) {
|
|
19802
|
+
opencodeInstalledVersion = readOpencodeAdapterDiskVersion() ?? opencodeInstalledVersion;
|
|
19803
|
+
opencodeVersionCheck = buildOpencodeVersionCheck({
|
|
19804
|
+
isOrgRepo: Boolean(cfg.sagaApiUrl),
|
|
19805
|
+
installedVersion: opencodeInstalledVersion,
|
|
19806
|
+
releasedVersion
|
|
19807
|
+
});
|
|
19808
|
+
if (opencodeVersionCheck.ok) {
|
|
19809
|
+
markPluginReloadRequired();
|
|
19810
|
+
io.err(` \u21BB force-refreshed OpenCode MMI plugin \u2192 ${opencodeInstalledVersion ?? releasedVersion ?? "latest"} \u2014 ${reloadAction("opencode")} to load it`);
|
|
19811
|
+
}
|
|
19812
|
+
}
|
|
19813
|
+
}
|
|
19814
|
+
checks.push(opencodeVersionCheck);
|
|
19815
|
+
let surfaceAssetsCheck = buildOpencodeSurfaceAssetsCheck({
|
|
19816
|
+
isOrgRepo: Boolean(cfg.sagaApiUrl),
|
|
19817
|
+
configPath: openCodeConfigSnapshot.path,
|
|
19818
|
+
commandsDir: opencodeCommandsDir(),
|
|
19819
|
+
existingCommands: opencodeExistingCommands(),
|
|
19820
|
+
skillsPath: opencodeSkillsPath(),
|
|
19821
|
+
configuredSkillsPaths: openCodeConfigSnapshot.skillsPaths
|
|
19822
|
+
});
|
|
19823
|
+
if (!surfaceAssetsCheck.ok && repairLocal) {
|
|
19824
|
+
const wroteCommands = surfaceAssetsCheck.missingCommands?.length ? writeOpencodeCommandFiles() : true;
|
|
19825
|
+
const wroteSkills = surfaceAssetsCheck.hasSkillsPath ? true : writeOpencodeSkillsPath(openCodeConfigSnapshot, opencodeSkillsPath());
|
|
19826
|
+
if (wroteCommands || wroteSkills) {
|
|
19827
|
+
openCodeConfigSnapshot = opencodeConfigSnapshot();
|
|
19828
|
+
surfaceAssetsCheck = buildOpencodeSurfaceAssetsCheck({
|
|
19829
|
+
isOrgRepo: Boolean(cfg.sagaApiUrl),
|
|
19830
|
+
configPath: openCodeConfigSnapshot.path,
|
|
19831
|
+
commandsDir: opencodeCommandsDir(),
|
|
19832
|
+
existingCommands: opencodeExistingCommands(),
|
|
19833
|
+
skillsPath: opencodeSkillsPath(),
|
|
19834
|
+
configuredSkillsPaths: openCodeConfigSnapshot.skillsPaths
|
|
19835
|
+
});
|
|
19836
|
+
if (surfaceAssetsCheck.ok) {
|
|
19837
|
+
markPluginReloadRequired();
|
|
19838
|
+
io.err(` \u21BB materialized OpenCode MMI commands + skills path \u2014 ${reloadAction("opencode")} to load them`);
|
|
19839
|
+
}
|
|
19840
|
+
}
|
|
19841
|
+
}
|
|
19842
|
+
checks.push(surfaceAssetsCheck);
|
|
19635
19843
|
checks.push(buildOpencodeDesktopBootstrapCheck({
|
|
19636
19844
|
isOrgRepo: Boolean(cfg.sagaApiUrl),
|
|
19637
19845
|
surface,
|
|
@@ -19885,7 +20093,7 @@ async function runDoctor(opts, io = consoleIo) {
|
|
|
19885
20093
|
claudePluginVersions: sourceVersions("claude"),
|
|
19886
20094
|
codexPluginVersions: sourceVersions("codex"),
|
|
19887
20095
|
codexCacheVersions: cacheVersionsFor("codex"),
|
|
19888
|
-
opencodePluginVersions:
|
|
20096
|
+
opencodePluginVersions: opencodePluginVersionsForReport(),
|
|
19889
20097
|
releasedVersion
|
|
19890
20098
|
});
|
|
19891
20099
|
const resources = doctorResourcesForGaps(gaps);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mutmutco/cli",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.51.0",
|
|
4
4
|
"description": "MMI Future CLI — delivers the org rules (whole-file), plus saga and KB access. The cross-IDE engine the plugin's SessionStart hook drives.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "UNLICENSED",
|