0xray 3.2.0 → 3.3.1

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.
Files changed (36) hide show
  1. package/.opencode/codex.codex +1 -1
  2. package/dist/CHANGELOG.md +36 -0
  3. package/dist/core/features-config.js +3 -0
  4. package/dist/integrations/grok/grok-cli.js +6 -0
  5. package/dist/mcps/index.js +1 -0
  6. package/dist/mcps/knowledge-skills/skill-invocation.server.js +3 -2
  7. package/dist/mcps/knowledge-skills/storyteller.server.js +167 -0
  8. package/dist/mcps/orchestrator/config/agent-capabilities.js +30 -11
  9. package/dist/mcps/orchestrator/config/memory-routing-bridge.js +70 -0
  10. package/dist/mcps/orchestrator/execution/execution-planner.js +38 -8
  11. package/dist/mcps/orchestrator/handlers/task-handler.js +55 -2
  12. package/dist/mcps/researcher-confidence.js +92 -0
  13. package/dist/mcps/researcher.server.js +19 -3
  14. package/dist/memory-routing/index.js +4 -0
  15. package/dist/memory-routing/null-provider.js +63 -0
  16. package/dist/memory-routing/provider-loader.js +91 -0
  17. package/dist/memory-routing/provider-registry.js +40 -0
  18. package/dist/memory-routing/types.js +7 -0
  19. package/dist/memory-routing/validate-config.js +32 -0
  20. package/dist/nucleus/thin-dispatch.js +29 -1
  21. package/package.json +1 -1
  22. package/scripts/node/install-bridges.cjs +364 -0
  23. package/scripts/node/postinstall.cjs +24 -83
  24. package/scripts/node/setup.cjs +2 -6
  25. package/scripts/node/universal-version-manager.js +2 -2
  26. package/src/mcps/index.ts +1 -0
  27. package/src/mcps/knowledge-skills/skill-invocation.server.ts +3 -2
  28. package/src/mcps/knowledge-skills/storyteller.server.ts +206 -0
  29. package/src/mcps/orchestrator/config/agent-capabilities.ts +49 -14
  30. package/src/mcps/orchestrator/config/memory-routing-bridge.ts +80 -0
  31. package/src/mcps/orchestrator/execution/execution-planner.ts +49 -10
  32. package/src/mcps/orchestrator/handlers/task-handler.ts +71 -2
  33. package/src/mcps/orchestrator/types.ts +17 -0
  34. package/src/mcps/researcher-confidence.ts +144 -0
  35. package/src/mcps/researcher.server.ts +28 -3
  36. package/src/opencode/codex.codex +1 -1
@@ -0,0 +1,92 @@
1
+ import { frameworkLogger } from '../core/framework-logger.js';
2
+ import { getMemoryRoutingProviderSync } from '../memory-routing/index.js';
3
+ const TRAP_LANGUAGE = /TYPE:\s*ontological-trap|ontological[- ]trap/i;
4
+ const DEFAULT_MIN_CONFIDENCE_GATE = 0.55;
5
+ export function shouldQueryRepertoireConfidence(description, proposalType = '') {
6
+ const text = `${description} ${proposalType}`.trim();
7
+ return TRAP_LANGUAGE.test(text);
8
+ }
9
+ export function hasHighConfidencePrimitiveMatch(routingContext, minConfidence = DEFAULT_MIN_CONFIDENCE_GATE) {
10
+ const confidences = routingContext.signalConfidences ?? {};
11
+ return Object.values(confidences).some((confidence) => confidence >= minConfidence);
12
+ }
13
+ function buildTaskText(proposalTitle, proposalDescription, proposalType) {
14
+ return [proposalTitle, proposalDescription, proposalType].filter(Boolean).join('\n');
15
+ }
16
+ /**
17
+ * Resolve Repertoire task confidence for researcher proposal analysis.
18
+ * Triggered by ontological-trap language or high-confidence primitive matches.
19
+ */
20
+ export function resolveResearcherMemoryContext(input) {
21
+ const proposalTitle = input.proposalTitle ?? '';
22
+ const proposalDescription = input.proposalDescription ?? '';
23
+ const proposalType = input.proposalType ?? '';
24
+ const taskText = buildTaskText(proposalTitle, proposalDescription, proposalType);
25
+ const provider = getMemoryRoutingProviderSync();
26
+ if (provider.id === 'null' || !provider.getTaskConfidence) {
27
+ return null;
28
+ }
29
+ const trapLanguageDetected = shouldQueryRepertoireConfidence(proposalDescription, proposalType);
30
+ const routingContext = provider.buildRoutingContext(taskText);
31
+ const primitiveMatchDetected = hasHighConfidencePrimitiveMatch(routingContext);
32
+ if (!trapLanguageDetected && !primitiveMatchDetected) {
33
+ return null;
34
+ }
35
+ const confidence = provider.getTaskConfidence({
36
+ id: 'researcher-proposal',
37
+ description: taskText,
38
+ type: proposalType || 'governance',
39
+ });
40
+ const matchedSignals = confidence.matchedSignals.length > 0
41
+ ? confidence.matchedSignals
42
+ : routingContext.matchedSignals;
43
+ const context = {
44
+ providerId: provider.id,
45
+ confidence,
46
+ matchedSignals,
47
+ recommendedAgent: confidence.recommendedAgent,
48
+ triggeredBy: trapLanguageDetected ? 'trap-language' : 'high-confidence-primitives',
49
+ };
50
+ if (confidence.highConfidenceTrapPresent) {
51
+ frameworkLogger.log('mcps/researcher', 'repertoire-trap-detected', 'info', {
52
+ providerId: provider.id,
53
+ matchedSignals,
54
+ complexityBoost: confidence.complexityBoost,
55
+ recommendedAgent: confidence.recommendedAgent,
56
+ triggeredBy: context.triggeredBy,
57
+ });
58
+ }
59
+ return context;
60
+ }
61
+ export function buildMemoryRoutingEvidence(context) {
62
+ const { confidence, matchedSignals, recommendedAgent } = context;
63
+ const signalSummary = confidence.signals
64
+ .map((entry) => `${entry.name} (${entry.confidence.toFixed(2)})`)
65
+ .join(', ');
66
+ const lines = [
67
+ `Repertoire memory routing (${context.providerId}, trigger: ${context.triggeredBy})`,
68
+ `Matched signals: ${matchedSignals.join(', ') || 'none'}`,
69
+ `Signal confidences: ${signalSummary || 'none'}`,
70
+ `High-confidence trap present: ${confidence.highConfidenceTrapPresent}`,
71
+ `Complexity boost: ${confidence.complexityBoost}`,
72
+ ];
73
+ if (recommendedAgent) {
74
+ lines.push(`Recommended agent for trap handling: ${recommendedAgent}`);
75
+ }
76
+ return lines;
77
+ }
78
+ export function formatMemoryRoutingBlock(context) {
79
+ const { confidence, matchedSignals, recommendedAgent } = context;
80
+ const lines = [
81
+ 'MEMORY_ROUTING:',
82
+ ` provider: ${context.providerId}`,
83
+ ` trigger: ${context.triggeredBy}`,
84
+ ` matchedSignals: ${matchedSignals.join(', ') || 'none'}`,
85
+ ` highConfidenceTrapPresent: ${confidence.highConfidenceTrapPresent}`,
86
+ ` complexityBoost: ${confidence.complexityBoost}`,
87
+ ];
88
+ if (recommendedAgent) {
89
+ lines.push(` recommendedAgent: ${recommendedAgent}`);
90
+ }
91
+ return lines.join('\n');
92
+ }
@@ -11,6 +11,7 @@ import * as fs from "fs";
11
11
  import * as path from "path";
12
12
  import { frameworkLogger } from "../core/framework-logger.js";
13
13
  import { tryLLMGovernance } from "../governance/llm-governance-provider.js";
14
+ import { buildMemoryRoutingEvidence, formatMemoryRoutingBlock, resolveResearcherMemoryContext, } from "./researcher-confidence.js";
14
15
  import { XrayKnowledgeSkillBase } from "./shared/knowledge-skill-base.js";
15
16
  class XrayLibrarianServer extends XrayKnowledgeSkillBase {
16
17
  constructor() {
@@ -377,13 +378,28 @@ class XrayLibrarianServer extends XrayKnowledgeSkillBase {
377
378
  */
378
379
  async analyzeProposal(args) {
379
380
  const { proposalTitle = "", proposalDescription = "", evidence = [], proposalType = "" } = args || {};
380
- const vote = await tryLLMGovernance("researcher", proposalTitle || "", proposalDescription || "", evidence || [], proposalType || "");
381
+ const memoryContext = resolveResearcherMemoryContext({
382
+ proposalTitle,
383
+ proposalDescription,
384
+ proposalType,
385
+ });
386
+ const enrichedEvidence = [...(evidence || [])];
387
+ if (memoryContext?.confidence.highConfidenceTrapPresent) {
388
+ enrichedEvidence.push(...buildMemoryRoutingEvidence(memoryContext));
389
+ }
390
+ const vote = await tryLLMGovernance("researcher", proposalTitle || "", proposalDescription || "", enrichedEvidence, proposalType || "");
391
+ const memoryRoutingBlock = memoryContext?.confidence.highConfidenceTrapPresent
392
+ ? `\n${formatMemoryRoutingBlock(memoryContext)}`
393
+ : "";
381
394
  if (!vote) {
395
+ const abstainReason = memoryContext?.confidence.highConfidenceTrapPresent
396
+ ? "No LLM governance provider configured. Repertoire detected a high-confidence ontological trap — route to the recommended agent before proceeding."
397
+ : "No LLM governance provider configured. Set XRAY_GOVERNANCE_LLM_ENABLED=true + XRAY_LLM_ENDPOINT, or install Hermes and run: hermes auth add xai-oauth --no-browser";
382
398
  return {
383
399
  content: [
384
400
  {
385
401
  type: "text",
386
- text: "DECISION: abstain\nCONFIDENCE: 0.50\nREASONING: No LLM governance provider configured. Set XRAY_GOVERNANCE_LLM_ENABLED=true + XRAY_LLM_ENDPOINT, or install Hermes and run: hermes auth add xai-oauth --no-browser",
402
+ text: `DECISION: abstain\nCONFIDENCE: 0.50\nREASONING: ${abstainReason}${memoryRoutingBlock}`,
387
403
  },
388
404
  ],
389
405
  };
@@ -392,7 +408,7 @@ class XrayLibrarianServer extends XrayKnowledgeSkillBase {
392
408
  content: [
393
409
  {
394
410
  type: "text",
395
- text: `DECISION: ${vote.decision}\nCONFIDENCE: ${vote.confidence.toFixed(2)}\nREASONING: ${vote.reasoning}`,
411
+ text: `DECISION: ${vote.decision}\nCONFIDENCE: ${vote.confidence.toFixed(2)}\nREASONING: ${vote.reasoning}${memoryRoutingBlock}`,
396
412
  },
397
413
  ],
398
414
  };
@@ -0,0 +1,4 @@
1
+ export { getMemoryRoutingProvider, getMemoryRoutingProviderSync, getMemoryRoutingConfig, resetMemoryRoutingProvider, initializeMemoryRouting, } from './provider-registry.js';
2
+ export { NullMemoryRoutingProvider, createMemoryRoutingProvider } from './null-provider.js';
3
+ export { loadMemoryRoutingProvider } from './provider-loader.js';
4
+ export { validateMemoryRoutingConfig } from './validate-config.js';
@@ -0,0 +1,63 @@
1
+ const EMPTY_CONTEXT = {
2
+ providerId: 'null',
3
+ matchedSignals: [],
4
+ matchedTags: [],
5
+ flags: {},
6
+ synthesisAvailable: false,
7
+ };
8
+ export class NullMemoryRoutingProvider {
9
+ id = 'null';
10
+ name = 'Null (no memory routing)';
11
+ isAvailable() {
12
+ return true;
13
+ }
14
+ buildRoutingContext() {
15
+ return { ...EMPTY_CONTEXT };
16
+ }
17
+ enhanceAgentCapabilities(base) {
18
+ return new Map(base);
19
+ }
20
+ enrichTasks(tasks) {
21
+ return tasks;
22
+ }
23
+ buildInheritedContext() {
24
+ return { providerId: 'null', matchedSignals: [], flags: {} };
25
+ }
26
+ selectAgent(capabilities, requiredCapabilities, complexity) {
27
+ let bestAgent = null;
28
+ let bestScore = -1;
29
+ for (const [agent, caps] of capabilities) {
30
+ if (complexity > caps.complexityThreshold)
31
+ continue;
32
+ const matchCount = requiredCapabilities.filter((c) => caps.capabilities.includes(c)).length;
33
+ const score = matchCount * 10 + caps.concurrentTasks;
34
+ if (score > bestScore) {
35
+ bestScore = score;
36
+ bestAgent = agent;
37
+ }
38
+ }
39
+ return bestAgent;
40
+ }
41
+ resolveThinDispatch(baseAgent, _operation, complexityScore) {
42
+ return {
43
+ agent: baseAgent,
44
+ adjustedScore: complexityScore,
45
+ context: { ...EMPTY_CONTEXT },
46
+ };
47
+ }
48
+ getTaskConfidence() {
49
+ return {
50
+ signals: [],
51
+ matchedSignals: [],
52
+ avgConfidence: 0,
53
+ maxConfidence: 0,
54
+ highConfidenceTrapPresent: false,
55
+ ontologicalTrapDetected: false,
56
+ complexityBoost: 0,
57
+ recommendedAgent: null,
58
+ };
59
+ }
60
+ }
61
+ export function createMemoryRoutingProvider() {
62
+ return new NullMemoryRoutingProvider();
63
+ }
@@ -0,0 +1,91 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { resolve, dirname } from 'node:path';
3
+ import { pathToFileURL } from 'node:url';
4
+ import { frameworkLogger } from '../core/framework-logger.js';
5
+ import { createMemoryRoutingProvider as createNullProvider } from './null-provider.js';
6
+ import { validateMemoryRoutingConfig } from './validate-config.js';
7
+ const REPERTOIRE_CANDIDATE_PATHS = [
8
+ '../repertoire/dist/provider/memory-routing-provider.js',
9
+ '../../repertoire/dist/provider/memory-routing-provider.js',
10
+ '../../../repertoire/dist/provider/memory-routing-provider.js',
11
+ ];
12
+ /**
13
+ * SECURITY: features.json is a trusted configuration boundary.
14
+ * module_path is resolved from disk and dynamically imported without signature
15
+ * verification. Only grant write access to features.json to trusted operators.
16
+ */
17
+ function resolveModulePath(configuredPath, cwd) {
18
+ if (!configuredPath)
19
+ return null;
20
+ const candidates = [
21
+ resolve(cwd, configuredPath),
22
+ configuredPath,
23
+ ];
24
+ for (const candidate of candidates) {
25
+ if (existsSync(candidate))
26
+ return candidate;
27
+ }
28
+ return null;
29
+ }
30
+ function defaultPathForProvider(provider, cwd) {
31
+ if (provider !== 'repertoire')
32
+ return null;
33
+ for (const rel of REPERTOIRE_CANDIDATE_PATHS) {
34
+ const abs = resolve(cwd, rel);
35
+ if (existsSync(abs))
36
+ return abs;
37
+ }
38
+ return null;
39
+ }
40
+ export async function loadMemoryRoutingProvider(config, cwd = process.cwd()) {
41
+ const validation = validateMemoryRoutingConfig(config);
42
+ if (!validation.valid) {
43
+ await frameworkLogger.log('memory-routing', 'config-invalid', 'error', { errors: validation.errors, provider: config.provider });
44
+ return createNullProvider();
45
+ }
46
+ const effective = validation.normalized;
47
+ if (!effective.enabled || effective.provider === 'null') {
48
+ return createNullProvider();
49
+ }
50
+ const modulePath = resolveModulePath(effective.module_path, cwd) ??
51
+ defaultPathForProvider(effective.provider, cwd);
52
+ if (!modulePath) {
53
+ await frameworkLogger.log('memory-routing', 'provider-not-found', 'error', {
54
+ provider: effective.provider,
55
+ module_path: effective.module_path,
56
+ message: `Provider "${effective.provider}" is configured but module_path could not be resolved. Falling back to null provider.`,
57
+ });
58
+ return createNullProvider();
59
+ }
60
+ try {
61
+ const mod = await import(pathToFileURL(modulePath).href);
62
+ const factory = mod.createMemoryRoutingProvider ??
63
+ mod.default?.createMemoryRoutingProvider;
64
+ if (typeof factory !== 'function') {
65
+ throw new Error(`Module ${modulePath} must export createMemoryRoutingProvider()`);
66
+ }
67
+ const provider = factory((effective.config ?? {}));
68
+ if (!provider?.id || typeof provider.isAvailable !== 'function') {
69
+ throw new Error(`Invalid memory routing provider from ${modulePath}`);
70
+ }
71
+ if (!provider.isAvailable()) {
72
+ await frameworkLogger.log('memory-routing', 'provider-unavailable', 'error', {
73
+ providerId: provider.id,
74
+ modulePath,
75
+ message: `Provider "${provider.id}" loaded but isAvailable() returned false. Falling back to null provider.`,
76
+ });
77
+ return createNullProvider();
78
+ }
79
+ await frameworkLogger.log('memory-routing', 'provider-loaded', 'info', { providerId: provider.id, name: provider.name, modulePath });
80
+ return provider;
81
+ }
82
+ catch (err) {
83
+ await frameworkLogger.log('memory-routing', 'provider-load-failed', 'error', {
84
+ modulePath,
85
+ error: err instanceof Error ? err.message : String(err),
86
+ cwd,
87
+ configDir: dirname(modulePath),
88
+ });
89
+ return createNullProvider();
90
+ }
91
+ }
@@ -0,0 +1,40 @@
1
+ import { featuresConfigLoader } from '../core/features-config.js';
2
+ import { NullMemoryRoutingProvider } from './null-provider.js';
3
+ import { loadMemoryRoutingProvider } from './provider-loader.js';
4
+ import { validateMemoryRoutingConfig } from './validate-config.js';
5
+ let cachedProvider = null;
6
+ let loadPromise = null;
7
+ const nullProviderSingleton = new NullMemoryRoutingProvider();
8
+ export function getMemoryRoutingConfig() {
9
+ const raw = featuresConfigLoader.loadConfig().memory_routing;
10
+ const validation = validateMemoryRoutingConfig(raw ?? { enabled: false, provider: 'null' });
11
+ return validation.normalized;
12
+ }
13
+ export async function getMemoryRoutingProvider(forceReload = false) {
14
+ if (!forceReload && cachedProvider)
15
+ return cachedProvider;
16
+ if (!forceReload && loadPromise)
17
+ return loadPromise;
18
+ const config = getMemoryRoutingConfig();
19
+ loadPromise = loadMemoryRoutingProvider(config).then((provider) => {
20
+ cachedProvider = provider;
21
+ loadPromise = null;
22
+ return provider;
23
+ });
24
+ return loadPromise;
25
+ }
26
+ /** Synchronous accessor — returns shared null singleton until async load completes. */
27
+ export function getMemoryRoutingProviderSync() {
28
+ return cachedProvider ?? nullProviderSingleton;
29
+ }
30
+ export function resetMemoryRoutingProvider() {
31
+ cachedProvider = null;
32
+ loadPromise = null;
33
+ }
34
+ /** Kick off background load at module init. */
35
+ export function initializeMemoryRouting() {
36
+ const config = getMemoryRoutingConfig();
37
+ if (config.enabled) {
38
+ void getMemoryRoutingProvider();
39
+ }
40
+ }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Memory Routing Provider — pluggable contract for long-term memory enrichment.
3
+ *
4
+ * Repertoire is one implementation. Any provider exposing createMemoryRoutingProvider()
5
+ * can be loaded via features.json memory_routing.module_path.
6
+ */
7
+ export {};
@@ -0,0 +1,32 @@
1
+ const VALID_PROVIDERS = new Set(['null', 'repertoire', 'custom']);
2
+ export function validateMemoryRoutingConfig(raw) {
3
+ const errors = [];
4
+ const input = (raw ?? {});
5
+ const enabled = input.enabled === true;
6
+ const provider = typeof input.provider === 'string' ? input.provider : 'null';
7
+ if (!VALID_PROVIDERS.has(provider)) {
8
+ errors.push(`Invalid memory_routing.provider "${provider}". Must be one of: null, repertoire, custom.`);
9
+ }
10
+ if (enabled && provider !== 'null' && !input.module_path) {
11
+ errors.push(`memory_routing.provider "${provider}" requires module_path when enabled.`);
12
+ }
13
+ if (input.module_path !== undefined && typeof input.module_path !== 'string') {
14
+ errors.push('memory_routing.module_path must be a string.');
15
+ }
16
+ if (input.config !== undefined && (typeof input.config !== 'object' || input.config === null)) {
17
+ errors.push('memory_routing.config must be an object.');
18
+ }
19
+ const normalized = {
20
+ enabled,
21
+ provider: VALID_PROVIDERS.has(provider)
22
+ ? provider
23
+ : 'null',
24
+ };
25
+ if (typeof input.module_path === 'string') {
26
+ normalized.module_path = input.module_path;
27
+ }
28
+ if (input.config && typeof input.config === 'object') {
29
+ normalized.config = input.config;
30
+ }
31
+ return { valid: errors.length === 0, errors, normalized };
32
+ }
@@ -9,6 +9,8 @@
9
9
  import { frameworkLogger } from "../core/framework-logger.js";
10
10
  import { getLevelFromScore, getAgentForTier, levelToTier, } from "../delegation/complexity-core.js";
11
11
  import { ComplexityAnalyzer } from "../delegation/complexity-analyzer.js";
12
+ import { getMemoryRoutingProviderSync, initializeMemoryRouting, } from "../memory-routing/index.js";
13
+ initializeMemoryRouting();
12
14
  export const NUCLEUS_THIN_DISPATCH_VERSION = "0.1.0";
13
15
  /**
14
16
  * Score the complexity of an operation given its description and context.
@@ -52,6 +54,32 @@ export function routeToAgent(scoreOrLevel, level) {
52
54
  */
53
55
  export function scoreAndRoute(operation, context, thresholds) {
54
56
  const score = scoreComplexity(operation, context, thresholds);
55
- const agent = routeToAgent(score);
57
+ let agent = routeToAgent(score);
58
+ const provider = getMemoryRoutingProviderSync();
59
+ let memoryRouting;
60
+ if (provider.id !== "null") {
61
+ const resolved = provider.resolveThinDispatch(agent, operation, score.score);
62
+ agent = resolved.agent;
63
+ memoryRouting = {
64
+ providerId: resolved.context.providerId,
65
+ adjustedScore: resolved.adjustedScore,
66
+ signals: resolved.context.matchedSignals,
67
+ };
68
+ const adjustedLevel = getLevelFromScore(resolved.adjustedScore, thresholds);
69
+ frameworkLogger.log("nucleus-thin-dispatch", "memory-routing", "info", {
70
+ providerId: resolved.context.providerId,
71
+ baseAgent: routeToAgent(score),
72
+ resolvedAgent: agent,
73
+ baseScore: score.score,
74
+ adjustedScore: resolved.adjustedScore,
75
+ level: adjustedLevel,
76
+ signals: resolved.context.matchedSignals,
77
+ });
78
+ return {
79
+ score: { ...score, score: resolved.adjustedScore, level: adjustedLevel },
80
+ agent,
81
+ memoryRouting,
82
+ };
83
+ }
56
84
  return { score, agent };
57
85
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "0xray",
3
- "version": "3.2.0",
3
+ "version": "3.3.1",
4
4
  "description": "Multi-agent orchestration and Codex governance for OpenCode, Hermes, Grok Build, and OpenClaw",
5
5
  "readme": "README.md",
6
6
  "license": "MIT",