0xray 4.0.40 → 4.0.42
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/.grok-plugin/plugin.json +1 -1
- package/.opencode/agents/api-design.yml +31 -0
- package/.opencode/agents/architect.yml +15 -0
- package/.opencode/agents/architecture-patterns.yml +14 -0
- package/.opencode/agents/auto-format.yml +14 -0
- package/.opencode/agents/backend-engineer.yml +12 -0
- package/.opencode/agents/boot-orchestrator.yml +14 -0
- package/.opencode/agents/bug-triage-specialist.yml +15 -0
- package/.opencode/agents/code-analyzer.yml +12 -0
- package/.opencode/agents/code-reviewer.yml +14 -0
- package/.opencode/agents/content-creator.yml +12 -0
- package/.opencode/agents/database-engineer.yml +12 -0
- package/.opencode/agents/devops-engineer.yml +12 -0
- package/.opencode/agents/framework-compliance-audit.yml +14 -0
- package/.opencode/agents/frontend-engineer.yml +12 -0
- package/.opencode/agents/frontend-ui-ux-engineer.yml +12 -0
- package/.opencode/agents/git-workflow.yml +15 -0
- package/.opencode/agents/growth-strategist.yml +12 -0
- package/.opencode/agents/hermes-agent.yml +12 -0
- package/.opencode/agents/inference-improve.yml +12 -0
- package/.opencode/agents/lint.yml +14 -0
- package/.opencode/agents/log-monitor.yml +12 -0
- package/.opencode/agents/mobile-developer.yml +12 -0
- package/.opencode/agents/model-health-check.yml +12 -0
- package/.opencode/agents/multimodal-looker.yml +12 -0
- package/.opencode/agents/performance-analysis.yml +12 -0
- package/.opencode/agents/performance-engineer.yml +12 -0
- package/.opencode/agents/performance-optimization.yml +12 -0
- package/.opencode/agents/processor-pipeline.yml +14 -0
- package/.opencode/agents/project-analysis.yml +12 -0
- package/.opencode/agents/refactorer.yml +12 -0
- package/.opencode/agents/researcher.yml +12 -0
- package/.opencode/agents/security-auditor.yml +12 -0
- package/.opencode/agents/security-scan.yml +12 -0
- package/.opencode/agents/seo-consultant.yml +12 -0
- package/.opencode/agents/session-management.yml +12 -0
- package/.opencode/agents/state-manager.yml +12 -0
- package/.opencode/agents/storyteller.yml +12 -0
- package/.opencode/agents/strategist.yml +12 -0
- package/.opencode/agents/tech-writer.yml +12 -0
- package/.opencode/agents/testing-best-practices.yml +12 -0
- package/.opencode/agents/testing-lead.yml +12 -0
- package/.opencode/agents/ui-ux-design.yml +12 -0
- package/.opencode/codex.codex +8 -0
- package/.opencode/commands/auto-format.md +99 -0
- package/.opencode/commands/auto-summary-capture.md +90 -0
- package/.opencode/commands/dependency-audit.md +184 -0
- package/.opencode/commands/enforcer-daily-scan.md +137 -0
- package/.opencode/commands/framework-compliance-audit.md +205 -0
- package/.opencode/commands/interactive-validator.md +75 -0
- package/.opencode/commands/job-summary-logger.md +68 -0
- package/.opencode/commands/lint.md +11 -0
- package/.opencode/commands/mode-switch.md +95 -0
- package/.opencode/commands/model-health-check.md +186 -0
- package/.opencode/commands/performance-analysis.md +144 -0
- package/.opencode/commands/pre-commit-introspection.md +185 -0
- package/.opencode/commands/pre-commit-introspection.sh +133 -0
- package/.opencode/commands/security-scan.md +157 -0
- package/.opencode/commands/sisyphus-validation.md +128 -0
- package/.opencode/commands/summary-logger.md +83 -0
- package/.opencode/enforcer-config.json +282 -0
- package/.opencode/skills/orchestrator/SKILL.md +12 -0
- package/.opencode/workflows/post-deployment-audit.yml +123 -0
- package/.xray/features.json +1 -1
- package/.xray/features.schema.json +1 -1
- package/AGENTS-consumer.md +2 -0
- package/AGENTS.md +2 -0
- package/README.md +52 -12
- package/SKILLS.md +2 -0
- package/dist/AGENTS.md +2 -0
- package/dist/CHANGELOG.md +29 -0
- package/dist/README.md +52 -12
- package/dist/SKILLS.md +2 -0
- package/dist/cli/commands/openclaw-install.js +1 -1
- package/dist/cli/index.js +12 -0
- package/dist/enforcement/index.d.ts +4 -0
- package/dist/enforcement/index.js +4 -0
- package/dist/enforcement/validators/code-quality-validators.js +6 -4
- package/dist/governance/llm-governance-provider.d.ts +7 -1
- package/dist/governance/llm-governance-provider.js +72 -14
- package/dist/governance/local-confer.d.ts +4 -1
- package/dist/governance/local-confer.js +22 -1
- package/dist/integrations/grok/grok-cli.js +10 -37
- package/dist/integrations/grok/hooks/grok-hook-utils.js +29 -2
- package/dist/integrations/grok/hooks/session-start.js +2 -20
- package/dist/integrations/hooks/confer-hook-runtime.mjs +23 -1
- package/dist/integrations/hooks/goggles-mcp.mjs +36 -4
- package/dist/integrations/hooks/goggles-pipeline.mjs +55 -15
- package/dist/integrations/hooks/goggles-planes.json +13 -4
- package/dist/integrations/hooks/plates.cjs +22 -0
- package/dist/integrations/hooks/session-note-index.cjs +298 -0
- package/dist/integrations/hooks/session-note-index.mjs +22 -0
- package/dist/integrations/hooks/sleeve.cjs +335 -0
- package/dist/integrations/hooks/sleeve.mjs +18 -0
- package/dist/integrations/hooks/station-hook-runtime.cjs +205 -9
- package/dist/integrations/hooks/wake-cascade.cjs +102 -0
- package/dist/integrations/hooks/wake-cascade.mjs +16 -0
- package/dist/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
- package/dist/mcps/architect-tools.server.d.ts +6 -0
- package/dist/mcps/architect-tools.server.js +19 -2
- package/dist/mcps/config/server-config-registry.js +8 -6
- package/dist/mcps/governance.server.d.ts +1 -0
- package/dist/mcps/governance.server.js +46 -0
- package/dist/mcps/knowledge-skills/code-review.server.js +7 -0
- package/dist/mcps/knowledge-skills/security-audit.server.js +5 -3
- package/dist/mcps/mcp-client.js +1 -1
- package/dist/mcps/orchestrator/handlers/complexity-handler.js +2 -2
- package/dist/mcps/researcher.server.js +12 -3
- package/dist/memory-routing/plates.d.ts +1 -1
- package/dist/memory-routing/plates.js +1 -0
- package/dist/nucleus/autonomy-kernel.d.ts +2 -0
- package/dist/nucleus/autonomy-kernel.js +17 -13
- package/dist/nucleus/confer-host.d.ts +35 -0
- package/dist/nucleus/confer-host.js +55 -0
- package/dist/nucleus/confer.d.ts +19 -3
- package/dist/nucleus/confer.js +111 -55
- package/dist/nucleus/lead-dev-plan-persistence.js +4 -2
- package/dist/nucleus/suit-temperament.d.ts +1 -1
- package/dist/nucleus/suit-temperament.js +2 -2
- package/dist/nucleus/synthesis-consult-receipt.d.ts +7 -1
- package/dist/nucleus/synthesis-consult-receipt.js +86 -35
- package/dist/reporting/framework-reporting-system.js +2 -5
- package/dist/reporting/log-parser.d.ts +2 -0
- package/dist/reporting/log-parser.js +7 -6
- package/dist/skills/orchestrator/SKILL.md +12 -0
- package/docs-site/docs/plates/activity-log.md +1 -1
- package/docs-site/docs/plates/boot.md +2 -0
- package/docs-site/docs/plates/centrifuge.md +30 -0
- package/docs-site/docs/plates/cursor-compact.md +1 -1
- package/docs-site/docs/plates/glossary.md +1 -2
- package/docs-site/docs/plates/goggles.md +4 -0
- package/docs-site/docs/plates/governance.md +2 -0
- package/docs-site/docs/plates/grok-compact.md +1 -1
- package/docs-site/docs/plates/grokbot.md +1 -1
- package/docs-site/docs/plates/host-pack.md +2 -0
- package/docs-site/docs/plates/house.md +1 -1
- package/docs-site/docs/plates/index.md +3 -1
- package/docs-site/docs/plates/inference-files.md +1 -1
- package/docs-site/docs/plates/kept-line.md +1 -1
- package/docs-site/docs/plates/kits.md +2 -0
- package/docs-site/docs/plates/lens-gate.md +1 -1
- package/docs-site/docs/plates/lens-page.md +1 -1
- package/docs-site/docs/plates/live-mesh.md +1 -1
- package/docs-site/docs/plates/memory-recall.md +4 -0
- package/docs-site/docs/plates/notes-page.md +2 -1
- package/docs-site/docs/plates/orchestration.md +2 -0
- package/docs-site/docs/plates/package-face.md +1 -1
- package/docs-site/docs/plates/payload-heat.md +1 -1
- package/docs-site/docs/plates/pickup-stamp.md +1 -1
- package/docs-site/docs/plates/pre-tool.md +1 -1
- package/docs-site/docs/plates/processor.md +2 -0
- package/docs-site/docs/plates/record-map.md +2 -1
- package/docs-site/docs/plates/reflection-page.md +1 -1
- package/docs-site/docs/plates/reporting.md +2 -0
- package/docs-site/docs/plates/review.md +1 -1
- package/docs-site/docs/plates/routing.md +2 -0
- package/docs-site/docs/plates/session-capture.md +1 -1
- package/docs-site/docs/plates/site-manual.md +1 -1
- package/docs-site/docs/plates/stamp-plate.md +1 -1
- package/docs-site/docs/plates/station-card.md +4 -1
- package/docs-site/docs/plates/station-heat.md +1 -1
- package/docs-site/docs/plates/suit-organs.md +1 -1
- package/docs-site/docs/plates/suit-settings.md +1 -1
- package/docs-site/docs/plates/suit-wear.md +3 -1
- package/docs-site/docs/plates/suit.md +2 -0
- package/docs-site/docs/plates/trail-state.md +1 -1
- package/docs-site/docs/plates/work-fresh.md +1 -1
- package/docs-site/docs/plates/write-home.md +1 -1
- package/llms.txt +2 -0
- package/package.json +2 -2
- package/scripts/mjs/verify-confer-core.mjs +153 -29
- package/scripts/mjs/verify-user-aside-core.mjs +3 -4
- package/scripts/node/bridge-mcp-wiring.cjs +273 -9
- package/scripts/node/confer-switch.cjs +66 -0
- package/scripts/node/install-bridges.cjs +188 -60
- package/scripts/node/setup.cjs +2 -46
- package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
- package/src/mcps/architect-tools.server.ts +26 -2
- package/src/mcps/config/__tests__/server-config-registry.test.ts +15 -6
- package/src/mcps/config/server-config-registry.ts +9 -6
- package/src/mcps/governance.server.ts +49 -0
- package/src/mcps/knowledge-skills/code-review.server.ts +8 -0
- package/src/mcps/knowledge-skills/security-audit.server.ts +11 -12
- package/src/mcps/mcp-client.ts +1 -1
- package/src/mcps/orchestrator/handlers/complexity-handler.ts +2 -1
- package/src/mcps/researcher.server.ts +19 -10
- package/src/skills/orchestrator/SKILL.md +12 -0
- package/vendor/@0xray/repertoire/scripts/run-live-synthesis-checkpoint.mjs +5 -51
- package/xray/features.json +1 -1
- package/xray/features.schema.json +1 -1
|
@@ -139,11 +139,32 @@ function enableMemoryRoutingIfResolves(features, targetDir) {
|
|
|
139
139
|
};
|
|
140
140
|
}
|
|
141
141
|
|
|
142
|
+
function isDogfoodXrayPackage(targetDir) {
|
|
143
|
+
try {
|
|
144
|
+
const pkgPath = path.join(targetDir, "package.json");
|
|
145
|
+
if (!fs.existsSync(pkgPath)) return false;
|
|
146
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf8"));
|
|
147
|
+
return pkg && pkg.name === "0xray";
|
|
148
|
+
} catch {
|
|
149
|
+
return false;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
142
153
|
function resolveGogglesMcp(targetDir) {
|
|
143
|
-
const
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
154
|
+
const installed = path.join(
|
|
155
|
+
targetDir,
|
|
156
|
+
"node_modules",
|
|
157
|
+
"0xray",
|
|
158
|
+
"scripts",
|
|
159
|
+
"mjs",
|
|
160
|
+
"run-goggles-mcp.mjs",
|
|
161
|
+
);
|
|
162
|
+
const checkout = path.join(targetDir, "scripts", "mjs", "run-goggles-mcp.mjs");
|
|
163
|
+
// The factory package is not installed into its own node_modules. npm upgrade
|
|
164
|
+
// removes that folder, and a recorded node_modules path then fails the handshake.
|
|
165
|
+
const candidates = isDogfoodXrayPackage(targetDir)
|
|
166
|
+
? [checkout, installed]
|
|
167
|
+
: [installed, checkout];
|
|
147
168
|
return candidates.find((file) => fs.existsSync(file)) || null;
|
|
148
169
|
}
|
|
149
170
|
|
|
@@ -315,7 +336,18 @@ function pinnedMcpLaunch(targetDir, mcpCmd) {
|
|
|
315
336
|
*/
|
|
316
337
|
const LIVE_ENV_NAMES = ["PATH", "HOME"];
|
|
317
338
|
|
|
339
|
+
let launcherPackageRoot = "";
|
|
340
|
+
|
|
341
|
+
/** Wear sets this so a /tmp checkout is not the path written into a real project. */
|
|
342
|
+
function pinLauncherPackageRoot(packageRoot) {
|
|
343
|
+
launcherPackageRoot = packageRoot ? path.resolve(packageRoot) : "";
|
|
344
|
+
}
|
|
345
|
+
|
|
318
346
|
function mcpLauncherPath() {
|
|
347
|
+
if (launcherPackageRoot) {
|
|
348
|
+
const candidate = path.join(launcherPackageRoot, "scripts", "node", "mcp-launch.cjs");
|
|
349
|
+
if (fs.existsSync(candidate)) return candidate;
|
|
350
|
+
}
|
|
319
351
|
return path.join(__dirname, "mcp-launch.cjs");
|
|
320
352
|
}
|
|
321
353
|
|
|
@@ -837,7 +869,125 @@ function resolveOpenClawPluginDir(packageRoot) {
|
|
|
837
869
|
].find((p) => fs.existsSync(path.join(p, "index.js"))) || null;
|
|
838
870
|
}
|
|
839
871
|
|
|
840
|
-
function
|
|
872
|
+
function isCheckoutOpenClawPluginPath(pluginPath) {
|
|
873
|
+
const normalized = String(pluginPath || "").replace(/\\/g, "/");
|
|
874
|
+
return (
|
|
875
|
+
normalized.includes("/src/integrations/openclaw/plugin/xray-pre-tool") &&
|
|
876
|
+
!normalized.includes("/node_modules/")
|
|
877
|
+
);
|
|
878
|
+
}
|
|
879
|
+
|
|
880
|
+
function isInstalledOpenClawPluginPath(pluginPath) {
|
|
881
|
+
const normalized = String(pluginPath || "").replace(/\\/g, "/");
|
|
882
|
+
return (
|
|
883
|
+
normalized.includes("/node_modules/") &&
|
|
884
|
+
normalized.includes("/integrations/openclaw/plugin/xray-pre-tool")
|
|
885
|
+
);
|
|
886
|
+
}
|
|
887
|
+
|
|
888
|
+
/** Installed package first. A checkout src path drops once any installed plugin is present. */
|
|
889
|
+
function settleOpenClawPluginPaths(paths, wornPluginDir) {
|
|
890
|
+
const list = (Array.isArray(paths) ? paths : []).map((entry) => String(entry));
|
|
891
|
+
const wornIsInstalled = Boolean(wornPluginDir && isInstalledOpenClawPluginPath(wornPluginDir));
|
|
892
|
+
const dropCheckout =
|
|
893
|
+
wornIsInstalled || list.some((entry) => isInstalledOpenClawPluginPath(entry));
|
|
894
|
+
const next = [];
|
|
895
|
+
const seen = new Set();
|
|
896
|
+
const push = (entry) => {
|
|
897
|
+
if (!entry) return;
|
|
898
|
+
const resolved = path.resolve(String(entry));
|
|
899
|
+
if (dropCheckout && isCheckoutOpenClawPluginPath(resolved)) return;
|
|
900
|
+
if (seen.has(resolved)) return;
|
|
901
|
+
seen.add(resolved);
|
|
902
|
+
next.push(resolved);
|
|
903
|
+
};
|
|
904
|
+
if (wornIsInstalled) push(wornPluginDir);
|
|
905
|
+
for (const entry of list) push(entry);
|
|
906
|
+
return next;
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
function resolveWornOpenClawPlugin(targetDir, packageRoot) {
|
|
910
|
+
const candidates = [];
|
|
911
|
+
if (targetDir) {
|
|
912
|
+
candidates.push(
|
|
913
|
+
path.join(targetDir, "node_modules", "0xray", "dist", "integrations", "openclaw", "plugin", "xray-pre-tool"),
|
|
914
|
+
path.join(targetDir, "node_modules", "0xray", "src", "integrations", "openclaw", "plugin", "xray-pre-tool"),
|
|
915
|
+
);
|
|
916
|
+
}
|
|
917
|
+
const fromPackage = resolveOpenClawPluginDir(packageRoot);
|
|
918
|
+
if (fromPackage) candidates.push(fromPackage);
|
|
919
|
+
return candidates.find((dir) => fs.existsSync(path.join(dir, "index.js"))) || null;
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
function replaceJsonPathsArray(raw, before, next) {
|
|
923
|
+
const keyAt = raw.indexOf('"paths"');
|
|
924
|
+
if (keyAt < 0) return null;
|
|
925
|
+
const bracket = raw.indexOf("[", keyAt);
|
|
926
|
+
if (bracket < 0) return null;
|
|
927
|
+
let depth = 0;
|
|
928
|
+
let end = -1;
|
|
929
|
+
for (let i = bracket; i < raw.length; i += 1) {
|
|
930
|
+
const ch = raw[i];
|
|
931
|
+
if (ch === "[") depth += 1;
|
|
932
|
+
else if (ch === "]") {
|
|
933
|
+
depth -= 1;
|
|
934
|
+
if (depth === 0) {
|
|
935
|
+
end = i;
|
|
936
|
+
break;
|
|
937
|
+
}
|
|
938
|
+
}
|
|
939
|
+
}
|
|
940
|
+
if (end < 0) return null;
|
|
941
|
+
let parsed;
|
|
942
|
+
try {
|
|
943
|
+
parsed = JSON.parse(raw.slice(bracket, end + 1));
|
|
944
|
+
} catch {
|
|
945
|
+
return null;
|
|
946
|
+
}
|
|
947
|
+
if (JSON.stringify(parsed) !== JSON.stringify(before)) return null;
|
|
948
|
+
const lineStart = raw.lastIndexOf("\n", keyAt) + 1;
|
|
949
|
+
const indent = (raw.slice(lineStart, keyAt).match(/^\s*/) || [""])[0];
|
|
950
|
+
const itemIndent = `${indent} `;
|
|
951
|
+
const body = next
|
|
952
|
+
.map((entry) => `${itemIndent}${JSON.stringify(entry)}`)
|
|
953
|
+
.join(",\n");
|
|
954
|
+
const array = `[\n${body}\n${indent}]`;
|
|
955
|
+
return `${raw.slice(0, bracket)}${array}${raw.slice(end + 1)}`;
|
|
956
|
+
}
|
|
957
|
+
|
|
958
|
+
/** Rewrite plugins.load.paths in place. Leaves the rest of the config file alone. */
|
|
959
|
+
function pinOpenClawPluginLoad(configPath, wornPluginDir) {
|
|
960
|
+
if (!configPath || !fs.existsSync(configPath)) return null;
|
|
961
|
+
const raw = fs.readFileSync(configPath, "utf8");
|
|
962
|
+
const config = JSON.parse(raw);
|
|
963
|
+
if (!config.plugins || typeof config.plugins !== "object") return null;
|
|
964
|
+
if (!config.plugins.load || typeof config.plugins.load !== "object") config.plugins.load = {};
|
|
965
|
+
const before = Array.isArray(config.plugins.load.paths) ? config.plugins.load.paths : [];
|
|
966
|
+
const next = settleOpenClawPluginPaths(before, wornPluginDir);
|
|
967
|
+
if (JSON.stringify(before) === JSON.stringify(next)) return next;
|
|
968
|
+
const replaced = replaceJsonPathsArray(raw, before, next);
|
|
969
|
+
if (replaced == null) return null;
|
|
970
|
+
fs.writeFileSync(configPath, replaced);
|
|
971
|
+
return next;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
function recordOpenClawProjectPlugin(targetDir, packageRoot) {
|
|
975
|
+
const pluginDir = resolveWornOpenClawPlugin(targetDir, packageRoot);
|
|
976
|
+
if (!pluginDir || !isInstalledOpenClawPluginPath(pluginDir)) return null;
|
|
977
|
+
const configPath = path.join(targetDir, ".xray", "config", "openclaw.json");
|
|
978
|
+
if (!fs.existsSync(configPath)) return null;
|
|
979
|
+
let config;
|
|
980
|
+
try {
|
|
981
|
+
config = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
982
|
+
} catch {
|
|
983
|
+
return null;
|
|
984
|
+
}
|
|
985
|
+
config.pluginPath = path.resolve(pluginDir);
|
|
986
|
+
fs.writeFileSync(configPath, `${JSON.stringify(config, null, 2)}\n`);
|
|
987
|
+
return config.pluginPath;
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
function installOpenClawHostWear(packageRoot, targetDir) {
|
|
841
991
|
if (millSuit.isIsolatedHome()) return null;
|
|
842
992
|
const source = resolveOpenClawPreToolHookSource(packageRoot);
|
|
843
993
|
if (!source) return null;
|
|
@@ -846,6 +996,11 @@ function installOpenClawHostWear(packageRoot) {
|
|
|
846
996
|
fs.mkdirSync(hookDir, { recursive: true });
|
|
847
997
|
const dest = path.join(hookDir, "xray-pre-tool.mjs");
|
|
848
998
|
fs.copyFileSync(source, dest);
|
|
999
|
+
const worn = resolveWornOpenClawPlugin(targetDir, packageRoot);
|
|
1000
|
+
const hookRoot =
|
|
1001
|
+
worn && isInstalledOpenClawPluginPath(worn) && targetDir
|
|
1002
|
+
? path.join(path.resolve(targetDir), "node_modules", "0xray")
|
|
1003
|
+
: packageRoot;
|
|
849
1004
|
fs.writeFileSync(
|
|
850
1005
|
path.join(hookDir, "xray-pre-tool.json"),
|
|
851
1006
|
`${JSON.stringify(
|
|
@@ -855,17 +1010,16 @@ function installOpenClawHostWear(packageRoot) {
|
|
|
855
1010
|
args: [dest],
|
|
856
1011
|
stdin: "json",
|
|
857
1012
|
blockExitCode: 2,
|
|
858
|
-
env: { XRAY_AI_PATH:
|
|
1013
|
+
env: { XRAY_AI_PATH: hookRoot },
|
|
859
1014
|
},
|
|
860
1015
|
null,
|
|
861
1016
|
2,
|
|
862
1017
|
)}\n`,
|
|
863
1018
|
);
|
|
864
1019
|
|
|
865
|
-
|
|
866
|
-
if (pluginSrc) {
|
|
1020
|
+
if (worn && isInstalledOpenClawPluginPath(worn)) {
|
|
867
1021
|
try {
|
|
868
|
-
execFileSync("openclaw", ["plugins", "install", "-l",
|
|
1022
|
+
execFileSync("openclaw", ["plugins", "install", "-l", path.resolve(worn)], {
|
|
869
1023
|
stdio: "pipe",
|
|
870
1024
|
encoding: "utf8",
|
|
871
1025
|
timeout: 60000,
|
|
@@ -883,6 +1037,13 @@ function installOpenClawHostWear(packageRoot) {
|
|
|
883
1037
|
/* enable is best-effort */
|
|
884
1038
|
}
|
|
885
1039
|
}
|
|
1040
|
+
const configPath = resolveOpenClawConfigPath();
|
|
1041
|
+
if (fs.existsSync(configPath)) {
|
|
1042
|
+
pinOpenClawPluginLoad(
|
|
1043
|
+
configPath,
|
|
1044
|
+
worn && isInstalledOpenClawPluginPath(worn) ? worn : null,
|
|
1045
|
+
);
|
|
1046
|
+
}
|
|
886
1047
|
return dest;
|
|
887
1048
|
}
|
|
888
1049
|
|
|
@@ -947,6 +1108,102 @@ function wireOpenClawBridge(targetDir) {
|
|
|
947
1108
|
return syncOpenClawMcpRegistry(targetDir);
|
|
948
1109
|
}
|
|
949
1110
|
|
|
1111
|
+
function tomlString(value) {
|
|
1112
|
+
return JSON.stringify(String(value));
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
function suitServerNames() {
|
|
1116
|
+
return new Set(XRAY_MCP_SERVERS.map((server) => server.name));
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
function isSuitMcpHeader(line, names) {
|
|
1120
|
+
const match = /^\[([^\]]+)\]\s*$/.exec(line.trim());
|
|
1121
|
+
if (!match) return false;
|
|
1122
|
+
const parts = match[1].split(".");
|
|
1123
|
+
return parts[0] === "mcp_servers" && names.has(parts[1]);
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
function stripSuitMcpBlocks(toml, names) {
|
|
1127
|
+
const kept = [];
|
|
1128
|
+
let skip = false;
|
|
1129
|
+
for (const line of String(toml || "").split(/\r?\n/)) {
|
|
1130
|
+
if (/^\s*\[/.test(line)) skip = isSuitMcpHeader(line, names);
|
|
1131
|
+
if (!skip) kept.push(line);
|
|
1132
|
+
}
|
|
1133
|
+
return kept.join("\n").replace(/\n{3,}/g, "\n\n").trim();
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
function suitMcpBlock(server, launch) {
|
|
1137
|
+
const args = launch.args.map((arg) => ` ${tomlString(arg)},`).join("\n");
|
|
1138
|
+
const lines = [
|
|
1139
|
+
`[mcp_servers.${server.name}]`,
|
|
1140
|
+
`command = ${tomlString(launch.command)}`,
|
|
1141
|
+
"args = [",
|
|
1142
|
+
args,
|
|
1143
|
+
"]",
|
|
1144
|
+
"enabled = true",
|
|
1145
|
+
];
|
|
1146
|
+
const env = launch.env && typeof launch.env === "object" ? launch.env : {};
|
|
1147
|
+
const envKeys = Object.keys(env);
|
|
1148
|
+
if (envKeys.length > 0) {
|
|
1149
|
+
lines.push("", `[mcp_servers.${server.name}.env]`);
|
|
1150
|
+
for (const key of envKeys) lines.push(`${key} = ${tomlString(env[key])}`);
|
|
1151
|
+
}
|
|
1152
|
+
return lines.join("\n");
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
/**
|
|
1156
|
+
* Project `.grok/config.toml` replaces a same-named user server.
|
|
1157
|
+
* The launch is the worn package, not `npx -y 0xray`.
|
|
1158
|
+
*/
|
|
1159
|
+
function writeProjectSuitMcp(targetDir) {
|
|
1160
|
+
const root = path.resolve(targetDir);
|
|
1161
|
+
const names = suitServerNames();
|
|
1162
|
+
const blocks = XRAY_MCP_SERVERS.map((server) =>
|
|
1163
|
+
suitMcpBlock(server, scopedMcpLaunch(root, server.mcpCmd, server.env)),
|
|
1164
|
+
);
|
|
1165
|
+
const grokDir = path.join(root, ".grok");
|
|
1166
|
+
fs.mkdirSync(grokDir, { recursive: true });
|
|
1167
|
+
const tomlPath = path.join(grokDir, "config.toml");
|
|
1168
|
+
const existing = fs.existsSync(tomlPath) ? fs.readFileSync(tomlPath, "utf8") : "";
|
|
1169
|
+
const kept = stripSuitMcpBlocks(existing, names);
|
|
1170
|
+
const body = [kept, blocks.join("\n\n")].filter((part) => part && part.trim()).join("\n\n");
|
|
1171
|
+
fs.writeFileSync(tomlPath, `${body.trim()}\n`);
|
|
1172
|
+
return tomlPath;
|
|
1173
|
+
}
|
|
1174
|
+
|
|
1175
|
+
function grokConfigHome(env) {
|
|
1176
|
+
const source = env || process.env;
|
|
1177
|
+
const home = source.HOME || source.USERPROFILE;
|
|
1178
|
+
return home ? path.resolve(home) : os.homedir();
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
/** Grok 1.0.50 has no --trust flag. An untrusted folder skips project MCP. */
|
|
1182
|
+
function trustGrokFolder(targetDir, env) {
|
|
1183
|
+
const home = grokConfigHome(env);
|
|
1184
|
+
const grokDir = path.join(home, ".grok");
|
|
1185
|
+
fs.mkdirSync(grokDir, { recursive: true });
|
|
1186
|
+
const file = path.join(grokDir, "trusted_folders.toml");
|
|
1187
|
+
let text = fs.existsSync(file) ? fs.readFileSync(file, "utf8") : "";
|
|
1188
|
+
const folders = [path.resolve(targetDir)];
|
|
1189
|
+
try {
|
|
1190
|
+
const real = fs.realpathSync(folders[0]);
|
|
1191
|
+
if (real !== folders[0]) folders.push(real);
|
|
1192
|
+
} catch {
|
|
1193
|
+
/* the path is the one Grok will see */
|
|
1194
|
+
}
|
|
1195
|
+
const now = Math.floor(Date.now() / 1000);
|
|
1196
|
+
let added = 0;
|
|
1197
|
+
for (const folder of folders) {
|
|
1198
|
+
const header = `[folders.${tomlString(folder)}]`;
|
|
1199
|
+
if (text.includes(header)) continue;
|
|
1200
|
+
text = `${text.replace(/\s*$/, "")}\n${header}\ntrusted = true\ndecided_at = ${now}\n`;
|
|
1201
|
+
added += 1;
|
|
1202
|
+
}
|
|
1203
|
+
if (added > 0) fs.writeFileSync(file, text.endsWith("\n") ? text : `${text}\n`);
|
|
1204
|
+
return file;
|
|
1205
|
+
}
|
|
1206
|
+
|
|
950
1207
|
module.exports = {
|
|
951
1208
|
XRAY_MCP_SERVERS,
|
|
952
1209
|
HERMES_CONFIG_PATH,
|
|
@@ -988,9 +1245,16 @@ module.exports = {
|
|
|
988
1245
|
enableMemoryRoutingIfResolves,
|
|
989
1246
|
isEphemeralInstallRoot,
|
|
990
1247
|
isIsolatedHome,
|
|
1248
|
+
pinLauncherPackageRoot,
|
|
991
1249
|
copyHermesHookRuntimes,
|
|
992
1250
|
resolveOpenClawPreToolHookSource,
|
|
993
1251
|
resolveOpenClawPluginDir,
|
|
994
1252
|
installOpenClawHostWear,
|
|
1253
|
+
settleOpenClawPluginPaths,
|
|
1254
|
+
pinOpenClawPluginLoad,
|
|
1255
|
+
recordOpenClawProjectPlugin,
|
|
1256
|
+
resolveWornOpenClawPlugin,
|
|
995
1257
|
maybeWriteOpenClawCliBackend,
|
|
1258
|
+
writeProjectSuitMcp,
|
|
1259
|
+
trustGrokFolder,
|
|
996
1260
|
};
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Turn confer on or off in the worn .xray/features.json.
|
|
4
|
+
* A missing key stays off until this runs. Synthesis stays untouched.
|
|
5
|
+
*/
|
|
6
|
+
"use strict";
|
|
7
|
+
|
|
8
|
+
const fs = require("fs");
|
|
9
|
+
const path = require("path");
|
|
10
|
+
|
|
11
|
+
function fail(message) {
|
|
12
|
+
process.stderr.write(`${message}\n`);
|
|
13
|
+
process.exit(1);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function orchestrationBlock(data) {
|
|
17
|
+
const current = data.multi_agent_orchestration;
|
|
18
|
+
if (current && typeof current === "object" && !Array.isArray(current)) return current;
|
|
19
|
+
const created = {};
|
|
20
|
+
data.multi_agent_orchestration = created;
|
|
21
|
+
return created;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function conferBlock(orch) {
|
|
25
|
+
const current = orch.confer;
|
|
26
|
+
if (current && typeof current === "object" && !Array.isArray(current)) return current;
|
|
27
|
+
const created = {};
|
|
28
|
+
orch.confer = created;
|
|
29
|
+
return created;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function main() {
|
|
33
|
+
const state = process.argv[2];
|
|
34
|
+
if (state !== "on" && state !== "off") fail("confer: say on or off");
|
|
35
|
+
|
|
36
|
+
const featuresPath = path.join(process.cwd(), ".xray", "features.json");
|
|
37
|
+
if (!fs.existsSync(featuresPath)) {
|
|
38
|
+
fail("confer: .xray/features.json is missing. Run npx 0xray wear first.");
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let data;
|
|
42
|
+
try {
|
|
43
|
+
data = JSON.parse(fs.readFileSync(featuresPath, "utf8"));
|
|
44
|
+
} catch {
|
|
45
|
+
fail("confer: .xray/features.json is not valid JSON");
|
|
46
|
+
}
|
|
47
|
+
if (!data || typeof data !== "object" || Array.isArray(data)) {
|
|
48
|
+
fail("confer: .xray/features.json is not valid JSON");
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const orch = orchestrationBlock(data);
|
|
52
|
+
const confer = conferBlock(orch);
|
|
53
|
+
if (state === "on") {
|
|
54
|
+
confer.enabled = true;
|
|
55
|
+
if (confer.on_synthesis !== false) confer.on_synthesis = true;
|
|
56
|
+
} else {
|
|
57
|
+
confer.enabled = false;
|
|
58
|
+
confer.on_synthesis = false;
|
|
59
|
+
orch.confer_on_synthesis = false;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
fs.writeFileSync(featuresPath, `${JSON.stringify(data, null, 2)}\n`);
|
|
63
|
+
process.stdout.write(`confer: ${state}\n`);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
if (require.main === module) main();
|