11// Copyright (c) Microsoft Corporation.
22// Licensed under the MIT License.
3+ import * as fs from 'fs' ;
34import { AgentIdentity } from './identity' ;
45import {
56 TrustConfig ,
@@ -27,15 +28,20 @@ interface AgentTrustState {
2728 * with configurable decay.
2829 */
2930export class TrustManager {
30- private readonly config : Required < TrustConfig > ;
31+ private readonly config : Required < Omit < TrustConfig , 'persistPath' > > ;
3132 private readonly agents : Map < string , AgentTrustState > = new Map ( ) ;
33+ private readonly persistPath ?: string ;
3234
3335 constructor ( config ?: TrustConfig ) {
3436 this . config = {
3537 initialScore : config ?. initialScore ?? 0.5 ,
3638 decayFactor : config ?. decayFactor ?? 0.95 ,
3739 thresholds : { ...DEFAULT_THRESHOLDS , ...config ?. thresholds } ,
3840 } ;
41+ this . persistPath = config ?. persistPath ;
42+ if ( this . persistPath ) {
43+ this . loadFromDisk ( ) ;
44+ }
3945 }
4046
4147 /** Verify a peer agent's identity and return a trust result. */
@@ -83,6 +89,7 @@ export class TrustManager {
8389 state . successes += 1 ;
8490 state . score = Math . min ( 1 , state . score + reward ) ;
8591 state . lastUpdate = Date . now ( ) ;
92+ this . saveToDisk ( ) ;
8693 }
8794
8895 /** Record a failed interaction with an agent. */
@@ -92,6 +99,7 @@ export class TrustManager {
9299 state . failures += 1 ;
93100 state . score = Math . max ( 0 , state . score - penalty ) ;
94101 state . lastUpdate = Date . now ( ) ;
102+ this . saveToDisk ( ) ;
95103 }
96104
97105 // ── Private helpers ──
@@ -133,4 +141,30 @@ export class TrustManager {
133141 if ( total === 0 ) return this . config . initialScore ;
134142 return Math . round ( ( state . successes / total ) * 1000 ) / 1000 ;
135143 }
144+
145+ private saveToDisk ( ) : void {
146+ if ( ! this . persistPath ) return ;
147+ try {
148+ const data : Record < string , AgentTrustState > = { } ;
149+ for ( const [ key , value ] of this . agents ) {
150+ data [ key ] = value ;
151+ }
152+ fs . writeFileSync ( this . persistPath , JSON . stringify ( data ) , 'utf-8' ) ;
153+ } catch {
154+ // best-effort: ignore write errors
155+ }
156+ }
157+
158+ private loadFromDisk ( ) : void {
159+ if ( ! this . persistPath ) return ;
160+ try {
161+ const raw = fs . readFileSync ( this . persistPath , 'utf-8' ) ;
162+ const data = JSON . parse ( raw ) as Record < string , AgentTrustState > ;
163+ for ( const [ key , value ] of Object . entries ( data ) ) {
164+ this . agents . set ( key , value ) ;
165+ }
166+ } catch {
167+ // best-effort: ignore missing or corrupt files
168+ }
169+ }
136170}
0 commit comments