0xray 4.0.36 → 4.0.37
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/.xray/features.json +1 -1
- package/dist/CHANGELOG.md +15 -0
- package/dist/analytics/emerging-pattern-detector.d.ts +12 -1
- package/dist/analytics/emerging-pattern-detector.js +37 -12
- package/dist/analytics/pattern-learning-engine.js +1 -9
- package/dist/analytics/predictive-analytics.js +51 -33
- package/dist/analytics/prompt-pattern-analyzer.d.ts +1 -0
- package/dist/analytics/prompt-pattern-analyzer.js +39 -20
- package/dist/analytics/routing-performance-analyzer.d.ts +2 -0
- package/dist/analytics/routing-performance-analyzer.js +89 -37
- package/dist/analytics/simple-pattern-analyzer.d.ts +4 -0
- package/dist/analytics/simple-pattern-analyzer.js +66 -28
- package/dist/architect/architect-tools.d.ts +3 -0
- package/dist/architect/architect-tools.js +22 -0
- package/dist/cli/commands/grok-install.js +1 -1
- package/dist/cli/commands/hermes-install.js +11 -5
- package/dist/cli/commands/openclaw-install.js +13 -7
- package/dist/cli/commands/opencode-install.js +7 -4
- package/dist/cli/commands/suit-monitor.d.ts +30 -0
- package/dist/cli/commands/suit-monitor.js +128 -0
- package/dist/cli/index.js +52 -15
- package/dist/cli/suit-pulse.d.ts +29 -0
- package/dist/cli/suit-pulse.js +270 -0
- package/dist/delegation/agent-delegator.d.ts +4 -2
- package/dist/delegation/agent-delegator.js +46 -27
- package/dist/delegation/agent-expertise.js +2 -1
- package/dist/delegation/analytics/outcome-tracker.d.ts +6 -0
- package/dist/delegation/analytics/outcome-tracker.js +17 -3
- package/dist/delegation/ast-code-parser.d.ts +5 -0
- package/dist/delegation/ast-code-parser.js +53 -48
- package/dist/delegation/codebase-context-analyzer.d.ts +3 -7
- package/dist/delegation/codebase-context-analyzer.js +188 -159
- package/dist/delegation/session-coordinator.js +3 -2
- package/dist/enforcement/loaders/codex-loader.js +18 -14
- package/dist/enforcement/validators/architecture-validators.js +115 -9
- package/dist/governance/codex-policy.service.d.ts +12 -2
- package/dist/governance/codex-policy.service.js +91 -16
- package/dist/integrations/grok/hooks/session-start.js +6 -6
- package/dist/integrations/hooks/goggles-pipeline.mjs +169 -28
- package/dist/integrations/hooks/goggles-planes.json +172 -8
- package/dist/integrations/hooks/plates.cjs +138 -0
- package/dist/integrations/hooks/station-hook-runtime.cjs +63 -5
- package/dist/integrations/hooks/write-home.cjs +59 -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 -18
- package/dist/mcps/orchestrator/server.d.ts +4 -3
- package/dist/mcps/orchestrator/server.js +29 -17
- package/dist/memory-routing/lookup-cache.d.ts +8 -0
- package/dist/memory-routing/lookup-cache.js +72 -0
- package/dist/memory-routing/plates.d.ts +1 -1
- package/dist/memory-routing/plates.js +26 -0
- package/dist/memory-routing/provider-loader.js +3 -0
- package/dist/metrics/agent-metrics.d.ts +14 -5
- package/dist/metrics/agent-metrics.js +362 -224
- package/dist/nucleus/synthesis-consult-receipt.js +38 -16
- package/dist/orchestrator/enhanced-multi-agent-orchestrator.d.ts +5 -0
- package/dist/orchestrator/enhanced-multi-agent-orchestrator.js +9 -0
- package/dist/orchestrator/multi-agent-orchestration-coordinator.js +1 -2
- package/dist/orchestrator/orchestrator.js +1 -2
- package/dist/processors/implementations/agents-md-validation-processor.d.ts +0 -1
- package/dist/processors/implementations/agents-md-validation-processor.js +0 -11
- package/dist/processors/implementations/console-log-guard-processor.js +39 -50
- package/dist/processors/implementations/performance-budget-processor.d.ts +0 -5
- package/dist/processors/implementations/performance-budget-processor.js +29 -38
- package/dist/processors/implementations/storytelling-trigger-processor.d.ts +5 -0
- package/dist/processors/implementations/storytelling-trigger-processor.js +69 -16
- package/dist/processors/implementations/test-auto-creation-processor.js +39 -36
- package/dist/reporting/framework-reporting-system.d.ts +3 -0
- package/dist/reporting/framework-reporting-system.js +61 -8
- package/dist/reporting/log-parser.js +188 -105
- package/dist/reporting/metrics.js +42 -18
- package/dist/security/prompt-security-validator.js +8 -7
- package/dist/security/security-auditor.d.ts +4 -0
- package/dist/security/security-auditor.js +132 -57
- package/dist/security/security-hardener.d.ts +2 -0
- package/dist/security/security-hardener.js +31 -6
- package/dist/security/security-headers.d.ts +2 -0
- package/dist/security/security-headers.js +23 -21
- package/dist/security/security-scanner.js +18 -4
- package/dist/session/session-cleanup-manager.d.ts +2 -0
- package/dist/session/session-cleanup-manager.js +29 -8
- package/dist/session/session-monitor.d.ts +14 -4
- package/dist/session/session-monitor.js +208 -106
- package/dist/session/session-state-manager.d.ts +11 -0
- package/dist/session/session-state-manager.js +90 -8
- package/docs-site/docs/plates/activity-log.md +38 -0
- package/docs-site/docs/plates/cursor-compact.md +35 -0
- package/docs-site/docs/plates/grok-compact.md +35 -0
- package/docs-site/docs/plates/index.md +25 -3
- package/docs-site/docs/plates/inference-files.md +35 -0
- package/docs-site/docs/plates/kept-line.md +35 -0
- package/docs-site/docs/plates/lens-gate.md +35 -0
- package/docs-site/docs/plates/lens-page.md +35 -0
- package/docs-site/docs/plates/notes-page.md +35 -0
- package/docs-site/docs/plates/package-face.md +35 -0
- package/docs-site/docs/plates/payload-heat.md +35 -0
- package/docs-site/docs/plates/pickup-stamp.md +35 -0
- package/docs-site/docs/plates/pre-tool.md +35 -0
- package/docs-site/docs/plates/record-map.md +41 -0
- package/docs-site/docs/plates/reflection-page.md +35 -0
- package/docs-site/docs/plates/review.md +57 -0
- package/docs-site/docs/plates/session-capture.md +38 -0
- package/docs-site/docs/plates/site-manual.md +35 -0
- package/docs-site/docs/plates/stamp-plate.md +35 -0
- package/docs-site/docs/plates/station-card.md +35 -0
- package/docs-site/docs/plates/station-heat.md +35 -0
- package/docs-site/docs/plates/suit-organs.md +38 -0
- package/docs-site/docs/plates/suit-settings.md +35 -0
- package/docs-site/docs/plates/suit-wear.md +37 -0
- package/docs-site/docs/plates/trail-state.md +35 -0
- package/docs-site/docs/plates/work-fresh.md +35 -0
- package/docs-site/docs/plates/write-home.md +38 -0
- package/package.json +3 -2
- package/scripts/node/install-bridges.cjs +302 -78
- package/scripts/node/postinstall.cjs +14 -3
- package/src/integrations/openclaw/plugin/xray-pre-tool/package.json +1 -1
- package/src/mcps/architect-tools.server.ts +25 -20
- package/src/mcps/orchestrator/server.ts +33 -19
- package/xray/features.json +1 -1
- package/vendor/@0xray/repertoire/dist/RepertoireService.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/RepertoireService.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/governance/ontological-trap-enforcer.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/governance/ontological-trap-enforcer.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/index.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/index.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/ingestion/groover-log-ingester.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/ingestion/groover-log-parser.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/ingestion/groover-log-parser.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/ingestion/orchestrator-feedback-ingester.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/ingestion/orchestrator-feedback-ingester.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/ingestion/xray-session-ingester.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/mcp/server.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/mcp/server.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/RepertoireOrchestratorBridge.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/RepertoireOrchestratorBridge.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/capability-enhancer.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/capability-enhancer.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/confidence-gate.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-agent-affinity.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-agent-affinity.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/orchestrator-bridge/signal-injector.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/paths.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/paths.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/provider/memory-routing-provider.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/registry/CuratedSignalsManager.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/registry/InferenceStateManager.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/registry/confidence-decay.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/registry/confidence-decay.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/registry/signal-prune.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/registry/signal-prune.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/synthesis/concrete-sections.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/synthesis/concrete-sections.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/synthesis/meta-inference-engine.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/synthesis/primitive-confidence-aggregator.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/synthesis/primitive-confidence-aggregator.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/synthesis/synthesis-prompt-builder.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/synthesis/synthesis-prompt-builder.js.map +0 -1
- package/vendor/@0xray/repertoire/dist/types.d.ts.map +0 -1
- package/vendor/@0xray/repertoire/dist/types.js.map +0 -1
|
@@ -50,16 +50,22 @@ export class SimplePatternAnalyzer {
|
|
|
50
50
|
// Fall back to activity log parsing if no outcomes
|
|
51
51
|
if (entries.length === 0 && fs.existsSync(this.logPath)) {
|
|
52
52
|
const content = fs.readFileSync(this.logPath, "utf-8");
|
|
53
|
-
const
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
line.includes("task-completed")
|
|
53
|
+
const completionLines = [];
|
|
54
|
+
for (const line of content.split("\n")) {
|
|
55
|
+
if (!line.trim())
|
|
56
|
+
continue;
|
|
57
|
+
if (line.includes("complex-task-completed") ||
|
|
58
|
+
line.includes("job-completed") ||
|
|
59
|
+
line.includes("task-completed")) {
|
|
60
|
+
completionLines.push(line);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
58
63
|
const entriesToAnalyze = limit ? completionLines.slice(-limit) : completionLines;
|
|
59
|
-
const
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
64
|
+
for (const line of entriesToAnalyze) {
|
|
65
|
+
const parsed = this.parseLine(line);
|
|
66
|
+
if (parsed)
|
|
67
|
+
entries.push(parsed);
|
|
68
|
+
}
|
|
63
69
|
}
|
|
64
70
|
if (entries.length === 0) {
|
|
65
71
|
return this.emptyInsights();
|
|
@@ -189,32 +195,64 @@ export class SimplePatternAnalyzer {
|
|
|
189
195
|
}
|
|
190
196
|
}
|
|
191
197
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
198
|
+
let attempts = 0;
|
|
199
|
+
let successes = 0;
|
|
200
|
+
for (const stats of agentStats.values()) {
|
|
201
|
+
attempts += stats.attempts;
|
|
202
|
+
successes += stats.successes;
|
|
197
203
|
}
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
successes: acc.successes + s.successes,
|
|
202
|
-
}), { attempts: 0, successes: 0 });
|
|
203
|
-
stats.successRate =
|
|
204
|
-
agentStatsForTask.attempts > 0
|
|
205
|
-
? (agentStatsForTask.successes / agentStatsForTask.attempts) * 100
|
|
206
|
-
: 0;
|
|
204
|
+
const successRate = attempts > 0 ? (successes / attempts) * 100 : 0;
|
|
205
|
+
for (const stats of taskTypeStats.values()) {
|
|
206
|
+
stats.successRate = successRate;
|
|
207
207
|
}
|
|
208
|
-
const sortedEntries = [...entries].sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
|
|
209
208
|
return {
|
|
210
209
|
agentStats,
|
|
211
210
|
taskTypeStats,
|
|
212
211
|
complexityStats,
|
|
213
212
|
totalEntries: entries.length,
|
|
214
|
-
dateRange:
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
213
|
+
dateRange: this.entryDateRange(entries),
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Earliest and latest timestamp. Matches a stable sort on finite times.
|
|
218
|
+
*/
|
|
219
|
+
entryDateRange(entries) {
|
|
220
|
+
if (entries.length === 0)
|
|
221
|
+
return { start: "", end: "" };
|
|
222
|
+
const first = entries[0];
|
|
223
|
+
if (!first)
|
|
224
|
+
return { start: "", end: "" };
|
|
225
|
+
let start = first.timestamp;
|
|
226
|
+
let end = start;
|
|
227
|
+
let startTime = new Date(start).getTime();
|
|
228
|
+
let endTime = startTime;
|
|
229
|
+
if (!Number.isNaN(startTime)) {
|
|
230
|
+
let finite = true;
|
|
231
|
+
for (let i = 1; i < entries.length; i++) {
|
|
232
|
+
const entry = entries[i];
|
|
233
|
+
if (!entry)
|
|
234
|
+
continue;
|
|
235
|
+
const time = new Date(entry.timestamp).getTime();
|
|
236
|
+
if (Number.isNaN(time)) {
|
|
237
|
+
finite = false;
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
if (time < startTime) {
|
|
241
|
+
startTime = time;
|
|
242
|
+
start = entry.timestamp;
|
|
243
|
+
}
|
|
244
|
+
if (time >= endTime) {
|
|
245
|
+
endTime = time;
|
|
246
|
+
end = entry.timestamp;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
if (finite)
|
|
250
|
+
return { start, end };
|
|
251
|
+
}
|
|
252
|
+
const sortedEntries = [...entries].sort((a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime());
|
|
253
|
+
return {
|
|
254
|
+
start: sortedEntries[0]?.timestamp || "",
|
|
255
|
+
end: sortedEntries[sortedEntries.length - 1]?.timestamp || "",
|
|
218
256
|
};
|
|
219
257
|
}
|
|
220
258
|
/**
|
|
@@ -62,6 +62,9 @@ export declare function dependencyAnalysis(projectRoot: string, focusAreas?: str
|
|
|
62
62
|
* Architecture Assessment Tool - Overall architectural health evaluation
|
|
63
63
|
*/
|
|
64
64
|
export declare function architectureAssessment(projectRoot: string, assessmentType?: "quick" | "comprehensive"): Promise<ArchitectureAssessment>;
|
|
65
|
+
/** Confer text follows the assessment. A critical coupling issue is FAIL. */
|
|
66
|
+
export declare function conferVerdictFromAssessment(assessment: ArchitectureAssessment): "PASS" | "CONDITIONAL" | "FAIL";
|
|
67
|
+
export declare function formatConferArchitectureText(conferPrompt: string, assessment: ArchitectureAssessment): string;
|
|
65
68
|
export declare const architectTools: {
|
|
66
69
|
contextAnalysis: typeof contextAnalysis;
|
|
67
70
|
codebaseStructure: typeof codebaseStructure;
|
|
@@ -189,6 +189,28 @@ export async function architectureAssessment(projectRoot, assessmentType = "comp
|
|
|
189
189
|
});
|
|
190
190
|
return result;
|
|
191
191
|
}
|
|
192
|
+
/** Confer text follows the assessment. A critical coupling issue is FAIL. */
|
|
193
|
+
export function conferVerdictFromAssessment(assessment) {
|
|
194
|
+
const criticalIssue = assessment.issues.some((issue) => issue.type === "critical");
|
|
195
|
+
if (criticalIssue ||
|
|
196
|
+
assessment.overallHealth === "critical" ||
|
|
197
|
+
assessment.overallHealth === "poor") {
|
|
198
|
+
return "FAIL";
|
|
199
|
+
}
|
|
200
|
+
if (assessment.overallHealth === "fair" ||
|
|
201
|
+
assessment.issues.some((issue) => issue.type === "major")) {
|
|
202
|
+
return "CONDITIONAL";
|
|
203
|
+
}
|
|
204
|
+
return "PASS";
|
|
205
|
+
}
|
|
206
|
+
export function formatConferArchitectureText(conferPrompt, assessment) {
|
|
207
|
+
const assessmentJson = JSON.stringify(assessment, null, 2);
|
|
208
|
+
const prompt = conferPrompt.trim();
|
|
209
|
+
if (!prompt)
|
|
210
|
+
return assessmentJson;
|
|
211
|
+
const verdict = conferVerdictFromAssessment(assessment);
|
|
212
|
+
return `${prompt}\n\n## Architecture assessment\n${assessmentJson}\n\nVerdict: ${verdict}\nTop risks: review assessment metrics above\nHardening: address high-complexity or coupling findings before resuming`;
|
|
213
|
+
}
|
|
192
214
|
// Helper functions
|
|
193
215
|
function identifyArchitecturalPatterns(codebaseAnalysis, dependencyAnalysis) {
|
|
194
216
|
const patterns = [];
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Helps users register 0xRay MCP servers with the Grok CLI.
|
|
5
5
|
*/
|
|
6
|
-
import { installForGrokCLI } from '../../integrations/grok/grok-cli.js';
|
|
7
6
|
export function registerGrokCommands(grokCmd) {
|
|
8
7
|
grokCmd
|
|
9
8
|
.command('install')
|
|
@@ -11,6 +10,7 @@ export function registerGrokCommands(grokCmd) {
|
|
|
11
10
|
.option('--dry-run', 'Show what would be done without making changes')
|
|
12
11
|
.option('--force', 'Force reinstall even if already present')
|
|
13
12
|
.action(async (options) => {
|
|
13
|
+
const { installForGrokCLI } = await import('../../integrations/grok/grok-cli.js');
|
|
14
14
|
await installForGrokCLI({ dryRun: options.dryRun, force: options.force });
|
|
15
15
|
});
|
|
16
16
|
}
|
|
@@ -2,14 +2,15 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { createRequire } from 'module';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import { frameworkLogger } from '../../core/framework-logger.js';
|
|
6
|
-
import { syncBuiltinSkills } from './skill-install.js';
|
|
7
|
-
import { mintAfterWear } from './foundry-mint-wear.js';
|
|
8
5
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
6
|
const require = createRequire(import.meta.url);
|
|
10
7
|
const packageRoot = path.join(__dirname, '..', '..', '..');
|
|
11
|
-
|
|
12
|
-
|
|
8
|
+
function loadMillSuit() {
|
|
9
|
+
return require(path.join(packageRoot, 'scripts', 'foundry', 'mint-suit.cjs'));
|
|
10
|
+
}
|
|
11
|
+
function loadWiring() {
|
|
12
|
+
return require(path.join(packageRoot, 'scripts', 'node', 'bridge-mcp-wiring.cjs'));
|
|
13
|
+
}
|
|
13
14
|
export function registerHermesCommands(hermesCmd) {
|
|
14
15
|
hermesCmd
|
|
15
16
|
.command('install')
|
|
@@ -21,6 +22,11 @@ export function registerHermesCommands(hermesCmd) {
|
|
|
21
22
|
});
|
|
22
23
|
}
|
|
23
24
|
async function installForHermes(options = {}) {
|
|
25
|
+
const { frameworkLogger } = await import('../../core/framework-logger.js');
|
|
26
|
+
const { syncBuiltinSkills } = await import('./skill-install.js');
|
|
27
|
+
const { mintAfterWear } = await import('./foundry-mint-wear.js');
|
|
28
|
+
const millSuit = loadMillSuit();
|
|
29
|
+
const wiring = loadWiring();
|
|
24
30
|
frameworkLogger.log('hermes-integration', 'install-start', 'info', { options });
|
|
25
31
|
const isolated = millSuit.isIsolatedHome();
|
|
26
32
|
const targetPluginDir = isolated
|
|
@@ -2,15 +2,14 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { createRequire } from 'module';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import { frameworkLogger } from '../../core/framework-logger.js';
|
|
6
|
-
import { syncBuiltinSkills } from './skill-install.js';
|
|
7
|
-
import { mintAfterWear } from './foundry-mint-wear.js';
|
|
8
|
-
import { OpenClawConfigLoader } from '../../integrations/openclaw/config.js';
|
|
9
|
-
import { writeSuitSessionBoot } from '../../nucleus/suit-temperament.js';
|
|
10
5
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
11
6
|
const require = createRequire(import.meta.url);
|
|
12
|
-
|
|
13
|
-
|
|
7
|
+
function loadMillSuit() {
|
|
8
|
+
return require(path.join(__dirname, '..', '..', '..', 'scripts', 'foundry', 'mint-suit.cjs'));
|
|
9
|
+
}
|
|
10
|
+
function loadWiring() {
|
|
11
|
+
return require(path.join(__dirname, '..', '..', '..', 'scripts', 'node', 'bridge-mcp-wiring.cjs'));
|
|
12
|
+
}
|
|
14
13
|
export function registerOpenClawCommands(openclawCmd) {
|
|
15
14
|
openclawCmd
|
|
16
15
|
.command('install')
|
|
@@ -22,6 +21,13 @@ export function registerOpenClawCommands(openclawCmd) {
|
|
|
22
21
|
});
|
|
23
22
|
}
|
|
24
23
|
async function installForOpenClaw(options = {}) {
|
|
24
|
+
const { frameworkLogger } = await import('../../core/framework-logger.js');
|
|
25
|
+
const { syncBuiltinSkills } = await import('./skill-install.js');
|
|
26
|
+
const { mintAfterWear } = await import('./foundry-mint-wear.js');
|
|
27
|
+
const { OpenClawConfigLoader } = await import('../../integrations/openclaw/config.js');
|
|
28
|
+
const { writeSuitSessionBoot } = await import('../../nucleus/suit-temperament.js');
|
|
29
|
+
const millSuit = loadMillSuit();
|
|
30
|
+
const wiring = loadWiring();
|
|
25
31
|
frameworkLogger.log('openclaw-integration', 'install-start', 'info', { options });
|
|
26
32
|
const configPath = path.join(process.cwd(), '.xray', 'config', 'openclaw.json');
|
|
27
33
|
if (options.dryRun) {
|
|
@@ -2,12 +2,11 @@ import fs from 'fs';
|
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { createRequire } from 'module';
|
|
4
4
|
import { fileURLToPath } from 'node:url';
|
|
5
|
-
import { frameworkLogger } from '../../core/framework-logger.js';
|
|
6
|
-
import { syncBuiltinSkills } from './skill-install.js';
|
|
7
|
-
import { mintAfterWear, wantsCostume } from './foundry-mint-wear.js';
|
|
8
5
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
9
6
|
const require = createRequire(import.meta.url);
|
|
10
|
-
|
|
7
|
+
function loadWiring() {
|
|
8
|
+
return require(path.join(__dirname, '..', '..', '..', 'scripts', 'node', 'bridge-mcp-wiring.cjs'));
|
|
9
|
+
}
|
|
11
10
|
export function registerOpencodeCommands(opencodeCmd) {
|
|
12
11
|
opencodeCmd
|
|
13
12
|
.command('install')
|
|
@@ -74,6 +73,10 @@ function copyDir(src, dest, relPath = "") {
|
|
|
74
73
|
}
|
|
75
74
|
}
|
|
76
75
|
async function installForOpencode(options = {}) {
|
|
76
|
+
const { frameworkLogger } = await import('../../core/framework-logger.js');
|
|
77
|
+
const { syncBuiltinSkills } = await import('./skill-install.js');
|
|
78
|
+
const { mintAfterWear, wantsCostume } = await import('./foundry-mint-wear.js');
|
|
79
|
+
const wiring = loadWiring();
|
|
77
80
|
frameworkLogger.log('opencode-integration', 'install-start', 'info', { options });
|
|
78
81
|
const opencodeSource = path.join(__dirname, '..', '..', '..', '.opencode');
|
|
79
82
|
const opencodeDest = path.join(process.cwd(), '.opencode');
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Current picture of the worn suit.
|
|
3
|
+
*
|
|
4
|
+
* Inventory, already on disk, not a second store:
|
|
5
|
+
* - logs/framework/activity.log — activity-logger.ts and grok-hook-activity appendHookActivity
|
|
6
|
+
* - inference state — InferenceStateManager.load() from vendored @0xray/repertoire
|
|
7
|
+
* (.xray/state/repertoire/inference-state.json)
|
|
8
|
+
* - repertoire version — that organ's package.json
|
|
9
|
+
* - worn 0xray version — package.json beside this CLI
|
|
10
|
+
* - 0xray report stays the health report; scripts/mjs/goggles-observer.mjs stays the lens check
|
|
11
|
+
*/
|
|
12
|
+
export type SuitSources = {
|
|
13
|
+
activityLogPath: string;
|
|
14
|
+
inferenceStatePath: string;
|
|
15
|
+
repertoirePackageJson: string | null;
|
|
16
|
+
xrayPackageJson: string;
|
|
17
|
+
tail?: number;
|
|
18
|
+
};
|
|
19
|
+
export type SuitPicture = {
|
|
20
|
+
activityLines: string[];
|
|
21
|
+
inferenceStatePresent: boolean;
|
|
22
|
+
inferenceLastRun: string | null;
|
|
23
|
+
repertoireVersion: string | null;
|
|
24
|
+
xrayVersion: string | null;
|
|
25
|
+
};
|
|
26
|
+
export declare function resolveRepertoirePackageJson(cwd: string): string | null;
|
|
27
|
+
export declare function defaultSuitSources(cwd: string, xrayPackageJson: string): SuitSources;
|
|
28
|
+
export declare function readSuitPicture(sources: SuitSources): Promise<SuitPicture>;
|
|
29
|
+
export declare function formatSuitPicture(picture: SuitPicture): string;
|
|
30
|
+
export declare function printSuitMonitor(cwd: string, packageRoot: string, lines?: number): Promise<void>;
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Current picture of the worn suit.
|
|
3
|
+
*
|
|
4
|
+
* Inventory, already on disk, not a second store:
|
|
5
|
+
* - logs/framework/activity.log — activity-logger.ts and grok-hook-activity appendHookActivity
|
|
6
|
+
* - inference state — InferenceStateManager.load() from vendored @0xray/repertoire
|
|
7
|
+
* (.xray/state/repertoire/inference-state.json)
|
|
8
|
+
* - repertoire version — that organ's package.json
|
|
9
|
+
* - worn 0xray version — package.json beside this CLI
|
|
10
|
+
* - 0xray report stays the health report; scripts/mjs/goggles-observer.mjs stays the lens check
|
|
11
|
+
*/
|
|
12
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
13
|
+
import { pathToFileURL } from "node:url";
|
|
14
|
+
import { dirname, join, resolve } from "node:path";
|
|
15
|
+
const REPERTOIRE_PACKAGE_CANDIDATES = [
|
|
16
|
+
"node_modules/@0xray/repertoire/package.json",
|
|
17
|
+
"vendor/@0xray/repertoire/package.json",
|
|
18
|
+
"node_modules/0xray/vendor/@0xray/repertoire/package.json",
|
|
19
|
+
];
|
|
20
|
+
function isRecord(value) {
|
|
21
|
+
return typeof value === "object" && value !== null;
|
|
22
|
+
}
|
|
23
|
+
function isConstructor(value) {
|
|
24
|
+
return typeof value === "function";
|
|
25
|
+
}
|
|
26
|
+
export function resolveRepertoirePackageJson(cwd) {
|
|
27
|
+
for (const rel of REPERTOIRE_PACKAGE_CANDIDATES) {
|
|
28
|
+
const abs = resolve(cwd, rel);
|
|
29
|
+
if (existsSync(abs))
|
|
30
|
+
return abs;
|
|
31
|
+
}
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
export function defaultSuitSources(cwd, xrayPackageJson) {
|
|
35
|
+
return {
|
|
36
|
+
activityLogPath: join(cwd, "logs", "framework", "activity.log"),
|
|
37
|
+
inferenceStatePath: join(cwd, ".xray", "state", "repertoire", "inference-state.json"),
|
|
38
|
+
repertoirePackageJson: resolveRepertoirePackageJson(cwd),
|
|
39
|
+
xrayPackageJson,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function readPackageVersion(packageJsonPath) {
|
|
43
|
+
try {
|
|
44
|
+
const raw = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
45
|
+
if (!isRecord(raw) || typeof raw.version !== "string")
|
|
46
|
+
return null;
|
|
47
|
+
return raw.version;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
function readLastActivityLines(logPath, tail) {
|
|
54
|
+
if (!existsSync(logPath) || tail <= 0)
|
|
55
|
+
return [];
|
|
56
|
+
try {
|
|
57
|
+
const lines = readFileSync(logPath, "utf8")
|
|
58
|
+
.split(/\r?\n/)
|
|
59
|
+
.filter((line) => line.length > 0);
|
|
60
|
+
return lines.slice(-tail);
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
return [];
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function inferenceModuleFromPackage(packageJsonPath) {
|
|
67
|
+
const modulePath = join(dirname(packageJsonPath), "dist", "registry", "InferenceStateManager.js");
|
|
68
|
+
return existsSync(modulePath) ? modulePath : null;
|
|
69
|
+
}
|
|
70
|
+
/** Reuse the organ's read. A missing file stays absent; load() is not a second parser. */
|
|
71
|
+
async function loadLastRun(modulePath, filePath) {
|
|
72
|
+
try {
|
|
73
|
+
const loaded = await import(pathToFileURL(modulePath).href);
|
|
74
|
+
if (!isRecord(loaded) || !isConstructor(loaded.InferenceStateManager))
|
|
75
|
+
return null;
|
|
76
|
+
const instance = new loaded.InferenceStateManager(filePath);
|
|
77
|
+
if (!isRecord(instance) || typeof instance.load !== "function")
|
|
78
|
+
return null;
|
|
79
|
+
const state = instance.load();
|
|
80
|
+
if (!isRecord(state) || typeof state.lastRun !== "string")
|
|
81
|
+
return null;
|
|
82
|
+
return state.lastRun;
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return null;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
export async function readSuitPicture(sources) {
|
|
89
|
+
const tail = sources.tail ?? 8;
|
|
90
|
+
const modulePath = sources.repertoirePackageJson
|
|
91
|
+
? inferenceModuleFromPackage(sources.repertoirePackageJson)
|
|
92
|
+
: null;
|
|
93
|
+
const inferenceStatePresent = existsSync(sources.inferenceStatePath);
|
|
94
|
+
const inferenceLastRun = inferenceStatePresent && modulePath
|
|
95
|
+
? await loadLastRun(modulePath, sources.inferenceStatePath)
|
|
96
|
+
: null;
|
|
97
|
+
return {
|
|
98
|
+
activityLines: readLastActivityLines(sources.activityLogPath, tail),
|
|
99
|
+
inferenceStatePresent,
|
|
100
|
+
inferenceLastRun,
|
|
101
|
+
repertoireVersion: sources.repertoirePackageJson
|
|
102
|
+
? readPackageVersion(sources.repertoirePackageJson)
|
|
103
|
+
: null,
|
|
104
|
+
xrayVersion: readPackageVersion(sources.xrayPackageJson),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
export function formatSuitPicture(picture) {
|
|
108
|
+
const inference = picture.inferenceStatePresent
|
|
109
|
+
? `present${picture.inferenceLastRun ? ` lastRun ${picture.inferenceLastRun}` : ""}`
|
|
110
|
+
: "absent";
|
|
111
|
+
const activity = picture.activityLines.length > 0
|
|
112
|
+
? picture.activityLines.map((line) => ` ${line}`).join("\n")
|
|
113
|
+
: " (none)";
|
|
114
|
+
return [
|
|
115
|
+
"suit monitor",
|
|
116
|
+
`xray: ${picture.xrayVersion ?? "missing"}`,
|
|
117
|
+
`repertoire: ${picture.repertoireVersion ?? "missing"}`,
|
|
118
|
+
`inference state: ${inference}`,
|
|
119
|
+
"activity:",
|
|
120
|
+
activity,
|
|
121
|
+
].join("\n");
|
|
122
|
+
}
|
|
123
|
+
export async function printSuitMonitor(cwd, packageRoot, lines = 8) {
|
|
124
|
+
const sources = defaultSuitSources(cwd, join(packageRoot, "package.json"));
|
|
125
|
+
sources.tail = lines;
|
|
126
|
+
const picture = await readSuitPicture(sources);
|
|
127
|
+
process.stdout.write(`${formatSuitPicture(picture)}\n`);
|
|
128
|
+
}
|
package/dist/cli/index.js
CHANGED
|
@@ -9,9 +9,10 @@ import { execSync, spawn, spawnSync } from "child_process";
|
|
|
9
9
|
import { join, resolve } from "path";
|
|
10
10
|
import { fileURLToPath } from "node:url";
|
|
11
11
|
import { readFileSync, existsSync } from "fs";
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
async function loadFrameworkLogger() {
|
|
13
|
+
const { frameworkLogger } = await import("../core/framework-logger.js");
|
|
14
|
+
return frameworkLogger;
|
|
15
|
+
}
|
|
15
16
|
// Get package root relative to this script location
|
|
16
17
|
const packageRoot = resolve(fileURLToPath(new URL("../..", import.meta.url)));
|
|
17
18
|
// Read version dynamically from package.json
|
|
@@ -54,7 +55,8 @@ function runNodeScript(scriptName, args = []) {
|
|
|
54
55
|
program
|
|
55
56
|
.command("install")
|
|
56
57
|
.description("Install xray framework in the current project")
|
|
57
|
-
.action(() => {
|
|
58
|
+
.action(async () => {
|
|
59
|
+
const frameworkLogger = await loadFrameworkLogger();
|
|
58
60
|
frameworkLogger.log('cli', 'install', 'info', { message: 'nothing written' });
|
|
59
61
|
process.stdout.write("nothing written\n");
|
|
60
62
|
});
|
|
@@ -62,7 +64,7 @@ program
|
|
|
62
64
|
.command("setup")
|
|
63
65
|
.description("Set up .mcp.json and the OpenCode, Grok, Hermes, and OpenClaw bridges")
|
|
64
66
|
.option("--git-hooks", "also install git hooks")
|
|
65
|
-
.action((opts) => {
|
|
67
|
+
.action(async (opts) => {
|
|
66
68
|
const args = ["setup"];
|
|
67
69
|
if (opts.gitHooks)
|
|
68
70
|
args.push("--git-hooks");
|
|
@@ -70,6 +72,7 @@ program
|
|
|
70
72
|
runNodeScript("install-bridges.cjs", args);
|
|
71
73
|
}
|
|
72
74
|
catch (error) {
|
|
75
|
+
const frameworkLogger = await loadFrameworkLogger();
|
|
73
76
|
frameworkLogger.log("cli", "setup-error", "error", {
|
|
74
77
|
error: error instanceof Error ? error.message : String(error),
|
|
75
78
|
});
|
|
@@ -116,11 +119,12 @@ program
|
|
|
116
119
|
program
|
|
117
120
|
.command("wear")
|
|
118
121
|
.description("Wear the 0xray suit in this git checkout")
|
|
119
|
-
.action(() => {
|
|
122
|
+
.action(async () => {
|
|
120
123
|
try {
|
|
121
124
|
runNodeScript("wear-cursor-hooks.cjs");
|
|
122
125
|
}
|
|
123
126
|
catch (error) {
|
|
127
|
+
const frameworkLogger = await loadFrameworkLogger();
|
|
124
128
|
frameworkLogger.log('cli', 'wear-error', 'error', {
|
|
125
129
|
error: error instanceof Error ? error.message : String(error),
|
|
126
130
|
});
|
|
@@ -130,11 +134,12 @@ program
|
|
|
130
134
|
program
|
|
131
135
|
.command("unwear")
|
|
132
136
|
.description("Remove the 0xray suit and restore the pre-wear hooks file")
|
|
133
|
-
.action(() => {
|
|
137
|
+
.action(async () => {
|
|
134
138
|
try {
|
|
135
139
|
runNodeScript("unwear-cursor-hooks.cjs");
|
|
136
140
|
}
|
|
137
141
|
catch (error) {
|
|
142
|
+
const frameworkLogger = await loadFrameworkLogger();
|
|
138
143
|
frameworkLogger.log('cli', 'unwear-error', 'error', {
|
|
139
144
|
error: error instanceof Error ? error.message : String(error),
|
|
140
145
|
});
|
|
@@ -154,6 +159,16 @@ program
|
|
|
154
159
|
const { statusCommand } = await import("./commands/status.js");
|
|
155
160
|
await statusCommand(packageRoot);
|
|
156
161
|
});
|
|
162
|
+
program
|
|
163
|
+
.command("monitor")
|
|
164
|
+
.description("Current picture of the worn suit (activity, inference state, repertoire, version)")
|
|
165
|
+
.option("-n, --lines <count>", "Activity lines to show", "8")
|
|
166
|
+
.action(async (options) => {
|
|
167
|
+
const { printSuitMonitor } = await import("./commands/suit-monitor.js");
|
|
168
|
+
const parsed = Number(options.lines);
|
|
169
|
+
const lines = Number.isFinite(parsed) && parsed > 0 ? Math.floor(parsed) : 8;
|
|
170
|
+
await printSuitMonitor(process.cwd(), packageRoot, lines);
|
|
171
|
+
});
|
|
157
172
|
program
|
|
158
173
|
.command("validate")
|
|
159
174
|
.description("Validate consumer wear (pack paths, Cursor hooks, mill plant) — not leftover init.sh")
|
|
@@ -391,6 +406,13 @@ program
|
|
|
391
406
|
process.exit(1);
|
|
392
407
|
}
|
|
393
408
|
});
|
|
409
|
+
program
|
|
410
|
+
.command("pulse")
|
|
411
|
+
.description("Print one line: worn CLI, repertoire, inference age, activity, lens, plant")
|
|
412
|
+
.action(async () => {
|
|
413
|
+
const { readSuitPulse } = await import("./suit-pulse.js");
|
|
414
|
+
process.stdout.write(`${readSuitPulse(process.cwd()).line}\n`);
|
|
415
|
+
});
|
|
394
416
|
program
|
|
395
417
|
.command("fix")
|
|
396
418
|
.description("Automatically fix common framework issues by running the postinstall setup")
|
|
@@ -496,6 +518,7 @@ program
|
|
|
496
518
|
process.stdout.write("not worn\n");
|
|
497
519
|
}
|
|
498
520
|
const opencodeConfigPath = path.join(cwd, "opencode.json");
|
|
521
|
+
const { getConfigDir } = await import("../core/config-paths.js");
|
|
499
522
|
const xrayDir = getConfigDir(cwd);
|
|
500
523
|
const opencodeExists = fs.existsSync(opencodeConfigPath);
|
|
501
524
|
const configDirExists = fs.existsSync(xrayDir);
|
|
@@ -727,6 +750,7 @@ program
|
|
|
727
750
|
return;
|
|
728
751
|
}
|
|
729
752
|
const features = featuresConfigLoader.loadConfig();
|
|
753
|
+
const { inferenceRunMayEnter } = await import('../inference/inference-run-gate.js');
|
|
730
754
|
if (!inferenceRunMayEnter(features.inference, options.force === true)) {
|
|
731
755
|
if (options.json) {
|
|
732
756
|
console.log(JSON.stringify({ triggered: false, reason: 'Inference feature disabled in features.json' }));
|
|
@@ -957,22 +981,33 @@ program
|
|
|
957
981
|
const child = spawn(process.execPath, [serverPath], { stdio: 'inherit', env });
|
|
958
982
|
child.on('exit', (code) => process.exit(code ?? 0));
|
|
959
983
|
});
|
|
984
|
+
function argvSelects(name) {
|
|
985
|
+
return process.argv.slice(2).includes(name);
|
|
986
|
+
}
|
|
960
987
|
// Grok CLI integration
|
|
961
988
|
const grokCmd = program.command('grok').description('Grok CLI integration commands');
|
|
962
|
-
|
|
963
|
-
registerGrokCommands(
|
|
989
|
+
if (argvSelects('grok')) {
|
|
990
|
+
const { registerGrokCommands } = await import('./commands/grok-install.js');
|
|
991
|
+
registerGrokCommands(grokCmd);
|
|
992
|
+
}
|
|
964
993
|
// Hermes Agent integration
|
|
965
994
|
const hermesCmd = program.command('hermes').description('Hermes Agent integration commands');
|
|
966
|
-
|
|
967
|
-
registerHermesCommands(
|
|
995
|
+
if (argvSelects('hermes')) {
|
|
996
|
+
const { registerHermesCommands } = await import('./commands/hermes-install.js');
|
|
997
|
+
registerHermesCommands(hermesCmd);
|
|
998
|
+
}
|
|
968
999
|
// OpenClaw integration
|
|
969
1000
|
const openclawCmd = program.command('openclaw').description('OpenClaw integration commands');
|
|
970
|
-
|
|
971
|
-
registerOpenClawCommands(
|
|
1001
|
+
if (argvSelects('openclaw')) {
|
|
1002
|
+
const { registerOpenClawCommands } = await import('./commands/openclaw-install.js');
|
|
1003
|
+
registerOpenClawCommands(openclawCmd);
|
|
1004
|
+
}
|
|
972
1005
|
// OpenCode integration
|
|
973
1006
|
const opencodeCmd = program.command('opencode').description('OpenCode integration commands');
|
|
974
|
-
|
|
975
|
-
registerOpencodeCommands(
|
|
1007
|
+
if (argvSelects('opencode')) {
|
|
1008
|
+
const { registerOpencodeCommands } = await import('./commands/opencode-install.js');
|
|
1009
|
+
registerOpencodeCommands(opencodeCmd);
|
|
1010
|
+
}
|
|
976
1011
|
// Analytics enable command
|
|
977
1012
|
// Plugin subcommands
|
|
978
1013
|
const pluginCmd = program.command('plugin').description('Manage plugins');
|
|
@@ -1029,6 +1064,8 @@ Examples:
|
|
|
1029
1064
|
$ npx 0xray capabilities # Show all available capabilities
|
|
1030
1065
|
$ npx 0xray health # Check framework health and status
|
|
1031
1066
|
$ npx 0xray report # Generate activity and health reports
|
|
1067
|
+
$ npx 0xray monitor # Current picture of the worn suit
|
|
1068
|
+
$ npx 0xray pulse # One line: worn, repertoire, inference, activity, lens, plant
|
|
1032
1069
|
$ npx 0xray fix # Automatically restore missing config files
|
|
1033
1070
|
$ npx 0xray doctor # Diagnose issues (does not fix them)
|
|
1034
1071
|
$ npx 0xray analytics # Pattern analytics and insights
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One line from streams the suit already writes.
|
|
3
|
+
* Not a doctor, not a second memory.
|
|
4
|
+
*/
|
|
5
|
+
export type SuitLens = "none" | "armed" | "spent";
|
|
6
|
+
export interface SuitPulseActivity {
|
|
7
|
+
gate: string | null;
|
|
8
|
+
decision: string;
|
|
9
|
+
tool: string | null;
|
|
10
|
+
}
|
|
11
|
+
export interface SuitPulse {
|
|
12
|
+
worn: {
|
|
13
|
+
version: string;
|
|
14
|
+
directory: string;
|
|
15
|
+
} | null;
|
|
16
|
+
repertoire: string | null;
|
|
17
|
+
inferenceSeconds: number | null;
|
|
18
|
+
activity: SuitPulseActivity | null;
|
|
19
|
+
lens: SuitLens;
|
|
20
|
+
plant: boolean;
|
|
21
|
+
line: string;
|
|
22
|
+
}
|
|
23
|
+
export interface SuitPulseOptions {
|
|
24
|
+
/** Epoch ms. Tests pin this so inference age stays exact. */
|
|
25
|
+
now?: number;
|
|
26
|
+
/** Override the CLI directory. Hooks and node_modules/0xray are the default. */
|
|
27
|
+
wornDir?: string;
|
|
28
|
+
}
|
|
29
|
+
export declare function readSuitPulse(root: string, opts?: SuitPulseOptions): SuitPulse;
|