Add cloud venue scout: EC2 IMDS tags infer batch/spot/gpu biomes for persona packs and weather.
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
This commit is contained in:
28
server/web/src/help/cloudVenueBiomeWeather.test.ts
Normal file
28
server/web/src/help/cloudVenueBiomeWeather.test.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { PAGE_WEATHER } from './pageWeather';
|
||||
import { mergeScoutBiomeWeather } from './scoutBiomeWeather';
|
||||
import { activeBiomeLabel, dominantCloudVenue, mergeBiomeWeather, mergeCloudVenueBiomeWeather } from './cloudVenueBiomeWeather';
|
||||
|
||||
describe('cloudVenueBiomeWeather', () => {
|
||||
it('picks dominant cloud venue by agent weight', () => {
|
||||
expect(dominantCloudVenue({ biomes: [
|
||||
{ biome_key: 'ou/batch', venue_class: 'batch', agent_ids: ['1', '2'] },
|
||||
{ biome_key: 'ou/gpu', venue_class: 'gpu', agent_ids: ['3', '4', '5'] },
|
||||
]})).toBe('gpu');
|
||||
});
|
||||
it('boosts pulse for spot cloud biome', () => {
|
||||
const base = PAGE_WEATHER['/dashboard'];
|
||||
const merged = mergeCloudVenueBiomeWeather(base, { biomes: [{ biome_key: 'ou/spot', venue_class: 'spot', agent_ids: ['a'] }] });
|
||||
expect(merged.pulse).toBeGreaterThan(base.pulse);
|
||||
expect(merged.energyPulse).toBe(true);
|
||||
});
|
||||
it('prefers cloud label over scout for weather chip', () => {
|
||||
expect(activeBiomeLabel(
|
||||
{ constellations: [{ ssid: 'a', venue_class: 'airport', agent_ids: ['1', '2', '3'] }] },
|
||||
{ biomes: [{ biome_key: 'ou/batch', venue_class: 'batch', agent_ids: ['x'] }] },
|
||||
)).toBe('cloud:batch');
|
||||
});
|
||||
it('returns base weather when no cloud biomes', () => {
|
||||
expect(mergeCloudVenueBiomeWeather(PAGE_WEATHER['/dashboard'], null)).toEqual(PAGE_WEATHER['/dashboard']);
|
||||
});
|
||||
});
|
||||
86
server/web/src/help/cloudVenueBiomeWeather.ts
Normal file
86
server/web/src/help/cloudVenueBiomeWeather.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
/** Cloud venue OU/tags → ambient weather biome overlay. */
|
||||
|
||||
import type { PageWeatherConfig } from './pageWeather';
|
||||
import { mergeScoutBiomeWeather, type ScoutConstellationSnapshot } from './scoutBiomeWeather';
|
||||
|
||||
export interface CloudVenueBiome {
|
||||
biome_key: string;
|
||||
venue_class: string;
|
||||
persona_pack?: string;
|
||||
agent_ids?: string[];
|
||||
environment?: string;
|
||||
workload?: string;
|
||||
}
|
||||
|
||||
export interface CloudVenueSnapshot {
|
||||
biomes?: CloudVenueBiome[];
|
||||
}
|
||||
|
||||
const CLOUD_VENUE_BIOME: Record<string, Partial<PageWeatherConfig>> = {
|
||||
batch: { pulse: 0.85, speed: 0.55, linkStrength: 0.75, density: 0.82 },
|
||||
interactive: { pulse: 1.05, linkStrength: 0.8, density: 0.9, palette: 'default' },
|
||||
spot: { pulse: 1.6, speed: 0.7, linkStrength: 0.9, palette: 'campaign', energyPulse: true },
|
||||
gpu: { pulse: 1.25, linkStrength: 0.95, density: 1.05, palette: 'campaign' },
|
||||
};
|
||||
|
||||
export function dominantCloudVenue(snapshot: CloudVenueSnapshot | null | undefined): string | null {
|
||||
const list = snapshot?.biomes ?? [];
|
||||
if (!list.length) return null;
|
||||
const rank: Record<string, number> = { gpu: 4, spot: 3, batch: 2, interactive: 1 };
|
||||
let best = list[0].venue_class || 'interactive';
|
||||
let bestScore = (list[0].agent_ids?.length ?? 1) * (rank[best] ?? 1);
|
||||
for (let i = 1; i < list.length; i++) {
|
||||
const venue = list[i].venue_class || 'interactive';
|
||||
const score = (list[i].agent_ids?.length ?? 1) * (rank[venue] ?? 1);
|
||||
if (score > bestScore) { best = venue; bestScore = score; }
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
export function mergeCloudVenueBiomeWeather(
|
||||
base: PageWeatherConfig,
|
||||
snapshot: CloudVenueSnapshot | null | undefined,
|
||||
): PageWeatherConfig {
|
||||
const venue = dominantCloudVenue(snapshot);
|
||||
if (!venue) return base;
|
||||
const overlay = CLOUD_VENUE_BIOME[venue] ?? CLOUD_VENUE_BIOME.interactive;
|
||||
return {
|
||||
...base,
|
||||
...overlay,
|
||||
intensity: Math.min(1, (base.intensity + (overlay.intensity ?? base.intensity)) / 2 + 0.06),
|
||||
energyPulse: overlay.energyPulse ?? base.energyPulse,
|
||||
};
|
||||
}
|
||||
|
||||
export function mergeBiomeWeather(
|
||||
base: PageWeatherConfig,
|
||||
scout: ScoutConstellationSnapshot | null | undefined,
|
||||
cloud: CloudVenueSnapshot | null | undefined,
|
||||
): PageWeatherConfig {
|
||||
return mergeCloudVenueBiomeWeather(mergeScoutBiomeWeather(base, scout), cloud);
|
||||
}
|
||||
|
||||
export function activeBiomeLabel(
|
||||
scout: ScoutConstellationSnapshot | null | undefined,
|
||||
cloud: CloudVenueSnapshot | null | undefined,
|
||||
): string | null {
|
||||
const cloudVenue = dominantCloudVenue(cloud);
|
||||
const scoutVenue = scout?.constellations?.length ? dominantScoutVenueFromSnapshot(scout) : null;
|
||||
if (cloudVenue) return `cloud:${cloudVenue}`;
|
||||
if (scoutVenue) return `wifi:${scoutVenue}`;
|
||||
return null;
|
||||
}
|
||||
|
||||
function dominantScoutVenueFromSnapshot(snapshot: ScoutConstellationSnapshot): string | null {
|
||||
const list = snapshot.constellations ?? [];
|
||||
if (!list.length) return null;
|
||||
const rank: Record<string, number> = { airport: 4, retail: 3, campus: 2, unknown: 1 };
|
||||
let best = list[0].venue_class || 'unknown';
|
||||
let bestScore = (list[0].agent_ids?.length ?? 1) * (rank[best] ?? 1);
|
||||
for (let i = 1; i < list.length; i++) {
|
||||
const venue = list[i].venue_class || 'unknown';
|
||||
const score = (list[i].agent_ids?.length ?? 1) * (rank[venue] ?? 1);
|
||||
if (score > bestScore) { best = venue; bestScore = score; }
|
||||
}
|
||||
return best;
|
||||
}
|
||||
@@ -91,6 +91,7 @@ export const WS_LATEST_MESSAGE_TYPES = new Set([
|
||||
'emberwake_notes_updated',
|
||||
'emberwake_war_room',
|
||||
'scout_constellations',
|
||||
'cloud_venue_biomes',
|
||||
'agent_online',
|
||||
'agent_offline',
|
||||
'new_share',
|
||||
|
||||
Reference in New Issue
Block a user