@directive-run/core 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +57 -0
  3. package/dist/adapter-utils.cjs +2 -0
  4. package/dist/adapter-utils.cjs.map +1 -0
  5. package/dist/adapter-utils.d.cts +230 -0
  6. package/dist/adapter-utils.d.ts +230 -0
  7. package/dist/adapter-utils.js +2 -0
  8. package/dist/adapter-utils.js.map +1 -0
  9. package/dist/index.cjs +35 -0
  10. package/dist/index.cjs.map +1 -0
  11. package/dist/index.d.cts +2016 -0
  12. package/dist/index.d.ts +2016 -0
  13. package/dist/index.js +35 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/migration.cjs +25 -0
  16. package/dist/migration.cjs.map +1 -0
  17. package/dist/migration.d.cts +109 -0
  18. package/dist/migration.d.ts +109 -0
  19. package/dist/migration.js +25 -0
  20. package/dist/migration.js.map +1 -0
  21. package/dist/plugins/index.cjs +3 -0
  22. package/dist/plugins/index.cjs.map +1 -0
  23. package/dist/plugins/index.d.cts +697 -0
  24. package/dist/plugins/index.d.ts +697 -0
  25. package/dist/plugins/index.js +3 -0
  26. package/dist/plugins/index.js.map +1 -0
  27. package/dist/plugins-CcwEXXMS.d.cts +1876 -0
  28. package/dist/plugins-CcwEXXMS.d.ts +1876 -0
  29. package/dist/testing.cjs +12 -0
  30. package/dist/testing.cjs.map +1 -0
  31. package/dist/testing.d.cts +235 -0
  32. package/dist/testing.d.ts +235 -0
  33. package/dist/testing.js +12 -0
  34. package/dist/testing.js.map +1 -0
  35. package/dist/utils-4JrY5fk9.d.cts +198 -0
  36. package/dist/utils-4JrY5fk9.d.ts +198 -0
  37. package/dist/worker.cjs +12 -0
  38. package/dist/worker.cjs.map +1 -0
  39. package/dist/worker.d.cts +241 -0
  40. package/dist/worker.d.ts +241 -0
  41. package/dist/worker.js +12 -0
  42. package/dist/worker.js.map +1 -0
  43. package/package.json +85 -0
@@ -0,0 +1,3 @@
1
+ var U={debug:0,info:1,warn:2,error:3};function W(s={}){let{level:l="info",filter:a=()=>true,logger:o=console,prefix:c="[Directive]"}=s,i=U[l],t=(e,r,...f)=>{U[e]<i||a(r)&&o[e](`${c} ${r}`,...f);};return {name:"logging",onInit:()=>t("debug","init"),onStart:()=>t("info","start"),onStop:()=>t("info","stop"),onDestroy:()=>t("debug","destroy"),onFactSet:(e,r,f)=>{t("debug","fact.set",{key:e,value:r,prev:f});},onFactDelete:(e,r)=>{t("debug","fact.delete",{key:e,prev:r});},onFactsBatch:e=>{t("debug","facts.batch",{count:e.length,changes:e});},onDerivationCompute:(e,r,f)=>{t("debug","derivation.compute",{id:e,value:r,deps:f});},onDerivationInvalidate:e=>{t("debug","derivation.invalidate",{id:e});},onReconcileStart:()=>{t("debug","reconcile.start");},onReconcileEnd:e=>{t("debug","reconcile.end",{unmet:e.unmet.length,inflight:e.inflight.length,completed:e.completed.length,canceled:e.canceled.length});},onConstraintEvaluate:(e,r)=>{t("debug","constraint.evaluate",{id:e,active:r});},onConstraintError:(e,r)=>{t("error","constraint.error",{id:e,error:r});},onRequirementCreated:e=>{t("debug","requirement.created",{id:e.id,type:e.requirement.type});},onRequirementMet:(e,r)=>{t("info","requirement.met",{id:e.id,byResolver:r});},onRequirementCanceled:e=>{t("debug","requirement.canceled",{id:e.id});},onResolverStart:(e,r)=>{t("debug","resolver.start",{resolver:e,requirementId:r.id});},onResolverComplete:(e,r,f)=>{t("info","resolver.complete",{resolver:e,requirementId:r.id,duration:f});},onResolverError:(e,r,f)=>{t("error","resolver.error",{resolver:e,requirementId:r.id,error:f});},onResolverRetry:(e,r,f)=>{t("warn","resolver.retry",{resolver:e,requirementId:r.id,attempt:f});},onResolverCancel:(e,r)=>{t("debug","resolver.cancel",{resolver:e,requirementId:r.id});},onEffectRun:e=>{t("debug","effect.run",{id:e});},onEffectError:(e,r)=>{t("error","effect.error",{id:e,error:r});},onSnapshot:e=>{t("debug","timetravel.snapshot",{id:e.id,trigger:e.trigger});},onTimeTravel:(e,r)=>{t("info","timetravel.jump",{from:e,to:r});},onError:e=>{t("error","error",{source:e.source,sourceId:e.sourceId,message:e.message});},onErrorRecovery:(e,r)=>{t("warn","error.recovery",{source:e.source,sourceId:e.sourceId,strategy:r});}}}function J(){if(typeof window>"u")return {systems:new Map,getSystem:()=>null,getSystems:()=>[],inspect:()=>null,getEvents:()=>[]};if(!window.__DIRECTIVE__){let s=new Map;window.__DIRECTIVE__={systems:s,getSystem(l){return l?s.get(l)?.system??null:s.values().next().value?.system??null},getSystems(){return [...s.keys()]},inspect(l){return this.getSystem(l)?.inspect()??null},getEvents(l){return l?s.get(l)?.events??[]:s.values().next().value?.events??[]}};}return window.__DIRECTIVE__}function G(s={}){let{name:l="default",trace:a=false}=s,o=J(),c={system:null,events:[],maxEvents:1e3};o.systems.set(l,c);let i=(t,e)=>{a&&(c.events.push({timestamp:Date.now(),type:t,data:e}),c.events.length>c.maxEvents&&c.events.shift());};return {name:"devtools",onInit:t=>{c.system=t,i("init",{}),typeof window<"u"&&console.log(`%c[Directive Devtools]%c System "${l}" initialized. Access via window.__DIRECTIVE__`,"color: #7c3aed; font-weight: bold","color: inherit");},onStart:()=>i("start",{}),onStop:()=>i("stop",{}),onDestroy:()=>{i("destroy",{}),o.systems.delete(l);},onFactSet:(t,e,r)=>{i("fact.set",{key:t,value:e,prev:r});},onFactsBatch:t=>{i("facts.batch",{changes:t});},onReconcileStart:()=>{i("reconcile.start",{});},onReconcileEnd:t=>{i("reconcile.end",t);},onConstraintEvaluate:(t,e)=>{i("constraint.evaluate",{id:t,active:e});},onRequirementCreated:t=>{i("requirement.created",{id:t.id,type:t.requirement.type});},onRequirementMet:(t,e)=>{i("requirement.met",{id:t.id,byResolver:e});},onResolverStart:(t,e)=>{i("resolver.start",{resolver:t,requirementId:e.id});},onResolverComplete:(t,e,r)=>{i("resolver.complete",{resolver:t,requirementId:e.id,duration:r});},onResolverError:(t,e,r)=>{i("resolver.error",{resolver:t,requirementId:e.id,error:String(r)});},onSnapshot:t=>{i("timetravel.snapshot",{id:t.id,trigger:t.trigger});},onTimeTravel:(t,e)=>{i("timetravel.jump",{from:t,to:e});},onError:t=>{i("error",{source:t.source,sourceId:t.sourceId,message:t.message});}}}function j(s,l=50){let a=new Set(["__proto__","constructor","prototype"]),o=new WeakSet;function c(i,t){if(t>l)return false;if(i==null||typeof i!="object")return true;let e=i;if(o.has(e))return true;if(o.add(e),Array.isArray(e)){for(let r of e)if(!c(r,t+1))return o.delete(e),false;return o.delete(e),true}for(let r of Object.keys(e))if(a.has(r)||!c(e[r],t+1))return o.delete(e),false;return o.delete(e),true}return c(s,0)}function z(s){let{storage:l,key:a,include:o,exclude:c=[],debounce:i=100,onRestore:t,onSave:e,onError:r}=s,f=null,b=null,y=new Set,T=n=>c.includes(n)?false:o?o.includes(n):true,E=()=>{try{let n=l.getItem(a);if(!n)return null;let g=JSON.parse(n);return typeof g!="object"||g===null?null:j(g)?g:(r?.(new Error("Potential prototype pollution detected in stored data")),null)}catch(n){return r?.(n instanceof Error?n:new Error(String(n))),null}},D=()=>{if(b)try{let n={};for(let g of y)T(g)&&(n[g]=b.facts[g]);l.setItem(a,JSON.stringify(n)),e?.(n);}catch(n){r?.(n instanceof Error?n:new Error(String(n)));}},S=()=>{f&&clearTimeout(f),f=setTimeout(D,i);};return {name:"persistence",onInit:n=>{b=n;let g=E();g&&(b.facts.$store.batch(()=>{for(let[v,p]of Object.entries(g))T(v)&&(b.facts[v]=p,y.add(v));}),t?.(g));},onDestroy:()=>{f&&clearTimeout(f),D();},onFactSet:n=>{y.add(n),T(n)&&S();},onFactDelete:n=>{y.delete(n),T(n)&&S();},onFactsBatch:n=>{let g=false;for(let v of n)v.type==="set"?y.add(v.key):y.delete(v.key),T(v.key)&&(g=true);g&&S();}}}function K(s={}){let{onSlowConstraint:l,onSlowResolver:a,slowConstraintThresholdMs:o=16,slowResolverThresholdMs:c=1e3}=s,i=new Map,t=new Map,e=new Map,r={runs:0,totalDurationMs:0,avgDurationMs:0,maxDurationMs:0},f=0,b=0,y=0;function T(n){let g=i.get(n);return g||(g={evaluations:0,totalDurationMs:0,avgDurationMs:0,maxDurationMs:0,lastEvaluatedAt:0},i.set(n,g)),g}function E(n){let g=t.get(n);return g||(g={starts:0,completions:0,errors:0,retries:0,cancellations:0,totalDurationMs:0,avgDurationMs:0,maxDurationMs:0,lastCompletedAt:0},t.set(n,g)),g}function D(n){let g=e.get(n);return g||(g={runs:0,errors:0,lastRunAt:0},e.set(n,g)),g}return {name:"performance",onStart(){f=Date.now();},onConstraintEvaluate(n,g){let v=performance.now(),p=T(n);if(p.evaluations++,p.lastEvaluatedAt=Date.now(),y>0){let h=v-y;p.totalDurationMs+=h;let A=p.evaluations;p.avgDurationMs=p.totalDurationMs/A,h>p.maxDurationMs&&(p.maxDurationMs=h),h>o&&l?.(n,h);}y=v;},onResolverStart(n,g){let v=E(n);v.starts++;},onResolverComplete(n,g,v){let p=E(n);p.completions++,p.totalDurationMs+=v,p.avgDurationMs=p.totalDurationMs/p.completions,v>p.maxDurationMs&&(p.maxDurationMs=v),p.lastCompletedAt=Date.now(),v>c&&a?.(n,v);},onResolverError(n,g,v){E(n).errors++;},onResolverRetry(n,g,v){E(n).retries++;},onResolverCancel(n,g){E(n).cancellations++;},onEffectRun(n){let g=D(n);g.runs++,g.lastRunAt=Date.now();},onEffectError(n,g){D(n).errors++;},onReconcileStart(){b=performance.now(),y=0;},onReconcileEnd(){let n=performance.now()-b;r.runs++,r.totalDurationMs+=n,r.avgDurationMs=r.totalDurationMs/r.runs,n>r.maxDurationMs&&(r.maxDurationMs=n);},getSnapshot(){let n={};for(let[p,h]of i)n[p]={...h};let g={};for(let[p,h]of t)g[p]={...h};let v={};for(let[p,h]of e)v[p]={...h};return {constraints:n,resolvers:g,effects:v,reconcile:{...r},uptime:f?Date.now()-f:0}},reset(){i.clear(),t.clear(),e.clear(),r.runs=0,r.totalDurationMs=0,r.avgDurationMs=0,r.maxDurationMs=0,y=0;}}}function F(){return globalThis.crypto?.randomUUID?.()??`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,11)}`}function H(s,l){if(s.length===0)return 0;let a=[...s].sort((c,i)=>c-i),o=Math.ceil(l/100*a.length)-1;return a[Math.max(0,o)]??0}function Q(s={}){let{serviceName:l="directive-agents",metrics:a={},tracing:o={},alerts:c=[],summaryMetrics:i={},events:t={}}=s,e={requests:i.requests??"agent.requests",errors:i.errors??"agent.errors",latency:i.latency??"agent.latency",tokens:i.tokens??"agent.tokens",cost:i.cost??"agent.cost"},{enabled:r=true,exportInterval:f,exporter:b,maxDataPoints:y=1e3}=a,{enabled:T=true,sampleRate:E=1,maxSpans:D=1e3,exporter:S}=o,n=Date.now(),g=new Map,v=new Map,p=[],h=[],A=new Map,w=new Map,_;f&&(b||S)&&(_=setInterval(async()=>{try{if(b&&r&&await b(Array.from(w.values())),S&&T){let u=p.splice(0,100);u.length>0&&await S(u);}}catch(u){console.error("[Directive Observability] Export error:",u);}},f));function L(u){if(!r)return;let d=`${u.name}:${JSON.stringify(Object.fromEntries(Object.entries(u.labels).sort()))}`,m=g.get(d);m||(m=[],g.set(d,m)),m.push(u),m.length>y&&m.shift(),B(u.name,m),t.onMetricRecorded?.(u),M(u.name);}function B(u,d){if(d.length===0)return;let m=d.map(C=>C.value),x=m.reduce((C,R)=>C+R,0),P=d[0],O=m[m.length-1],I={name:u,type:P.type,count:d.length,sum:x,min:Math.min(...m),max:Math.max(...m),avg:x/d.length,lastValue:O,lastUpdated:Date.now()};w.set(u,I);}function M(u){for(let d of c){if(d.metric!==u)continue;let m=w.get(u);if(!m)continue;let x=`${d.metric}:${d.threshold}`,P=A.get(x),O=d.cooldownMs??6e4;if(P&&Date.now()-P<O)continue;let I=d.operator??">",C=m.lastValue,R=d.threshold,N=false;switch(I){case ">":N=C>R;break;case "<":N=C<R;break;case ">=":N=C>=R;break;case "<=":N=C<=R;break;case "==":N=C===R;break}if(N){let V={alertId:F(),metric:u,currentValue:C,threshold:R,operator:I,action:d.action,timestamp:Date.now(),message:`Alert: ${u} ${I} ${R} (current: ${C})`};switch(h.push(V),h.length>1e3&&h.splice(0,h.length-1e3),A.set(x,Date.now()),t.onAlert?.(V),d.action){case "log":console.log(`[Observability] ${V.message}`);break;case "warn":console.warn(`[Observability] ${V.message}`);break;case "alert":console.error(`[Observability ALERT] ${V.message}`);break;case "callback":d.callback?.(m,R);break}}}}function k(u){let d=[];for(let[m,x]of g)if(m.startsWith(`${u}:`))for(let P of x)d.push(P.value);return d.length===0?{}:{p50:H(d,50),p90:H(d,90),p99:H(d,99)}}return {incrementCounter(u,d={},m=1){L({name:u,type:"counter",value:m,labels:d,timestamp:Date.now()});},setGauge(u,d,m={}){L({name:u,type:"gauge",value:d,labels:m,timestamp:Date.now()});},observeHistogram(u,d,m={}){L({name:u,type:"histogram",value:d,labels:m,timestamp:Date.now()});},startSpan(u,d){if(Math.random()>E)return {traceId:"sampled-out",spanId:"sampled-out",operationName:u,serviceName:l,startTime:Date.now(),status:"ok",tags:{},logs:[]};let m={traceId:d?v.get(d)?.traceId??F():F(),spanId:F(),parentSpanId:d,operationName:u,serviceName:l,startTime:Date.now(),status:"ok",tags:{},logs:[]};return T&&(v.set(m.spanId,m),t.onSpanStart?.(m)),m},endSpan(u,d="ok"){if(u==="sampled-out")return;let m=v.get(u);if(m){for(m.endTime=Date.now(),m.duration=m.endTime-m.startTime,m.status=d,v.delete(u),p.push(m);p.length>D;)p.shift();L({name:`${m.operationName}.latency`,type:"histogram",value:m.duration,labels:{},timestamp:Date.now()}),d==="error"&&L({name:`${m.operationName}.errors`,type:"counter",value:1,labels:{},timestamp:Date.now()}),t.onSpanEnd?.(m);}},addSpanLog(u,d,m="info"){if(u==="sampled-out")return;let x=v.get(u);x&&x.logs.push({timestamp:Date.now(),message:d,level:m});},addSpanTag(u,d,m){if(u==="sampled-out")return;let x=v.get(u);x&&(x.tags[d]=m);},getDashboard(){let u=w.get(e.requests),d=w.get(e.errors),m=w.get(e.latency),x=w.get(e.tokens),P=w.get(e.cost),O=u?.sum??0,I=d?.sum??0,C=O>0?I/O:0,R=m?k(e.latency):{};return {service:{name:l,uptime:Date.now()-n,startTime:n},metrics:Object.fromEntries(w),traces:[...p].slice(-100),alerts:[...h].slice(-50),summary:{totalRequests:O,totalErrors:I,errorRate:C,avgLatency:m?.avg??0,p99Latency:R.p99??0,activeSpans:v.size,totalTokens:x?.sum??0,totalCost:P?.sum??0}}},getMetric(u){let d=w.get(u);if(!d)return;let m=k(u);return {...d,...m}},getTraces(u=100){return [...p].slice(-u)},getAlerts(){return [...h]},export(){return {metrics:Array.from(w.values()),traces:[...p],alerts:[...h]}},clear(){g.clear(),w.clear(),v.clear(),p.length=0,h.length=0,A.clear();},async dispose(){_&&(clearInterval(_),_=void 0);try{b&&r&&w.size>0&&await b(Array.from(w.values())),S&&T&&p.length>0&&await S([...p]);}catch(u){console.error("[Directive Observability] Error flushing data during dispose:",u);}g.clear(),w.clear(),v.clear(),p.length=0,h.length=0,A.clear();},getHealthStatus(){let u=w.get(e.requests),d=w.get(e.errors),m=u?.sum??0,x=d?.sum??0,P=m>0?x/m:0,O=h.filter(I=>Date.now()-I.timestamp<3e5).length;return {healthy:P<.1&&O===0,uptime:Date.now()-n,errorRate:P,activeAlerts:O}}}}function X(s){return {trackRun(l,a){let o={agent:l};s.incrementCounter("agent.requests",o),a.success||s.incrementCounter("agent.errors",o),s.observeHistogram("agent.latency",a.latencyMs,o),a.inputTokens!==void 0&&(s.incrementCounter("agent.tokens.input",o,a.inputTokens),s.incrementCounter("agent.tokens",o,a.inputTokens)),a.outputTokens!==void 0&&(s.incrementCounter("agent.tokens.output",o,a.outputTokens),s.incrementCounter("agent.tokens",o,a.outputTokens)),a.cost!==void 0&&s.incrementCounter("agent.cost",o,a.cost),a.toolCalls!==void 0&&s.incrementCounter("agent.tool_calls",o,a.toolCalls);},trackGuardrail(l,a){let o={guardrail:l};s.incrementCounter("guardrail.checks",o),a.passed||s.incrementCounter("guardrail.failures",o),a.blocked&&s.incrementCounter("guardrail.blocks",o),s.observeHistogram("guardrail.latency",a.latencyMs,o);},trackApproval(l,a){let o={tool:l};s.incrementCounter("approval.requests",o),a.approved?s.incrementCounter("approval.approved",o):s.incrementCounter("approval.rejected",o),a.timedOut&&s.incrementCounter("approval.timeouts",o),s.observeHistogram("approval.wait_time",a.waitTimeMs,o);},trackHandoff(l,a,o){s.incrementCounter("handoff.count",{from:l,to:a}),s.observeHistogram("handoff.latency",o);}}}function Y(s){let l=[{key:"service.name",value:{stringValue:s.serviceName??"directive-agents"}}];if(s.serviceVersion&&l.push({key:"service.version",value:{stringValue:s.serviceVersion}}),s.resourceAttributes)for(let[a,o]of Object.entries(s.resourceAttributes))l.push({key:a,value:{stringValue:o}});return {attributes:l}}function $(s){return `${BigInt(s)*BigInt(1e6)}`}function Z(s){switch(s){case "counter":return "sum";case "gauge":return "gauge";case "histogram":return "histogram";default:return "gauge"}}function ee(s,l,a){let o=s.map(c=>{let i=c.lastUpdated-6e4,t=[{asInt:c.type==="counter"?c.sum:void 0,asDouble:c.type!=="counter"?c.lastValue:void 0,timeUnixNano:$(c.lastUpdated),startTimeUnixNano:$(i),attributes:[]}],e=Z(c.type),r={name:c.name,unit:""};return e==="sum"?r.sum={dataPoints:t,aggregationTemporality:2,isMonotonic:true}:e==="histogram"?r.histogram={dataPoints:[{count:c.count,sum:c.sum,min:c.min,max:c.max,timeUnixNano:$(c.lastUpdated),startTimeUnixNano:$(i),attributes:[]}],aggregationTemporality:2}:r.gauge={dataPoints:t},r});return {resourceMetrics:[{resource:l,scopeMetrics:[{scope:{name:"directive",version:a},metrics:o}]}]}}function te(s,l,a){let o=s.map(c=>{let i=c.logs.map(r=>({timeUnixNano:$(r.timestamp),name:r.level,attributes:[{key:"message",value:{stringValue:r.message}},{key:"level",value:{stringValue:r.level}}]})),t=Object.entries(c.tags).map(([r,f])=>({key:r,value:typeof f=="string"?{stringValue:f}:typeof f=="number"?{intValue:`${f}`}:{boolValue:f}})),e=c.status==="ok"?1:c.status==="error"?2:0;return {traceId:c.traceId.replace(/-/g,"").padEnd(32,"0").slice(0,32),spanId:c.spanId.replace(/-/g,"").padEnd(16,"0").slice(0,16),parentSpanId:c.parentSpanId?c.parentSpanId.replace(/-/g,"").padEnd(16,"0").slice(0,16):void 0,name:c.operationName,kind:1,startTimeUnixNano:$(c.startTime),endTimeUnixNano:c.endTime?$(c.endTime):$(c.startTime),attributes:t,events:i,status:{code:e}}});return {resourceSpans:[{resource:l,scopeSpans:[{scope:{name:"directive",version:a},spans:o}]}]}}function re(s){let{endpoint:l,headers:a={},scopeVersion:o="0.1.0",timeoutMs:c=1e4,fetch:i=globalThis.fetch,onError:t}=s;try{let f=new URL(l);if(f.protocol!=="http:"&&f.protocol!=="https:")throw new Error("Only http: and https: protocols are supported")}catch(f){throw new Error(`[Directive OTLP] Invalid endpoint URL "${l}": ${f instanceof Error?f.message:String(f)}`)}if(/\/v1\/(metrics|traces)/.test(l)&&console.warn(`[Directive OTLP] Endpoint "${l}" already contains a /v1/metrics or /v1/traces path. The exporter will append /v1/metrics or /v1/traces automatically. Use the base URL (e.g., "http://localhost:4318") instead.`),c<=0||!Number.isFinite(c))throw new Error(`[Directive OTLP] timeoutMs must be > 0, got ${c}`);let e=Y(s);async function r(f,b,y){let T=`${l.replace(/\/$/,"")}${f}`,E=new AbortController,D=setTimeout(()=>E.abort(),c);try{let S=await i(T,{method:"POST",headers:{"Content-Type":"application/json",...a},body:JSON.stringify(b),signal:E.signal});if(!S.ok)throw new Error(`OTLP export failed: ${S.status} ${S.statusText}`)}catch(S){let n=S instanceof Error?S:new Error(String(S));t?t(n,y):console.error(`[Directive OTLP] Export ${y} error:`,n.message);}finally{clearTimeout(D);}}return {async exportMetrics(f){if(f.length===0)return;let b=ee(f,e,o);await r("/v1/metrics",b,"metrics");},async exportTraces(f){if(f.length===0)return;let b=te(f,e,o);await r("/v1/traces",b,"traces");}}}var q=class extends Error{code="CIRCUIT_OPEN";retryAfterMs;state;constructor(l,a,o="OPEN",c){let i=c?`[Directive CircuitBreaker] Circuit "${l}" is ${o}. ${c}`:`[Directive CircuitBreaker] Circuit "${l}" is ${o}. Request rejected. Try again in ${Math.ceil(a/1e3)}s.`;super(i),this.name="CircuitBreakerOpenError",this.retryAfterMs=a,this.state=o;}};function ne(s={}){let{failureThreshold:l=5,recoveryTimeMs:a=3e4,halfOpenMaxRequests:o=3,failureWindowMs:c=6e4,observability:i,metricPrefix:t="circuit_breaker",name:e="default",isFailure:r=()=>true,onStateChange:f}=s;if(l<1||!Number.isFinite(l))throw new Error(`[Directive CircuitBreaker] failureThreshold must be >= 1, got ${l}`);if(a<=0||!Number.isFinite(a))throw new Error(`[Directive CircuitBreaker] recoveryTimeMs must be > 0, got ${a}`);if(o<1||!Number.isFinite(o))throw new Error(`[Directive CircuitBreaker] halfOpenMaxRequests must be >= 1, got ${o}`);if(c<=0||!Number.isFinite(c))throw new Error(`[Directive CircuitBreaker] failureWindowMs must be > 0, got ${c}`);let b="CLOSED",y=[],T=0,E=0,D=Date.now(),S=0,n=0,g=0,v=0,p=0,h=null,A=null;function w(M){if(b===M)return;let k=b;b=M,D=Date.now(),M==="OPEN"&&(S=Date.now()),M==="HALF_OPEN"&&(T=0,E=0),f?.(k,M),i&&i.incrementCounter(`${t}.state_change`,{name:e,from:k,to:M});}function _(){let M=Date.now()-c;return y=y.filter(k=>k>M),y.length}function L(){v++,A=Date.now(),i&&i.incrementCounter(`${t}.success`,{name:e}),b==="HALF_OPEN"&&(E++,E>=o&&(w("CLOSED"),y=[]));}function B(M){if(!r(M)){L();return}g++,h=Date.now(),y.push(Date.now());let k=l*2;if(y.length>k&&(y=y.slice(-k)),i&&i.incrementCounter(`${t}.failure`,{name:e}),b==="HALF_OPEN"){w("OPEN");return}b==="CLOSED"&&_()>=l&&w("OPEN");}return {async execute(M){if(n++,i&&i.incrementCounter(`${t}.requests`,{name:e}),b==="OPEN")if(Date.now()-S>=a)w("HALF_OPEN");else throw p++,i&&i.incrementCounter(`${t}.rejected`,{name:e}),new q(e,a-(Date.now()-S));if(b==="HALF_OPEN"){if(T>=o)throw p++,new q(e,a,"HALF_OPEN",`Max trial requests (${o}) reached.`);T++;}let k=Date.now();try{let u=await M();return L(),i&&i.observeHistogram(`${t}.latency`,Date.now()-k,{name:e}),u}catch(u){let d=u instanceof Error?u:new Error(String(u));throw B(d),i&&i.observeHistogram(`${t}.latency`,Date.now()-k,{name:e}),u}},getState(){return b==="OPEN"&&Date.now()-S>=a&&w("HALF_OPEN"),b},getStats(){return {state:this.getState(),totalRequests:n,totalFailures:g,totalSuccesses:v,totalRejected:p,recentFailures:_(),lastFailureTime:h,lastSuccessTime:A,lastStateChange:D}},forceState(M){w(M);},reset(){let M=b;b="CLOSED",y=[],T=0,E=0,D=Date.now(),S=0,n=0,g=0,v=0,p=0,h=null,A=null,M!=="CLOSED"&&f?.(M,"CLOSED");},isAllowed(){return b==="CLOSED"?true:b==="OPEN"?Date.now()-S>=a:T<o}}}
2
+ export{q as CircuitBreakerOpenError,X as createAgentMetrics,ne as createCircuitBreaker,re as createOTLPExporter,Q as createObservability,G as devtoolsPlugin,W as loggingPlugin,K as performancePlugin,z as persistencePlugin};//# sourceMappingURL=index.js.map
3
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/plugins/logging.ts","../../src/plugins/devtools.ts","../../src/utils/utils.ts","../../src/plugins/persistence.ts","../../src/plugins/performance.ts","../../src/plugins/observability.ts","../../src/plugins/otlp-exporter.ts","../../src/plugins/circuit-breaker.ts"],"names":["LOG_LEVELS","loggingPlugin","options","level","filter","logger","prefix","minLevel","log","eventLevel","event","args","key","value","prev","changes","id","deps","result","active","error","req","byResolver","resolver","duration","attempt","snapshot","from","to","strategy","initDevtools","systems","name","devtoolsPlugin","trace","devtools","state","addEvent","type","data","system","isPrototypeSafe","obj","maxDepth","dangerousKeys","seen","check","val","depth","objVal","item","persistencePlugin","storage","include","exclude","debounce","onRestore","onSave","onError","saveTimeout","trackedKeys","shouldPersist","factKey","load","json","save","scheduleSave","sys","shouldSave","change","performancePlugin","onSlowConstraint","onSlowResolver","slowConstraintThresholdMs","slowResolverThresholdMs","constraints","resolvers","effects","reconcile","startedAt","reconcileStartTime","lastConstraintEvalEndTime","getConstraintMetrics","m","getResolverMetrics","getEffectMetrics","_active","now","timedEvals","_req","_error","_attempt","constraintsObj","resolversObj","effectsObj","generateId","calculatePercentile","values","percentile","sorted","a","b","index","createObservability","config","serviceName","metricsConfig","tracingConfig","alertConfigs","summaryMetricsConfig","events","summaryMetricNames","metricsEnabled","exportInterval","metricsExporter","maxDataPoints","tracingEnabled","sampleRate","maxSpans","tracingExporter","startTime","metricDataPoints","activeSpans","completedSpans","alertEvents","alertCooldowns","aggregatedMetrics","exportTimer","spansToExport","recordMetric","dataPoint","points","updateAggregation","checkAlerts","p","sum","firstPoint","lastValue","aggregated","metricName","alertConfig","metric","cooldownKey","lastAlert","cooldown","operator","threshold","triggered","alertEvent","getPercentiles","allValues","labels","operationName","parentSpanId","span","spanId","status","message","requestsMetric","errorsMetric","latencyMetric","tokensMetric","costMetric","totalRequests","totalErrors","errorRate","latencyPercentiles","percentiles","limit","activeAlertCount","createAgentMetrics","obs","agentName","guardrailName","toolName","fromAgent","toAgent","latencyMs","buildResource","attrs","toNanos","timestampMs","metricTypeToOTLP","convertMetrics","metrics","resource","scopeVersion","scopeMetrics","startTimeMs","dataPoints","otlpType","metricData","convertTraces","traces","spans","attributes","statusCode","createOTLPExporter","endpoint","headers","timeoutMs","fetchFn","url","send","path","body","controller","timer","response","err","CircuitBreakerOpenError","retryAfterMs","detail","msg","createCircuitBreaker","failureThreshold","recoveryTimeMs","halfOpenMaxRequests","failureWindowMs","observability","metricPrefix","isFailure","onStateChange","failureTimestamps","halfOpenRequests","halfOpenSuccesses","lastStateChange","openedAt","totalFailures","totalSuccesses","totalRejected","lastFailureTime","lastSuccessTime","transition","newState","oldState","getRecentFailures","cutoff","t","recordSuccess","recordFailure","maxTimestamps","fn","start"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Logging Plugin - Console logging for Directive events\n */\n\nimport type { Plugin, ModuleSchema } from \"../core/types.js\";\n\nexport interface LoggingPluginOptions {\n\t/** Log level */\n\tlevel?: \"debug\" | \"info\" | \"warn\" | \"error\";\n\t/** Filter function to include/exclude events */\n\tfilter?: (event: string) => boolean;\n\t/** Custom logger (defaults to console) */\n\tlogger?: Pick<Console, \"debug\" | \"info\" | \"warn\" | \"error\" | \"group\" | \"groupEnd\">;\n\t/** Prefix for log messages */\n\tprefix?: string;\n}\n\nconst LOG_LEVELS = { debug: 0, info: 1, warn: 2, error: 3 };\n\n/**\n * Create a logging plugin.\n *\n * @example\n * ```ts\n * const system = createSystem({\n * modules: [myModule],\n * plugins: [loggingPlugin({ level: \"debug\" })],\n * });\n * ```\n */\nexport function loggingPlugin<M extends ModuleSchema = ModuleSchema>(\n\toptions: LoggingPluginOptions = {},\n): Plugin<M> {\n\tconst {\n\t\tlevel = \"info\",\n\t\tfilter = () => true,\n\t\tlogger = console,\n\t\tprefix = \"[Directive]\",\n\t} = options;\n\n\tconst minLevel = LOG_LEVELS[level];\n\n\tconst log = (eventLevel: keyof typeof LOG_LEVELS, event: string, ...args: unknown[]) => {\n\t\tif (LOG_LEVELS[eventLevel] < minLevel) return;\n\t\tif (!filter(event)) return;\n\t\tlogger[eventLevel](`${prefix} ${event}`, ...args);\n\t};\n\n\treturn {\n\t\tname: \"logging\",\n\n\t\tonInit: () => log(\"debug\", \"init\"),\n\t\tonStart: () => log(\"info\", \"start\"),\n\t\tonStop: () => log(\"info\", \"stop\"),\n\t\tonDestroy: () => log(\"debug\", \"destroy\"),\n\n\t\tonFactSet: (key, value, prev) => {\n\t\t\tlog(\"debug\", \"fact.set\", { key, value, prev });\n\t\t},\n\n\t\tonFactDelete: (key, prev) => {\n\t\t\tlog(\"debug\", \"fact.delete\", { key, prev });\n\t\t},\n\n\t\tonFactsBatch: (changes) => {\n\t\t\tlog(\"debug\", \"facts.batch\", { count: changes.length, changes });\n\t\t},\n\n\t\tonDerivationCompute: (id, value, deps) => {\n\t\t\tlog(\"debug\", \"derivation.compute\", { id, value, deps });\n\t\t},\n\n\t\tonDerivationInvalidate: (id) => {\n\t\t\tlog(\"debug\", \"derivation.invalidate\", { id });\n\t\t},\n\n\t\tonReconcileStart: () => {\n\t\t\tlog(\"debug\", \"reconcile.start\");\n\t\t},\n\n\t\tonReconcileEnd: (result) => {\n\t\t\tlog(\"debug\", \"reconcile.end\", {\n\t\t\t\tunmet: result.unmet.length,\n\t\t\t\tinflight: result.inflight.length,\n\t\t\t\tcompleted: result.completed.length,\n\t\t\t\tcanceled: result.canceled.length,\n\t\t\t});\n\t\t},\n\n\t\tonConstraintEvaluate: (id, active) => {\n\t\t\tlog(\"debug\", \"constraint.evaluate\", { id, active });\n\t\t},\n\n\t\tonConstraintError: (id, error) => {\n\t\t\tlog(\"error\", \"constraint.error\", { id, error });\n\t\t},\n\n\t\tonRequirementCreated: (req) => {\n\t\t\tlog(\"debug\", \"requirement.created\", { id: req.id, type: req.requirement.type });\n\t\t},\n\n\t\tonRequirementMet: (req, byResolver) => {\n\t\t\tlog(\"info\", \"requirement.met\", { id: req.id, byResolver });\n\t\t},\n\n\t\tonRequirementCanceled: (req) => {\n\t\t\tlog(\"debug\", \"requirement.canceled\", { id: req.id });\n\t\t},\n\n\t\tonResolverStart: (resolver, req) => {\n\t\t\tlog(\"debug\", \"resolver.start\", { resolver, requirementId: req.id });\n\t\t},\n\n\t\tonResolverComplete: (resolver, req, duration) => {\n\t\t\tlog(\"info\", \"resolver.complete\", { resolver, requirementId: req.id, duration });\n\t\t},\n\n\t\tonResolverError: (resolver, req, error) => {\n\t\t\tlog(\"error\", \"resolver.error\", { resolver, requirementId: req.id, error });\n\t\t},\n\n\t\tonResolverRetry: (resolver, req, attempt) => {\n\t\t\tlog(\"warn\", \"resolver.retry\", { resolver, requirementId: req.id, attempt });\n\t\t},\n\n\t\tonResolverCancel: (resolver, req) => {\n\t\t\tlog(\"debug\", \"resolver.cancel\", { resolver, requirementId: req.id });\n\t\t},\n\n\t\tonEffectRun: (id) => {\n\t\t\tlog(\"debug\", \"effect.run\", { id });\n\t\t},\n\n\t\tonEffectError: (id, error) => {\n\t\t\tlog(\"error\", \"effect.error\", { id, error });\n\t\t},\n\n\t\tonSnapshot: (snapshot) => {\n\t\t\tlog(\"debug\", \"timetravel.snapshot\", { id: snapshot.id, trigger: snapshot.trigger });\n\t\t},\n\n\t\tonTimeTravel: (from, to) => {\n\t\t\tlog(\"info\", \"timetravel.jump\", { from, to });\n\t\t},\n\n\t\tonError: (error) => {\n\t\t\tlog(\"error\", \"error\", { source: error.source, sourceId: error.sourceId, message: error.message });\n\t\t},\n\n\t\tonErrorRecovery: (error, strategy) => {\n\t\t\tlog(\"warn\", \"error.recovery\", { source: error.source, sourceId: error.sourceId, strategy });\n\t\t},\n\t};\n}\n","/**\n * Devtools Plugin - Browser devtools integration\n *\n * Exposes the system to browser devtools via window.__DIRECTIVE__\n */\n\nimport type { Plugin, ModuleSchema, System } from \"../core/types.js\";\n\nexport interface DevtoolsPluginOptions {\n\t/** Name for this system in devtools */\n\tname?: string;\n\t/** Enable trace logging */\n\ttrace?: boolean;\n}\n\ninterface DevtoolsState<M extends ModuleSchema> {\n\tsystem: System<M> | null;\n\tevents: Array<{ timestamp: number; type: string; data: unknown }>;\n\tmaxEvents: number;\n}\n\ndeclare global {\n\tinterface Window {\n\t\t__DIRECTIVE__?: {\n\t\t\tsystems: Map<string, DevtoolsState<ModuleSchema>>;\n\t\t\tgetSystem(name?: string): System<ModuleSchema> | null;\n\t\t\tgetSystems(): string[];\n\t\t\tinspect(name?: string): unknown;\n\t\t\tgetEvents(name?: string): Array<{ timestamp: number; type: string; data: unknown }>;\n\t\t};\n\t}\n}\n\n/**\n * Initialize global devtools object.\n */\nfunction initDevtools(): NonNullable<Window[\"__DIRECTIVE__\"]> {\n\tif (typeof window === \"undefined\") {\n\t\t// Return no-op for non-browser environments\n\t\treturn {\n\t\t\tsystems: new Map(),\n\t\t\tgetSystem: () => null,\n\t\t\tgetSystems: () => [],\n\t\t\tinspect: () => null,\n\t\t\tgetEvents: () => [],\n\t\t};\n\t}\n\n\tif (!window.__DIRECTIVE__) {\n\t\tconst systems = new Map<string, DevtoolsState<ModuleSchema>>();\n\n\t\twindow.__DIRECTIVE__ = {\n\t\t\tsystems,\n\t\t\tgetSystem(name) {\n\t\t\t\tif (name) {\n\t\t\t\t\treturn systems.get(name)?.system ?? null;\n\t\t\t\t}\n\t\t\t\t// Return first system if no name specified\n\t\t\t\tconst first = systems.values().next().value;\n\t\t\t\treturn first?.system ?? null;\n\t\t\t},\n\t\t\tgetSystems() {\n\t\t\t\treturn [...systems.keys()];\n\t\t\t},\n\t\t\tinspect(name) {\n\t\t\t\tconst system = this.getSystem(name);\n\t\t\t\treturn system?.inspect() ?? null;\n\t\t\t},\n\t\t\tgetEvents(name) {\n\t\t\t\tif (name) {\n\t\t\t\t\treturn systems.get(name)?.events ?? [];\n\t\t\t\t}\n\t\t\t\tconst first = systems.values().next().value;\n\t\t\t\treturn first?.events ?? [];\n\t\t\t},\n\t\t};\n\t}\n\n\treturn window.__DIRECTIVE__;\n}\n\n/**\n * Create a devtools plugin.\n *\n * @example\n * ```ts\n * const system = createSystem({\n * modules: [myModule],\n * plugins: [devtoolsPlugin({ name: \"my-app\" })],\n * });\n *\n * // In browser console:\n * // __DIRECTIVE__.inspect()\n * // __DIRECTIVE__.getEvents()\n * ```\n */\nexport function devtoolsPlugin<M extends ModuleSchema = ModuleSchema>(\n\toptions: DevtoolsPluginOptions = {},\n): Plugin<M> {\n\tconst { name = \"default\", trace = false } = options;\n\n\tconst devtools = initDevtools();\n\tconst state: DevtoolsState<M> = {\n\t\tsystem: null,\n\t\tevents: [],\n\t\tmaxEvents: 1000,\n\t};\n\n\tdevtools.systems.set(name, state as DevtoolsState<ModuleSchema>);\n\n\tconst addEvent = (type: string, data: unknown) => {\n\t\tif (!trace) return;\n\n\t\tstate.events.push({\n\t\t\ttimestamp: Date.now(),\n\t\t\ttype,\n\t\t\tdata,\n\t\t});\n\n\t\t// Keep events bounded\n\t\tif (state.events.length > state.maxEvents) {\n\t\t\tstate.events.shift();\n\t\t}\n\t};\n\n\treturn {\n\t\tname: \"devtools\",\n\n\t\tonInit: (system) => {\n\t\t\tstate.system = system;\n\t\t\taddEvent(\"init\", {});\n\n\t\t\tif (typeof window !== \"undefined\") {\n\t\t\t\tconsole.log(\n\t\t\t\t\t`%c[Directive Devtools]%c System \"${name}\" initialized. Access via window.__DIRECTIVE__`,\n\t\t\t\t\t\"color: #7c3aed; font-weight: bold\",\n\t\t\t\t\t\"color: inherit\",\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\n\t\tonStart: () => addEvent(\"start\", {}),\n\t\tonStop: () => addEvent(\"stop\", {}),\n\n\t\tonDestroy: () => {\n\t\t\taddEvent(\"destroy\", {});\n\t\t\tdevtools.systems.delete(name);\n\t\t},\n\n\t\tonFactSet: (key, value, prev) => {\n\t\t\taddEvent(\"fact.set\", { key, value, prev });\n\t\t},\n\n\t\tonFactsBatch: (changes) => {\n\t\t\taddEvent(\"facts.batch\", { changes });\n\t\t},\n\n\t\tonReconcileStart: () => {\n\t\t\taddEvent(\"reconcile.start\", {});\n\t\t},\n\n\t\tonReconcileEnd: (result) => {\n\t\t\taddEvent(\"reconcile.end\", result);\n\t\t},\n\n\t\tonConstraintEvaluate: (id, active) => {\n\t\t\taddEvent(\"constraint.evaluate\", { id, active });\n\t\t},\n\n\t\tonRequirementCreated: (req) => {\n\t\t\taddEvent(\"requirement.created\", { id: req.id, type: req.requirement.type });\n\t\t},\n\n\t\tonRequirementMet: (req, byResolver) => {\n\t\t\taddEvent(\"requirement.met\", { id: req.id, byResolver });\n\t\t},\n\n\t\tonResolverStart: (resolver, req) => {\n\t\t\taddEvent(\"resolver.start\", { resolver, requirementId: req.id });\n\t\t},\n\n\t\tonResolverComplete: (resolver, req, duration) => {\n\t\t\taddEvent(\"resolver.complete\", { resolver, requirementId: req.id, duration });\n\t\t},\n\n\t\tonResolverError: (resolver, req, error) => {\n\t\t\taddEvent(\"resolver.error\", { resolver, requirementId: req.id, error: String(error) });\n\t\t},\n\n\t\tonSnapshot: (snapshot) => {\n\t\t\taddEvent(\"timetravel.snapshot\", { id: snapshot.id, trigger: snapshot.trigger });\n\t\t},\n\n\t\tonTimeTravel: (from, to) => {\n\t\t\taddEvent(\"timetravel.jump\", { from, to });\n\t\t},\n\n\t\tonError: (error) => {\n\t\t\taddEvent(\"error\", { source: error.source, sourceId: error.sourceId, message: error.message });\n\t\t},\n\t};\n}\n","/**\n * Shared utilities for Directive\n */\n\n/**\n * Execute a promise with a timeout, properly cleaning up the timer.\n * Used by both constraints and resolvers for timeout handling.\n *\n * @param promise - The promise to wrap with a timeout\n * @param ms - Timeout duration in milliseconds\n * @param errorMessage - Error message if timeout occurs\n * @returns The promise result\n * @throws Error if timeout is exceeded\n */\nexport async function withTimeout<T>(\n\tpromise: Promise<T>,\n\tms: number,\n\terrorMessage: string,\n): Promise<T> {\n\tlet timeoutId: ReturnType<typeof setTimeout>;\n\n\tconst timeoutPromise = new Promise<never>((_, reject) => {\n\t\ttimeoutId = setTimeout(() => reject(new Error(errorMessage)), ms);\n\t});\n\n\ttry {\n\t\treturn await Promise.race([promise, timeoutPromise]);\n\t} finally {\n\t\tclearTimeout(timeoutId!);\n\t}\n}\n\n/**\n * Normalize an error to an Error instance.\n * Ensures consistent error handling throughout the library.\n *\n * @param error - The error to normalize (can be anything)\n * @returns An Error instance\n */\nexport function normalizeError(error: unknown): Error {\n\tif (error instanceof Error) {\n\t\treturn error;\n\t}\n\treturn new Error(String(error));\n}\n\n/**\n * Create a stable JSON string with sorted keys.\n * Handles circular references and deeply nested objects safely.\n *\n * @param value - The value to stringify\n * @param maxDepth - Maximum nesting depth (default: 50)\n * @returns A stable JSON string\n */\nexport function stableStringify(value: unknown, maxDepth = 50): string {\n\tconst seen = new WeakSet();\n\n\tfunction stringify(val: unknown, depth: number): string {\n\t\tif (depth > maxDepth) {\n\t\t\treturn '\"[max depth exceeded]\"';\n\t\t}\n\n\t\tif (val === null) return \"null\";\n\t\tif (val === undefined) return \"undefined\";\n\n\t\tconst type = typeof val;\n\n\t\tif (type === \"string\") return JSON.stringify(val);\n\t\tif (type === \"number\" || type === \"boolean\") return String(val);\n\t\tif (type === \"function\") return '\"[function]\"';\n\t\tif (type === \"symbol\") return '\"[symbol]\"';\n\n\t\tif (Array.isArray(val)) {\n\t\t\t// Check for circular reference\n\t\t\tif (seen.has(val)) {\n\t\t\t\treturn '\"[circular]\"';\n\t\t\t}\n\t\t\tseen.add(val);\n\t\t\tconst result = `[${val.map((v) => stringify(v, depth + 1)).join(\",\")}]`;\n\t\t\tseen.delete(val);\n\t\t\treturn result;\n\t\t}\n\n\t\tif (type === \"object\") {\n\t\t\tconst obj = val as Record<string, unknown>;\n\t\t\t// Check for circular reference\n\t\t\tif (seen.has(obj)) {\n\t\t\t\treturn '\"[circular]\"';\n\t\t\t}\n\t\t\tseen.add(obj);\n\t\t\tconst keys = Object.keys(obj).sort();\n\t\t\tconst pairs = keys.map((k) => `${JSON.stringify(k)}:${stringify(obj[k], depth + 1)}`);\n\t\t\tconst result = `{${pairs.join(\",\")}}`;\n\t\t\tseen.delete(obj);\n\t\t\treturn result;\n\t\t}\n\n\t\treturn '\"[unknown]\"';\n\t}\n\n\treturn stringify(value, 0);\n}\n\n/**\n * Check for prototype pollution in an object, including nested objects.\n * Returns true if the object is safe, false if dangerous keys are found.\n *\n * @param obj - The object to check\n * @param maxDepth - Maximum nesting depth to check (default: 50)\n * @returns True if safe, false if dangerous keys found\n */\nexport function isPrototypeSafe(obj: unknown, maxDepth = 50): boolean {\n\tconst dangerousKeys = new Set([\"__proto__\", \"constructor\", \"prototype\"]);\n\tconst seen = new WeakSet();\n\n\tfunction check(val: unknown, depth: number): boolean {\n\t\tif (depth > maxDepth) return false; // Fail safe at max depth - don't assume safety\n\t\tif (val === null || val === undefined) return true;\n\t\tif (typeof val !== \"object\") return true;\n\n\t\tconst objVal = val as Record<string, unknown>;\n\n\t\t// Check for circular reference\n\t\tif (seen.has(objVal)) return true;\n\t\tseen.add(objVal);\n\n\t\t// Check array elements\n\t\tif (Array.isArray(objVal)) {\n\t\t\tfor (const item of objVal) {\n\t\t\t\tif (!check(item, depth + 1)) {\n\t\t\t\t\tseen.delete(objVal);\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\t\t\tseen.delete(objVal);\n\t\t\treturn true;\n\t\t}\n\n\t\t// Check object keys and values\n\t\tfor (const key of Object.keys(objVal)) {\n\t\t\tif (dangerousKeys.has(key)) {\n\t\t\t\tseen.delete(objVal);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t\tif (!check(objVal[key], depth + 1)) {\n\t\t\t\tseen.delete(objVal);\n\t\t\t\treturn false;\n\t\t\t}\n\t\t}\n\n\t\tseen.delete(objVal);\n\t\treturn true;\n\t}\n\n\treturn check(obj, 0);\n}\n\n/**\n * Shallow equality comparison for objects.\n * Used by React hooks to avoid unnecessary re-renders.\n *\n * @param a - First object\n * @param b - Second object\n * @returns True if objects are shallowly equal\n */\nexport function shallowEqual<T extends Record<string, unknown>>(a: T, b: T): boolean {\n\tif (a === b) return true;\n\tif (!a || !b) return false;\n\n\tconst keysA = Object.keys(a);\n\tconst keysB = Object.keys(b);\n\n\tif (keysA.length !== keysB.length) return false;\n\n\tfor (const key of keysA) {\n\t\tif (a[key] !== b[key]) return false;\n\t}\n\n\treturn true;\n}\n\n/**\n * Generate a simple hash string from an object.\n * Uses djb2 algorithm on the stable stringified value.\n *\n * **Limitations:**\n * - 32-bit hash output means collision probability increases with data set size\n * (birthday paradox: ~50% collision chance at ~77,000 distinct values)\n * - Suitable for: cache invalidation, change detection, deduplication of small sets\n * - NOT suitable for: cryptographic use, security-sensitive operations, large-scale deduplication\n *\n * For security-sensitive use cases requiring stronger collision resistance,\n * consider using a cryptographic hash like SHA-256.\n *\n * @param value - The value to hash\n * @returns A hex hash string (8 characters, 32 bits)\n */\nexport function hashObject(value: unknown): string {\n\tconst str = stableStringify(value);\n\tlet hash = 5381;\n\tfor (let i = 0; i < str.length; i++) {\n\t\thash = ((hash << 5) + hash) ^ str.charCodeAt(i);\n\t}\n\t// Convert to unsigned 32-bit and then to hex\n\treturn (hash >>> 0).toString(16);\n}\n\n// ============================================================================\n// Distributable Snapshot Utilities\n// ============================================================================\n\n/**\n * Distributable snapshot type for type-safe helper functions.\n */\nexport interface DistributableSnapshotLike<T = Record<string, unknown>> {\n\tdata: T;\n\tcreatedAt: number;\n\texpiresAt?: number;\n\tversion?: string;\n\tmetadata?: Record<string, unknown>;\n}\n\n/**\n * Check if a distributable snapshot has expired.\n * Returns false if the snapshot has no expiresAt field.\n *\n * @example\n * ```typescript\n * const snapshot = system.getDistributableSnapshot({ ttlSeconds: 3600 });\n * // ... later ...\n * if (isSnapshotExpired(snapshot)) {\n * // Refresh the snapshot\n * }\n * ```\n *\n * @param snapshot - The snapshot to check\n * @param now - Optional current timestamp (defaults to Date.now())\n * @returns True if the snapshot has expired, false otherwise\n */\nexport function isSnapshotExpired<T>(\n\tsnapshot: DistributableSnapshotLike<T>,\n\tnow: number = Date.now(),\n): boolean {\n\treturn snapshot.expiresAt !== undefined && now > snapshot.expiresAt;\n}\n\n/**\n * Validate a distributable snapshot and return its data.\n * Throws if the snapshot is malformed or has expired.\n *\n * @example\n * ```typescript\n * const cached = JSON.parse(await redis.get(`entitlements:${userId}`));\n * try {\n * const data = validateSnapshot(cached);\n * // Use data.canUseFeature, etc.\n * } catch (e) {\n * // Snapshot invalid or expired, refresh it\n * }\n * ```\n *\n * @example Using custom timestamp for testing\n * ```typescript\n * const snapshot = { data: { test: true }, createdAt: 1000, expiresAt: 2000 };\n * validateSnapshot(snapshot, 1500); // Returns { test: true }\n * validateSnapshot(snapshot, 2500); // Throws: Snapshot expired\n * ```\n *\n * @param snapshot - The snapshot to validate\n * @param now - Optional current timestamp (defaults to Date.now())\n * @returns The snapshot data if valid\n * @throws Error if the snapshot is malformed or has expired\n */\nexport function validateSnapshot<T>(\n\tsnapshot: DistributableSnapshotLike<T>,\n\tnow: number = Date.now(),\n): T {\n\t// Structural validation\n\tif (!snapshot || typeof snapshot !== \"object\") {\n\t\tthrow new Error(\n\t\t\t\"[Directive] Invalid snapshot: expected an object with 'data' and 'createdAt' properties.\",\n\t\t);\n\t}\n\tif (!(\"data\" in snapshot)) {\n\t\tthrow new Error(\n\t\t\t\"[Directive] Invalid snapshot: missing required 'data' property.\",\n\t\t);\n\t}\n\tif (!(\"createdAt\" in snapshot) || typeof snapshot.createdAt !== \"number\") {\n\t\tthrow new Error(\n\t\t\t\"[Directive] Invalid snapshot: missing or invalid 'createdAt' property (expected number).\",\n\t\t);\n\t}\n\n\t// Expiration validation\n\tif (isSnapshotExpired(snapshot, now)) {\n\t\tconst expiredAt = new Date(snapshot.expiresAt!).toISOString();\n\t\tthrow new Error(\n\t\t\t`[Directive] Snapshot expired at ${expiredAt}. Obtain a fresh snapshot from the source.`,\n\t\t);\n\t}\n\treturn snapshot.data;\n}\n\n/**\n * Diff result for a single changed value.\n */\nexport interface SnapshotDiffEntry {\n\t/** The key path that changed (e.g., \"canUseApi\" or \"limits.apiCalls\") */\n\tpath: string;\n\t/** The value in the old snapshot */\n\toldValue: unknown;\n\t/** The value in the new snapshot */\n\tnewValue: unknown;\n\t/** Type of change: \"added\", \"removed\", or \"changed\" */\n\ttype: \"added\" | \"removed\" | \"changed\";\n}\n\n/**\n * Result of diffing two snapshots.\n */\nexport interface SnapshotDiff {\n\t/** Whether the snapshots are identical */\n\tidentical: boolean;\n\t/** List of changes between snapshots */\n\tchanges: SnapshotDiffEntry[];\n\t/** Whether the version changed (if both have versions) */\n\tversionChanged: boolean;\n\t/** Old version (if available) */\n\toldVersion?: string;\n\t/** New version (if available) */\n\tnewVersion?: string;\n}\n\n/**\n * Compare two distributable snapshots and return the differences.\n * Useful for debugging, audit logs, and webhook payloads.\n *\n * @example\n * ```typescript\n * const oldSnapshot = system.getDistributableSnapshot({ includeVersion: true });\n * system.dispatch({ type: \"upgradePlan\", plan: \"pro\" });\n * const newSnapshot = system.getDistributableSnapshot({ includeVersion: true });\n *\n * const diff = diffSnapshots(oldSnapshot, newSnapshot);\n * if (!diff.identical) {\n * console.log(\"Changes:\", diff.changes);\n * // [{ path: \"canUseApi\", oldValue: false, newValue: true, type: \"changed\" }]\n * }\n * ```\n *\n * @param oldSnapshot - The previous snapshot\n * @param newSnapshot - The new snapshot\n * @returns A diff result with all changes\n */\nexport function diffSnapshots<T = Record<string, unknown>>(\n\toldSnapshot: DistributableSnapshotLike<T>,\n\tnewSnapshot: DistributableSnapshotLike<T>,\n): SnapshotDiff {\n\tconst changes: SnapshotDiffEntry[] = [];\n\n\t// Deep compare function\n\tfunction compare(\n\t\toldObj: unknown,\n\t\tnewObj: unknown,\n\t\tpath: string,\n\t): void {\n\t\t// Handle null/undefined\n\t\tif (oldObj === null || oldObj === undefined) {\n\t\t\tif (newObj !== null && newObj !== undefined) {\n\t\t\t\tchanges.push({ path, oldValue: oldObj, newValue: newObj, type: \"added\" });\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (newObj === null || newObj === undefined) {\n\t\t\tchanges.push({ path, oldValue: oldObj, newValue: newObj, type: \"removed\" });\n\t\t\treturn;\n\t\t}\n\n\t\t// Handle primitives\n\t\tif (typeof oldObj !== \"object\" || typeof newObj !== \"object\") {\n\t\t\tif (!Object.is(oldObj, newObj)) {\n\t\t\t\tchanges.push({ path, oldValue: oldObj, newValue: newObj, type: \"changed\" });\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Handle arrays\n\t\tif (Array.isArray(oldObj) && Array.isArray(newObj)) {\n\t\t\tif (oldObj.length !== newObj.length) {\n\t\t\t\tchanges.push({ path, oldValue: oldObj, newValue: newObj, type: \"changed\" });\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfor (let i = 0; i < oldObj.length; i++) {\n\t\t\t\tcompare(oldObj[i], newObj[i], `${path}[${i}]`);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Handle objects\n\t\tconst oldRecord = oldObj as Record<string, unknown>;\n\t\tconst newRecord = newObj as Record<string, unknown>;\n\t\tconst allKeys = new Set([...Object.keys(oldRecord), ...Object.keys(newRecord)]);\n\n\t\tfor (const key of allKeys) {\n\t\t\tconst childPath = path ? `${path}.${key}` : key;\n\t\t\tif (!(key in oldRecord)) {\n\t\t\t\tchanges.push({ path: childPath, oldValue: undefined, newValue: newRecord[key], type: \"added\" });\n\t\t\t} else if (!(key in newRecord)) {\n\t\t\t\tchanges.push({ path: childPath, oldValue: oldRecord[key], newValue: undefined, type: \"removed\" });\n\t\t\t} else {\n\t\t\t\tcompare(oldRecord[key], newRecord[key], childPath);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Compare data\n\tcompare(oldSnapshot.data, newSnapshot.data, \"\");\n\n\t// Check version change\n\tconst versionChanged = oldSnapshot.version !== newSnapshot.version &&\n\t\t(oldSnapshot.version !== undefined || newSnapshot.version !== undefined);\n\n\treturn {\n\t\tidentical: changes.length === 0,\n\t\tchanges,\n\t\tversionChanged,\n\t\toldVersion: oldSnapshot.version,\n\t\tnewVersion: newSnapshot.version,\n\t};\n}\n\n// ============================================================================\n// Snapshot Signing (HMAC)\n// ============================================================================\n\n/**\n * A signed distributable snapshot.\n * Contains the original snapshot plus a cryptographic signature.\n */\nexport interface SignedSnapshot<T = Record<string, unknown>>\n\textends DistributableSnapshotLike<T> {\n\t/** HMAC-SHA256 signature in hex format */\n\tsignature: string;\n\t/** Signing algorithm used */\n\talgorithm: \"hmac-sha256\";\n}\n\n/**\n * Check if a snapshot is signed.\n *\n * @param snapshot - The snapshot to check\n * @returns True if the snapshot has a signature\n */\nexport function isSignedSnapshot<T>(\n\tsnapshot: DistributableSnapshotLike<T> | SignedSnapshot<T>,\n): snapshot is SignedSnapshot<T> {\n\treturn \"signature\" in snapshot && typeof snapshot.signature === \"string\";\n}\n\n/**\n * Sign a distributable snapshot using HMAC-SHA256.\n * Creates a tamper-proof signature that can be verified later.\n *\n * **Security Notes:**\n * - Use a cryptographically random secret of at least 32 bytes\n * - Store the secret securely (environment variable, secrets manager)\n * - Never expose the secret to clients\n * - The signature covers all snapshot fields for integrity\n *\n * @example\n * ```typescript\n * const snapshot = system.getDistributableSnapshot({\n * includeDerivations: ['canUseFeature', 'limits'],\n * ttlSeconds: 3600,\n * });\n *\n * // Sign the snapshot (server-side only)\n * const signed = await signSnapshot(snapshot, process.env.SNAPSHOT_SECRET);\n *\n * // Store in JWT, Redis, or send to client\n * const jwt = createJWT({ snapshot: signed });\n *\n * // Later, verify the signature\n * const isValid = await verifySnapshotSignature(signed, process.env.SNAPSHOT_SECRET);\n * if (!isValid) {\n * throw new Error('Snapshot has been tampered with');\n * }\n * ```\n *\n * @param snapshot - The snapshot to sign\n * @param secret - The HMAC secret (string or Uint8Array)\n * @returns A signed snapshot with the signature attached\n */\nexport async function signSnapshot<T>(\n\tsnapshot: DistributableSnapshotLike<T>,\n\tsecret: string | Uint8Array,\n): Promise<SignedSnapshot<T>> {\n\t// Create a canonical representation for signing\n\tconst payload = stableStringify({\n\t\tdata: snapshot.data,\n\t\tcreatedAt: snapshot.createdAt,\n\t\texpiresAt: snapshot.expiresAt,\n\t\tversion: snapshot.version,\n\t\tmetadata: snapshot.metadata,\n\t});\n\n\tconst signature = await hmacSha256(payload, secret);\n\n\treturn {\n\t\t...snapshot,\n\t\tsignature,\n\t\talgorithm: \"hmac-sha256\",\n\t};\n}\n\n/**\n * Verify the signature of a signed snapshot.\n * Returns true if the signature is valid, false otherwise.\n *\n * **Important:** Always verify signatures before trusting snapshot data,\n * especially if the snapshot was received from an untrusted source (client, cache).\n *\n * @example\n * ```typescript\n * // Receive signed snapshot from client or cache\n * const snapshot = JSON.parse(cachedData);\n *\n * // Verify before using\n * const isValid = await verifySnapshotSignature(snapshot, process.env.SNAPSHOT_SECRET);\n * if (!isValid) {\n * throw new Error('Invalid snapshot signature - possible tampering');\n * }\n *\n * // Now safe to use snapshot.data\n * if (snapshot.data.canUseFeature.api) {\n * // Grant access\n * }\n * ```\n *\n * @param signedSnapshot - The signed snapshot to verify\n * @param secret - The HMAC secret (must match the signing secret)\n * @returns True if signature is valid, false otherwise\n */\nexport async function verifySnapshotSignature<T>(\n\tsignedSnapshot: SignedSnapshot<T>,\n\tsecret: string | Uint8Array,\n): Promise<boolean> {\n\tif (!signedSnapshot.signature || signedSnapshot.algorithm !== \"hmac-sha256\") {\n\t\treturn false;\n\t}\n\n\t// Recreate the canonical payload (same as signing)\n\tconst payload = stableStringify({\n\t\tdata: signedSnapshot.data,\n\t\tcreatedAt: signedSnapshot.createdAt,\n\t\texpiresAt: signedSnapshot.expiresAt,\n\t\tversion: signedSnapshot.version,\n\t\tmetadata: signedSnapshot.metadata,\n\t});\n\n\tconst expectedSignature = await hmacSha256(payload, secret);\n\n\t// Use timing-safe comparison\n\treturn timingSafeEqual(signedSnapshot.signature, expectedSignature);\n}\n\n/**\n * Create HMAC-SHA256 signature of a message.\n * Uses Web Crypto API for cross-platform support (Node.js, browsers, Deno, Bun).\n */\nasync function hmacSha256(\n\tmessage: string,\n\tsecret: string | Uint8Array,\n): Promise<string> {\n\t// Convert secret to Uint8Array if string\n\tconst secretBytes: Uint8Array =\n\t\ttypeof secret === \"string\" ? new TextEncoder().encode(secret) : secret;\n\n\t// Import key for HMAC\n\tconst algorithm: HmacImportParams = { name: \"HMAC\", hash: { name: \"SHA-256\" } };\n\tconst key = await crypto.subtle.importKey(\n\t\t\"raw\",\n\t\tsecretBytes as unknown as ArrayBuffer,\n\t\talgorithm,\n\t\tfalse,\n\t\t[\"sign\"],\n\t);\n\n\t// Sign the message\n\tconst messageBytes = new TextEncoder().encode(message);\n\tconst signature = await crypto.subtle.sign(\"HMAC\", key, messageBytes);\n\n\t// Convert to hex string\n\treturn Array.from(new Uint8Array(signature))\n\t\t.map((b) => b.toString(16).padStart(2, \"0\"))\n\t\t.join(\"\");\n}\n\n/**\n * Timing-safe string comparison to prevent timing attacks.\n * Both strings should be the same length (hex signatures from same algorithm).\n */\nfunction timingSafeEqual(a: string, b: string): boolean {\n\tif (a.length !== b.length) {\n\t\treturn false;\n\t}\n\n\tlet result = 0;\n\tfor (let i = 0; i < a.length; i++) {\n\t\tresult |= a.charCodeAt(i) ^ b.charCodeAt(i);\n\t}\n\treturn result === 0;\n}\n","/**\n * Persistence Plugin - Save/restore facts to storage\n */\n\nimport type { Plugin, ModuleSchema, System } from \"../core/types.js\";\nimport { isPrototypeSafe } from \"../utils/utils.js\";\n\nexport interface PersistencePluginOptions {\n\t/** Storage backend (localStorage, sessionStorage, or custom) */\n\tstorage: Storage;\n\t/** Key to use in storage */\n\tkey: string;\n\t/** Only persist these fact keys (default: all) */\n\tinclude?: string[];\n\t/** Exclude these fact keys from persistence */\n\texclude?: string[];\n\t/** Debounce saves by this many ms (default: 100) */\n\tdebounce?: number;\n\t/** Called when state is restored */\n\tonRestore?: (data: Record<string, unknown>) => void;\n\t/** Called when state is saved */\n\tonSave?: (data: Record<string, unknown>) => void;\n\t/** Called on error */\n\tonError?: (error: Error) => void;\n}\n\n/**\n * Create a persistence plugin.\n *\n * @example\n * ```ts\n * const system = createSystem({\n * modules: [myModule],\n * plugins: [\n * persistencePlugin({\n * storage: localStorage,\n * key: \"my-app-state\",\n * include: [\"user\", \"preferences\"],\n * }),\n * ],\n * });\n * ```\n */\nexport function persistencePlugin<M extends ModuleSchema = ModuleSchema>(\n\toptions: PersistencePluginOptions,\n): Plugin<M> {\n\tconst {\n\t\tstorage,\n\t\tkey,\n\t\tinclude,\n\t\texclude = [],\n\t\tdebounce = 100,\n\t\tonRestore,\n\t\tonSave,\n\t\tonError,\n\t} = options;\n\n\tlet saveTimeout: ReturnType<typeof setTimeout> | null = null;\n\tlet system: System<M> | null = null;\n\tconst trackedKeys = new Set<string>();\n\n\t/** Check if a key should be persisted */\n\tconst shouldPersist = (factKey: string): boolean => {\n\t\tif (exclude.includes(factKey)) return false;\n\t\tif (include) return include.includes(factKey);\n\t\treturn true;\n\t};\n\n\t/** Load state from storage */\n\tconst load = (): Record<string, unknown> | null => {\n\t\ttry {\n\t\t\tconst json = storage.getItem(key);\n\t\t\tif (!json) return null;\n\n\t\t\tconst data = JSON.parse(json);\n\t\t\tif (typeof data !== \"object\" || data === null) return null;\n\n\t\t\t// Security: Check for prototype pollution\n\t\t\tif (!isPrototypeSafe(data)) {\n\t\t\t\tonError?.(new Error(\"Potential prototype pollution detected in stored data\"));\n\t\t\t\treturn null;\n\t\t\t}\n\n\t\t\treturn data as Record<string, unknown>;\n\t\t} catch (error) {\n\t\t\tonError?.(error instanceof Error ? error : new Error(String(error)));\n\t\t\treturn null;\n\t\t}\n\t};\n\n\t/** Save state to storage */\n\tconst save = () => {\n\t\tif (!system) return;\n\n\t\ttry {\n\t\t\tconst data: Record<string, unknown> = {};\n\n\t\t\tfor (const factKey of trackedKeys) {\n\t\t\t\tif (shouldPersist(factKey)) {\n\t\t\t\t\tdata[factKey] = (system.facts as Record<string, unknown>)[factKey];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tstorage.setItem(key, JSON.stringify(data));\n\t\t\tonSave?.(data);\n\t\t} catch (error) {\n\t\t\tonError?.(error instanceof Error ? error : new Error(String(error)));\n\t\t}\n\t};\n\n\t/** Schedule a debounced save */\n\tconst scheduleSave = () => {\n\t\tif (saveTimeout) {\n\t\t\tclearTimeout(saveTimeout);\n\t\t}\n\t\tsaveTimeout = setTimeout(save, debounce);\n\t};\n\n\treturn {\n\t\tname: \"persistence\",\n\n\t\tonInit: (sys) => {\n\t\t\tsystem = sys;\n\n\t\t\t// Restore state from storage\n\t\t\tconst data = load();\n\t\t\tif (data) {\n\t\t\t\tsystem.facts.$store.batch(() => {\n\t\t\t\t\tfor (const [factKey, value] of Object.entries(data)) {\n\t\t\t\t\t\tif (shouldPersist(factKey)) {\n\t\t\t\t\t\t\t(system!.facts as Record<string, unknown>)[factKey] = value;\n\t\t\t\t\t\t\ttrackedKeys.add(factKey);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t\tonRestore?.(data);\n\t\t\t}\n\t\t},\n\n\t\tonDestroy: () => {\n\t\t\t// Final save before destroy\n\t\t\tif (saveTimeout) {\n\t\t\t\tclearTimeout(saveTimeout);\n\t\t\t}\n\t\t\tsave();\n\t\t},\n\n\t\tonFactSet: (factKey) => {\n\t\t\ttrackedKeys.add(factKey);\n\t\t\tif (shouldPersist(factKey)) {\n\t\t\t\tscheduleSave();\n\t\t\t}\n\t\t},\n\n\t\tonFactDelete: (factKey) => {\n\t\t\ttrackedKeys.delete(factKey);\n\t\t\tif (shouldPersist(factKey)) {\n\t\t\t\tscheduleSave();\n\t\t\t}\n\t\t},\n\n\t\tonFactsBatch: (changes) => {\n\t\t\tlet shouldSave = false;\n\t\t\tfor (const change of changes) {\n\t\t\t\tif (change.type === \"set\") {\n\t\t\t\t\ttrackedKeys.add(change.key);\n\t\t\t\t} else {\n\t\t\t\t\ttrackedKeys.delete(change.key);\n\t\t\t\t}\n\t\t\t\tif (shouldPersist(change.key)) {\n\t\t\t\t\tshouldSave = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (shouldSave) {\n\t\t\t\tscheduleSave();\n\t\t\t}\n\t\t},\n\t};\n}\n","/**\n * Performance Plugin - Track constraint, resolver, and reconciliation metrics\n *\n * Uses existing plugin hooks to measure performance without modifying core runtime.\n */\n\nimport type { Plugin, ModuleSchema } from \"../core/types.js\";\n\n/** Metrics for a single constraint */\nexport interface ConstraintMetrics {\n\tevaluations: number;\n\ttotalDurationMs: number;\n\tavgDurationMs: number;\n\tmaxDurationMs: number;\n\tlastEvaluatedAt: number;\n}\n\n/** Metrics for a single resolver */\nexport interface ResolverMetrics {\n\tstarts: number;\n\tcompletions: number;\n\terrors: number;\n\tretries: number;\n\tcancellations: number;\n\ttotalDurationMs: number;\n\tavgDurationMs: number;\n\tmaxDurationMs: number;\n\tlastCompletedAt: number;\n}\n\n/** Metrics for the reconciliation loop */\nexport interface ReconcileMetrics {\n\truns: number;\n\ttotalDurationMs: number;\n\tavgDurationMs: number;\n\tmaxDurationMs: number;\n}\n\n/** Metrics for effects */\nexport interface EffectMetrics {\n\truns: number;\n\terrors: number;\n\tlastRunAt: number;\n}\n\n/** Full performance snapshot */\nexport interface PerformanceSnapshot {\n\tconstraints: Record<string, ConstraintMetrics>;\n\tresolvers: Record<string, ResolverMetrics>;\n\teffects: Record<string, EffectMetrics>;\n\treconcile: ReconcileMetrics;\n\tuptime: number;\n}\n\n/** Options for the performance plugin */\nexport interface PerformancePluginOptions {\n\t/** Callback when a slow constraint is detected (default threshold: 16ms) */\n\tonSlowConstraint?: (id: string, durationMs: number) => void;\n\t/** Callback when a slow resolver is detected (default threshold: 1000ms) */\n\tonSlowResolver?: (id: string, durationMs: number) => void;\n\t/** Threshold in ms for slow constraint warning (default: 16) */\n\tslowConstraintThresholdMs?: number;\n\t/** Threshold in ms for slow resolver warning (default: 1000) */\n\tslowResolverThresholdMs?: number;\n}\n\n/**\n * Create a performance monitoring plugin.\n *\n * Tracks constraint evaluation time, resolver latency, reconciliation cost,\n * and effect runs using existing plugin hooks.\n *\n * @example\n * ```typescript\n * const perf = performancePlugin({\n * onSlowResolver: (id, ms) => console.warn(`Slow resolver ${id}: ${ms}ms`),\n * });\n *\n * const system = createSystem({\n * module: myModule,\n * plugins: [perf],\n * });\n *\n * // Later: get a performance snapshot\n * const snapshot = perf.getSnapshot();\n * console.log(snapshot.resolvers);\n * ```\n */\nexport function performancePlugin<M extends ModuleSchema = ModuleSchema>(\n\toptions: PerformancePluginOptions = {},\n): Plugin<M> & { getSnapshot(): PerformanceSnapshot; reset(): void } {\n\tconst {\n\t\tonSlowConstraint,\n\t\tonSlowResolver,\n\t\tslowConstraintThresholdMs = 16,\n\t\tslowResolverThresholdMs = 1000,\n\t} = options;\n\n\tconst constraints = new Map<string, ConstraintMetrics>();\n\tconst resolvers = new Map<string, ResolverMetrics>();\n\tconst effects = new Map<string, EffectMetrics>();\n\tconst reconcile: ReconcileMetrics = { runs: 0, totalDurationMs: 0, avgDurationMs: 0, maxDurationMs: 0 };\n\n\tlet startedAt = 0;\n\tlet reconcileStartTime = 0;\n\n\t// Track constraint evaluation timing within a reconcile cycle.\n\t// Since constraints are evaluated sequentially, the time between consecutive\n\t// onConstraintEvaluate calls approximates each constraint's evaluation time.\n\t// The first constraint in each cycle cannot be timed (no baseline), so only\n\t// subsequent constraints get duration metrics.\n\tlet lastConstraintEvalEndTime = 0;\n\n\tfunction getConstraintMetrics(id: string): ConstraintMetrics {\n\t\tlet m = constraints.get(id);\n\t\tif (!m) {\n\t\t\tm = { evaluations: 0, totalDurationMs: 0, avgDurationMs: 0, maxDurationMs: 0, lastEvaluatedAt: 0 };\n\t\t\tconstraints.set(id, m);\n\t\t}\n\t\treturn m;\n\t}\n\n\tfunction getResolverMetrics(id: string): ResolverMetrics {\n\t\tlet m = resolvers.get(id);\n\t\tif (!m) {\n\t\t\tm = { starts: 0, completions: 0, errors: 0, retries: 0, cancellations: 0, totalDurationMs: 0, avgDurationMs: 0, maxDurationMs: 0, lastCompletedAt: 0 };\n\t\t\tresolvers.set(id, m);\n\t\t}\n\t\treturn m;\n\t}\n\n\tfunction getEffectMetrics(id: string): EffectMetrics {\n\t\tlet m = effects.get(id);\n\t\tif (!m) {\n\t\t\tm = { runs: 0, errors: 0, lastRunAt: 0 };\n\t\t\teffects.set(id, m);\n\t\t}\n\t\treturn m;\n\t}\n\n\tconst plugin: Plugin<M> & { getSnapshot(): PerformanceSnapshot; reset(): void } = {\n\t\tname: \"performance\",\n\n\t\tonStart() {\n\t\t\tstartedAt = Date.now();\n\t\t},\n\n\t\tonConstraintEvaluate(id, _active) {\n\t\t\tconst now = performance.now();\n\t\t\tconst m = getConstraintMetrics(id);\n\t\t\tm.evaluations++;\n\t\t\tm.lastEvaluatedAt = Date.now();\n\n\t\t\t// Constraints evaluate sequentially within a reconcile cycle.\n\t\t\t// Measure duration as time since the previous constraint finished evaluating\n\t\t\t// (or since reconcileStart for the first constraint in the cycle).\n\t\t\t// The first constraint per cycle has no baseline and is not timed.\n\t\t\tif (lastConstraintEvalEndTime > 0) {\n\t\t\t\tconst duration = now - lastConstraintEvalEndTime;\n\t\t\t\tm.totalDurationMs += duration;\n\t\t\t\tconst timedEvals = m.evaluations; // approximation — some evals may be untimed\n\t\t\t\tm.avgDurationMs = m.totalDurationMs / timedEvals;\n\t\t\t\tif (duration > m.maxDurationMs) m.maxDurationMs = duration;\n\t\t\t\tif (duration > slowConstraintThresholdMs) {\n\t\t\t\t\tonSlowConstraint?.(id, duration);\n\t\t\t\t}\n\t\t\t}\n\t\t\tlastConstraintEvalEndTime = now;\n\t\t},\n\n\t\tonResolverStart(resolver, _req) {\n\t\t\tconst m = getResolverMetrics(resolver);\n\t\t\tm.starts++;\n\t\t},\n\n\t\tonResolverComplete(resolver, _req, duration) {\n\t\t\tconst m = getResolverMetrics(resolver);\n\t\t\tm.completions++;\n\t\t\tm.totalDurationMs += duration;\n\t\t\tm.avgDurationMs = m.totalDurationMs / m.completions;\n\t\t\tif (duration > m.maxDurationMs) m.maxDurationMs = duration;\n\t\t\tm.lastCompletedAt = Date.now();\n\t\t\tif (duration > slowResolverThresholdMs) {\n\t\t\t\tonSlowResolver?.(resolver, duration);\n\t\t\t}\n\t\t},\n\n\t\tonResolverError(resolver, _req, _error) {\n\t\t\tgetResolverMetrics(resolver).errors++;\n\t\t},\n\n\t\tonResolverRetry(resolver, _req, _attempt) {\n\t\t\tgetResolverMetrics(resolver).retries++;\n\t\t},\n\n\t\tonResolverCancel(resolver, _req) {\n\t\t\tgetResolverMetrics(resolver).cancellations++;\n\t\t},\n\n\t\tonEffectRun(id) {\n\t\t\tconst m = getEffectMetrics(id);\n\t\t\tm.runs++;\n\t\t\tm.lastRunAt = Date.now();\n\t\t},\n\n\t\tonEffectError(id, _error) {\n\t\t\tgetEffectMetrics(id).errors++;\n\t\t},\n\n\t\tonReconcileStart() {\n\t\t\treconcileStartTime = performance.now();\n\t\t\t// Reset constraint timing baseline — first constraint in this cycle won't be timed\n\t\t\tlastConstraintEvalEndTime = 0;\n\t\t},\n\n\t\tonReconcileEnd() {\n\t\t\tconst duration = performance.now() - reconcileStartTime;\n\t\t\treconcile.runs++;\n\t\t\treconcile.totalDurationMs += duration;\n\t\t\treconcile.avgDurationMs = reconcile.totalDurationMs / reconcile.runs;\n\t\t\tif (duration > reconcile.maxDurationMs) reconcile.maxDurationMs = duration;\n\t\t},\n\n\t\tgetSnapshot(): PerformanceSnapshot {\n\t\t\tconst constraintsObj: Record<string, ConstraintMetrics> = {};\n\t\t\tfor (const [id, m] of constraints) constraintsObj[id] = { ...m };\n\n\t\t\tconst resolversObj: Record<string, ResolverMetrics> = {};\n\t\t\tfor (const [id, m] of resolvers) resolversObj[id] = { ...m };\n\n\t\t\tconst effectsObj: Record<string, EffectMetrics> = {};\n\t\t\tfor (const [id, m] of effects) effectsObj[id] = { ...m };\n\n\t\t\treturn {\n\t\t\t\tconstraints: constraintsObj,\n\t\t\t\tresolvers: resolversObj,\n\t\t\t\teffects: effectsObj,\n\t\t\t\treconcile: { ...reconcile },\n\t\t\t\tuptime: startedAt ? Date.now() - startedAt : 0,\n\t\t\t};\n\t\t},\n\n\t\treset(): void {\n\t\t\tconstraints.clear();\n\t\t\tresolvers.clear();\n\t\t\teffects.clear();\n\t\t\treconcile.runs = 0;\n\t\t\treconcile.totalDurationMs = 0;\n\t\t\treconcile.avgDurationMs = 0;\n\t\t\treconcile.maxDurationMs = 0;\n\t\t\tlastConstraintEvalEndTime = 0;\n\t\t},\n\t};\n\n\treturn plugin;\n}\n","/**\n * Observability Dashboard Plugin\n *\n * Provides comprehensive monitoring, metrics collection, and dashboard integration\n * for AI agent operations.\n *\n * @example\n * ```typescript\n * import { createObservability, createAgentMetrics } from '@directive-run/ai';\n *\n * const observability = createObservability({\n * metrics: {\n * enabled: true,\n * exportInterval: 10000, // Export every 10 seconds\n * },\n * tracing: {\n * enabled: true,\n * sampleRate: 1.0, // 100% sampling for dev\n * },\n * alerts: [\n * { metric: 'agent.errors', threshold: 10, action: 'warn' },\n * { metric: 'agent.latency', threshold: 5000, action: 'alert' },\n * ],\n * });\n *\n * // Use createAgentMetrics for standard metric names (required for getDashboard() summary)\n * const agentMetrics = createAgentMetrics(observability);\n *\n * // Access dashboard data\n * const dashboard = observability.getDashboard();\n *\n * // Clean up when done\n * await observability.dispose();\n * ```\n */\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** Metric types that can be collected */\nexport type MetricType =\n\t| \"counter\"\n\t| \"gauge\"\n\t| \"histogram\"\n\t| \"summary\";\n\n/** A single metric data point */\nexport interface MetricDataPoint {\n\tname: string;\n\ttype: MetricType;\n\tvalue: number;\n\tlabels: Record<string, string>;\n\ttimestamp: number;\n}\n\n/** Histogram bucket for latency/size distributions */\nexport interface HistogramBucket {\n\tle: number; // less than or equal\n\tcount: number;\n}\n\n/** Aggregated metric for dashboard display */\nexport interface AggregatedMetric {\n\tname: string;\n\ttype: MetricType;\n\tcount: number;\n\tsum: number;\n\tmin: number;\n\tmax: number;\n\tavg: number;\n\tp50?: number;\n\tp90?: number;\n\tp99?: number;\n\tlastValue: number;\n\tlastUpdated: number;\n}\n\n/** Trace span for distributed tracing */\nexport interface TraceSpan {\n\ttraceId: string;\n\tspanId: string;\n\tparentSpanId?: string;\n\toperationName: string;\n\tserviceName: string;\n\tstartTime: number;\n\tendTime?: number;\n\tduration?: number;\n\tstatus: \"ok\" | \"error\" | \"timeout\";\n\ttags: Record<string, string | number | boolean>;\n\tlogs: Array<{\n\t\ttimestamp: number;\n\t\tmessage: string;\n\t\tlevel: \"debug\" | \"info\" | \"warn\" | \"error\";\n\t}>;\n}\n\n/** Alert configuration */\nexport interface AlertConfig {\n\tmetric: string;\n\tthreshold: number;\n\toperator?: \">\" | \"<\" | \">=\" | \"<=\" | \"==\";\n\taction: \"log\" | \"warn\" | \"alert\" | \"callback\";\n\tcallback?: (metric: AggregatedMetric, threshold: number) => void;\n\tcooldownMs?: number;\n}\n\n/** Alert event when threshold is crossed */\nexport interface AlertEvent {\n\talertId: string;\n\tmetric: string;\n\tcurrentValue: number;\n\tthreshold: number;\n\toperator: string;\n\taction: string;\n\ttimestamp: number;\n\tmessage: string;\n}\n\n/** Observability configuration */\nexport interface ObservabilityConfig {\n\t/** Service name for tracing */\n\tserviceName?: string;\n\t/** Metrics configuration */\n\tmetrics?: {\n\t\tenabled?: boolean;\n\t\t/** Export interval in milliseconds */\n\t\texportInterval?: number;\n\t\t/** Custom exporter function */\n\t\texporter?: (metrics: AggregatedMetric[]) => Promise<void>;\n\t\t/** Maximum data points to retain per metric */\n\t\tmaxDataPoints?: number;\n\t};\n\t/** Tracing configuration */\n\ttracing?: {\n\t\tenabled?: boolean;\n\t\t/** Sample rate (0.0 to 1.0) */\n\t\tsampleRate?: number;\n\t\t/** Maximum spans to retain */\n\t\tmaxSpans?: number;\n\t\t/** Custom trace exporter */\n\t\texporter?: (spans: TraceSpan[]) => Promise<void>;\n\t};\n\t/** Alert configurations */\n\talerts?: AlertConfig[];\n\t/**\n\t * Metric names used by `getDashboard().summary` and `getHealthStatus()`.\n\t * Defaults to `agent.requests`, `agent.errors`, `agent.latency`, `agent.tokens`, `agent.cost`.\n\t * Must match the metric names you record via `incrementCounter` / `observeHistogram`,\n\t * or use `createAgentMetrics()` which records with these default names.\n\t */\n\tsummaryMetrics?: {\n\t\trequests?: string;\n\t\terrors?: string;\n\t\tlatency?: string;\n\t\ttokens?: string;\n\t\tcost?: string;\n\t};\n\t/** Event callbacks */\n\tevents?: {\n\t\tonMetricRecorded?: (metric: MetricDataPoint) => void;\n\t\tonSpanStart?: (span: TraceSpan) => void;\n\t\tonSpanEnd?: (span: TraceSpan) => void;\n\t\tonAlert?: (alert: AlertEvent) => void;\n\t};\n}\n\n/** Dashboard data for UI display */\nexport interface DashboardData {\n\t/** Service info */\n\tservice: {\n\t\tname: string;\n\t\tuptime: number;\n\t\tstartTime: number;\n\t};\n\t/** Aggregated metrics */\n\tmetrics: Record<string, AggregatedMetric>;\n\t/** Recent traces */\n\ttraces: TraceSpan[];\n\t/** Active alerts */\n\talerts: AlertEvent[];\n\t/** Summary stats */\n\tsummary: {\n\t\ttotalRequests: number;\n\t\ttotalErrors: number;\n\t\terrorRate: number;\n\t\tavgLatency: number;\n\t\tp99Latency: number;\n\t\tactiveSpans: number;\n\t\ttotalTokens: number;\n\t\ttotalCost: number;\n\t};\n}\n\n/** Observability instance */\nexport interface ObservabilityInstance {\n\t/** Record a counter metric */\n\tincrementCounter(name: string, labels?: Record<string, string>, value?: number): void;\n\t/** Record a gauge metric */\n\tsetGauge(name: string, value: number, labels?: Record<string, string>): void;\n\t/** Record a histogram observation */\n\tobserveHistogram(name: string, value: number, labels?: Record<string, string>): void;\n\t/** Start a trace span */\n\tstartSpan(operationName: string, parentSpanId?: string): TraceSpan;\n\t/** End a trace span */\n\tendSpan(spanId: string, status?: \"ok\" | \"error\" | \"timeout\"): void;\n\t/** Add log to a span */\n\taddSpanLog(spanId: string, message: string, level?: \"debug\" | \"info\" | \"warn\" | \"error\"): void;\n\t/** Add tag to a span */\n\taddSpanTag(spanId: string, key: string, value: string | number | boolean): void;\n\t/** Get dashboard data */\n\tgetDashboard(): DashboardData;\n\t/** Get a specific metric */\n\tgetMetric(name: string): AggregatedMetric | undefined;\n\t/** Get recent traces */\n\tgetTraces(limit?: number): TraceSpan[];\n\t/** Get active alerts */\n\tgetAlerts(): AlertEvent[];\n\t/** Export all data */\n\texport(): { metrics: AggregatedMetric[]; traces: TraceSpan[]; alerts: AlertEvent[] };\n\t/** Clear all data and reset statistics */\n\tclear(): void;\n\t/** Dispose of the instance, clearing timers and flushing data */\n\tdispose(): Promise<void>;\n\t/** Get health status for status pages */\n\tgetHealthStatus(): {\n\t\thealthy: boolean;\n\t\tuptime: number;\n\t\terrorRate: number;\n\t\tactiveAlerts: number;\n\t};\n}\n\n// ============================================================================\n// Utility Functions\n// ============================================================================\n\nfunction generateId(): string {\n\treturn globalThis.crypto?.randomUUID?.() ?? `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 11)}`;\n}\n\nfunction calculatePercentile(values: number[], percentile: number): number {\n\tif (values.length === 0) return 0;\n\tconst sorted = [...values].sort((a, b) => a - b);\n\tconst index = Math.ceil((percentile / 100) * sorted.length) - 1;\n\treturn sorted[Math.max(0, index)] ?? 0;\n}\n\n// ============================================================================\n// Factory\n// ============================================================================\n\n/**\n * Create an observability instance for monitoring AI agents.\n *\n * @example\n * ```typescript\n * const obs = createObservability({\n * serviceName: 'my-agent-service',\n * metrics: { enabled: true },\n * tracing: { enabled: true, sampleRate: 0.1 },\n * alerts: [\n * { metric: 'agent.errors', threshold: 10, action: 'alert' },\n * ],\n * });\n *\n * // Track agent operations\n * const span = obs.startSpan('agent.run');\n * obs.incrementCounter('agent.requests', { agent: 'support' });\n *\n * try {\n * await runAgent();\n * obs.observeHistogram('agent.latency', Date.now() - start);\n * obs.endSpan(span.spanId, 'ok');\n * } catch (e) {\n * obs.incrementCounter('agent.errors');\n * obs.endSpan(span.spanId, 'error');\n * }\n * ```\n */\nexport function createObservability(config: ObservabilityConfig = {}): ObservabilityInstance {\n\tconst {\n\t\tserviceName = \"directive-agents\",\n\t\tmetrics: metricsConfig = {},\n\t\ttracing: tracingConfig = {},\n\t\talerts: alertConfigs = [],\n\t\tsummaryMetrics: summaryMetricsConfig = {},\n\t\tevents = {},\n\t} = config;\n\n\tconst summaryMetricNames = {\n\t\trequests: summaryMetricsConfig.requests ?? \"agent.requests\",\n\t\terrors: summaryMetricsConfig.errors ?? \"agent.errors\",\n\t\tlatency: summaryMetricsConfig.latency ?? \"agent.latency\",\n\t\ttokens: summaryMetricsConfig.tokens ?? \"agent.tokens\",\n\t\tcost: summaryMetricsConfig.cost ?? \"agent.cost\",\n\t};\n\n\tconst {\n\t\tenabled: metricsEnabled = true,\n\t\texportInterval,\n\t\texporter: metricsExporter,\n\t\tmaxDataPoints = 1000,\n\t} = metricsConfig;\n\n\tconst {\n\t\tenabled: tracingEnabled = true,\n\t\tsampleRate = 1.0,\n\t\tmaxSpans = 1000,\n\t\texporter: tracingExporter,\n\t} = tracingConfig;\n\n\t// State\n\tconst startTime = Date.now();\n\tconst metricDataPoints = new Map<string, MetricDataPoint[]>();\n\tconst activeSpans = new Map<string, TraceSpan>();\n\tconst completedSpans: TraceSpan[] = [];\n\tconst alertEvents: AlertEvent[] = [];\n\tconst alertCooldowns = new Map<string, number>();\n\n\t// Aggregated metrics cache\n\tconst aggregatedMetrics = new Map<string, AggregatedMetric>();\n\n\t// Export timer\n\tlet exportTimer: ReturnType<typeof setInterval> | undefined;\n\tif (exportInterval && (metricsExporter || tracingExporter)) {\n\t\texportTimer = setInterval(async () => {\n\t\t\ttry {\n\t\t\t\tif (metricsExporter && metricsEnabled) {\n\t\t\t\t\tawait metricsExporter(Array.from(aggregatedMetrics.values()));\n\t\t\t\t}\n\t\t\t\tif (tracingExporter && tracingEnabled) {\n\t\t\t\t\tconst spansToExport = completedSpans.splice(0, 100);\n\t\t\t\t\tif (spansToExport.length > 0) {\n\t\t\t\t\t\tawait tracingExporter(spansToExport);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"[Directive Observability] Export error:\", error);\n\t\t\t}\n\t\t}, exportInterval);\n\t}\n\n\tfunction recordMetric(dataPoint: MetricDataPoint): void {\n\t\tif (!metricsEnabled) return;\n\n\t\tconst key = `${dataPoint.name}:${JSON.stringify(Object.fromEntries(Object.entries(dataPoint.labels).sort()))}`;\n\t\tlet points = metricDataPoints.get(key);\n\t\tif (!points) {\n\t\t\tpoints = [];\n\t\t\tmetricDataPoints.set(key, points);\n\t\t}\n\n\t\tpoints.push(dataPoint);\n\n\t\t// Trim old data points\n\t\tif (points.length > maxDataPoints) {\n\t\t\tpoints.shift();\n\t\t}\n\n\t\t// Update aggregation\n\t\tupdateAggregation(dataPoint.name, points);\n\n\t\tevents.onMetricRecorded?.(dataPoint);\n\n\t\t// Check alerts\n\t\tcheckAlerts(dataPoint.name);\n\t}\n\n\tfunction updateAggregation(name: string, points: MetricDataPoint[]): void {\n\t\tif (points.length === 0) return;\n\n\t\tconst values = points.map((p) => p.value);\n\t\tconst sum = values.reduce((a, b) => a + b, 0);\n\n\t\t// We've already checked points.length === 0 above, so these are safe\n\t\tconst firstPoint = points[0]!;\n\t\tconst lastValue = values[values.length - 1]!;\n\n\t\tconst aggregated: AggregatedMetric = {\n\t\t\tname,\n\t\t\ttype: firstPoint.type,\n\t\t\tcount: points.length,\n\t\t\tsum,\n\t\t\tmin: Math.min(...values),\n\t\t\tmax: Math.max(...values),\n\t\t\tavg: sum / points.length,\n\t\t\tlastValue,\n\t\t\tlastUpdated: Date.now(),\n\t\t};\n\n\t\taggregatedMetrics.set(name, aggregated);\n\t}\n\n\tfunction checkAlerts(metricName: string): void {\n\t\tfor (const alertConfig of alertConfigs) {\n\t\t\tif (alertConfig.metric !== metricName) continue;\n\n\t\t\tconst metric = aggregatedMetrics.get(metricName);\n\t\t\tif (!metric) continue;\n\n\t\t\tconst cooldownKey = `${alertConfig.metric}:${alertConfig.threshold}`;\n\t\t\tconst lastAlert = alertCooldowns.get(cooldownKey);\n\t\t\tconst cooldown = alertConfig.cooldownMs ?? 60000;\n\n\t\t\tif (lastAlert && Date.now() - lastAlert < cooldown) continue;\n\n\t\t\tconst operator = alertConfig.operator ?? \">\";\n\t\t\tconst value = metric.lastValue;\n\t\t\tconst threshold = alertConfig.threshold;\n\n\t\t\tlet triggered = false;\n\t\t\tswitch (operator) {\n\t\t\t\tcase \">\":\n\t\t\t\t\ttriggered = value > threshold;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"<\":\n\t\t\t\t\ttriggered = value < threshold;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \">=\":\n\t\t\t\t\ttriggered = value >= threshold;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"<=\":\n\t\t\t\t\ttriggered = value <= threshold;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"==\":\n\t\t\t\t\ttriggered = value === threshold;\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (triggered) {\n\t\t\t\tconst alertEvent: AlertEvent = {\n\t\t\t\t\talertId: generateId(),\n\t\t\t\t\tmetric: metricName,\n\t\t\t\t\tcurrentValue: value,\n\t\t\t\t\tthreshold,\n\t\t\t\t\toperator,\n\t\t\t\t\taction: alertConfig.action,\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t\tmessage: `Alert: ${metricName} ${operator} ${threshold} (current: ${value})`,\n\t\t\t\t};\n\n\t\t\t\talertEvents.push(alertEvent);\n\t\t\t\tif (alertEvents.length > 1000) alertEvents.splice(0, alertEvents.length - 1000);\n\t\t\t\talertCooldowns.set(cooldownKey, Date.now());\n\n\t\t\t\tevents.onAlert?.(alertEvent);\n\n\t\t\t\tswitch (alertConfig.action) {\n\t\t\t\t\tcase \"log\":\n\t\t\t\t\t\tconsole.log(`[Observability] ${alertEvent.message}`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"warn\":\n\t\t\t\t\t\tconsole.warn(`[Observability] ${alertEvent.message}`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"alert\":\n\t\t\t\t\t\tconsole.error(`[Observability ALERT] ${alertEvent.message}`);\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"callback\":\n\t\t\t\t\t\talertConfig.callback?.(metric, threshold);\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction getPercentiles(name: string): { p50?: number; p90?: number; p99?: number } {\n\t\t// Collect all data points for this metric name across all label combinations\n\t\tconst allValues: number[] = [];\n\t\tfor (const [key, points] of metricDataPoints) {\n\t\t\tif (key.startsWith(`${name}:`)) {\n\t\t\t\tfor (const p of points) {\n\t\t\t\t\tallValues.push(p.value);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (allValues.length === 0) return {};\n\t\treturn {\n\t\t\tp50: calculatePercentile(allValues, 50),\n\t\t\tp90: calculatePercentile(allValues, 90),\n\t\t\tp99: calculatePercentile(allValues, 99),\n\t\t};\n\t}\n\n\treturn {\n\t\tincrementCounter(name: string, labels: Record<string, string> = {}, value = 1): void {\n\t\t\trecordMetric({\n\t\t\t\tname,\n\t\t\t\ttype: \"counter\",\n\t\t\t\tvalue,\n\t\t\t\tlabels,\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t});\n\t\t},\n\n\t\tsetGauge(name: string, value: number, labels: Record<string, string> = {}): void {\n\t\t\trecordMetric({\n\t\t\t\tname,\n\t\t\t\ttype: \"gauge\",\n\t\t\t\tvalue,\n\t\t\t\tlabels,\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t});\n\t\t},\n\n\t\tobserveHistogram(name: string, value: number, labels: Record<string, string> = {}): void {\n\t\t\trecordMetric({\n\t\t\t\tname,\n\t\t\t\ttype: \"histogram\",\n\t\t\t\tvalue,\n\t\t\t\tlabels,\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t});\n\t\t},\n\n\t\tstartSpan(operationName: string, parentSpanId?: string): TraceSpan {\n\t\t\t// Apply sampling\n\t\t\tif (Math.random() > sampleRate) {\n\t\t\t\t// Return a no-op span that won't be tracked\n\t\t\t\treturn {\n\t\t\t\t\ttraceId: \"sampled-out\",\n\t\t\t\t\tspanId: \"sampled-out\",\n\t\t\t\t\toperationName,\n\t\t\t\t\tserviceName,\n\t\t\t\t\tstartTime: Date.now(),\n\t\t\t\t\tstatus: \"ok\",\n\t\t\t\t\ttags: {},\n\t\t\t\t\tlogs: [],\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst span: TraceSpan = {\n\t\t\t\ttraceId: parentSpanId\n\t\t\t\t\t? activeSpans.get(parentSpanId)?.traceId ?? generateId()\n\t\t\t\t\t: generateId(),\n\t\t\t\tspanId: generateId(),\n\t\t\t\tparentSpanId,\n\t\t\t\toperationName,\n\t\t\t\tserviceName,\n\t\t\t\tstartTime: Date.now(),\n\t\t\t\tstatus: \"ok\",\n\t\t\t\ttags: {},\n\t\t\t\tlogs: [],\n\t\t\t};\n\n\t\t\tif (tracingEnabled) {\n\t\t\t\tactiveSpans.set(span.spanId, span);\n\t\t\t\tevents.onSpanStart?.(span);\n\t\t\t}\n\n\t\t\treturn span;\n\t\t},\n\n\t\tendSpan(spanId: string, status: \"ok\" | \"error\" | \"timeout\" = \"ok\"): void {\n\t\t\tif (spanId === \"sampled-out\") return;\n\n\t\t\tconst span = activeSpans.get(spanId);\n\t\t\tif (!span) return;\n\n\t\t\tspan.endTime = Date.now();\n\t\t\tspan.duration = span.endTime - span.startTime;\n\t\t\tspan.status = status;\n\n\t\t\tactiveSpans.delete(spanId);\n\t\t\tcompletedSpans.push(span);\n\n\t\t\t// Trim old spans\n\t\t\twhile (completedSpans.length > maxSpans) {\n\t\t\t\tcompletedSpans.shift();\n\t\t\t}\n\n\t\t\t// Record latency metric (use recordMetric directly to avoid `this` binding issues)\n\t\t\trecordMetric({\n\t\t\t\tname: `${span.operationName}.latency`,\n\t\t\t\ttype: \"histogram\",\n\t\t\t\tvalue: span.duration,\n\t\t\t\tlabels: {},\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t});\n\n\t\t\tif (status === \"error\") {\n\t\t\t\trecordMetric({\n\t\t\t\t\tname: `${span.operationName}.errors`,\n\t\t\t\t\ttype: \"counter\",\n\t\t\t\t\tvalue: 1,\n\t\t\t\t\tlabels: {},\n\t\t\t\t\ttimestamp: Date.now(),\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tevents.onSpanEnd?.(span);\n\t\t},\n\n\t\taddSpanLog(spanId: string, message: string, level: \"debug\" | \"info\" | \"warn\" | \"error\" = \"info\"): void {\n\t\t\tif (spanId === \"sampled-out\") return;\n\n\t\t\tconst span = activeSpans.get(spanId);\n\t\t\tif (!span) return;\n\n\t\t\tspan.logs.push({\n\t\t\t\ttimestamp: Date.now(),\n\t\t\t\tmessage,\n\t\t\t\tlevel,\n\t\t\t});\n\t\t},\n\n\t\taddSpanTag(spanId: string, key: string, value: string | number | boolean): void {\n\t\t\tif (spanId === \"sampled-out\") return;\n\n\t\t\tconst span = activeSpans.get(spanId);\n\t\t\tif (!span) return;\n\n\t\t\tspan.tags[key] = value;\n\t\t},\n\n\t\tgetDashboard(): DashboardData {\n\t\t\t// Calculate summary stats using configurable metric names\n\t\t\tconst requestsMetric = aggregatedMetrics.get(summaryMetricNames.requests);\n\t\t\tconst errorsMetric = aggregatedMetrics.get(summaryMetricNames.errors);\n\t\t\tconst latencyMetric = aggregatedMetrics.get(summaryMetricNames.latency);\n\t\t\tconst tokensMetric = aggregatedMetrics.get(summaryMetricNames.tokens);\n\t\t\tconst costMetric = aggregatedMetrics.get(summaryMetricNames.cost);\n\n\t\t\tconst totalRequests = requestsMetric?.sum ?? 0;\n\t\t\tconst totalErrors = errorsMetric?.sum ?? 0;\n\t\t\tconst errorRate = totalRequests > 0 ? totalErrors / totalRequests : 0;\n\n\t\t\t// Calculate percentiles on demand for latency\n\t\t\tconst latencyPercentiles = latencyMetric ? getPercentiles(summaryMetricNames.latency) : {};\n\n\t\t\treturn {\n\t\t\t\tservice: {\n\t\t\t\t\tname: serviceName,\n\t\t\t\t\tuptime: Date.now() - startTime,\n\t\t\t\t\tstartTime,\n\t\t\t\t},\n\t\t\t\tmetrics: Object.fromEntries(aggregatedMetrics),\n\t\t\t\ttraces: [...completedSpans].slice(-100),\n\t\t\t\talerts: [...alertEvents].slice(-50),\n\t\t\t\tsummary: {\n\t\t\t\t\ttotalRequests,\n\t\t\t\t\ttotalErrors,\n\t\t\t\t\terrorRate,\n\t\t\t\t\tavgLatency: latencyMetric?.avg ?? 0,\n\t\t\t\t\tp99Latency: latencyPercentiles.p99 ?? 0,\n\t\t\t\t\tactiveSpans: activeSpans.size,\n\t\t\t\t\ttotalTokens: tokensMetric?.sum ?? 0,\n\t\t\t\t\ttotalCost: costMetric?.sum ?? 0,\n\t\t\t\t},\n\t\t\t};\n\t\t},\n\n\t\tgetMetric(name: string): AggregatedMetric | undefined {\n\t\t\tconst metric = aggregatedMetrics.get(name);\n\t\t\tif (!metric) return undefined;\n\t\t\t// Calculate percentiles on demand\n\t\t\tconst percentiles = getPercentiles(name);\n\t\t\treturn { ...metric, ...percentiles };\n\t\t},\n\n\t\tgetTraces(limit = 100): TraceSpan[] {\n\t\t\treturn [...completedSpans].slice(-limit);\n\t\t},\n\n\t\tgetAlerts(): AlertEvent[] {\n\t\t\treturn [...alertEvents];\n\t\t},\n\n\t\texport() {\n\t\t\treturn {\n\t\t\t\tmetrics: Array.from(aggregatedMetrics.values()),\n\t\t\t\ttraces: [...completedSpans],\n\t\t\t\talerts: [...alertEvents],\n\t\t\t};\n\t\t},\n\n\t\tclear() {\n\t\t\tmetricDataPoints.clear();\n\t\t\taggregatedMetrics.clear();\n\t\t\tactiveSpans.clear();\n\t\t\tcompletedSpans.length = 0;\n\t\t\talertEvents.length = 0;\n\t\t\talertCooldowns.clear();\n\t\t},\n\n\t\tasync dispose() {\n\t\t\t// Clear the export timer\n\t\t\tif (exportTimer) {\n\t\t\t\tclearInterval(exportTimer);\n\t\t\t\texportTimer = undefined;\n\t\t\t}\n\n\t\t\t// Flush any remaining data to exporters\n\t\t\ttry {\n\t\t\t\tif (metricsExporter && metricsEnabled && aggregatedMetrics.size > 0) {\n\t\t\t\t\tawait metricsExporter(Array.from(aggregatedMetrics.values()));\n\t\t\t\t}\n\t\t\t\tif (tracingExporter && tracingEnabled && completedSpans.length > 0) {\n\t\t\t\t\tawait tracingExporter([...completedSpans]);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconsole.error(\"[Directive Observability] Error flushing data during dispose:\", error);\n\t\t\t}\n\n\t\t\t// Clear all data\n\t\t\tmetricDataPoints.clear();\n\t\t\taggregatedMetrics.clear();\n\t\t\tactiveSpans.clear();\n\t\t\tcompletedSpans.length = 0;\n\t\t\talertEvents.length = 0;\n\t\t\talertCooldowns.clear();\n\t\t},\n\n\t\tgetHealthStatus() {\n\t\t\tconst requestsMetric = aggregatedMetrics.get(summaryMetricNames.requests);\n\t\t\tconst errorsMetric = aggregatedMetrics.get(summaryMetricNames.errors);\n\n\t\t\tconst totalRequests = requestsMetric?.sum ?? 0;\n\t\t\tconst totalErrors = errorsMetric?.sum ?? 0;\n\t\t\tconst errorRate = totalRequests > 0 ? totalErrors / totalRequests : 0;\n\n\t\t\t// Consider unhealthy if error rate > 10% or there are active alerts\n\t\t\tconst activeAlertCount = alertEvents.filter(\n\t\t\t\t(a) => Date.now() - a.timestamp < 300000 // Last 5 minutes\n\t\t\t).length;\n\n\t\t\treturn {\n\t\t\t\thealthy: errorRate < 0.1 && activeAlertCount === 0,\n\t\t\t\tuptime: Date.now() - startTime,\n\t\t\t\terrorRate,\n\t\t\t\tactiveAlerts: activeAlertCount,\n\t\t\t};\n\t\t},\n\t};\n}\n\n// ============================================================================\n// Pre-built Metric Helpers\n// ============================================================================\n\n/**\n * Create standard agent metrics for an observability instance.\n *\n * @example\n * ```typescript\n * const obs = createObservability({ serviceName: 'my-service' });\n * const agentMetrics = createAgentMetrics(obs);\n *\n * // Track an agent run\n * agentMetrics.trackRun('support-agent', {\n * success: true,\n * latencyMs: 1500,\n * inputTokens: 100,\n * outputTokens: 500,\n * cost: 0.05,\n * });\n * ```\n */\nexport function createAgentMetrics(obs: ObservabilityInstance) {\n\treturn {\n\t\ttrackRun(\n\t\t\tagentName: string,\n\t\t\tresult: {\n\t\t\t\tsuccess: boolean;\n\t\t\t\tlatencyMs: number;\n\t\t\t\tinputTokens?: number;\n\t\t\t\toutputTokens?: number;\n\t\t\t\tcost?: number;\n\t\t\t\ttoolCalls?: number;\n\t\t\t}\n\t\t): void {\n\t\t\tconst labels = { agent: agentName };\n\n\t\t\tobs.incrementCounter(\"agent.requests\", labels);\n\n\t\t\tif (!result.success) {\n\t\t\t\tobs.incrementCounter(\"agent.errors\", labels);\n\t\t\t}\n\n\t\t\tobs.observeHistogram(\"agent.latency\", result.latencyMs, labels);\n\n\t\t\tif (result.inputTokens !== undefined) {\n\t\t\t\tobs.incrementCounter(\"agent.tokens.input\", labels, result.inputTokens);\n\t\t\t\tobs.incrementCounter(\"agent.tokens\", labels, result.inputTokens);\n\t\t\t}\n\n\t\t\tif (result.outputTokens !== undefined) {\n\t\t\t\tobs.incrementCounter(\"agent.tokens.output\", labels, result.outputTokens);\n\t\t\t\tobs.incrementCounter(\"agent.tokens\", labels, result.outputTokens);\n\t\t\t}\n\n\t\t\tif (result.cost !== undefined) {\n\t\t\t\tobs.incrementCounter(\"agent.cost\", labels, result.cost);\n\t\t\t}\n\n\t\t\tif (result.toolCalls !== undefined) {\n\t\t\t\tobs.incrementCounter(\"agent.tool_calls\", labels, result.toolCalls);\n\t\t\t}\n\t\t},\n\n\t\ttrackGuardrail(\n\t\t\tguardrailName: string,\n\t\t\tresult: {\n\t\t\t\tpassed: boolean;\n\t\t\t\tlatencyMs: number;\n\t\t\t\tblocked?: boolean;\n\t\t\t}\n\t\t): void {\n\t\t\tconst labels = { guardrail: guardrailName };\n\n\t\t\tobs.incrementCounter(\"guardrail.checks\", labels);\n\n\t\t\tif (!result.passed) {\n\t\t\t\tobs.incrementCounter(\"guardrail.failures\", labels);\n\t\t\t}\n\n\t\t\tif (result.blocked) {\n\t\t\t\tobs.incrementCounter(\"guardrail.blocks\", labels);\n\t\t\t}\n\n\t\t\tobs.observeHistogram(\"guardrail.latency\", result.latencyMs, labels);\n\t\t},\n\n\t\ttrackApproval(\n\t\t\ttoolName: string,\n\t\t\tresult: {\n\t\t\t\tapproved: boolean;\n\t\t\t\twaitTimeMs: number;\n\t\t\t\ttimedOut?: boolean;\n\t\t\t}\n\t\t): void {\n\t\t\tconst labels = { tool: toolName };\n\n\t\t\tobs.incrementCounter(\"approval.requests\", labels);\n\n\t\t\tif (result.approved) {\n\t\t\t\tobs.incrementCounter(\"approval.approved\", labels);\n\t\t\t} else {\n\t\t\t\tobs.incrementCounter(\"approval.rejected\", labels);\n\t\t\t}\n\n\t\t\tif (result.timedOut) {\n\t\t\t\tobs.incrementCounter(\"approval.timeouts\", labels);\n\t\t\t}\n\n\t\t\tobs.observeHistogram(\"approval.wait_time\", result.waitTimeMs, labels);\n\t\t},\n\n\t\ttrackHandoff(\n\t\t\tfromAgent: string,\n\t\t\ttoAgent: string,\n\t\t\tlatencyMs: number\n\t\t): void {\n\t\t\tobs.incrementCounter(\"handoff.count\", { from: fromAgent, to: toAgent });\n\t\t\tobs.observeHistogram(\"handoff.latency\", latencyMs);\n\t\t},\n\t};\n}\n","/**\n * OTLP (OpenTelemetry Protocol) Exporter\n *\n * Converts Directive observability data to OTLP JSON format for export to\n * Grafana, Datadog, Jaeger, and other OpenTelemetry-compatible backends.\n *\n * @example\n * ```typescript\n * import { createObservability } from '@directive-run/ai';\n * import { createOTLPExporter } from '@directive-run/ai';\n *\n * const exporter = createOTLPExporter({\n * endpoint: 'http://localhost:4318',\n * headers: { 'Authorization': 'Bearer token' },\n * serviceName: 'my-agent-service',\n * });\n *\n * const obs = createObservability({\n * metrics: { exporter: exporter.exportMetrics, exportInterval: 10000 },\n * tracing: { exporter: exporter.exportTraces },\n * });\n * ```\n */\n\nimport type { AggregatedMetric, TraceSpan } from \"./observability.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** OTLP exporter configuration */\nexport interface OTLPExporterConfig {\n\t/** OTLP endpoint base URL (e.g., http://localhost:4318) */\n\tendpoint: string;\n\t/** Optional headers (e.g., auth tokens) */\n\theaders?: Record<string, string>;\n\t/** Service name for resource identification */\n\tserviceName?: string;\n\t/** Service version */\n\tserviceVersion?: string;\n\t/** Custom resource attributes */\n\tresourceAttributes?: Record<string, string>;\n\t/** Instrumentation scope version (default: \"0.1.0\") */\n\tscopeVersion?: string;\n\t/** Request timeout in ms (default: 10000) */\n\ttimeoutMs?: number;\n\t/** Custom fetch function (for testing or custom HTTP clients) */\n\tfetch?: typeof globalThis.fetch;\n\t/** Callback on export error */\n\tonError?: (error: Error, type: \"metrics\" | \"traces\") => void;\n}\n\n/** OTLP exporter instance */\nexport interface OTLPExporter {\n\t/** Export metrics in OTLP format (compatible with ObservabilityConfig.metrics.exporter) */\n\texportMetrics: (metrics: AggregatedMetric[]) => Promise<void>;\n\t/** Export traces in OTLP format (compatible with ObservabilityConfig.tracing.exporter) */\n\texportTraces: (traces: TraceSpan[]) => Promise<void>;\n}\n\n// ============================================================================\n// OTLP JSON Conversion\n// ============================================================================\n\ninterface OTLPResource {\n\tattributes: Array<{ key: string; value: { stringValue: string } }>;\n}\n\nfunction buildResource(config: OTLPExporterConfig): OTLPResource {\n\tconst attrs: Array<{ key: string; value: { stringValue: string } }> = [\n\t\t{ key: \"service.name\", value: { stringValue: config.serviceName ?? \"directive-agents\" } },\n\t];\n\n\tif (config.serviceVersion) {\n\t\tattrs.push({ key: \"service.version\", value: { stringValue: config.serviceVersion } });\n\t}\n\n\tif (config.resourceAttributes) {\n\t\tfor (const [key, val] of Object.entries(config.resourceAttributes)) {\n\t\t\tattrs.push({ key, value: { stringValue: val } });\n\t\t}\n\t}\n\n\treturn { attributes: attrs };\n}\n\nfunction toNanos(timestampMs: number): string {\n\treturn `${BigInt(timestampMs) * BigInt(1_000_000)}`;\n}\n\nfunction metricTypeToOTLP(type: string): string {\n\tswitch (type) {\n\t\tcase \"counter\":\n\t\t\treturn \"sum\";\n\t\tcase \"gauge\":\n\t\t\treturn \"gauge\";\n\t\tcase \"histogram\":\n\t\t\treturn \"histogram\";\n\t\tdefault:\n\t\t\treturn \"gauge\";\n\t}\n}\n\nfunction convertMetrics(\n\tmetrics: AggregatedMetric[],\n\tresource: OTLPResource,\n\tscopeVersion: string,\n): Record<string, unknown> {\n\tconst scopeMetrics = metrics.map((metric) => {\n\t\t// Known limitation: startTimeUnixNano is approximated as lastUpdated minus 60s.\n\t\t// A more accurate value would require tracking the actual collection start time\n\t\t// per metric, which is not available in the current AggregatedMetric type.\n\t\tconst startTimeMs = metric.lastUpdated - 60000;\n\n\t\tconst dataPoints = [\n\t\t\t{\n\t\t\t\tasInt: metric.type === \"counter\" ? metric.sum : undefined,\n\t\t\t\tasDouble: metric.type !== \"counter\" ? metric.lastValue : undefined,\n\t\t\t\ttimeUnixNano: toNanos(metric.lastUpdated),\n\t\t\t\tstartTimeUnixNano: toNanos(startTimeMs),\n\t\t\t\tattributes: [],\n\t\t\t},\n\t\t];\n\n\t\tconst otlpType = metricTypeToOTLP(metric.type);\n\t\tconst metricData: Record<string, unknown> = {\n\t\t\tname: metric.name,\n\t\t\tunit: \"\",\n\t\t};\n\n\t\tif (otlpType === \"sum\") {\n\t\t\tmetricData.sum = {\n\t\t\t\tdataPoints,\n\t\t\t\taggregationTemporality: 2, // CUMULATIVE\n\t\t\t\tisMonotonic: true,\n\t\t\t};\n\t\t} else if (otlpType === \"histogram\") {\n\t\t\tmetricData.histogram = {\n\t\t\t\tdataPoints: [\n\t\t\t\t\t{\n\t\t\t\t\t\tcount: metric.count,\n\t\t\t\t\t\tsum: metric.sum,\n\t\t\t\t\t\tmin: metric.min,\n\t\t\t\t\t\tmax: metric.max,\n\t\t\t\t\t\ttimeUnixNano: toNanos(metric.lastUpdated),\n\t\t\t\t\t\tstartTimeUnixNano: toNanos(startTimeMs),\n\t\t\t\t\t\tattributes: [],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\taggregationTemporality: 2,\n\t\t\t};\n\t\t} else {\n\t\t\tmetricData.gauge = { dataPoints };\n\t\t}\n\n\t\treturn metricData;\n\t});\n\n\treturn {\n\t\tresourceMetrics: [\n\t\t\t{\n\t\t\t\tresource,\n\t\t\t\tscopeMetrics: [\n\t\t\t\t\t{\n\t\t\t\t\t\tscope: { name: \"directive\", version: scopeVersion },\n\t\t\t\t\t\tmetrics: scopeMetrics,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t};\n}\n\nfunction convertTraces(\n\ttraces: TraceSpan[],\n\tresource: OTLPResource,\n\tscopeVersion: string,\n): Record<string, unknown> {\n\tconst spans = traces.map((span) => {\n\t\tconst events = span.logs.map((log) => ({\n\t\t\ttimeUnixNano: toNanos(log.timestamp),\n\t\t\tname: log.level,\n\t\t\tattributes: [\n\t\t\t\t{ key: \"message\", value: { stringValue: log.message } },\n\t\t\t\t{ key: \"level\", value: { stringValue: log.level } },\n\t\t\t],\n\t\t}));\n\n\t\tconst attributes = Object.entries(span.tags).map(([key, val]) => ({\n\t\t\tkey,\n\t\t\tvalue:\n\t\t\t\ttypeof val === \"string\"\n\t\t\t\t\t? { stringValue: val }\n\t\t\t\t\t: typeof val === \"number\"\n\t\t\t\t\t\t? { intValue: `${val}` }\n\t\t\t\t\t\t: { boolValue: val },\n\t\t}));\n\n\t\tconst statusCode =\n\t\t\tspan.status === \"ok\" ? 1 : span.status === \"error\" ? 2 : 0;\n\n\t\treturn {\n\t\t\ttraceId: span.traceId.replace(/-/g, \"\").padEnd(32, \"0\").slice(0, 32),\n\t\t\tspanId: span.spanId.replace(/-/g, \"\").padEnd(16, \"0\").slice(0, 16),\n\t\t\tparentSpanId: span.parentSpanId\n\t\t\t\t? span.parentSpanId.replace(/-/g, \"\").padEnd(16, \"0\").slice(0, 16)\n\t\t\t\t: undefined,\n\t\t\tname: span.operationName,\n\t\t\tkind: 1, // INTERNAL\n\t\t\tstartTimeUnixNano: toNanos(span.startTime),\n\t\t\tendTimeUnixNano: span.endTime ? toNanos(span.endTime) : toNanos(span.startTime),\n\t\t\tattributes,\n\t\t\tevents,\n\t\t\tstatus: { code: statusCode },\n\t\t};\n\t});\n\n\treturn {\n\t\tresourceSpans: [\n\t\t\t{\n\t\t\t\tresource,\n\t\t\t\tscopeSpans: [\n\t\t\t\t\t{\n\t\t\t\t\t\tscope: { name: \"directive\", version: scopeVersion },\n\t\t\t\t\t\tspans,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t],\n\t};\n}\n\n// ============================================================================\n// Factory\n// ============================================================================\n\n/**\n * Create an OTLP exporter for sending metrics and traces to OpenTelemetry-compatible backends.\n *\n * Supports:\n * - Grafana (via OTLP endpoint)\n * - Datadog (via OTLP ingest)\n * - Jaeger (via OTLP collector)\n * - Any OpenTelemetry Collector\n *\n * @example\n * ```typescript\n * const exporter = createOTLPExporter({\n * endpoint: 'http://localhost:4318',\n * serviceName: 'my-agent-service',\n * });\n *\n * // Wire into observability\n * const obs = createObservability({\n * metrics: { exporter: exporter.exportMetrics, exportInterval: 10000 },\n * tracing: { exporter: exporter.exportTraces },\n * });\n * ```\n */\nexport function createOTLPExporter(config: OTLPExporterConfig): OTLPExporter {\n\tconst {\n\t\tendpoint,\n\t\theaders = {},\n\t\tscopeVersion = \"0.1.0\",\n\t\ttimeoutMs = 10000,\n\t\tfetch: fetchFn = globalThis.fetch,\n\t\tonError,\n\t} = config;\n\n\t// Validate endpoint URL\n\ttry {\n\t\tconst url = new URL(endpoint);\n\t\tif (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n\t\t\tthrow new Error(\"Only http: and https: protocols are supported\");\n\t\t}\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`[Directive OTLP] Invalid endpoint URL \"${endpoint}\": ${error instanceof Error ? error.message : String(error)}`\n\t\t);\n\t}\n\n\t// Warn if endpoint already contains a path like /v1/metrics or /v1/traces\n\tif (/\\/v1\\/(metrics|traces)/.test(endpoint)) {\n\t\tconsole.warn(\n\t\t\t`[Directive OTLP] Endpoint \"${endpoint}\" already contains a /v1/metrics or /v1/traces path. ` +\n\t\t\t`The exporter will append /v1/metrics or /v1/traces automatically. ` +\n\t\t\t`Use the base URL (e.g., \"http://localhost:4318\") instead.`\n\t\t);\n\t}\n\n\t// Validate timeoutMs\n\tif (timeoutMs <= 0 || !Number.isFinite(timeoutMs)) {\n\t\tthrow new Error(`[Directive OTLP] timeoutMs must be > 0, got ${timeoutMs}`);\n\t}\n\n\tconst resource = buildResource(config);\n\n\tasync function send(path: string, body: Record<string, unknown>, type: \"metrics\" | \"traces\"): Promise<void> {\n\t\tconst url = `${endpoint.replace(/\\/$/, \"\")}${path}`;\n\t\tconst controller = new AbortController();\n\t\tconst timer = setTimeout(() => controller.abort(), timeoutMs);\n\n\t\ttry {\n\t\t\tconst response = await fetchFn(url, {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\t...headers,\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t\tsignal: controller.signal,\n\t\t\t});\n\n\t\t\tif (!response.ok) {\n\t\t\t\tthrow new Error(`OTLP export failed: ${response.status} ${response.statusText}`);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst err = error instanceof Error ? error : new Error(String(error));\n\t\t\tif (onError) {\n\t\t\t\tonError(err, type);\n\t\t\t} else {\n\t\t\t\tconsole.error(`[Directive OTLP] Export ${type} error:`, err.message);\n\t\t\t}\n\t\t} finally {\n\t\t\tclearTimeout(timer);\n\t\t}\n\t}\n\n\treturn {\n\t\tasync exportMetrics(metrics: AggregatedMetric[]): Promise<void> {\n\t\t\tif (metrics.length === 0) return;\n\t\t\tconst body = convertMetrics(metrics, resource, scopeVersion);\n\t\t\tawait send(\"/v1/metrics\", body, \"metrics\");\n\t\t},\n\n\t\tasync exportTraces(traces: TraceSpan[]): Promise<void> {\n\t\t\tif (traces.length === 0) return;\n\t\t\tconst body = convertTraces(traces, resource, scopeVersion);\n\t\t\tawait send(\"/v1/traces\", body, \"traces\");\n\t\t},\n\t};\n}\n","/**\n * Circuit Breaker for AI Agent Operations\n *\n * Implements the circuit breaker pattern to prevent cascading failures when\n * downstream services (MCP servers, LLM APIs) are degraded. Integrates with\n * the observability plugin to wire error rates into constraint decisions.\n *\n * States:\n * - CLOSED: Normal operation, requests pass through\n * - OPEN: Failures exceeded threshold, requests are rejected immediately\n * - HALF_OPEN: After recovery timeout, a limited number of requests are allowed through\n *\n * @example\n * ```typescript\n * import { createCircuitBreaker } from '@directive-run/ai';\n *\n * const breaker = createCircuitBreaker({\n * failureThreshold: 5,\n * recoveryTimeMs: 30000,\n * halfOpenMaxRequests: 3,\n * });\n *\n * // Use with MCP or any async operation\n * const result = await breaker.execute(async () => {\n * return await callExternalAPI();\n * });\n *\n * // Wire into Directive constraints\n * constraints: {\n * apiDown: {\n * when: () => breaker.getState() === 'OPEN',\n * require: { type: 'FALLBACK_RESPONSE' },\n * },\n * }\n * ```\n */\n\nimport type { ObservabilityInstance } from \"./observability.js\";\n\n// ============================================================================\n// Types\n// ============================================================================\n\n/** Circuit breaker states */\nexport type CircuitState = \"CLOSED\" | \"OPEN\" | \"HALF_OPEN\";\n\n/** Circuit breaker configuration */\nexport interface CircuitBreakerConfig {\n\t/** Number of failures before opening the circuit (default: 5) */\n\tfailureThreshold?: number;\n\t/** Time in ms before transitioning from OPEN to HALF_OPEN (default: 30000) */\n\trecoveryTimeMs?: number;\n\t/** Number of requests allowed in HALF_OPEN state (default: 3) */\n\thalfOpenMaxRequests?: number;\n\t/** Time window in ms for counting failures (default: 60000). Failures outside this window are forgotten. */\n\tfailureWindowMs?: number;\n\t/** Optional observability instance for automatic metric tracking */\n\tobservability?: ObservabilityInstance;\n\t/** Metric name prefix for observability (default: \"circuit_breaker\") */\n\tmetricPrefix?: string;\n\t/** Name for this circuit breaker (used in metrics and errors) */\n\tname?: string;\n\t/** Custom error classifier. Return true if the error should count as a failure. Default: all errors count. */\n\tisFailure?: (error: Error) => boolean;\n\t/** Callback when state changes */\n\tonStateChange?: (from: CircuitState, to: CircuitState) => void;\n}\n\n/** Circuit breaker statistics */\nexport interface CircuitBreakerStats {\n\tstate: CircuitState;\n\ttotalRequests: number;\n\ttotalFailures: number;\n\ttotalSuccesses: number;\n\ttotalRejected: number;\n\trecentFailures: number;\n\tlastFailureTime: number | null;\n\tlastSuccessTime: number | null;\n\tlastStateChange: number;\n}\n\n/** Circuit breaker instance */\nexport interface CircuitBreaker {\n\t/** Execute an operation through the circuit breaker */\n\texecute<T>(fn: () => Promise<T>): Promise<T>;\n\t/** Get the current state */\n\tgetState(): CircuitState;\n\t/** Get statistics */\n\tgetStats(): CircuitBreakerStats;\n\t/** Force the circuit to a specific state (useful for testing) */\n\tforceState(state: CircuitState): void;\n\t/** Reset the circuit breaker to CLOSED with cleared stats */\n\treset(): void;\n\t/** Check if a request would be allowed (without executing) */\n\tisAllowed(): boolean;\n}\n\n// ============================================================================\n// Errors\n// ============================================================================\n\n/** Error thrown when a request is rejected because the circuit is open */\nexport class CircuitBreakerOpenError extends Error {\n\treadonly code = \"CIRCUIT_OPEN\" as const;\n\treadonly retryAfterMs: number;\n\treadonly state: \"OPEN\" | \"HALF_OPEN\";\n\n\tconstructor(name: string, retryAfterMs: number, state: \"OPEN\" | \"HALF_OPEN\" = \"OPEN\", detail?: string) {\n\t\tconst msg = detail\n\t\t\t? `[Directive CircuitBreaker] Circuit \"${name}\" is ${state}. ${detail}`\n\t\t\t: `[Directive CircuitBreaker] Circuit \"${name}\" is ${state}. Request rejected. Try again in ${Math.ceil(retryAfterMs / 1000)}s.`;\n\t\tsuper(msg);\n\t\tthis.name = \"CircuitBreakerOpenError\";\n\t\tthis.retryAfterMs = retryAfterMs;\n\t\tthis.state = state;\n\t}\n}\n\n// ============================================================================\n// Factory\n// ============================================================================\n\n/**\n * Create a circuit breaker for protecting against cascading failures.\n *\n * @example\n * ```typescript\n * const breaker = createCircuitBreaker({\n * name: 'openai-api',\n * failureThreshold: 5,\n * recoveryTimeMs: 30000,\n * observability: obs, // Optional: auto-track metrics\n * });\n *\n * try {\n * const result = await breaker.execute(async () => {\n * return await openai.chat.completions.create({ ... });\n * });\n * } catch (error) {\n * if (error.message.includes('Circuit breaker')) {\n * // Circuit is open, use fallback\n * }\n * }\n * ```\n *\n * @throws {Error} If failureThreshold is less than 1 or not a finite number\n * @throws {Error} If recoveryTimeMs is not positive or not a finite number\n * @throws {Error} If halfOpenMaxRequests is less than 1 or not a finite number\n * @throws {Error} If failureWindowMs is not positive or not a finite number\n */\nexport function createCircuitBreaker(config: CircuitBreakerConfig = {}): CircuitBreaker {\n\tconst {\n\t\tfailureThreshold = 5,\n\t\trecoveryTimeMs = 30000,\n\t\thalfOpenMaxRequests = 3,\n\t\tfailureWindowMs = 60000,\n\t\tobservability,\n\t\tmetricPrefix = \"circuit_breaker\",\n\t\tname = \"default\",\n\t\tisFailure = () => true,\n\t\tonStateChange,\n\t} = config;\n\n\t// Validate config\n\tif (failureThreshold < 1 || !Number.isFinite(failureThreshold)) {\n\t\tthrow new Error(`[Directive CircuitBreaker] failureThreshold must be >= 1, got ${failureThreshold}`);\n\t}\n\tif (recoveryTimeMs <= 0 || !Number.isFinite(recoveryTimeMs)) {\n\t\tthrow new Error(`[Directive CircuitBreaker] recoveryTimeMs must be > 0, got ${recoveryTimeMs}`);\n\t}\n\tif (halfOpenMaxRequests < 1 || !Number.isFinite(halfOpenMaxRequests)) {\n\t\tthrow new Error(`[Directive CircuitBreaker] halfOpenMaxRequests must be >= 1, got ${halfOpenMaxRequests}`);\n\t}\n\tif (failureWindowMs <= 0 || !Number.isFinite(failureWindowMs)) {\n\t\tthrow new Error(`[Directive CircuitBreaker] failureWindowMs must be > 0, got ${failureWindowMs}`);\n\t}\n\n\tlet state: CircuitState = \"CLOSED\";\n\tlet failureTimestamps: number[] = [];\n\tlet halfOpenRequests = 0;\n\tlet halfOpenSuccesses = 0;\n\tlet lastStateChange = Date.now();\n\tlet openedAt = 0;\n\n\t// Stats\n\tlet totalRequests = 0;\n\tlet totalFailures = 0;\n\tlet totalSuccesses = 0;\n\tlet totalRejected = 0;\n\tlet lastFailureTime: number | null = null;\n\tlet lastSuccessTime: number | null = null;\n\n\tfunction transition(newState: CircuitState): void {\n\t\tif (state === newState) return;\n\t\tconst oldState = state;\n\t\tstate = newState;\n\t\tlastStateChange = Date.now();\n\n\t\tif (newState === \"OPEN\") {\n\t\t\topenedAt = Date.now();\n\t\t}\n\t\tif (newState === \"HALF_OPEN\") {\n\t\t\thalfOpenRequests = 0;\n\t\t\thalfOpenSuccesses = 0;\n\t\t}\n\n\t\tonStateChange?.(oldState, newState);\n\n\t\tif (observability) {\n\t\t\tobservability.incrementCounter(`${metricPrefix}.state_change`, {\n\t\t\t\tname,\n\t\t\t\tfrom: oldState,\n\t\t\t\tto: newState,\n\t\t\t});\n\t\t}\n\t}\n\n\tfunction getRecentFailures(): number {\n\t\tconst cutoff = Date.now() - failureWindowMs;\n\t\tfailureTimestamps = failureTimestamps.filter((t) => t > cutoff);\n\t\treturn failureTimestamps.length;\n\t}\n\n\tfunction recordSuccess(): void {\n\t\ttotalSuccesses++;\n\t\tlastSuccessTime = Date.now();\n\n\t\tif (observability) {\n\t\t\tobservability.incrementCounter(`${metricPrefix}.success`, { name });\n\t\t}\n\n\t\tif (state === \"HALF_OPEN\") {\n\t\t\thalfOpenSuccesses++;\n\t\t\tif (halfOpenSuccesses >= halfOpenMaxRequests) {\n\t\t\t\ttransition(\"CLOSED\");\n\t\t\t\tfailureTimestamps = [];\n\t\t\t}\n\t\t}\n\t}\n\n\tfunction recordFailure(error: Error): void {\n\t\tif (!isFailure(error)) {\n\t\t\trecordSuccess();\n\t\t\treturn;\n\t\t}\n\n\t\ttotalFailures++;\n\t\tlastFailureTime = Date.now();\n\t\tfailureTimestamps.push(Date.now());\n\n\t\t// Cap array to prevent unbounded growth (keep 2x threshold as headroom)\n\t\tconst maxTimestamps = failureThreshold * 2;\n\t\tif (failureTimestamps.length > maxTimestamps) {\n\t\t\tfailureTimestamps = failureTimestamps.slice(-maxTimestamps);\n\t\t}\n\n\t\tif (observability) {\n\t\t\tobservability.incrementCounter(`${metricPrefix}.failure`, { name });\n\t\t}\n\n\t\tif (state === \"HALF_OPEN\") {\n\t\t\ttransition(\"OPEN\");\n\t\t\treturn;\n\t\t}\n\n\t\tif (state === \"CLOSED\" && getRecentFailures() >= failureThreshold) {\n\t\t\ttransition(\"OPEN\");\n\t\t}\n\t}\n\n\treturn {\n\t\tasync execute<T>(fn: () => Promise<T>): Promise<T> {\n\t\t\ttotalRequests++;\n\n\t\t\tif (observability) {\n\t\t\t\tobservability.incrementCounter(`${metricPrefix}.requests`, { name });\n\t\t\t}\n\n\t\t\t// Check if request should be allowed\n\t\t\tif (state === \"OPEN\") {\n\t\t\t\t// Check if recovery time has elapsed\n\t\t\t\tif (Date.now() - openedAt >= recoveryTimeMs) {\n\t\t\t\t\ttransition(\"HALF_OPEN\");\n\t\t\t\t} else {\n\t\t\t\t\ttotalRejected++;\n\t\t\t\t\tif (observability) {\n\t\t\t\t\t\tobservability.incrementCounter(`${metricPrefix}.rejected`, { name });\n\t\t\t\t\t}\n\t\t\t\t\tthrow new CircuitBreakerOpenError(name, recoveryTimeMs - (Date.now() - openedAt));\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (state === \"HALF_OPEN\") {\n\t\t\t\tif (halfOpenRequests >= halfOpenMaxRequests) {\n\t\t\t\t\ttotalRejected++;\n\t\t\t\t\tthrow new CircuitBreakerOpenError(name, recoveryTimeMs, \"HALF_OPEN\", `Max trial requests (${halfOpenMaxRequests}) reached.`);\n\t\t\t\t}\n\t\t\t\thalfOpenRequests++;\n\t\t\t}\n\n\t\t\t// Execute the operation\n\t\t\tconst start = Date.now();\n\t\t\ttry {\n\t\t\t\tconst result = await fn();\n\t\t\t\trecordSuccess();\n\n\t\t\t\tif (observability) {\n\t\t\t\t\tobservability.observeHistogram(`${metricPrefix}.latency`, Date.now() - start, { name });\n\t\t\t\t}\n\n\t\t\t\treturn result;\n\t\t\t} catch (error) {\n\t\t\t\tconst err = error instanceof Error ? error : new Error(String(error));\n\t\t\t\trecordFailure(err);\n\n\t\t\t\tif (observability) {\n\t\t\t\t\tobservability.observeHistogram(`${metricPrefix}.latency`, Date.now() - start, { name });\n\t\t\t\t}\n\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\n\t\tgetState(): CircuitState {\n\t\t\t// Auto-transition from OPEN to HALF_OPEN when recovery time has passed\n\t\t\tif (state === \"OPEN\" && Date.now() - openedAt >= recoveryTimeMs) {\n\t\t\t\ttransition(\"HALF_OPEN\");\n\t\t\t}\n\t\t\treturn state;\n\t\t},\n\n\t\tgetStats(): CircuitBreakerStats {\n\t\t\t// Ensure state freshness (auto-transition OPEN → HALF_OPEN)\n\t\t\tconst currentState = this.getState();\n\t\t\treturn {\n\t\t\t\tstate: currentState,\n\t\t\t\ttotalRequests,\n\t\t\t\ttotalFailures,\n\t\t\t\ttotalSuccesses,\n\t\t\t\ttotalRejected,\n\t\t\t\trecentFailures: getRecentFailures(),\n\t\t\t\tlastFailureTime,\n\t\t\t\tlastSuccessTime,\n\t\t\t\tlastStateChange,\n\t\t\t};\n\t\t},\n\n\t\tforceState(newState: CircuitState): void {\n\t\t\ttransition(newState);\n\t\t},\n\n\t\treset(): void {\n\t\t\tconst oldState = state;\n\t\t\tstate = \"CLOSED\";\n\t\t\tfailureTimestamps = [];\n\t\t\thalfOpenRequests = 0;\n\t\t\thalfOpenSuccesses = 0;\n\t\t\tlastStateChange = Date.now();\n\t\t\topenedAt = 0;\n\t\t\ttotalRequests = 0;\n\t\t\ttotalFailures = 0;\n\t\t\ttotalSuccesses = 0;\n\t\t\ttotalRejected = 0;\n\t\t\tlastFailureTime = null;\n\t\t\tlastSuccessTime = null;\n\t\t\tif (oldState !== \"CLOSED\") {\n\t\t\t\tonStateChange?.(oldState, \"CLOSED\");\n\t\t\t}\n\t\t},\n\n\t\tisAllowed(): boolean {\n\t\t\tif (state === \"CLOSED\") return true;\n\t\t\tif (state === \"OPEN\") {\n\t\t\t\treturn Date.now() - openedAt >= recoveryTimeMs;\n\t\t\t}\n\t\t\t// HALF_OPEN\n\t\t\treturn halfOpenRequests < halfOpenMaxRequests;\n\t\t},\n\t};\n}\n"]}