@massa-ai/opencode-plugin 1.61.0 → 1.62.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/agent-profiles/{open_models/massa-ai-builder.md → balanced/builder.md} +2 -3
- package/agent-profiles/balanced/code-explorer.md +103 -0
- package/agent-profiles/balanced/code-reviewer.md +135 -0
- package/agent-profiles/balanced/{massa-ai-designer.md → designer.md} +33 -16
- package/agent-profiles/balanced/judge.md +149 -0
- package/agent-profiles/balanced/product-manager.md +109 -0
- package/agent-profiles/balanced/test-engineer.md +102 -0
- package/agent-profiles/cheap/{massa-ai-builder.md → builder.md} +2 -3
- package/agent-profiles/cheap/code-explorer.md +103 -0
- package/agent-profiles/cheap/code-reviewer.md +135 -0
- package/agent-profiles/cheap/{massa-ai-designer.md → designer.md} +33 -16
- package/agent-profiles/cheap/judge.md +149 -0
- package/agent-profiles/cheap/product-manager.md +109 -0
- package/agent-profiles/cheap/test-engineer.md +102 -0
- package/agent-profiles/heavy/{massa-ai-builder.md → builder.md} +2 -3
- package/agent-profiles/heavy/code-explorer.md +103 -0
- package/agent-profiles/heavy/code-reviewer.md +135 -0
- package/agent-profiles/heavy/{massa-ai-designer.md → designer.md} +33 -16
- package/agent-profiles/heavy/judge.md +149 -0
- package/agent-profiles/heavy/product-manager.md +109 -0
- package/agent-profiles/heavy/test-engineer.md +102 -0
- package/agent-profiles/home/{massa-ai-builder.md → builder.md} +2 -3
- package/agent-profiles/home/code-explorer.md +103 -0
- package/agent-profiles/home/code-reviewer.md +135 -0
- package/agent-profiles/{open_models/massa-ai-designer.md → home/designer.md} +33 -16
- package/agent-profiles/home/judge.md +149 -0
- package/agent-profiles/home/product-manager.md +109 -0
- package/agent-profiles/home/test-engineer.md +102 -0
- package/agent-profiles/local_models/{massa-ai-builder.md → builder.md} +2 -3
- package/agent-profiles/local_models/code-explorer.md +103 -0
- package/agent-profiles/local_models/code-reviewer.md +135 -0
- package/agent-profiles/local_models/{massa-ai-designer.md → designer.md} +33 -16
- package/agent-profiles/local_models/judge.md +149 -0
- package/agent-profiles/local_models/product-manager.md +109 -0
- package/agent-profiles/local_models/test-engineer.md +102 -0
- package/agent-profiles/{balanced/massa-ai-builder.md → open_models/builder.md} +2 -3
- package/agent-profiles/open_models/code-explorer.md +103 -0
- package/agent-profiles/open_models/code-reviewer.md +135 -0
- package/agent-profiles/{home/massa-ai-designer.md → open_models/designer.md} +33 -16
- package/agent-profiles/open_models/judge.md +149 -0
- package/agent-profiles/open_models/product-manager.md +109 -0
- package/agent-profiles/open_models/test-engineer.md +102 -0
- package/agent-profiles/work/{massa-ai-builder.md → builder.md} +2 -3
- package/agent-profiles/work/code-explorer.md +103 -0
- package/agent-profiles/work/code-reviewer.md +135 -0
- package/agent-profiles/work/{massa-ai-designer.md → designer.md} +33 -16
- package/agent-profiles/work/judge.md +149 -0
- package/agent-profiles/work/product-manager.md +109 -0
- package/agent-profiles/work/test-engineer.md +102 -0
- package/agents/{massa-ai-builder.md → builder.md} +2 -3
- package/agents/code-explorer.md +103 -0
- package/agents/code-reviewer.md +135 -0
- package/agents/{massa-ai-designer.md → designer.md} +33 -16
- package/agents/judge.md +149 -0
- package/agents/product-manager.md +109 -0
- package/agents/test-engineer.md +102 -0
- package/command/{massa-ai-adr.md → massa-ai-create-adr.md} +3 -3
- package/command/{massa-ai-to-prd.md → massa-ai-create-prd.md} +3 -3
- package/command/{massa-ai-rfc.md → massa-ai-create-rfc.md} +3 -3
- package/command/{massa-ai-tdd.md → massa-ai-create-tdd.md} +3 -3
- package/command/{massa-ai-ticket.md → massa-ai-create-ticket.md} +3 -3
- package/command/massa-ai-product-discovery.md +13 -0
- package/dist/config-cli.js +221 -132
- package/package.json +3 -3
- package/agent-profiles/balanced/massa-ai-architecture-specialist.md +0 -64
- package/agent-profiles/balanced/massa-ai-audit-specialist.md +0 -81
- package/agent-profiles/balanced/massa-ai-context-curator.md +0 -66
- package/agent-profiles/balanced/massa-ai-documentation-agent.md +0 -64
- package/agent-profiles/balanced/massa-ai-furps-analyst.md +0 -70
- package/agent-profiles/balanced/massa-ai-investigator.md +0 -67
- package/agent-profiles/balanced/massa-ai-judge.md +0 -98
- package/agent-profiles/balanced/massa-ai-meta-judge.md +0 -86
- package/agent-profiles/balanced/massa-ai-mobile-specialist.md +0 -81
- package/agent-profiles/balanced/massa-ai-navigator.md +0 -74
- package/agent-profiles/balanced/massa-ai-plan-critic.md +0 -89
- package/agent-profiles/balanced/massa-ai-planner.md +0 -64
- package/agent-profiles/balanced/massa-ai-requirements-analyst.md +0 -63
- package/agent-profiles/balanced/massa-ai-reviewer.md +0 -65
- package/agent-profiles/balanced/massa-ai-test-engineer.md +0 -66
- package/agent-profiles/balanced/massa-ai-verification-agent.md +0 -64
- package/agent-profiles/cheap/massa-ai-architecture-specialist.md +0 -64
- package/agent-profiles/cheap/massa-ai-audit-specialist.md +0 -81
- package/agent-profiles/cheap/massa-ai-context-curator.md +0 -66
- package/agent-profiles/cheap/massa-ai-documentation-agent.md +0 -64
- package/agent-profiles/cheap/massa-ai-furps-analyst.md +0 -70
- package/agent-profiles/cheap/massa-ai-investigator.md +0 -67
- package/agent-profiles/cheap/massa-ai-judge.md +0 -98
- package/agent-profiles/cheap/massa-ai-meta-judge.md +0 -86
- package/agent-profiles/cheap/massa-ai-mobile-specialist.md +0 -81
- package/agent-profiles/cheap/massa-ai-navigator.md +0 -74
- package/agent-profiles/cheap/massa-ai-plan-critic.md +0 -89
- package/agent-profiles/cheap/massa-ai-planner.md +0 -64
- package/agent-profiles/cheap/massa-ai-requirements-analyst.md +0 -63
- package/agent-profiles/cheap/massa-ai-reviewer.md +0 -65
- package/agent-profiles/cheap/massa-ai-test-engineer.md +0 -66
- package/agent-profiles/cheap/massa-ai-verification-agent.md +0 -64
- package/agent-profiles/heavy/massa-ai-architecture-specialist.md +0 -64
- package/agent-profiles/heavy/massa-ai-audit-specialist.md +0 -81
- package/agent-profiles/heavy/massa-ai-context-curator.md +0 -66
- package/agent-profiles/heavy/massa-ai-documentation-agent.md +0 -64
- package/agent-profiles/heavy/massa-ai-furps-analyst.md +0 -70
- package/agent-profiles/heavy/massa-ai-investigator.md +0 -67
- package/agent-profiles/heavy/massa-ai-judge.md +0 -98
- package/agent-profiles/heavy/massa-ai-meta-judge.md +0 -86
- package/agent-profiles/heavy/massa-ai-mobile-specialist.md +0 -81
- package/agent-profiles/heavy/massa-ai-navigator.md +0 -74
- package/agent-profiles/heavy/massa-ai-plan-critic.md +0 -89
- package/agent-profiles/heavy/massa-ai-planner.md +0 -64
- package/agent-profiles/heavy/massa-ai-requirements-analyst.md +0 -63
- package/agent-profiles/heavy/massa-ai-reviewer.md +0 -65
- package/agent-profiles/heavy/massa-ai-test-engineer.md +0 -66
- package/agent-profiles/heavy/massa-ai-verification-agent.md +0 -64
- package/agent-profiles/home/massa-ai-architecture-specialist.md +0 -64
- package/agent-profiles/home/massa-ai-audit-specialist.md +0 -81
- package/agent-profiles/home/massa-ai-context-curator.md +0 -66
- package/agent-profiles/home/massa-ai-documentation-agent.md +0 -64
- package/agent-profiles/home/massa-ai-furps-analyst.md +0 -70
- package/agent-profiles/home/massa-ai-investigator.md +0 -67
- package/agent-profiles/home/massa-ai-judge.md +0 -98
- package/agent-profiles/home/massa-ai-meta-judge.md +0 -86
- package/agent-profiles/home/massa-ai-mobile-specialist.md +0 -81
- package/agent-profiles/home/massa-ai-navigator.md +0 -74
- package/agent-profiles/home/massa-ai-plan-critic.md +0 -89
- package/agent-profiles/home/massa-ai-planner.md +0 -64
- package/agent-profiles/home/massa-ai-requirements-analyst.md +0 -63
- package/agent-profiles/home/massa-ai-reviewer.md +0 -65
- package/agent-profiles/home/massa-ai-test-engineer.md +0 -66
- package/agent-profiles/home/massa-ai-verification-agent.md +0 -64
- package/agent-profiles/local_models/massa-ai-architecture-specialist.md +0 -64
- package/agent-profiles/local_models/massa-ai-audit-specialist.md +0 -81
- package/agent-profiles/local_models/massa-ai-context-curator.md +0 -66
- package/agent-profiles/local_models/massa-ai-documentation-agent.md +0 -64
- package/agent-profiles/local_models/massa-ai-furps-analyst.md +0 -70
- package/agent-profiles/local_models/massa-ai-investigator.md +0 -67
- package/agent-profiles/local_models/massa-ai-judge.md +0 -98
- package/agent-profiles/local_models/massa-ai-meta-judge.md +0 -86
- package/agent-profiles/local_models/massa-ai-mobile-specialist.md +0 -81
- package/agent-profiles/local_models/massa-ai-navigator.md +0 -74
- package/agent-profiles/local_models/massa-ai-plan-critic.md +0 -89
- package/agent-profiles/local_models/massa-ai-planner.md +0 -64
- package/agent-profiles/local_models/massa-ai-requirements-analyst.md +0 -63
- package/agent-profiles/local_models/massa-ai-reviewer.md +0 -65
- package/agent-profiles/local_models/massa-ai-test-engineer.md +0 -66
- package/agent-profiles/local_models/massa-ai-verification-agent.md +0 -64
- package/agent-profiles/open_models/massa-ai-architecture-specialist.md +0 -64
- package/agent-profiles/open_models/massa-ai-audit-specialist.md +0 -81
- package/agent-profiles/open_models/massa-ai-context-curator.md +0 -66
- package/agent-profiles/open_models/massa-ai-documentation-agent.md +0 -64
- package/agent-profiles/open_models/massa-ai-furps-analyst.md +0 -70
- package/agent-profiles/open_models/massa-ai-investigator.md +0 -67
- package/agent-profiles/open_models/massa-ai-judge.md +0 -98
- package/agent-profiles/open_models/massa-ai-meta-judge.md +0 -86
- package/agent-profiles/open_models/massa-ai-mobile-specialist.md +0 -81
- package/agent-profiles/open_models/massa-ai-navigator.md +0 -74
- package/agent-profiles/open_models/massa-ai-plan-critic.md +0 -89
- package/agent-profiles/open_models/massa-ai-planner.md +0 -64
- package/agent-profiles/open_models/massa-ai-requirements-analyst.md +0 -63
- package/agent-profiles/open_models/massa-ai-reviewer.md +0 -65
- package/agent-profiles/open_models/massa-ai-test-engineer.md +0 -66
- package/agent-profiles/open_models/massa-ai-verification-agent.md +0 -64
- package/agent-profiles/work/massa-ai-architecture-specialist.md +0 -64
- package/agent-profiles/work/massa-ai-audit-specialist.md +0 -81
- package/agent-profiles/work/massa-ai-context-curator.md +0 -66
- package/agent-profiles/work/massa-ai-documentation-agent.md +0 -64
- package/agent-profiles/work/massa-ai-furps-analyst.md +0 -70
- package/agent-profiles/work/massa-ai-investigator.md +0 -67
- package/agent-profiles/work/massa-ai-judge.md +0 -98
- package/agent-profiles/work/massa-ai-meta-judge.md +0 -86
- package/agent-profiles/work/massa-ai-mobile-specialist.md +0 -81
- package/agent-profiles/work/massa-ai-navigator.md +0 -74
- package/agent-profiles/work/massa-ai-plan-critic.md +0 -89
- package/agent-profiles/work/massa-ai-planner.md +0 -64
- package/agent-profiles/work/massa-ai-requirements-analyst.md +0 -63
- package/agent-profiles/work/massa-ai-reviewer.md +0 -65
- package/agent-profiles/work/massa-ai-test-engineer.md +0 -66
- package/agent-profiles/work/massa-ai-verification-agent.md +0 -64
- package/agents/massa-ai-architecture-specialist.md +0 -64
- package/agents/massa-ai-audit-specialist.md +0 -81
- package/agents/massa-ai-context-curator.md +0 -66
- package/agents/massa-ai-documentation-agent.md +0 -64
- package/agents/massa-ai-furps-analyst.md +0 -70
- package/agents/massa-ai-investigator.md +0 -67
- package/agents/massa-ai-judge.md +0 -98
- package/agents/massa-ai-meta-judge.md +0 -86
- package/agents/massa-ai-mobile-specialist.md +0 -81
- package/agents/massa-ai-navigator.md +0 -74
- package/agents/massa-ai-plan-critic.md +0 -89
- package/agents/massa-ai-planner.md +0 -64
- package/agents/massa-ai-requirements-analyst.md +0 -63
- package/agents/massa-ai-reviewer.md +0 -65
- package/agents/massa-ai-test-engineer.md +0 -66
- package/agents/massa-ai-verification-agent.md +0 -64
- package/command/massa-ai-discovery.md +0 -13
- package/command/massa-ai-general.md +0 -13
- package/command/massa-ai-maestro-audit.md +0 -13
- package/command/massa-ai-maestro-fix.md +0 -13
- package/command/massa-ai-maestro.md +0 -13
package/dist/config-cli.js
CHANGED
|
@@ -2193,12 +2193,12 @@ function isHost(v) {
|
|
|
2193
2193
|
return typeof v === "string" && HOSTS.includes(v);
|
|
2194
2194
|
}
|
|
2195
2195
|
var CURSOR_SKIP_REASON = "all tiers inherit \u2014 Cursor publishes no resolvable model IDs";
|
|
2196
|
-
function fileLayout(host, activeDir,
|
|
2196
|
+
function fileLayout(host, activeDir, activeExt, variantsRoot) {
|
|
2197
2197
|
return {
|
|
2198
2198
|
host,
|
|
2199
2199
|
route: "files",
|
|
2200
2200
|
activeDir,
|
|
2201
|
-
|
|
2201
|
+
activeExt,
|
|
2202
2202
|
variantsRoot,
|
|
2203
2203
|
variantDir: (profile) => path6.join(variantsRoot, profile)
|
|
2204
2204
|
};
|
|
@@ -2212,19 +2212,19 @@ function resolveHostLayout(host, opts = {}) {
|
|
|
2212
2212
|
case "claude": {
|
|
2213
2213
|
const marketplaceRoot = opts.marketplaceRoot?.claude;
|
|
2214
2214
|
if (override === undefined && marketplaceRoot !== undefined) {
|
|
2215
|
-
return fileLayout(host, path6.join(marketplaceRoot, "agents"), "
|
|
2215
|
+
return fileLayout(host, path6.join(marketplaceRoot, "agents"), ".md", path6.join(marketplaceRoot, "agent-profiles"));
|
|
2216
2216
|
}
|
|
2217
2217
|
const root = override ?? path6.join(targetHome, ".claude");
|
|
2218
|
-
return fileLayout(host, path6.join(root, "agents"), "
|
|
2218
|
+
return fileLayout(host, path6.join(root, "agents"), ".md", path6.join(root, "massa-ai", "agent-profiles"));
|
|
2219
2219
|
}
|
|
2220
2220
|
case "codex": {
|
|
2221
2221
|
const root = override ?? path6.join(targetHome, ".codex");
|
|
2222
|
-
return fileLayout(host, path6.join(root, "agents"), "
|
|
2222
|
+
return fileLayout(host, path6.join(root, "agents"), ".toml", path6.join(root, "massa-ai", "agent-profiles"));
|
|
2223
2223
|
}
|
|
2224
2224
|
case "opencode": {
|
|
2225
2225
|
const root = override ?? path6.join(targetHome, ".config", "opencode");
|
|
2226
2226
|
const pluginsDir = path6.join(root, "plugins", "massa-ai");
|
|
2227
|
-
return fileLayout(host, path6.join(root, "agents"), "
|
|
2227
|
+
return fileLayout(host, path6.join(root, "agents"), ".md", path6.join(pluginsDir, "agent-profiles"));
|
|
2228
2228
|
}
|
|
2229
2229
|
}
|
|
2230
2230
|
}
|
|
@@ -2427,8 +2427,8 @@ function acquireLock(stateFilePath, options = {}) {
|
|
|
2427
2427
|
}
|
|
2428
2428
|
}
|
|
2429
2429
|
// ../../packages/shared/dist/profile-switch/engine.js
|
|
2430
|
-
import
|
|
2431
|
-
import
|
|
2430
|
+
import fs8 from "fs";
|
|
2431
|
+
import path12 from "path";
|
|
2432
2432
|
import os7 from "os";
|
|
2433
2433
|
import crypto3 from "crypto";
|
|
2434
2434
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
@@ -2558,10 +2558,93 @@ function readInstalledPluginVersion(opts = {}) {
|
|
|
2558
2558
|
return selectRecord(records)?.version ?? null;
|
|
2559
2559
|
}
|
|
2560
2560
|
|
|
2561
|
-
// ../../packages/shared/dist/profile-switch/
|
|
2561
|
+
// ../../packages/shared/dist/profile-switch/ownership.js
|
|
2562
2562
|
import fs6 from "fs";
|
|
2563
|
-
import os6 from "os";
|
|
2564
2563
|
import path10 from "path";
|
|
2564
|
+
var OWNED_MARKER_MD = "<!-- massa-ai-owned: true -->";
|
|
2565
|
+
var OWNED_MARKER_TOML = "# massa-ai-owned";
|
|
2566
|
+
var LEGACY_AGENT_NAMES = [
|
|
2567
|
+
"architecture-specialist",
|
|
2568
|
+
"audit-specialist",
|
|
2569
|
+
"builder",
|
|
2570
|
+
"context-curator",
|
|
2571
|
+
"designer",
|
|
2572
|
+
"documentation-agent",
|
|
2573
|
+
"furps-analyst",
|
|
2574
|
+
"investigator",
|
|
2575
|
+
"judge",
|
|
2576
|
+
"meta-judge",
|
|
2577
|
+
"mobile-specialist",
|
|
2578
|
+
"navigator",
|
|
2579
|
+
"plan-critic",
|
|
2580
|
+
"planner",
|
|
2581
|
+
"requirements-analyst",
|
|
2582
|
+
"reviewer",
|
|
2583
|
+
"test-engineer",
|
|
2584
|
+
"verification-agent"
|
|
2585
|
+
];
|
|
2586
|
+
function isLegacyAgentName(fileName) {
|
|
2587
|
+
const base = path10.basename(fileName).replace(/\.[^.]*$/, "");
|
|
2588
|
+
return base.startsWith("massa-ai-") && LEGACY_AGENT_NAMES.includes(base.slice("massa-ai-".length));
|
|
2589
|
+
}
|
|
2590
|
+
function hasOwnedMarker(content) {
|
|
2591
|
+
const lines = content.split(`
|
|
2592
|
+
`);
|
|
2593
|
+
if (lines[0] !== "---")
|
|
2594
|
+
return false;
|
|
2595
|
+
const close = lines.indexOf("---", 1);
|
|
2596
|
+
return close !== -1 && lines[close + 1] === OWNED_MARKER_MD;
|
|
2597
|
+
}
|
|
2598
|
+
function isRegularFile(filePath) {
|
|
2599
|
+
try {
|
|
2600
|
+
return fs6.lstatSync(filePath).isFile();
|
|
2601
|
+
} catch {
|
|
2602
|
+
return false;
|
|
2603
|
+
}
|
|
2604
|
+
}
|
|
2605
|
+
function isOwnedAgentFile(filePath) {
|
|
2606
|
+
if (!isRegularFile(filePath))
|
|
2607
|
+
return false;
|
|
2608
|
+
if (!filePath.endsWith(".toml") && isLegacyAgentName(filePath))
|
|
2609
|
+
return true;
|
|
2610
|
+
let content;
|
|
2611
|
+
try {
|
|
2612
|
+
content = fs6.readFileSync(filePath, "utf8");
|
|
2613
|
+
} catch {
|
|
2614
|
+
return false;
|
|
2615
|
+
}
|
|
2616
|
+
if (filePath.endsWith(".toml"))
|
|
2617
|
+
return content.split(`
|
|
2618
|
+
`)[0] === OWNED_MARKER_TOML;
|
|
2619
|
+
return hasOwnedMarker(content);
|
|
2620
|
+
}
|
|
2621
|
+
function isOwnedAgentLink(linkPath) {
|
|
2622
|
+
try {
|
|
2623
|
+
if (!fs6.lstatSync(linkPath).isSymbolicLink())
|
|
2624
|
+
return false;
|
|
2625
|
+
} catch {
|
|
2626
|
+
return false;
|
|
2627
|
+
}
|
|
2628
|
+
if (isLegacyAgentName(linkPath))
|
|
2629
|
+
return true;
|
|
2630
|
+
const base = path10.basename(linkPath);
|
|
2631
|
+
const target = fs6.readlinkSync(linkPath);
|
|
2632
|
+
if (target.endsWith(`/opencode-plugin/agents/${base}`))
|
|
2633
|
+
return true;
|
|
2634
|
+
const escaped = base.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2635
|
+
if (new RegExp(`/plugins/massa-ai/agent-profiles/.*/${escaped}$`).test(target))
|
|
2636
|
+
return true;
|
|
2637
|
+
try {
|
|
2638
|
+
return fs6.statSync(linkPath).isFile() && hasOwnedMarker(fs6.readFileSync(linkPath, "utf8"));
|
|
2639
|
+
} catch {
|
|
2640
|
+
return false;
|
|
2641
|
+
}
|
|
2642
|
+
}
|
|
2643
|
+
|
|
2644
|
+
// ../../packages/shared/dist/profile-switch/doctor.js
|
|
2645
|
+
import fs7 from "fs";
|
|
2646
|
+
import os6 from "os";
|
|
2647
|
+
import path11 from "path";
|
|
2565
2648
|
|
|
2566
2649
|
// ../../packages/shared/dist/profile-switch/frontmatter.js
|
|
2567
2650
|
function parseFrontmatter(raw) {
|
|
@@ -2623,7 +2706,7 @@ function unquoteScalar(s) {
|
|
|
2623
2706
|
var ENV_OVERRIDE_VARS = ["CLAUDE_CODE_SUBAGENT_MODEL"];
|
|
2624
2707
|
function readTextFile(filePath) {
|
|
2625
2708
|
try {
|
|
2626
|
-
return
|
|
2709
|
+
return fs7.readFileSync(filePath, "utf8");
|
|
2627
2710
|
} catch {
|
|
2628
2711
|
return null;
|
|
2629
2712
|
}
|
|
@@ -2639,7 +2722,7 @@ function readJsonFile(filePath) {
|
|
|
2639
2722
|
}
|
|
2640
2723
|
}
|
|
2641
2724
|
function readPluginVersion(pluginRoot) {
|
|
2642
|
-
const manifest = readJsonFile(
|
|
2725
|
+
const manifest = readJsonFile(path11.join(pluginRoot, ".claude-plugin", "plugin.json"));
|
|
2643
2726
|
return typeof manifest?.version === "string" ? manifest.version : null;
|
|
2644
2727
|
}
|
|
2645
2728
|
function detectEnvOverride(env) {
|
|
@@ -2652,19 +2735,19 @@ function detectEnvOverride(env) {
|
|
|
2652
2735
|
return null;
|
|
2653
2736
|
}
|
|
2654
2737
|
function readRoles(liveRoot, activeProfile) {
|
|
2655
|
-
const agentsDir =
|
|
2738
|
+
const agentsDir = path11.join(liveRoot, "agents");
|
|
2656
2739
|
let entries;
|
|
2657
2740
|
try {
|
|
2658
|
-
entries =
|
|
2741
|
+
entries = fs7.readdirSync(agentsDir, { withFileTypes: true });
|
|
2659
2742
|
} catch {
|
|
2660
2743
|
return [];
|
|
2661
2744
|
}
|
|
2662
2745
|
const roles = [];
|
|
2663
2746
|
for (const entry of entries) {
|
|
2664
|
-
if (!entry.
|
|
2747
|
+
if (!entry.name.endsWith(".md") || !isOwnedAgentFile(path11.join(agentsDir, entry.name))) {
|
|
2665
2748
|
continue;
|
|
2666
2749
|
}
|
|
2667
|
-
const activeRaw = readTextFile(
|
|
2750
|
+
const activeRaw = readTextFile(path11.join(agentsDir, entry.name));
|
|
2668
2751
|
let model = null;
|
|
2669
2752
|
let effort = null;
|
|
2670
2753
|
if (activeRaw !== null) {
|
|
@@ -2676,7 +2759,7 @@ function readRoles(liveRoot, activeProfile) {
|
|
|
2676
2759
|
}
|
|
2677
2760
|
let staleVariant = false;
|
|
2678
2761
|
if (activeProfile && activeRaw !== null) {
|
|
2679
|
-
const variantRaw = readTextFile(
|
|
2762
|
+
const variantRaw = readTextFile(path11.join(liveRoot, "agent-profiles", activeProfile, entry.name));
|
|
2680
2763
|
if (variantRaw !== null) {
|
|
2681
2764
|
staleVariant = variantRaw !== activeRaw;
|
|
2682
2765
|
}
|
|
@@ -2688,7 +2771,7 @@ function readRoles(liveRoot, activeProfile) {
|
|
|
2688
2771
|
function runtimeDriftReport(opts = {}) {
|
|
2689
2772
|
const targetHome = opts.targetHome ?? os6.homedir();
|
|
2690
2773
|
const host = opts.host ?? "claude";
|
|
2691
|
-
const stateFilePath = opts.stateFilePath ??
|
|
2774
|
+
const stateFilePath = opts.stateFilePath ?? path11.join(targetHome, ".config", "massa-ai", "install-state.json");
|
|
2692
2775
|
let state = opts.state ?? null;
|
|
2693
2776
|
if (state === null) {
|
|
2694
2777
|
try {
|
|
@@ -2750,7 +2833,7 @@ function namedError3(name, message) {
|
|
|
2750
2833
|
var UnknownProfileError = (profile, known) => namedError3("UnknownProfileError", `unknown profile "${profile}" \u2014 installed: ${known.length > 0 ? known.join(", ") : "none"}`);
|
|
2751
2834
|
var NoHostsDetectedError = () => namedError3("NoHostsDetectedError", "no installed hosts found");
|
|
2752
2835
|
function defaultStatePath(targetHome) {
|
|
2753
|
-
return
|
|
2836
|
+
return path12.join(targetHome, ".config", "massa-ai", "install-state.json");
|
|
2754
2837
|
}
|
|
2755
2838
|
function resolveCommon(opts) {
|
|
2756
2839
|
const targetHome = opts.targetHome ?? os7.homedir();
|
|
@@ -2761,7 +2844,7 @@ function marketplaceRoots(targetHome, state) {
|
|
|
2761
2844
|
return state.platforms.claude?.installRoute === "marketplace" ? { claude: resolveClaudeMarketplaceRoot({ targetHome }) ?? undefined } : {};
|
|
2762
2845
|
}
|
|
2763
2846
|
function claudeMarketplaceUnresolvedReason(targetHome) {
|
|
2764
|
-
const registryPath =
|
|
2847
|
+
const registryPath = path12.join(targetHome, ".claude", "plugins", "installed_plugins.json");
|
|
2765
2848
|
return `claude installRoute is "marketplace" but no install root could be resolved from ${registryPath} ` + "\u2014 re-run the Claude plugin installer, or verify the plugin registry file";
|
|
2766
2849
|
}
|
|
2767
2850
|
function listProfiles(opts = {}) {
|
|
@@ -2802,7 +2885,7 @@ function listProfiles(opts = {}) {
|
|
|
2802
2885
|
...claudeDriftFields(host)
|
|
2803
2886
|
};
|
|
2804
2887
|
}
|
|
2805
|
-
const installed =
|
|
2888
|
+
const installed = fs8.existsSync(layout.activeDir);
|
|
2806
2889
|
const availableProfiles = listVariantProfiles(layout);
|
|
2807
2890
|
const platform = state.platforms[host];
|
|
2808
2891
|
return {
|
|
@@ -2819,20 +2902,20 @@ function listProfiles(opts = {}) {
|
|
|
2819
2902
|
return { hosts };
|
|
2820
2903
|
}
|
|
2821
2904
|
function listVariantProfiles(layout) {
|
|
2822
|
-
if (!
|
|
2905
|
+
if (!fs8.existsSync(layout.variantsRoot))
|
|
2823
2906
|
return [];
|
|
2824
|
-
return
|
|
2907
|
+
return fs8.readdirSync(layout.variantsRoot, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name).sort();
|
|
2825
2908
|
}
|
|
2826
|
-
function
|
|
2827
|
-
|
|
2828
|
-
if (starIdx === -1)
|
|
2829
|
-
return filename === glob;
|
|
2830
|
-
const prefix = glob.slice(0, starIdx);
|
|
2831
|
-
const suffix = glob.slice(starIdx + 1);
|
|
2832
|
-
return filename.length >= prefix.length + suffix.length && filename.startsWith(prefix) && filename.endsWith(suffix);
|
|
2909
|
+
function matchingFileNames(dir, ext) {
|
|
2910
|
+
return fs8.readdirSync(dir, { withFileTypes: true }).filter((e) => e.isFile() && e.name.endsWith(ext) && !isLegacyAgentName(e.name) && isOwnedAgentFile(path12.join(dir, e.name))).map((e) => e.name);
|
|
2833
2911
|
}
|
|
2834
|
-
function
|
|
2835
|
-
|
|
2912
|
+
function destIsAbsent(dest) {
|
|
2913
|
+
try {
|
|
2914
|
+
fs8.lstatSync(dest);
|
|
2915
|
+
return false;
|
|
2916
|
+
} catch {
|
|
2917
|
+
return true;
|
|
2918
|
+
}
|
|
2836
2919
|
}
|
|
2837
2920
|
function detectGitAvailability(dir) {
|
|
2838
2921
|
try {
|
|
@@ -2860,7 +2943,7 @@ function gitTrackedFileNames(dir, filenames) {
|
|
|
2860
2943
|
var GUARD_PASS = { blocked: false, unchecked: false };
|
|
2861
2944
|
var GUARD_UNCHECKED = { blocked: false, unchecked: true };
|
|
2862
2945
|
function checkTrackedPathGuard(activeDir, filenames) {
|
|
2863
|
-
if (filenames.length === 0 || !
|
|
2946
|
+
if (filenames.length === 0 || !fs8.existsSync(activeDir))
|
|
2864
2947
|
return GUARD_PASS;
|
|
2865
2948
|
const availability = detectGitAvailability(activeDir);
|
|
2866
2949
|
if (availability === "no-git")
|
|
@@ -2871,53 +2954,45 @@ function checkTrackedPathGuard(activeDir, filenames) {
|
|
|
2871
2954
|
if (tracked.size === 0)
|
|
2872
2955
|
return GUARD_PASS;
|
|
2873
2956
|
const offending = filenames.find((name) => tracked.has(name));
|
|
2874
|
-
return { blocked: true, path:
|
|
2957
|
+
return { blocked: true, path: path12.join(activeDir, offending), unchecked: false };
|
|
2875
2958
|
}
|
|
2876
2959
|
function assertStateWritable(stateFilePath) {
|
|
2877
|
-
const dir =
|
|
2960
|
+
const dir = path12.dirname(stateFilePath);
|
|
2878
2961
|
try {
|
|
2879
|
-
|
|
2962
|
+
fs8.mkdirSync(dir, { recursive: true });
|
|
2880
2963
|
} catch (err) {
|
|
2881
2964
|
throw UnwritableInstallStateError(stateFilePath, err.message);
|
|
2882
2965
|
}
|
|
2883
|
-
const checkPath =
|
|
2966
|
+
const checkPath = fs8.existsSync(stateFilePath) ? stateFilePath : dir;
|
|
2884
2967
|
try {
|
|
2885
|
-
|
|
2968
|
+
fs8.accessSync(checkPath, fs8.constants.W_OK);
|
|
2886
2969
|
} catch (err) {
|
|
2887
2970
|
throw UnwritableInstallStateError(stateFilePath, err.message);
|
|
2888
2971
|
}
|
|
2889
2972
|
}
|
|
2890
2973
|
function copyFileRouteVariant(layout, variantDir) {
|
|
2891
|
-
|
|
2974
|
+
fs8.mkdirSync(layout.activeDir, { recursive: true });
|
|
2892
2975
|
let changed = 0;
|
|
2893
|
-
for (const
|
|
2894
|
-
|
|
2976
|
+
for (const name of matchingFileNames(variantDir, layout.activeExt)) {
|
|
2977
|
+
const dest = path12.join(layout.activeDir, name);
|
|
2978
|
+
if (!destIsAbsent(dest) && !isOwnedAgentFile(dest))
|
|
2895
2979
|
continue;
|
|
2896
|
-
|
|
2980
|
+
fs8.copyFileSync(path12.join(variantDir, name), dest);
|
|
2897
2981
|
changed++;
|
|
2898
2982
|
}
|
|
2899
2983
|
return changed;
|
|
2900
2984
|
}
|
|
2901
2985
|
function repointOpencodeVariant(layout, variantDir) {
|
|
2902
|
-
|
|
2986
|
+
fs8.mkdirSync(layout.activeDir, { recursive: true });
|
|
2903
2987
|
let changed = 0;
|
|
2904
|
-
for (const
|
|
2905
|
-
|
|
2906
|
-
|
|
2907
|
-
|
|
2908
|
-
const target = path11.resolve(path11.join(variantDir, entry.name));
|
|
2909
|
-
let destExists = true;
|
|
2910
|
-
let destIsSymlink = false;
|
|
2911
|
-
try {
|
|
2912
|
-
destIsSymlink = fs7.lstatSync(dest).isSymbolicLink();
|
|
2913
|
-
} catch {
|
|
2914
|
-
destExists = false;
|
|
2915
|
-
}
|
|
2916
|
-
if (destExists && !destIsSymlink)
|
|
2988
|
+
for (const name of matchingFileNames(variantDir, layout.activeExt)) {
|
|
2989
|
+
const dest = path12.join(layout.activeDir, name);
|
|
2990
|
+
const target = path12.resolve(path12.join(variantDir, name));
|
|
2991
|
+
if (!destIsAbsent(dest) && !isOwnedAgentLink(dest))
|
|
2917
2992
|
continue;
|
|
2918
2993
|
const tmp = `${dest}.massa-ai-switch.${crypto3.randomUUID()}`;
|
|
2919
|
-
|
|
2920
|
-
|
|
2994
|
+
fs8.symlinkSync(target, tmp);
|
|
2995
|
+
fs8.renameSync(tmp, dest);
|
|
2921
2996
|
changed++;
|
|
2922
2997
|
}
|
|
2923
2998
|
return changed;
|
|
@@ -2957,13 +3032,13 @@ function switchProfile(opts) {
|
|
|
2957
3032
|
if (fileHosts.length === 0) {
|
|
2958
3033
|
return { profile: opts.profile, dryRun, hosts: orderRows(universe, skipRows), restartRequired: false };
|
|
2959
3034
|
}
|
|
2960
|
-
const installedFileHosts = fileHosts.filter((h) =>
|
|
3035
|
+
const installedFileHosts = fileHosts.filter((h) => fs8.existsSync(h.layout.activeDir));
|
|
2961
3036
|
if (installedFileHosts.length === 0)
|
|
2962
3037
|
throw NoHostsDetectedError();
|
|
2963
3038
|
const withAvailability = fileHosts.map((h) => {
|
|
2964
|
-
const variantsRootExists =
|
|
3039
|
+
const variantsRootExists = fs8.existsSync(h.layout.variantsRoot);
|
|
2965
3040
|
const variantDir = h.layout.variantDir(opts.profile);
|
|
2966
|
-
const available = variantsRootExists &&
|
|
3041
|
+
const available = variantsRootExists && fs8.existsSync(variantDir) && fs8.statSync(variantDir).isDirectory();
|
|
2967
3042
|
return { ...h, variantsRootExists, variantDir, available };
|
|
2968
3043
|
});
|
|
2969
3044
|
if (!withAvailability.some((h) => h.available)) {
|
|
@@ -3002,7 +3077,7 @@ function switchProfile(opts) {
|
|
|
3002
3077
|
rows.push({ host: h.host, status: "would-switch" });
|
|
3003
3078
|
continue;
|
|
3004
3079
|
}
|
|
3005
|
-
const candidateNames = matchingFileNames(h.variantDir, h.layout.
|
|
3080
|
+
const candidateNames = matchingFileNames(h.variantDir, h.layout.activeExt);
|
|
3006
3081
|
const guard = checkTrackedPathGuard(h.layout.activeDir, candidateNames);
|
|
3007
3082
|
if (guard.blocked) {
|
|
3008
3083
|
rows.push({
|
|
@@ -3043,12 +3118,12 @@ function reportSucceeded(report) {
|
|
|
3043
3118
|
return report.hosts.every((h) => h.status === "switched" || h.status === "would-switch" || h.status === "skipped");
|
|
3044
3119
|
}
|
|
3045
3120
|
// ../../packages/shared/dist/profile-switch/variant-sync.js
|
|
3046
|
-
import
|
|
3047
|
-
import
|
|
3121
|
+
import fs9 from "fs";
|
|
3122
|
+
import path13 from "path";
|
|
3048
3123
|
import os8 from "os";
|
|
3049
3124
|
import crypto4 from "crypto";
|
|
3050
3125
|
function defaultStatePath2(targetHome) {
|
|
3051
|
-
return
|
|
3126
|
+
return path13.join(targetHome, ".config", "massa-ai", "install-state.json");
|
|
3052
3127
|
}
|
|
3053
3128
|
function marketplaceRoots2(targetHome, state) {
|
|
3054
3129
|
return state.platforms.claude?.installRoute === "marketplace" ? { claude: resolveClaudeMarketplaceRoot({ targetHome }) ?? undefined } : {};
|
|
@@ -3056,13 +3131,13 @@ function marketplaceRoots2(targetHome, state) {
|
|
|
3056
3131
|
var tempFileCounter2 = 0;
|
|
3057
3132
|
function writeFileIntoDirAtomically(destDir, destName, content) {
|
|
3058
3133
|
const unique = `${process.pid}.${++tempFileCounter2}.${crypto4.randomBytes(6).toString("hex")}`;
|
|
3059
|
-
const tempFile =
|
|
3134
|
+
const tempFile = path13.join(destDir, `.${destName}.${unique}.tmp`);
|
|
3060
3135
|
try {
|
|
3061
|
-
|
|
3062
|
-
|
|
3136
|
+
fs9.writeFileSync(tempFile, content);
|
|
3137
|
+
fs9.renameSync(tempFile, path13.join(destDir, destName));
|
|
3063
3138
|
} catch (error) {
|
|
3064
3139
|
try {
|
|
3065
|
-
|
|
3140
|
+
fs9.unlinkSync(tempFile);
|
|
3066
3141
|
} catch {}
|
|
3067
3142
|
throw error;
|
|
3068
3143
|
}
|
|
@@ -3070,20 +3145,20 @@ function writeFileIntoDirAtomically(destDir, destName, content) {
|
|
|
3070
3145
|
function isSafeDirName(name) {
|
|
3071
3146
|
if (name === "." || name === "..")
|
|
3072
3147
|
return false;
|
|
3073
|
-
if (name.includes("/") || name.includes("\\") || name.includes(
|
|
3148
|
+
if (name.includes("/") || name.includes("\\") || name.includes(path13.sep))
|
|
3074
3149
|
return false;
|
|
3075
|
-
return
|
|
3150
|
+
return path13.basename(name) === name;
|
|
3076
3151
|
}
|
|
3077
3152
|
function syncHost(host, sourceRoot, targetHome, marketplaceRoot) {
|
|
3078
3153
|
const layout = resolveHostLayout(host, { targetHome, marketplaceRoot });
|
|
3079
3154
|
if (layout.route === "skip") {
|
|
3080
3155
|
return { host, status: "skipped", profiles: [], retained: [], files: 0, reason: layout.reason };
|
|
3081
3156
|
}
|
|
3082
|
-
const srcDir =
|
|
3083
|
-
if (!
|
|
3157
|
+
const srcDir = path13.join(sourceRoot, "apps", `${host}-plugin`, "agent-profiles");
|
|
3158
|
+
if (!fs9.existsSync(srcDir) || !fs9.statSync(srcDir).isDirectory()) {
|
|
3084
3159
|
return { host, status: "skipped", profiles: [], retained: [], files: 0, reason: "no generated variants for this host" };
|
|
3085
3160
|
}
|
|
3086
|
-
if (!
|
|
3161
|
+
if (!fs9.existsSync(layout.variantsRoot)) {
|
|
3087
3162
|
return {
|
|
3088
3163
|
host,
|
|
3089
3164
|
status: "skipped",
|
|
@@ -3095,24 +3170,24 @@ function syncHost(host, sourceRoot, targetHome, marketplaceRoot) {
|
|
|
3095
3170
|
}
|
|
3096
3171
|
const profiles = [];
|
|
3097
3172
|
let files = 0;
|
|
3098
|
-
for (const entry of
|
|
3173
|
+
for (const entry of fs9.readdirSync(srcDir, { withFileTypes: true })) {
|
|
3099
3174
|
if (!entry.isDirectory())
|
|
3100
3175
|
continue;
|
|
3101
3176
|
if (!isSafeDirName(entry.name))
|
|
3102
3177
|
continue;
|
|
3103
|
-
const srcProfileDir =
|
|
3104
|
-
const destProfileDir =
|
|
3105
|
-
|
|
3106
|
-
for (const fileEntry of
|
|
3178
|
+
const srcProfileDir = path13.join(srcDir, entry.name);
|
|
3179
|
+
const destProfileDir = path13.join(layout.variantsRoot, entry.name);
|
|
3180
|
+
fs9.mkdirSync(destProfileDir, { recursive: true });
|
|
3181
|
+
for (const fileEntry of fs9.readdirSync(srcProfileDir, { withFileTypes: true })) {
|
|
3107
3182
|
if (!fileEntry.isFile())
|
|
3108
3183
|
continue;
|
|
3109
|
-
const content =
|
|
3184
|
+
const content = fs9.readFileSync(path13.join(srcProfileDir, fileEntry.name));
|
|
3110
3185
|
writeFileIntoDirAtomically(destProfileDir, fileEntry.name, content);
|
|
3111
3186
|
files++;
|
|
3112
3187
|
}
|
|
3113
3188
|
profiles.push(entry.name);
|
|
3114
3189
|
}
|
|
3115
|
-
const retained =
|
|
3190
|
+
const retained = fs9.readdirSync(layout.variantsRoot, { withFileTypes: true }).filter((e) => e.isDirectory() && !profiles.includes(e.name)).map((e) => e.name).sort();
|
|
3116
3191
|
return { host, status: "synced", profiles: profiles.sort(), retained, files };
|
|
3117
3192
|
}
|
|
3118
3193
|
function syncGeneratedVariants(opts) {
|
|
@@ -3140,14 +3215,14 @@ function syncGeneratedVariants(opts) {
|
|
|
3140
3215
|
});
|
|
3141
3216
|
}
|
|
3142
3217
|
// ../../packages/shared/dist/profile-switch/repo-root.js
|
|
3143
|
-
import
|
|
3144
|
-
import
|
|
3218
|
+
import fs10 from "fs";
|
|
3219
|
+
import path14 from "path";
|
|
3145
3220
|
function findRepoRootWithMarker(startDir, marker, maxLevels) {
|
|
3146
3221
|
let dir = startDir;
|
|
3147
3222
|
for (let i = 0;i <= maxLevels; i++) {
|
|
3148
|
-
if (
|
|
3223
|
+
if (fs10.existsSync(path14.join(dir, marker)))
|
|
3149
3224
|
return dir;
|
|
3150
|
-
const parent =
|
|
3225
|
+
const parent = path14.dirname(dir);
|
|
3151
3226
|
if (parent === dir)
|
|
3152
3227
|
break;
|
|
3153
3228
|
dir = parent;
|
|
@@ -3158,7 +3233,6 @@ function findRepoRootWithMarker(startDir, marker, maxLevels) {
|
|
|
3158
3233
|
var BOOTSTRAP_RULE_IDS = [
|
|
3159
3234
|
"caveman",
|
|
3160
3235
|
"massa-ai-router",
|
|
3161
|
-
"persona-router",
|
|
3162
3236
|
"dedupe-guardrails",
|
|
3163
3237
|
"plan-challenge",
|
|
3164
3238
|
"conversation-feedback",
|
|
@@ -3166,6 +3240,10 @@ var BOOTSTRAP_RULE_IDS = [
|
|
|
3166
3240
|
"english-code",
|
|
3167
3241
|
"code-comments"
|
|
3168
3242
|
];
|
|
3243
|
+
var RETIRED_RULE_IDS = ["persona-router"];
|
|
3244
|
+
function isRetiredRuleId(value) {
|
|
3245
|
+
return RETIRED_RULE_IDS.includes(value);
|
|
3246
|
+
}
|
|
3169
3247
|
function isBootstrapRuleId(value) {
|
|
3170
3248
|
return typeof value === "string" && BOOTSTRAP_RULE_IDS.includes(value);
|
|
3171
3249
|
}
|
|
@@ -3180,11 +3258,6 @@ var BOOTSTRAP_RULES = [
|
|
|
3180
3258
|
defaultEnabled: true,
|
|
3181
3259
|
description: "Load the massa-ai skill as the workflow router before substantive work."
|
|
3182
3260
|
},
|
|
3183
|
-
{
|
|
3184
|
-
id: "persona-router",
|
|
3185
|
-
defaultEnabled: true,
|
|
3186
|
-
description: "Select one cataloged specialist persona after massa-ai context is available."
|
|
3187
|
-
},
|
|
3188
3261
|
{
|
|
3189
3262
|
id: "dedupe-guardrails",
|
|
3190
3263
|
defaultEnabled: true,
|
|
@@ -3235,14 +3308,17 @@ function namedError4(name, message) {
|
|
|
3235
3308
|
err.name = name;
|
|
3236
3309
|
return err;
|
|
3237
3310
|
}
|
|
3238
|
-
var UnknownRuleError = (id, known = BOOTSTRAP_RULE_IDS) =>
|
|
3311
|
+
var UnknownRuleError = (id, known = BOOTSTRAP_RULE_IDS) => {
|
|
3312
|
+
const what = isRetiredRuleId(id) ? `bootstrap rule "${id}" was retired and can no longer be toggled` : `unknown bootstrap rule "${id}"`;
|
|
3313
|
+
return namedError4("UnknownRuleError", `${what} \u2014 valid ids: ${known.join(", ")}`);
|
|
3314
|
+
};
|
|
3239
3315
|
function assertKnownRuleId(id) {
|
|
3240
3316
|
if (!isBootstrapRuleId(id))
|
|
3241
3317
|
throw UnknownRuleError(id, BOOTSTRAP_RULE_IDS);
|
|
3242
3318
|
}
|
|
3243
3319
|
// ../../packages/shared/dist/bootstrap/state.js
|
|
3244
3320
|
init_config_loader();
|
|
3245
|
-
import
|
|
3321
|
+
import fs11 from "fs";
|
|
3246
3322
|
var BOOTSTRAP_STATE_KEY = "bootstrap";
|
|
3247
3323
|
var BOOTSTRAP_RULES_KEY = "rules";
|
|
3248
3324
|
var BOOTSTRAP_STATE_PATH = `${BOOTSTRAP_STATE_KEY}.${BOOTSTRAP_RULES_KEY}`;
|
|
@@ -3266,6 +3342,8 @@ function resolveBootstrapState(doc) {
|
|
|
3266
3342
|
return { state, ignoredStateKeys: [BOOTSTRAP_STATE_PATH] };
|
|
3267
3343
|
}
|
|
3268
3344
|
for (const [key, value] of Object.entries(rules)) {
|
|
3345
|
+
if (isRetiredRuleId(key))
|
|
3346
|
+
continue;
|
|
3269
3347
|
if (!isBootstrapRuleId(key) || typeof value !== "boolean") {
|
|
3270
3348
|
ignored.push(key);
|
|
3271
3349
|
continue;
|
|
@@ -3276,7 +3354,7 @@ function resolveBootstrapState(doc) {
|
|
|
3276
3354
|
}
|
|
3277
3355
|
function readConfigBytes() {
|
|
3278
3356
|
try {
|
|
3279
|
-
return
|
|
3357
|
+
return fs11.readFileSync(getConfigPath(), "utf-8");
|
|
3280
3358
|
} catch (error) {
|
|
3281
3359
|
if (error?.code === "ENOENT")
|
|
3282
3360
|
return "";
|
|
@@ -3324,7 +3402,7 @@ function setBootstrapRuleEnabled(id, enabled) {
|
|
|
3324
3402
|
};
|
|
3325
3403
|
}
|
|
3326
3404
|
// ../../packages/shared/dist/bootstrap/render.js
|
|
3327
|
-
import
|
|
3405
|
+
import path15 from "path";
|
|
3328
3406
|
var BOOTSTRAP_BLOCK_START = "<!-- massa-ai:bootstrap:start -->";
|
|
3329
3407
|
var BOOTSTRAP_BLOCK_END = "<!-- massa-ai:bootstrap:end -->";
|
|
3330
3408
|
var CONTRACT_FILENAME = "MASSA-AI.md";
|
|
@@ -3356,19 +3434,19 @@ var HOST_CONFIG_DIR = {
|
|
|
3356
3434
|
function resolveHostRoot(host, targetHome, hostRoot) {
|
|
3357
3435
|
requireAbsoluteTargetHome(targetHome);
|
|
3358
3436
|
if (hostRoot === undefined)
|
|
3359
|
-
return
|
|
3360
|
-
const relative =
|
|
3361
|
-
if (!
|
|
3437
|
+
return path15.join(targetHome, ...HOST_CONFIG_DIR[host]);
|
|
3438
|
+
const relative = path15.relative(targetHome, hostRoot);
|
|
3439
|
+
if (!path15.isAbsolute(hostRoot) || relative === "" || relative.startsWith("..") || path15.isAbsolute(relative)) {
|
|
3362
3440
|
throw new BootstrapRenderError("HostRootOutsideTargetHomeError", `hostRoot must be an absolute directory inside targetHome, got "${hostRoot}" for targetHome "${targetHome}"`, [hostRoot, targetHome]);
|
|
3363
3441
|
}
|
|
3364
3442
|
return hostRoot;
|
|
3365
3443
|
}
|
|
3366
3444
|
function bootstrapContractPath(host, targetHome, hostRoot) {
|
|
3367
|
-
return
|
|
3445
|
+
return path15.join(resolveHostRoot(host, targetHome, hostRoot), CONTRACT_FILENAME);
|
|
3368
3446
|
}
|
|
3369
3447
|
function bootstrapStateFilePath(targetHome) {
|
|
3370
3448
|
requireAbsoluteTargetHome(targetHome);
|
|
3371
|
-
return
|
|
3449
|
+
return path15.join(targetHome, ".config", "massa-ai", "config.json");
|
|
3372
3450
|
}
|
|
3373
3451
|
function renderBootstrap(options) {
|
|
3374
3452
|
const { source, state, host, targetHome, hostRoot } = options;
|
|
@@ -3391,7 +3469,7 @@ ${body}`;
|
|
|
3391
3469
|
return { contract, pointer };
|
|
3392
3470
|
}
|
|
3393
3471
|
function requireAbsoluteTargetHome(targetHome) {
|
|
3394
|
-
if (!
|
|
3472
|
+
if (!path15.isAbsolute(targetHome)) {
|
|
3395
3473
|
throw new BootstrapRenderError("TargetHomeNotAbsoluteError", `targetHome must be an absolute path, got "${targetHome}"`, [targetHome]);
|
|
3396
3474
|
}
|
|
3397
3475
|
}
|
|
@@ -3544,8 +3622,8 @@ function buildBootstrapReport(input) {
|
|
|
3544
3622
|
}
|
|
3545
3623
|
// ../../packages/shared/dist/bootstrap/engine.js
|
|
3546
3624
|
init_config_loader();
|
|
3547
|
-
import
|
|
3548
|
-
import
|
|
3625
|
+
import fs12 from "fs";
|
|
3626
|
+
import path16 from "path";
|
|
3549
3627
|
var INSTALL_STATE_FILENAME = "install-state.json";
|
|
3550
3628
|
var WIRING_REMEDY = "scripts/install-skills.sh --apply";
|
|
3551
3629
|
|
|
@@ -3562,7 +3640,7 @@ function applyBootstrapState(options) {
|
|
|
3562
3640
|
const dryRun = options.dryRun ?? false;
|
|
3563
3641
|
const warn = options.onWarning ?? ((message) => console.warn(message));
|
|
3564
3642
|
const configPath = bootstrapStateFilePath(targetHome);
|
|
3565
|
-
const installStatePath =
|
|
3643
|
+
const installStatePath = path16.join(path16.dirname(configPath), INSTALL_STATE_FILENAME);
|
|
3566
3644
|
const { platforms } = readInstallState(installStatePath);
|
|
3567
3645
|
const installed = HOSTS.filter((host) => platforms[host] !== undefined);
|
|
3568
3646
|
if (installed.length === 0) {
|
|
@@ -3655,22 +3733,22 @@ function applyHost(input) {
|
|
|
3655
3733
|
}
|
|
3656
3734
|
function wiringArtifact(host, targetHome, hostRoot) {
|
|
3657
3735
|
const root = resolveHostRoot(host, targetHome, hostRoot);
|
|
3658
|
-
const contractPath =
|
|
3736
|
+
const contractPath = path16.join(root, CONTRACT_FILENAME);
|
|
3659
3737
|
switch (host) {
|
|
3660
3738
|
case "claude":
|
|
3661
|
-
return { file:
|
|
3739
|
+
return { file: path16.join(root, "CLAUDE.md"), token: `@${CONTRACT_FILENAME}` };
|
|
3662
3740
|
case "codex":
|
|
3663
3741
|
case "cursor":
|
|
3664
|
-
return { file:
|
|
3742
|
+
return { file: path16.join(root, "AGENTS.md"), token: contractPath };
|
|
3665
3743
|
case "opencode":
|
|
3666
3744
|
return { file: openCodeConfigPath(root), token: `"${contractPath}"` };
|
|
3667
3745
|
}
|
|
3668
3746
|
}
|
|
3669
3747
|
function openCodeConfigPath(root) {
|
|
3670
|
-
const json =
|
|
3671
|
-
if (
|
|
3748
|
+
const json = path16.join(root, "opencode.json");
|
|
3749
|
+
if (fs12.existsSync(json))
|
|
3672
3750
|
return json;
|
|
3673
|
-
return
|
|
3751
|
+
return path16.join(root, "opencode.jsonc");
|
|
3674
3752
|
}
|
|
3675
3753
|
function isWired(host, targetHome, hostRoot) {
|
|
3676
3754
|
const artifact = wiringArtifact(host, targetHome, hostRoot);
|
|
@@ -3683,7 +3761,7 @@ function notWiredReason(host, targetHome, hostRoot) {
|
|
|
3683
3761
|
}
|
|
3684
3762
|
function readFileOrNull(filePath) {
|
|
3685
3763
|
try {
|
|
3686
|
-
return
|
|
3764
|
+
return fs12.readFileSync(filePath, "utf-8");
|
|
3687
3765
|
} catch {
|
|
3688
3766
|
return null;
|
|
3689
3767
|
}
|
|
@@ -3729,11 +3807,11 @@ function formatBootstrapReport(report) {
|
|
|
3729
3807
|
init_config_loader();
|
|
3730
3808
|
// src/config-cli.ts
|
|
3731
3809
|
init_inference_providers();
|
|
3732
|
-
import { promises as
|
|
3733
|
-
import
|
|
3810
|
+
import { promises as fs13 } from "fs";
|
|
3811
|
+
import path17 from "path";
|
|
3734
3812
|
import os9 from "os";
|
|
3735
3813
|
import { fileURLToPath } from "url";
|
|
3736
|
-
var __dirname2 =
|
|
3814
|
+
var __dirname2 = path17.dirname(fileURLToPath(import.meta.url));
|
|
3737
3815
|
var WRITABLE_PROVIDERS = ["ollama", "lmstudio", "mistral", "openai", "google", "cohere"];
|
|
3738
3816
|
var GENERATOR_MARKER = "scripts/generate-subagent-artifacts.ts";
|
|
3739
3817
|
var GENERATOR_MARKER_MAX_LEVELS = 6;
|
|
@@ -3767,8 +3845,8 @@ Commands:
|
|
|
3767
3845
|
--model <name> Model name
|
|
3768
3846
|
--base-url <url> Base URL (for ollama/lmstudio)
|
|
3769
3847
|
|
|
3770
|
-
agents Manage the
|
|
3771
|
-
agents install [--user|--project] Write
|
|
3848
|
+
agents Manage the 7 subagent specialist definitions
|
|
3849
|
+
agents install [--user|--project] Write 7 agent .md files
|
|
3772
3850
|
agents uninstall [--user|--project] Remove only massa-ai-owned agents
|
|
3773
3851
|
|
|
3774
3852
|
profile list List shipped model profiles + per-host active profile
|
|
@@ -4045,18 +4123,30 @@ Using defaults:`);
|
|
|
4045
4123
|
return 1;
|
|
4046
4124
|
}
|
|
4047
4125
|
const scope = typeof options.project === "boolean" ? "project" : "user";
|
|
4048
|
-
const agentsDir = scope === "project" ?
|
|
4049
|
-
const sourceAgentsDir =
|
|
4126
|
+
const agentsDir = scope === "project" ? path17.join(process.cwd(), ".opencode/agents") : path17.join(process.env.XDG_CONFIG_HOME && process.env.XDG_CONFIG_HOME.trim() || path17.join(os9.homedir(), ".config"), "opencode", "agents");
|
|
4127
|
+
const sourceAgentsDir = path17.resolve(__dirname2, "..", "agents");
|
|
4050
4128
|
if (subcommand === "install") {
|
|
4051
|
-
await
|
|
4129
|
+
await fs13.mkdir(agentsDir, { recursive: true });
|
|
4052
4130
|
let count = 0;
|
|
4053
|
-
const entries = await
|
|
4131
|
+
const entries = await fs13.readdir(sourceAgentsDir);
|
|
4054
4132
|
for (const entry of entries) {
|
|
4055
|
-
if (!entry.
|
|
4133
|
+
if (!entry.endsWith(".md"))
|
|
4134
|
+
continue;
|
|
4135
|
+
const src = path17.join(sourceAgentsDir, entry);
|
|
4136
|
+
const dest = path17.join(agentsDir, entry);
|
|
4137
|
+
let destExists = true;
|
|
4138
|
+
try {
|
|
4139
|
+
await fs13.lstat(dest);
|
|
4140
|
+
} catch {
|
|
4141
|
+
destExists = false;
|
|
4142
|
+
}
|
|
4143
|
+
if (destExists && !isOwnedAgentFile(dest) && !isOwnedAgentLink(dest)) {
|
|
4144
|
+
console.warn(`\u26A0 ${dest} exists and is not massa-ai-owned \u2014 skipped`);
|
|
4056
4145
|
continue;
|
|
4057
|
-
|
|
4058
|
-
|
|
4059
|
-
|
|
4146
|
+
}
|
|
4147
|
+
if (isOwnedAgentLink(dest))
|
|
4148
|
+
await fs13.unlink(dest);
|
|
4149
|
+
await fs13.copyFile(src, dest);
|
|
4060
4150
|
count++;
|
|
4061
4151
|
}
|
|
4062
4152
|
console.log(`+ ${count} subagent specialists (generated from skills/agents/*/SKILL.md)`);
|
|
@@ -4064,14 +4154,13 @@ Using defaults:`);
|
|
|
4064
4154
|
} else {
|
|
4065
4155
|
let removed = 0;
|
|
4066
4156
|
try {
|
|
4067
|
-
const entries = await
|
|
4157
|
+
const entries = await fs13.readdir(agentsDir);
|
|
4068
4158
|
for (const entry of entries) {
|
|
4069
|
-
if (!entry.
|
|
4159
|
+
if (!entry.endsWith(".md"))
|
|
4070
4160
|
continue;
|
|
4071
|
-
const filePath =
|
|
4072
|
-
|
|
4073
|
-
|
|
4074
|
-
await fs12.unlink(filePath);
|
|
4161
|
+
const filePath = path17.join(agentsDir, entry);
|
|
4162
|
+
if (isOwnedAgentFile(filePath) || isOwnedAgentLink(filePath)) {
|
|
4163
|
+
await fs13.unlink(filePath);
|
|
4075
4164
|
removed++;
|
|
4076
4165
|
}
|
|
4077
4166
|
}
|
|
@@ -4181,7 +4270,7 @@ Using defaults:`);
|
|
|
4181
4270
|
return 1;
|
|
4182
4271
|
}
|
|
4183
4272
|
const targetOpt = typeof options.target === "string" ? options.target : undefined;
|
|
4184
|
-
const targetHome = targetOpt === undefined ? os9.homedir() :
|
|
4273
|
+
const targetHome = targetOpt === undefined ? os9.homedir() : path17.resolve(targetOpt);
|
|
4185
4274
|
if (targetHome !== os9.homedir() && options.yes !== true) {
|
|
4186
4275
|
console.error(`Error: --target ${targetHome} is not your home (${os9.homedir()}) \u2014 pass --yes to confirm writing there`);
|
|
4187
4276
|
return 1;
|
|
@@ -4201,7 +4290,7 @@ Using defaults:`);
|
|
|
4201
4290
|
const report = applyBootstrapState({
|
|
4202
4291
|
targetHome,
|
|
4203
4292
|
dryRun,
|
|
4204
|
-
sourcePath: repoRoot === null ? undefined :
|
|
4293
|
+
sourcePath: repoRoot === null ? undefined : path17.join(repoRoot, "skills", "AGENTS.md")
|
|
4205
4294
|
});
|
|
4206
4295
|
console.log(formatBootstrapReport(report));
|
|
4207
4296
|
return bootstrapReportSucceeded(report) ? 0 : 1;
|