fix: add missing lib files and fix gitignore
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -15,8 +15,8 @@ dist/
|
|||||||
downloads/
|
downloads/
|
||||||
eggs/
|
eggs/
|
||||||
.eggs/
|
.eggs/
|
||||||
lib/
|
/lib/
|
||||||
lib64/
|
/lib64/
|
||||||
parts/
|
parts/
|
||||||
sdist/
|
sdist/
|
||||||
var/
|
var/
|
||||||
|
|||||||
298
apps/web/src/lib/agent-dashboard.ts
Normal file
298
apps/web/src/lib/agent-dashboard.ts
Normal file
@@ -0,0 +1,298 @@
|
|||||||
|
import type { AgentMicrodaoMembership } from "@/lib/microdao";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Agent Dashboard Types and API
|
||||||
|
* Based on DAIS (Decentralized AI Agent Standard) v1
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Types
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
export interface DAISCore {
|
||||||
|
title?: string;
|
||||||
|
bio?: string;
|
||||||
|
mission?: string;
|
||||||
|
version?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DAISVis {
|
||||||
|
avatar_url?: string;
|
||||||
|
avatar_style?: string;
|
||||||
|
color_primary?: string;
|
||||||
|
color_secondary?: string;
|
||||||
|
lora_refs?: string[];
|
||||||
|
second_me_id?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DAISCog {
|
||||||
|
base_model?: string;
|
||||||
|
provider?: string;
|
||||||
|
node_id?: string;
|
||||||
|
context_window?: number;
|
||||||
|
temperature?: number;
|
||||||
|
memory?: {
|
||||||
|
type?: string;
|
||||||
|
store?: string;
|
||||||
|
collections?: string[];
|
||||||
|
max_tokens?: number;
|
||||||
|
};
|
||||||
|
tools_enabled?: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DAISAct {
|
||||||
|
matrix?: {
|
||||||
|
user_id?: string;
|
||||||
|
rooms?: string[];
|
||||||
|
};
|
||||||
|
tools?: string[];
|
||||||
|
apis?: string[];
|
||||||
|
web3?: {
|
||||||
|
wallet_address?: string;
|
||||||
|
chains?: string[];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface DAIS {
|
||||||
|
core: DAISCore;
|
||||||
|
vis?: DAISVis;
|
||||||
|
cog?: DAISCog;
|
||||||
|
act?: DAISAct;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CityPresence {
|
||||||
|
primary_room_slug?: string;
|
||||||
|
district?: string;
|
||||||
|
rooms?: Array<{
|
||||||
|
room_id: string;
|
||||||
|
slug: string;
|
||||||
|
name: string;
|
||||||
|
role?: string;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AgentProfile {
|
||||||
|
agent_id: string;
|
||||||
|
display_name: string;
|
||||||
|
kind: string;
|
||||||
|
status: 'online' | 'offline' | 'degraded' | 'training' | 'maintenance';
|
||||||
|
node_id?: string;
|
||||||
|
roles: string[];
|
||||||
|
tags: string[];
|
||||||
|
dais: DAIS;
|
||||||
|
city_presence?: CityPresence;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AgentNode {
|
||||||
|
node_id: string;
|
||||||
|
status: string;
|
||||||
|
gpu?: {
|
||||||
|
name?: string;
|
||||||
|
vram_gb?: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AgentRuntime {
|
||||||
|
router_endpoint?: string;
|
||||||
|
health?: string;
|
||||||
|
last_success_at?: string | null;
|
||||||
|
last_error_at?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AgentMetrics {
|
||||||
|
tasks_1h?: number;
|
||||||
|
tasks_24h?: number;
|
||||||
|
errors_1h?: number;
|
||||||
|
errors_24h?: number;
|
||||||
|
avg_latency_ms_1h?: number;
|
||||||
|
success_rate_24h?: number;
|
||||||
|
tokens_24h?: number;
|
||||||
|
last_task_at?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AgentActivity {
|
||||||
|
timestamp: string;
|
||||||
|
type: string;
|
||||||
|
room_slug?: string;
|
||||||
|
summary?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AgentPromptView {
|
||||||
|
content: string;
|
||||||
|
version: number;
|
||||||
|
updated_at: string;
|
||||||
|
updated_by?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AgentSystemPrompts {
|
||||||
|
core?: AgentPromptView | null;
|
||||||
|
safety?: AgentPromptView | null;
|
||||||
|
governance?: AgentPromptView | null;
|
||||||
|
tools?: AgentPromptView | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AgentPublicProfile {
|
||||||
|
is_public: boolean;
|
||||||
|
public_slug?: string | null;
|
||||||
|
public_title?: string | null;
|
||||||
|
public_tagline?: string | null;
|
||||||
|
public_skills?: string[];
|
||||||
|
public_district?: string | null;
|
||||||
|
public_primary_room_slug?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AgentDashboard {
|
||||||
|
profile: AgentProfile;
|
||||||
|
node?: AgentNode;
|
||||||
|
runtime?: AgentRuntime;
|
||||||
|
metrics?: AgentMetrics;
|
||||||
|
recent_activity?: AgentActivity[];
|
||||||
|
system_prompts?: AgentSystemPrompts;
|
||||||
|
public_profile?: AgentPublicProfile;
|
||||||
|
microdao_memberships?: AgentMicrodaoMembership[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// API Functions
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
export async function fetchAgentDashboard(agentId: string): Promise<AgentDashboard> {
|
||||||
|
const response = await fetch(`/api/agents/${encodeURIComponent(agentId)}/dashboard`);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Failed to fetch agent dashboard: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Utility Functions
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
export function getAgentStatusColor(status: string): string {
|
||||||
|
switch (status) {
|
||||||
|
case 'online':
|
||||||
|
return 'text-green-500';
|
||||||
|
case 'training':
|
||||||
|
case 'degraded':
|
||||||
|
return 'text-yellow-500';
|
||||||
|
case 'offline':
|
||||||
|
case 'maintenance':
|
||||||
|
return 'text-red-500';
|
||||||
|
default:
|
||||||
|
return 'text-gray-500';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getAgentKindIcon(kind: string): string {
|
||||||
|
const icons: Record<string, string> = {
|
||||||
|
orchestrator: '🎭',
|
||||||
|
coordinator: '🎯',
|
||||||
|
specialist: '🔬',
|
||||||
|
developer: '💻',
|
||||||
|
architect: '🏗️',
|
||||||
|
marketing: '📢',
|
||||||
|
finance: '💰',
|
||||||
|
security: '🛡️',
|
||||||
|
forensics: '🔍',
|
||||||
|
vision: '👁️',
|
||||||
|
research: '📚',
|
||||||
|
memory: '🧠',
|
||||||
|
web3: '⛓️',
|
||||||
|
strategic: '♟️',
|
||||||
|
mediator: '⚖️',
|
||||||
|
innovation: '💡',
|
||||||
|
civic: '🏛️',
|
||||||
|
oracle: '🔮',
|
||||||
|
builder: '🔨',
|
||||||
|
social: '💬'
|
||||||
|
};
|
||||||
|
return icons[kind] || '🤖';
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// System Prompts API
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
export type PromptKind = 'core' | 'safety' | 'governance' | 'tools';
|
||||||
|
|
||||||
|
export interface UpdatePromptResult {
|
||||||
|
agent_id: string;
|
||||||
|
kind: string;
|
||||||
|
version: number;
|
||||||
|
updated_at: string;
|
||||||
|
updated_by: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function updateAgentPrompt(
|
||||||
|
agentId: string,
|
||||||
|
kind: PromptKind,
|
||||||
|
content: string,
|
||||||
|
note?: string
|
||||||
|
): Promise<UpdatePromptResult> {
|
||||||
|
const response = await fetch(
|
||||||
|
`/api/agents/${encodeURIComponent(agentId)}/prompts/${encodeURIComponent(kind)}`,
|
||||||
|
{
|
||||||
|
method: 'PUT',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ content, note })
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const body = await response.json().catch(() => null);
|
||||||
|
throw new Error(body?.error || 'Failed to update prompt');
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getPromptHistory(agentId: string, kind: PromptKind): Promise<{
|
||||||
|
agent_id: string;
|
||||||
|
kind: string;
|
||||||
|
history: Array<{
|
||||||
|
version: number;
|
||||||
|
content: string;
|
||||||
|
created_at: string;
|
||||||
|
created_by: string;
|
||||||
|
note?: string;
|
||||||
|
is_active: boolean;
|
||||||
|
}>;
|
||||||
|
}> {
|
||||||
|
const response = await fetch(
|
||||||
|
`/api/agents/${encodeURIComponent(agentId)}/prompts/${encodeURIComponent(kind)}`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error('Failed to get prompt history');
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Public Profile API
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
export async function updateAgentPublicProfile(
|
||||||
|
agentId: string,
|
||||||
|
profile: AgentPublicProfile
|
||||||
|
): Promise<AgentPublicProfile> {
|
||||||
|
const response = await fetch(
|
||||||
|
`/api/agents/${encodeURIComponent(agentId)}/public-profile`,
|
||||||
|
{
|
||||||
|
method: 'PUT',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify(profile)
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
const body = await response.json().catch(() => null);
|
||||||
|
throw new Error(body?.detail || body?.error || 'Failed to update public profile');
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
|
||||||
27
apps/web/src/lib/api/citizens.ts
Normal file
27
apps/web/src/lib/api/citizens.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import type { CitizenAskResponse } from "@/lib/types/citizens";
|
||||||
|
|
||||||
|
export async function askCitizen(
|
||||||
|
slug: string,
|
||||||
|
params: { question: string; context?: string }
|
||||||
|
): Promise<CitizenAskResponse> {
|
||||||
|
const res = await fetch(
|
||||||
|
`/api/public/citizens/${encodeURIComponent(slug)}/ask`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify(params),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const data = await res.json().catch(() => null);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new Error(
|
||||||
|
data?.error || data?.detail || "Не вдалося отримати відповідь від агента."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data as CitizenAskResponse;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
69
apps/web/src/lib/api/microdao.ts
Normal file
69
apps/web/src/lib/api/microdao.ts
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
import type {
|
||||||
|
AgentMicrodaoMembership,
|
||||||
|
MicrodaoOption,
|
||||||
|
} from "@/lib/microdao";
|
||||||
|
|
||||||
|
async function request<T>(input: RequestInfo, init?: RequestInit): Promise<T> {
|
||||||
|
const res = await fetch(input, {
|
||||||
|
...init,
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
...(init?.headers ?? {}),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await res.json().catch(() => null);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
const message =
|
||||||
|
(data && (data.error || data.detail || data.message)) ||
|
||||||
|
"Request failed";
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return data as T;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchMicrodaoOptions(): Promise<MicrodaoOption[]> {
|
||||||
|
const data = await request<{ items?: MicrodaoOption[] }>(
|
||||||
|
"/api/microdao/options"
|
||||||
|
);
|
||||||
|
return data.items ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function assignAgentToMicrodao(
|
||||||
|
agentId: string,
|
||||||
|
payload: { microdao_id: string; role?: string; is_core?: boolean }
|
||||||
|
): Promise<AgentMicrodaoMembership> {
|
||||||
|
return request<AgentMicrodaoMembership>(
|
||||||
|
`/api/agents/${encodeURIComponent(agentId)}/microdao-membership`,
|
||||||
|
{
|
||||||
|
method: "PUT",
|
||||||
|
body: JSON.stringify(payload),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function removeAgentFromMicrodao(
|
||||||
|
agentId: string,
|
||||||
|
microdaoId: string
|
||||||
|
): Promise<void> {
|
||||||
|
const res = await fetch(
|
||||||
|
`/api/agents/${encodeURIComponent(
|
||||||
|
agentId
|
||||||
|
)}/microdao-membership/${encodeURIComponent(microdaoId)}`,
|
||||||
|
{
|
||||||
|
method: "DELETE",
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
const data = await res.json().catch(() => null);
|
||||||
|
const message =
|
||||||
|
(data && (data.error || data.detail || data.message)) ||
|
||||||
|
"Failed to remove MicroDAO membership";
|
||||||
|
throw new Error(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
230
apps/web/src/lib/node-dashboard.ts
Normal file
230
apps/web/src/lib/node-dashboard.ts
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
/**
|
||||||
|
* Node Dashboard Types and API
|
||||||
|
* Based on Node Profile Standard v1
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Types
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
export interface NodeInfo {
|
||||||
|
node_id: string;
|
||||||
|
name: string;
|
||||||
|
roles: string[];
|
||||||
|
status: 'online' | 'offline' | 'degraded' | 'maintenance';
|
||||||
|
public_hostname: string;
|
||||||
|
environment: string;
|
||||||
|
gpu: {
|
||||||
|
name: string;
|
||||||
|
vram_gb?: number;
|
||||||
|
unified_memory_gb?: number;
|
||||||
|
} | null;
|
||||||
|
modules: ModuleStatus[];
|
||||||
|
version: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ModuleStatus {
|
||||||
|
id: string;
|
||||||
|
status: 'up' | 'down' | 'degraded' | 'unknown';
|
||||||
|
port?: number;
|
||||||
|
error?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface InfraMetrics {
|
||||||
|
cpu_usage_pct: number;
|
||||||
|
ram: {
|
||||||
|
total_gb: number;
|
||||||
|
used_gb: number;
|
||||||
|
};
|
||||||
|
disk: {
|
||||||
|
total_gb: number;
|
||||||
|
used_gb: number;
|
||||||
|
};
|
||||||
|
gpus: Array<{
|
||||||
|
name: string;
|
||||||
|
vram_gb: number;
|
||||||
|
used_gb: number;
|
||||||
|
sm_util_pct: number;
|
||||||
|
}>;
|
||||||
|
network?: {
|
||||||
|
rx_mbps: number;
|
||||||
|
tx_mbps: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SwapperStatus {
|
||||||
|
status: 'up' | 'down' | 'degraded' | 'not_installed';
|
||||||
|
endpoint: string;
|
||||||
|
latency_ms: number;
|
||||||
|
active_model?: string;
|
||||||
|
mode?: string;
|
||||||
|
storage: {
|
||||||
|
total_gb: number;
|
||||||
|
used_gb: number;
|
||||||
|
free_gb: number;
|
||||||
|
};
|
||||||
|
models: Array<{
|
||||||
|
name: string;
|
||||||
|
size_gb: number;
|
||||||
|
device: string;
|
||||||
|
state: string;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RouterStatus {
|
||||||
|
status: 'up' | 'down' | 'degraded' | 'not_installed';
|
||||||
|
endpoint: string;
|
||||||
|
version: string;
|
||||||
|
nats_connected?: boolean;
|
||||||
|
backends: Array<{
|
||||||
|
name: string;
|
||||||
|
status: string;
|
||||||
|
latency_ms: number;
|
||||||
|
error?: string;
|
||||||
|
}>;
|
||||||
|
metrics: {
|
||||||
|
requests_1m: number;
|
||||||
|
requests_1h: number;
|
||||||
|
error_rate_1h: number;
|
||||||
|
avg_latency_ms_1h: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface OllamaStatus {
|
||||||
|
status: 'up' | 'down' | 'degraded' | 'not_installed';
|
||||||
|
endpoint: string;
|
||||||
|
latency_ms: number;
|
||||||
|
models: string[];
|
||||||
|
error?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ServiceStatus {
|
||||||
|
status: 'up' | 'down' | 'degraded' | 'not_installed';
|
||||||
|
endpoint: string;
|
||||||
|
latency_ms: number;
|
||||||
|
error?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AIServices {
|
||||||
|
swapper: SwapperStatus;
|
||||||
|
router: RouterStatus;
|
||||||
|
ollama: OllamaStatus;
|
||||||
|
services: Record<string, ServiceStatus>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AgentSummary {
|
||||||
|
total: number;
|
||||||
|
running: number;
|
||||||
|
by_kind: Record<string, number>;
|
||||||
|
top: Array<{
|
||||||
|
agent_id: string;
|
||||||
|
display_name: string;
|
||||||
|
kind: string;
|
||||||
|
status: string;
|
||||||
|
node_id?: string;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MatrixStatus {
|
||||||
|
enabled: boolean;
|
||||||
|
homeserver?: string;
|
||||||
|
synapse?: {
|
||||||
|
status: string;
|
||||||
|
latency_ms: number;
|
||||||
|
};
|
||||||
|
presence_bridge?: {
|
||||||
|
status: string;
|
||||||
|
latency_ms: number;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MonitoringStatus {
|
||||||
|
prometheus: {
|
||||||
|
url: string;
|
||||||
|
status: string;
|
||||||
|
};
|
||||||
|
grafana: {
|
||||||
|
url: string;
|
||||||
|
status: string;
|
||||||
|
};
|
||||||
|
logging: {
|
||||||
|
loki: {
|
||||||
|
status: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface NodeDashboard {
|
||||||
|
node: NodeInfo;
|
||||||
|
infra: InfraMetrics;
|
||||||
|
ai: AIServices;
|
||||||
|
agents: AgentSummary;
|
||||||
|
matrix: MatrixStatus;
|
||||||
|
monitoring: MonitoringStatus;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// API Functions
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
export async function fetchNodeDashboard(nodeId?: string): Promise<NodeDashboard> {
|
||||||
|
const url = nodeId
|
||||||
|
? `/api/node/dashboard?nodeId=${encodeURIComponent(nodeId)}`
|
||||||
|
: '/api/node/dashboard';
|
||||||
|
|
||||||
|
const response = await fetch(url);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`Failed to fetch dashboard: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.json();
|
||||||
|
}
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// Utility Functions
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
export function getStatusColor(status: string): string {
|
||||||
|
switch (status) {
|
||||||
|
case 'up':
|
||||||
|
case 'online':
|
||||||
|
return 'text-green-500';
|
||||||
|
case 'degraded':
|
||||||
|
case 'busy':
|
||||||
|
return 'text-yellow-500';
|
||||||
|
case 'down':
|
||||||
|
case 'offline':
|
||||||
|
return 'text-red-500';
|
||||||
|
default:
|
||||||
|
return 'text-gray-500';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getStatusBgColor(status: string): string {
|
||||||
|
switch (status) {
|
||||||
|
case 'up':
|
||||||
|
case 'online':
|
||||||
|
return 'bg-green-500/20';
|
||||||
|
case 'degraded':
|
||||||
|
case 'busy':
|
||||||
|
return 'bg-yellow-500/20';
|
||||||
|
case 'down':
|
||||||
|
case 'offline':
|
||||||
|
return 'bg-red-500/20';
|
||||||
|
default:
|
||||||
|
return 'bg-gray-500/20';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatBytes(gb: number): string {
|
||||||
|
if (gb >= 1000) {
|
||||||
|
return `${(gb / 1000).toFixed(1)} TB`;
|
||||||
|
}
|
||||||
|
return `${gb.toFixed(1)} GB`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function formatPercent(value: number): string {
|
||||||
|
return `${value.toFixed(1)}%`;
|
||||||
|
}
|
||||||
|
|
||||||
67
apps/web/src/lib/types/citizens.ts
Normal file
67
apps/web/src/lib/types/citizens.ts
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
export interface PublicCitizenSummary {
|
||||||
|
slug: string;
|
||||||
|
display_name: string;
|
||||||
|
public_title?: string | null;
|
||||||
|
public_tagline?: string | null;
|
||||||
|
avatar_url?: string | null;
|
||||||
|
kind?: string | null;
|
||||||
|
district?: string | null;
|
||||||
|
primary_room_slug?: string | null;
|
||||||
|
public_skills: string[];
|
||||||
|
online_status?: "online" | "offline" | "unknown" | string;
|
||||||
|
status?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CityPresenceRoom {
|
||||||
|
room_id?: string | null;
|
||||||
|
slug?: string | null;
|
||||||
|
name?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CityPresence {
|
||||||
|
primary_room_slug?: string | null;
|
||||||
|
rooms: CityPresenceRoom[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface PublicCitizenProfile {
|
||||||
|
slug: string;
|
||||||
|
display_name: string;
|
||||||
|
kind?: string | null;
|
||||||
|
public_title?: string | null;
|
||||||
|
public_tagline?: string | null;
|
||||||
|
district?: string | null;
|
||||||
|
avatar_url?: string | null;
|
||||||
|
status?: string | null;
|
||||||
|
node_id?: string | null;
|
||||||
|
public_skills: string[];
|
||||||
|
city_presence?: CityPresence;
|
||||||
|
dais_public: Record<string, unknown>;
|
||||||
|
interaction: Record<string, unknown>;
|
||||||
|
metrics_public: Record<string, unknown>;
|
||||||
|
admin_panel_url?: string | null;
|
||||||
|
microdao?: {
|
||||||
|
slug: string;
|
||||||
|
name: string;
|
||||||
|
district?: string | null;
|
||||||
|
} | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CitizenInteractionInfo {
|
||||||
|
slug: string;
|
||||||
|
display_name: string;
|
||||||
|
primary_room_slug?: string | null;
|
||||||
|
primary_room_id?: string | null;
|
||||||
|
primary_room_name?: string | null;
|
||||||
|
matrix_user_id?: string | null;
|
||||||
|
district?: string | null;
|
||||||
|
microdao_slug?: string | null;
|
||||||
|
microdao_name?: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CitizenAskResponse {
|
||||||
|
answer: string;
|
||||||
|
agent_display_name: string;
|
||||||
|
agent_id: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user