fix: add missing lib files and fix gitignore

This commit is contained in:
Apple
2025-11-28 03:14:46 -08:00
parent c2becd1314
commit 594a05f969
6 changed files with 693 additions and 2 deletions

4
.gitignore vendored
View File

@@ -15,8 +15,8 @@ dist/
downloads/
eggs/
.eggs/
lib/
lib64/
/lib/
/lib64/
parts/
sdist/
var/

View 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();
}

View 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;
}

View 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);
}
}

View 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)}%`;
}

View 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;
}