import type { AgentProfile, TrustBreakdown, PolicyContext } from './types' import { computeTrustScore } from './scoring/index' import { getSpendingLimits } from './scoring/limits' import { refreshOnChainData } from './scoring/onchain' import { getConfig } from './config' const agents = new Map() // --- Helpers --- function todayString(): string { return new Date().toISOString().split('T')[0] } function yesterdayString(): string { const d = new Date() d.setDate(d.getDate() - 1) return d.toISOString().split('T')[0] } function defaultBreakdown(): TrustBreakdown { return { identity: 4, onChain: 0, behavior: 0, compliance: 0, network: 0, risk: 0, total: 4 } } function recalc(agent: AgentProfile): void { const breakdown = computeTrustScore(agent, getAgent) agent.breakdown = breakdown agent.trustScore = breakdown.total agent.tier = getSpendingLimits(breakdown.total).tier.name } // --- Core Store Functions --- export function getOrCreateAgent(address: string): AgentProfile { if (agents.has(address)) return agents.get(address)! const today = todayString() const now = Date.now() const profile: AgentProfile = { address, isOWSWallet: false, worldIdVerified: false, webBotAuthVerified: false, trustScore: 4, tier: 'Restricted', breakdown: defaultBreakdown(), totalRequests: 0, successfulRequests: 0, failedRequests: 0, dailySpent: 0, dailyDate: today, consecutiveApprovals: 0, consecutiveDenials: 0, totalApproved: 0, totalDenied: 0, humanOverrides: 0, counterparties: [], requestTimestamps: [], lastActive: now, consecutiveCleanDays: 0, cleanDayDate: today, createdAt: now, } agents.set(address, profile) refreshOnChainData(address).catch(() => {}) return profile } export function getAgent(address: string): AgentProfile | undefined { return agents.get(address) } export function getAllAgents(): AgentProfile[] { return Array.from(agents.values()) } export function getTopAgents(n: number): AgentProfile[] { return getAllAgents().sort((a, b) => b.trustScore - a.trustScore).slice(0, n) } export function recordApproval(address: string, txTo: string, amount: number): AgentProfile { const agent = getOrCreateAgent(address) const now = Date.now() const today = todayString() agent.totalRequests++ agent.successfulRequests++ agent.totalApproved++ agent.consecutiveApprovals++ agent.consecutiveDenials = 0 agent.requestTimestamps.push(now) if (agent.requestTimestamps.length > 100) agent.requestTimestamps = agent.requestTimestamps.slice(-100) if (!agent.counterparties.includes(txTo)) agent.counterparties.push(txTo) if (agent.dailyDate !== today) { agent.dailySpent = 0 agent.dailyDate = today } agent.dailySpent += amount agent.lastActive = now if (agent.cleanDayDate === today) { // already counted today } else if (agent.cleanDayDate === yesterdayString()) { agent.consecutiveCleanDays++ } else { agent.consecutiveCleanDays = 1 } agent.cleanDayDate = today recalc(agent) refreshOnChainData(agent.address).catch(() => {}) return agent } export function recordDenial( address: string, tx?: PolicyContext['transaction'], amount?: number ): AgentProfile { const agent = getOrCreateAgent(address) const now = Date.now() agent.totalRequests++ agent.failedRequests++ agent.totalDenied++ agent.consecutiveDenials++ agent.consecutiveApprovals = 0 agent.requestTimestamps.push(now) if (agent.requestTimestamps.length > 100) agent.requestTimestamps = agent.requestTimestamps.slice(-100) agent.lastActive = now if (tx && amount !== undefined) { agent.pendingOverride = { tx, amount, createdAt: Date.now() } } recalc(agent) return agent } export function recordOverride(address: string): AgentProfile | undefined { const agent = getAgent(address) if (!agent || !agent.pendingOverride) return undefined const OVERRIDE_TTL = 5 * 60 * 1000 // 5 minutes if (Date.now() - (agent.pendingOverride.createdAt || 0) > OVERRIDE_TTL) { agent.pendingOverride = undefined return undefined // expired } agent.humanOverrides++ agent.pendingOverride = undefined agent.totalApproved++ agent.consecutiveApprovals++ agent.consecutiveDenials = 0 recalc(agent) const boost = getConfig().scoring?.overrideBoost ?? 3 agent.trustScore = Math.min(100, agent.trustScore + boost) agent.tier = getSpendingLimits(agent.trustScore).tier.name return agent } export function addVerifiedHuman(address: string, nullifierHash: string): AgentProfile { const agent = getOrCreateAgent(address) agent.worldIdVerified = true agent.nullifierHash = nullifierHash recalc(agent) return agent } export function isVerifiedHuman(address: string): boolean { return agents.get(address)?.worldIdVerified ?? false } export function setWebBotAuthVerified(address: string): AgentProfile { const agent = getOrCreateAgent(address) agent.webBotAuthVerified = true recalc(agent) return agent } export function setOWSWallet(address: string, walletId: string, apiKeyId: string): AgentProfile { const agent = getOrCreateAgent(address) agent.isOWSWallet = true agent.walletId = walletId agent.apiKeyId = apiKeyId recalc(agent) return agent }