obsidian-agent-fleet 0.13.0 → 0.13.6

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.
package/plugin/main.js CHANGED
@@ -1,10 +1,10 @@
1
- "use strict";var $o=Object.create;var Ns=Object.defineProperty;var jo=Object.getOwnPropertyDescriptor;var Wo=Object.getOwnPropertyNames;var Ho=Object.getPrototypeOf,qo=Object.prototype.hasOwnProperty;var qe=(i,t)=>()=>(t||i((t={exports:{}}).exports,t),t.exports),zo=(i,t)=>{for(var e in t)Ns(i,e,{get:t[e],enumerable:!0})},Ga=(i,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Wo(t))!qo.call(i,n)&&n!==e&&Ns(i,n,{get:()=>t[n],enumerable:!(s=jo(t,n))||s.enumerable});return i};var ze=(i,t,e)=>(e=i!=null?$o(Ho(i)):{},Ga(t||!i||!i.__esModule?Ns(e,"default",{value:i,enumerable:!0}):e,i)),Go=i=>Ga(Ns({},"__esModule",{value:!0}),i);var pt=qe((Iu,yr)=>{"use strict";var fr=["nodebuffer","arraybuffer","fragments"],gr=typeof Blob<"u";gr&&fr.push("blob");yr.exports={BINARY_TYPES:fr,CLOSE_TIMEOUT:3e4,EMPTY_BUFFER:Buffer.alloc(0),GUID:"258EAFA5-E914-47DA-95CA-C5AB0DC85B11",hasBlob:gr,kForOnEventAttribute:Symbol("kIsForOnEventAttribute"),kListener:Symbol("kListener"),kStatusCode:Symbol("status-code"),kWebSocket:Symbol("websocket"),NOOP:()=>{}}});var xs=qe((Mu,bn)=>{"use strict";var{EMPTY_BUFFER:nc}=pt(),ya=Buffer[Symbol.species];function ac(i,t){if(i.length===0)return nc;if(i.length===1)return i[0];let e=Buffer.allocUnsafe(t),s=0;for(let n=0;n<i.length;n++){let a=i[n];e.set(a,s),s+=a.length}return s<t?new ya(e.buffer,e.byteOffset,s):e}function vr(i,t,e,s,n){for(let a=0;a<n;a++)e[s+a]=i[a]^t[a&3]}function br(i,t){for(let e=0;e<i.length;e++)i[e]^=t[e&3]}function ic(i){return i.length===i.buffer.byteLength?i.buffer:i.buffer.slice(i.byteOffset,i.byteOffset+i.length)}function va(i){if(va.readOnly=!0,Buffer.isBuffer(i))return i;let t;return i instanceof ArrayBuffer?t=new ya(i):ArrayBuffer.isView(i)?t=new ya(i.buffer,i.byteOffset,i.byteLength):(t=Buffer.from(i),va.readOnly=!1),t}bn.exports={concat:ac,mask:vr,toArrayBuffer:ic,toBuffer:va,unmask:br};if(!process.env.WS_NO_BUFFER_UTIL)try{let i=require("bufferutil");bn.exports.mask=function(t,e,s,n,a){a<48?vr(t,e,s,n,a):i.mask(t,e,s,n,a)},bn.exports.unmask=function(t,e){t.length<32?br(t,e):i.unmask(t,e)}}catch{}});var xr=qe((Lu,kr)=>{"use strict";var wr=Symbol("kDone"),ba=Symbol("kRun"),wa=class{constructor(t){this[wr]=()=>{this.pending--,this[ba]()},this.concurrency=t||1/0,this.jobs=[],this.pending=0}add(t){this.jobs.push(t),this[ba]()}[ba](){if(this.pending!==this.concurrency&&this.jobs.length){let t=this.jobs.shift();this.pending++,t(this[wr])}}};kr.exports=wa});var Yt=qe((Fu,_r)=>{"use strict";var Ss=require("zlib"),Sr=xs(),rc=xr(),{kStatusCode:Cr}=pt(),oc=Buffer[Symbol.species],lc=Buffer.from([0,0,255,255]),kn=Symbol("permessage-deflate"),mt=Symbol("total-length"),Gt=Symbol("callback"),kt=Symbol("buffers"),Vt=Symbol("error"),wn,ka=class{constructor(t){if(this._options=t||{},this._threshold=this._options.threshold!==void 0?this._options.threshold:1024,this._maxPayload=this._options.maxPayload|0,this._isServer=!!this._options.isServer,this._deflate=null,this._inflate=null,this.params=null,!wn){let e=this._options.concurrencyLimit!==void 0?this._options.concurrencyLimit:10;wn=new rc(e)}}static get extensionName(){return"permessage-deflate"}offer(){let t={};return this._options.serverNoContextTakeover&&(t.server_no_context_takeover=!0),this._options.clientNoContextTakeover&&(t.client_no_context_takeover=!0),this._options.serverMaxWindowBits&&(t.server_max_window_bits=this._options.serverMaxWindowBits),this._options.clientMaxWindowBits?t.client_max_window_bits=this._options.clientMaxWindowBits:this._options.clientMaxWindowBits==null&&(t.client_max_window_bits=!0),t}accept(t){return t=this.normalizeParams(t),this.params=this._isServer?this.acceptAsServer(t):this.acceptAsClient(t),this.params}cleanup(){if(this._inflate&&(this._inflate.close(),this._inflate=null),this._deflate){let t=this._deflate[Gt];this._deflate.close(),this._deflate=null,t&&t(new Error("The deflate stream was closed while data was being processed"))}}acceptAsServer(t){let e=this._options,s=t.find(n=>!(e.serverNoContextTakeover===!1&&n.server_no_context_takeover||n.server_max_window_bits&&(e.serverMaxWindowBits===!1||typeof e.serverMaxWindowBits=="number"&&e.serverMaxWindowBits>n.server_max_window_bits)||typeof e.clientMaxWindowBits=="number"&&!n.client_max_window_bits));if(!s)throw new Error("None of the extension offers can be accepted");return e.serverNoContextTakeover&&(s.server_no_context_takeover=!0),e.clientNoContextTakeover&&(s.client_no_context_takeover=!0),typeof e.serverMaxWindowBits=="number"&&(s.server_max_window_bits=e.serverMaxWindowBits),typeof e.clientMaxWindowBits=="number"?s.client_max_window_bits=e.clientMaxWindowBits:(s.client_max_window_bits===!0||e.clientMaxWindowBits===!1)&&delete s.client_max_window_bits,s}acceptAsClient(t){let e=t[0];if(this._options.clientNoContextTakeover===!1&&e.client_no_context_takeover)throw new Error('Unexpected parameter "client_no_context_takeover"');if(!e.client_max_window_bits)typeof this._options.clientMaxWindowBits=="number"&&(e.client_max_window_bits=this._options.clientMaxWindowBits);else if(this._options.clientMaxWindowBits===!1||typeof this._options.clientMaxWindowBits=="number"&&e.client_max_window_bits>this._options.clientMaxWindowBits)throw new Error('Unexpected or invalid parameter "client_max_window_bits"');return e}normalizeParams(t){return t.forEach(e=>{Object.keys(e).forEach(s=>{let n=e[s];if(n.length>1)throw new Error(`Parameter "${s}" must have only a single value`);if(n=n[0],s==="client_max_window_bits"){if(n!==!0){let a=+n;if(!Number.isInteger(a)||a<8||a>15)throw new TypeError(`Invalid value for parameter "${s}": ${n}`);n=a}else if(!this._isServer)throw new TypeError(`Invalid value for parameter "${s}": ${n}`)}else if(s==="server_max_window_bits"){let a=+n;if(!Number.isInteger(a)||a<8||a>15)throw new TypeError(`Invalid value for parameter "${s}": ${n}`);n=a}else if(s==="client_no_context_takeover"||s==="server_no_context_takeover"){if(n!==!0)throw new TypeError(`Invalid value for parameter "${s}": ${n}`)}else throw new Error(`Unknown parameter "${s}"`);e[s]=n})}),t}decompress(t,e,s){wn.add(n=>{this._decompress(t,e,(a,r)=>{n(),s(a,r)})})}compress(t,e,s){wn.add(n=>{this._compress(t,e,(a,r)=>{n(),s(a,r)})})}_decompress(t,e,s){let n=this._isServer?"client":"server";if(!this._inflate){let a=`${n}_max_window_bits`,r=typeof this.params[a]!="number"?Ss.Z_DEFAULT_WINDOWBITS:this.params[a];this._inflate=Ss.createInflateRaw({...this._options.zlibInflateOptions,windowBits:r}),this._inflate[kn]=this,this._inflate[mt]=0,this._inflate[kt]=[],this._inflate.on("error",dc),this._inflate.on("data",Tr)}this._inflate[Gt]=s,this._inflate.write(t),e&&this._inflate.write(lc),this._inflate.flush(()=>{let a=this._inflate[Vt];if(a){this._inflate.close(),this._inflate=null,s(a);return}let r=Sr.concat(this._inflate[kt],this._inflate[mt]);this._inflate._readableState.endEmitted?(this._inflate.close(),this._inflate=null):(this._inflate[mt]=0,this._inflate[kt]=[],e&&this.params[`${n}_no_context_takeover`]&&this._inflate.reset()),s(null,r)})}_compress(t,e,s){let n=this._isServer?"server":"client";if(!this._deflate){let a=`${n}_max_window_bits`,r=typeof this.params[a]!="number"?Ss.Z_DEFAULT_WINDOWBITS:this.params[a];this._deflate=Ss.createDeflateRaw({...this._options.zlibDeflateOptions,windowBits:r}),this._deflate[mt]=0,this._deflate[kt]=[],this._deflate.on("data",cc)}this._deflate[Gt]=s,this._deflate.write(t),this._deflate.flush(Ss.Z_SYNC_FLUSH,()=>{if(!this._deflate)return;let a=Sr.concat(this._deflate[kt],this._deflate[mt]);e&&(a=new oc(a.buffer,a.byteOffset,a.length-4)),this._deflate[Gt]=null,this._deflate[mt]=0,this._deflate[kt]=[],e&&this.params[`${n}_no_context_takeover`]&&this._deflate.reset(),s(null,a)})}};_r.exports=ka;function cc(i){this[kt].push(i),this[mt]+=i.length}function Tr(i){if(this[mt]+=i.length,this[kn]._maxPayload<1||this[mt]<=this[kn]._maxPayload){this[kt].push(i);return}this[Vt]=new RangeError("Max payload size exceeded"),this[Vt].code="WS_ERR_UNSUPPORTED_MESSAGE_LENGTH",this[Vt][Cr]=1009,this.removeListener("data",Tr),this.reset()}function dc(i){if(this[kn]._inflate=null,this[Vt]){this[Gt](this[Vt]);return}i[Cr]=1007,this[Gt](i)}});var Kt=qe((Ou,xn)=>{"use strict";var{isUtf8:Ar}=require("buffer"),{hasBlob:hc}=pt(),uc=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0];function pc(i){return i>=1e3&&i<=1014&&i!==1004&&i!==1005&&i!==1006||i>=3e3&&i<=4999}function xa(i){let t=i.length,e=0;for(;e<t;)if((i[e]&128)===0)e++;else if((i[e]&224)===192){if(e+1===t||(i[e+1]&192)!==128||(i[e]&254)===192)return!1;e+=2}else if((i[e]&240)===224){if(e+2>=t||(i[e+1]&192)!==128||(i[e+2]&192)!==128||i[e]===224&&(i[e+1]&224)===128||i[e]===237&&(i[e+1]&224)===160)return!1;e+=3}else if((i[e]&248)===240){if(e+3>=t||(i[e+1]&192)!==128||(i[e+2]&192)!==128||(i[e+3]&192)!==128||i[e]===240&&(i[e+1]&240)===128||i[e]===244&&i[e+1]>143||i[e]>244)return!1;e+=4}else return!1;return!0}function mc(i){return hc&&typeof i=="object"&&typeof i.arrayBuffer=="function"&&typeof i.type=="string"&&typeof i.stream=="function"&&(i[Symbol.toStringTag]==="Blob"||i[Symbol.toStringTag]==="File")}xn.exports={isBlob:mc,isValidStatusCode:pc,isValidUTF8:xa,tokenChars:uc};if(Ar)xn.exports.isValidUTF8=function(i){return i.length<24?xa(i):Ar(i)};else if(!process.env.WS_NO_UTF_8_VALIDATE)try{let i=require("utf-8-validate");xn.exports.isValidUTF8=function(t){return t.length<32?xa(t):i(t)}}catch{}});var Aa=qe((Nu,Lr)=>{"use strict";var{Writable:fc}=require("stream"),Er=Yt(),{BINARY_TYPES:gc,EMPTY_BUFFER:Pr,kStatusCode:yc,kWebSocket:vc}=pt(),{concat:Sa,toArrayBuffer:bc,unmask:wc}=xs(),{isValidStatusCode:kc,isValidUTF8:Rr}=Kt(),Sn=Buffer[Symbol.species],Ze=0,Dr=1,Ir=2,Mr=3,Ca=4,Ta=5,Cn=6,_a=class extends fc{constructor(t={}){super(),this._allowSynchronousEvents=t.allowSynchronousEvents!==void 0?t.allowSynchronousEvents:!0,this._binaryType=t.binaryType||gc[0],this._extensions=t.extensions||{},this._isServer=!!t.isServer,this._maxPayload=t.maxPayload|0,this._skipUTF8Validation=!!t.skipUTF8Validation,this[vc]=void 0,this._bufferedBytes=0,this._buffers=[],this._compressed=!1,this._payloadLength=0,this._mask=void 0,this._fragmented=0,this._masked=!1,this._fin=!1,this._opcode=0,this._totalPayloadLength=0,this._messageLength=0,this._fragments=[],this._errored=!1,this._loop=!1,this._state=Ze}_write(t,e,s){if(this._opcode===8&&this._state==Ze)return s();this._bufferedBytes+=t.length,this._buffers.push(t),this.startLoop(s)}consume(t){if(this._bufferedBytes-=t,t===this._buffers[0].length)return this._buffers.shift();if(t<this._buffers[0].length){let s=this._buffers[0];return this._buffers[0]=new Sn(s.buffer,s.byteOffset+t,s.length-t),new Sn(s.buffer,s.byteOffset,t)}let e=Buffer.allocUnsafe(t);do{let s=this._buffers[0],n=e.length-t;t>=s.length?e.set(this._buffers.shift(),n):(e.set(new Uint8Array(s.buffer,s.byteOffset,t),n),this._buffers[0]=new Sn(s.buffer,s.byteOffset+t,s.length-t)),t-=s.length}while(t>0);return e}startLoop(t){this._loop=!0;do switch(this._state){case Ze:this.getInfo(t);break;case Dr:this.getPayloadLength16(t);break;case Ir:this.getPayloadLength64(t);break;case Mr:this.getMask();break;case Ca:this.getData(t);break;case Ta:case Cn:this._loop=!1;return}while(this._loop);this._errored||t()}getInfo(t){if(this._bufferedBytes<2){this._loop=!1;return}let e=this.consume(2);if((e[0]&48)!==0){let n=this.createError(RangeError,"RSV2 and RSV3 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_2_3");t(n);return}let s=(e[0]&64)===64;if(s&&!this._extensions[Er.extensionName]){let n=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");t(n);return}if(this._fin=(e[0]&128)===128,this._opcode=e[0]&15,this._payloadLength=e[1]&127,this._opcode===0){if(s){let n=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");t(n);return}if(!this._fragmented){let n=this.createError(RangeError,"invalid opcode 0",!0,1002,"WS_ERR_INVALID_OPCODE");t(n);return}this._opcode=this._fragmented}else if(this._opcode===1||this._opcode===2){if(this._fragmented){let n=this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,"WS_ERR_INVALID_OPCODE");t(n);return}this._compressed=s}else if(this._opcode>7&&this._opcode<11){if(!this._fin){let n=this.createError(RangeError,"FIN must be set",!0,1002,"WS_ERR_EXPECTED_FIN");t(n);return}if(s){let n=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");t(n);return}if(this._payloadLength>125||this._opcode===8&&this._payloadLength===1){let n=this.createError(RangeError,`invalid payload length ${this._payloadLength}`,!0,1002,"WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH");t(n);return}}else{let n=this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,"WS_ERR_INVALID_OPCODE");t(n);return}if(!this._fin&&!this._fragmented&&(this._fragmented=this._opcode),this._masked=(e[1]&128)===128,this._isServer){if(!this._masked){let n=this.createError(RangeError,"MASK must be set",!0,1002,"WS_ERR_EXPECTED_MASK");t(n);return}}else if(this._masked){let n=this.createError(RangeError,"MASK must be clear",!0,1002,"WS_ERR_UNEXPECTED_MASK");t(n);return}this._payloadLength===126?this._state=Dr:this._payloadLength===127?this._state=Ir:this.haveLength(t)}getPayloadLength16(t){if(this._bufferedBytes<2){this._loop=!1;return}this._payloadLength=this.consume(2).readUInt16BE(0),this.haveLength(t)}getPayloadLength64(t){if(this._bufferedBytes<8){this._loop=!1;return}let e=this.consume(8),s=e.readUInt32BE(0);if(s>Math.pow(2,21)-1){let n=this.createError(RangeError,"Unsupported WebSocket frame: payload length > 2^53 - 1",!1,1009,"WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH");t(n);return}this._payloadLength=s*Math.pow(2,32)+e.readUInt32BE(4),this.haveLength(t)}haveLength(t){if(this._payloadLength&&this._opcode<8&&(this._totalPayloadLength+=this._payloadLength,this._totalPayloadLength>this._maxPayload&&this._maxPayload>0)){let e=this.createError(RangeError,"Max payload size exceeded",!1,1009,"WS_ERR_UNSUPPORTED_MESSAGE_LENGTH");t(e);return}this._masked?this._state=Mr:this._state=Ca}getMask(){if(this._bufferedBytes<4){this._loop=!1;return}this._mask=this.consume(4),this._state=Ca}getData(t){let e=Pr;if(this._payloadLength){if(this._bufferedBytes<this._payloadLength){this._loop=!1;return}e=this.consume(this._payloadLength),this._masked&&(this._mask[0]|this._mask[1]|this._mask[2]|this._mask[3])!==0&&wc(e,this._mask)}if(this._opcode>7){this.controlMessage(e,t);return}if(this._compressed){this._state=Ta,this.decompress(e,t);return}e.length&&(this._messageLength=this._totalPayloadLength,this._fragments.push(e)),this.dataMessage(t)}decompress(t,e){this._extensions[Er.extensionName].decompress(t,this._fin,(n,a)=>{if(n)return e(n);if(a.length){if(this._messageLength+=a.length,this._messageLength>this._maxPayload&&this._maxPayload>0){let r=this.createError(RangeError,"Max payload size exceeded",!1,1009,"WS_ERR_UNSUPPORTED_MESSAGE_LENGTH");e(r);return}this._fragments.push(a)}this.dataMessage(e),this._state===Ze&&this.startLoop(e)})}dataMessage(t){if(!this._fin){this._state=Ze;return}let e=this._messageLength,s=this._fragments;if(this._totalPayloadLength=0,this._messageLength=0,this._fragmented=0,this._fragments=[],this._opcode===2){let n;this._binaryType==="nodebuffer"?n=Sa(s,e):this._binaryType==="arraybuffer"?n=bc(Sa(s,e)):this._binaryType==="blob"?n=new Blob(s):n=s,this._allowSynchronousEvents?(this.emit("message",n,!0),this._state=Ze):(this._state=Cn,setImmediate(()=>{this.emit("message",n,!0),this._state=Ze,this.startLoop(t)}))}else{let n=Sa(s,e);if(!this._skipUTF8Validation&&!Rr(n)){let a=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");t(a);return}this._state===Ta||this._allowSynchronousEvents?(this.emit("message",n,!1),this._state=Ze):(this._state=Cn,setImmediate(()=>{this.emit("message",n,!1),this._state=Ze,this.startLoop(t)}))}}controlMessage(t,e){if(this._opcode===8){if(t.length===0)this._loop=!1,this.emit("conclude",1005,Pr),this.end();else{let s=t.readUInt16BE(0);if(!kc(s)){let a=this.createError(RangeError,`invalid status code ${s}`,!0,1002,"WS_ERR_INVALID_CLOSE_CODE");e(a);return}let n=new Sn(t.buffer,t.byteOffset+2,t.length-2);if(!this._skipUTF8Validation&&!Rr(n)){let a=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");e(a);return}this._loop=!1,this.emit("conclude",s,n),this.end()}this._state=Ze;return}this._allowSynchronousEvents?(this.emit(this._opcode===9?"ping":"pong",t),this._state=Ze):(this._state=Cn,setImmediate(()=>{this.emit(this._opcode===9?"ping":"pong",t),this._state=Ze,this.startLoop(e)}))}createError(t,e,s,n,a){this._loop=!1,this._errored=!0;let r=new t(s?`Invalid WebSocket frame: ${e}`:e);return Error.captureStackTrace(r,this.createError),r.code=a,r[yc]=n,r}};Lr.exports=_a});var Ra=qe((Uu,Nr)=>{"use strict";var{Duplex:Bu}=require("stream"),{randomFillSync:xc}=require("crypto"),Fr=Yt(),{EMPTY_BUFFER:Sc,kWebSocket:Cc,NOOP:Tc}=pt(),{isBlob:Jt,isValidStatusCode:_c}=Kt(),{mask:Or,toBuffer:Rt}=xs(),et=Symbol("kByteLength"),Ac=Buffer.alloc(4),Tn=8*1024,Dt,Xt=Tn,it=0,Ec=1,Pc=2,Ea=class i{constructor(t,e,s){this._extensions=e||{},s&&(this._generateMask=s,this._maskBuffer=Buffer.alloc(4)),this._socket=t,this._firstFragment=!0,this._compress=!1,this._bufferedBytes=0,this._queue=[],this._state=it,this.onerror=Tc,this[Cc]=void 0}static frame(t,e){let s,n=!1,a=2,r=!1;e.mask&&(s=e.maskBuffer||Ac,e.generateMask?e.generateMask(s):(Xt===Tn&&(Dt===void 0&&(Dt=Buffer.alloc(Tn)),xc(Dt,0,Tn),Xt=0),s[0]=Dt[Xt++],s[1]=Dt[Xt++],s[2]=Dt[Xt++],s[3]=Dt[Xt++]),r=(s[0]|s[1]|s[2]|s[3])===0,a=6);let o;typeof t=="string"?(!e.mask||r)&&e[et]!==void 0?o=e[et]:(t=Buffer.from(t),o=t.length):(o=t.length,n=e.mask&&e.readOnly&&!r);let c=o;o>=65536?(a+=8,c=127):o>125&&(a+=2,c=126);let l=Buffer.allocUnsafe(n?o+a:a);return l[0]=e.fin?e.opcode|128:e.opcode,e.rsv1&&(l[0]|=64),l[1]=c,c===126?l.writeUInt16BE(o,2):c===127&&(l[2]=l[3]=0,l.writeUIntBE(o,4,6)),e.mask?(l[1]|=128,l[a-4]=s[0],l[a-3]=s[1],l[a-2]=s[2],l[a-1]=s[3],r?[l,t]:n?(Or(t,s,l,a,o),[l]):(Or(t,s,t,0,o),[l,t])):[l,t]}close(t,e,s,n){let a;if(t===void 0)a=Sc;else{if(typeof t!="number"||!_c(t))throw new TypeError("First argument must be a valid error code number");if(e===void 0||!e.length)a=Buffer.allocUnsafe(2),a.writeUInt16BE(t,0);else{let o=Buffer.byteLength(e);if(o>123)throw new RangeError("The message must not be greater than 123 bytes");a=Buffer.allocUnsafe(2+o),a.writeUInt16BE(t,0),typeof e=="string"?a.write(e,2):a.set(e,2)}}let r={[et]:a.length,fin:!0,generateMask:this._generateMask,mask:s,maskBuffer:this._maskBuffer,opcode:8,readOnly:!1,rsv1:!1};this._state!==it?this.enqueue([this.dispatch,a,!1,r,n]):this.sendFrame(i.frame(a,r),n)}ping(t,e,s){let n,a;if(typeof t=="string"?(n=Buffer.byteLength(t),a=!1):Jt(t)?(n=t.size,a=!1):(t=Rt(t),n=t.length,a=Rt.readOnly),n>125)throw new RangeError("The data size must not be greater than 125 bytes");let r={[et]:n,fin:!0,generateMask:this._generateMask,mask:e,maskBuffer:this._maskBuffer,opcode:9,readOnly:a,rsv1:!1};Jt(t)?this._state!==it?this.enqueue([this.getBlobData,t,!1,r,s]):this.getBlobData(t,!1,r,s):this._state!==it?this.enqueue([this.dispatch,t,!1,r,s]):this.sendFrame(i.frame(t,r),s)}pong(t,e,s){let n,a;if(typeof t=="string"?(n=Buffer.byteLength(t),a=!1):Jt(t)?(n=t.size,a=!1):(t=Rt(t),n=t.length,a=Rt.readOnly),n>125)throw new RangeError("The data size must not be greater than 125 bytes");let r={[et]:n,fin:!0,generateMask:this._generateMask,mask:e,maskBuffer:this._maskBuffer,opcode:10,readOnly:a,rsv1:!1};Jt(t)?this._state!==it?this.enqueue([this.getBlobData,t,!1,r,s]):this.getBlobData(t,!1,r,s):this._state!==it?this.enqueue([this.dispatch,t,!1,r,s]):this.sendFrame(i.frame(t,r),s)}send(t,e,s){let n=this._extensions[Fr.extensionName],a=e.binary?2:1,r=e.compress,o,c;typeof t=="string"?(o=Buffer.byteLength(t),c=!1):Jt(t)?(o=t.size,c=!1):(t=Rt(t),o=t.length,c=Rt.readOnly),this._firstFragment?(this._firstFragment=!1,r&&n&&n.params[n._isServer?"server_no_context_takeover":"client_no_context_takeover"]&&(r=o>=n._threshold),this._compress=r):(r=!1,a=0),e.fin&&(this._firstFragment=!0);let l={[et]:o,fin:e.fin,generateMask:this._generateMask,mask:e.mask,maskBuffer:this._maskBuffer,opcode:a,readOnly:c,rsv1:r};Jt(t)?this._state!==it?this.enqueue([this.getBlobData,t,this._compress,l,s]):this.getBlobData(t,this._compress,l,s):this._state!==it?this.enqueue([this.dispatch,t,this._compress,l,s]):this.dispatch(t,this._compress,l,s)}getBlobData(t,e,s,n){this._bufferedBytes+=s[et],this._state=Pc,t.arrayBuffer().then(a=>{if(this._socket.destroyed){let o=new Error("The socket was closed while the blob was being read");process.nextTick(Pa,this,o,n);return}this._bufferedBytes-=s[et];let r=Rt(a);e?this.dispatch(r,e,s,n):(this._state=it,this.sendFrame(i.frame(r,s),n),this.dequeue())}).catch(a=>{process.nextTick(Rc,this,a,n)})}dispatch(t,e,s,n){if(!e){this.sendFrame(i.frame(t,s),n);return}let a=this._extensions[Fr.extensionName];this._bufferedBytes+=s[et],this._state=Ec,a.compress(t,s.fin,(r,o)=>{if(this._socket.destroyed){let c=new Error("The socket was closed while data was being compressed");Pa(this,c,n);return}this._bufferedBytes-=s[et],this._state=it,s.readOnly=!1,this.sendFrame(i.frame(o,s),n),this.dequeue()})}dequeue(){for(;this._state===it&&this._queue.length;){let t=this._queue.shift();this._bufferedBytes-=t[3][et],Reflect.apply(t[0],this,t.slice(1))}}enqueue(t){this._bufferedBytes+=t[3][et],this._queue.push(t)}sendFrame(t,e){t.length===2?(this._socket.cork(),this._socket.write(t[0]),this._socket.write(t[1],e),this._socket.uncork()):this._socket.write(t[0],e)}};Nr.exports=Ea;function Pa(i,t,e){typeof e=="function"&&e(t);for(let s=0;s<i._queue.length;s++){let n=i._queue[s],a=n[n.length-1];typeof a=="function"&&a(t)}}function Rc(i,t,e){Pa(i,t,e),i.onerror(t)}});var Gr=qe(($u,zr)=>{"use strict";var{kForOnEventAttribute:Cs,kListener:Da}=pt(),Br=Symbol("kCode"),Ur=Symbol("kData"),$r=Symbol("kError"),jr=Symbol("kMessage"),Wr=Symbol("kReason"),Qt=Symbol("kTarget"),Hr=Symbol("kType"),qr=Symbol("kWasClean"),ft=class{constructor(t){this[Qt]=null,this[Hr]=t}get target(){return this[Qt]}get type(){return this[Hr]}};Object.defineProperty(ft.prototype,"target",{enumerable:!0});Object.defineProperty(ft.prototype,"type",{enumerable:!0});var It=class extends ft{constructor(t,e={}){super(t),this[Br]=e.code===void 0?0:e.code,this[Wr]=e.reason===void 0?"":e.reason,this[qr]=e.wasClean===void 0?!1:e.wasClean}get code(){return this[Br]}get reason(){return this[Wr]}get wasClean(){return this[qr]}};Object.defineProperty(It.prototype,"code",{enumerable:!0});Object.defineProperty(It.prototype,"reason",{enumerable:!0});Object.defineProperty(It.prototype,"wasClean",{enumerable:!0});var Zt=class extends ft{constructor(t,e={}){super(t),this[$r]=e.error===void 0?null:e.error,this[jr]=e.message===void 0?"":e.message}get error(){return this[$r]}get message(){return this[jr]}};Object.defineProperty(Zt.prototype,"error",{enumerable:!0});Object.defineProperty(Zt.prototype,"message",{enumerable:!0});var Ts=class extends ft{constructor(t,e={}){super(t),this[Ur]=e.data===void 0?null:e.data}get data(){return this[Ur]}};Object.defineProperty(Ts.prototype,"data",{enumerable:!0});var Dc={addEventListener(i,t,e={}){for(let n of this.listeners(i))if(!e[Cs]&&n[Da]===t&&!n[Cs])return;let s;if(i==="message")s=function(a,r){let o=new Ts("message",{data:r?a:a.toString()});o[Qt]=this,_n(t,this,o)};else if(i==="close")s=function(a,r){let o=new It("close",{code:a,reason:r.toString(),wasClean:this._closeFrameReceived&&this._closeFrameSent});o[Qt]=this,_n(t,this,o)};else if(i==="error")s=function(a){let r=new Zt("error",{error:a,message:a.message});r[Qt]=this,_n(t,this,r)};else if(i==="open")s=function(){let a=new ft("open");a[Qt]=this,_n(t,this,a)};else return;s[Cs]=!!e[Cs],s[Da]=t,e.once?this.once(i,s):this.on(i,s)},removeEventListener(i,t){for(let e of this.listeners(i))if(e[Da]===t&&!e[Cs]){this.removeListener(i,e);break}}};zr.exports={CloseEvent:It,ErrorEvent:Zt,Event:ft,EventTarget:Dc,MessageEvent:Ts};function _n(i,t,e){typeof i=="object"&&i.handleEvent?i.handleEvent.call(i,e):i.call(t,e)}});var An=qe((ju,Vr)=>{"use strict";var{tokenChars:_s}=Kt();function dt(i,t,e){i[t]===void 0?i[t]=[e]:i[t].push(e)}function Ic(i){let t=Object.create(null),e=Object.create(null),s=!1,n=!1,a=!1,r,o,c=-1,l=-1,d=-1,h=0;for(;h<i.length;h++)if(l=i.charCodeAt(h),r===void 0)if(d===-1&&_s[l]===1)c===-1&&(c=h);else if(h!==0&&(l===32||l===9))d===-1&&c!==-1&&(d=h);else if(l===59||l===44){if(c===-1)throw new SyntaxError(`Unexpected character at index ${h}`);d===-1&&(d=h);let p=i.slice(c,d);l===44?(dt(t,p,e),e=Object.create(null)):r=p,c=d=-1}else throw new SyntaxError(`Unexpected character at index ${h}`);else if(o===void 0)if(d===-1&&_s[l]===1)c===-1&&(c=h);else if(l===32||l===9)d===-1&&c!==-1&&(d=h);else if(l===59||l===44){if(c===-1)throw new SyntaxError(`Unexpected character at index ${h}`);d===-1&&(d=h),dt(e,i.slice(c,d),!0),l===44&&(dt(t,r,e),e=Object.create(null),r=void 0),c=d=-1}else if(l===61&&c!==-1&&d===-1)o=i.slice(c,h),c=d=-1;else throw new SyntaxError(`Unexpected character at index ${h}`);else if(n){if(_s[l]!==1)throw new SyntaxError(`Unexpected character at index ${h}`);c===-1?c=h:s||(s=!0),n=!1}else if(a)if(_s[l]===1)c===-1&&(c=h);else if(l===34&&c!==-1)a=!1,d=h;else if(l===92)n=!0;else throw new SyntaxError(`Unexpected character at index ${h}`);else if(l===34&&i.charCodeAt(h-1)===61)a=!0;else if(d===-1&&_s[l]===1)c===-1&&(c=h);else if(c!==-1&&(l===32||l===9))d===-1&&(d=h);else if(l===59||l===44){if(c===-1)throw new SyntaxError(`Unexpected character at index ${h}`);d===-1&&(d=h);let p=i.slice(c,d);s&&(p=p.replace(/\\/g,""),s=!1),dt(e,o,p),l===44&&(dt(t,r,e),e=Object.create(null),r=void 0),o=void 0,c=d=-1}else throw new SyntaxError(`Unexpected character at index ${h}`);if(c===-1||a||l===32||l===9)throw new SyntaxError("Unexpected end of input");d===-1&&(d=h);let u=i.slice(c,d);return r===void 0?dt(t,u,e):(o===void 0?dt(e,u,!0):s?dt(e,o,u.replace(/\\/g,"")):dt(e,o,u),dt(t,r,e)),t}function Mc(i){return Object.keys(i).map(t=>{let e=i[t];return Array.isArray(e)||(e=[e]),e.map(s=>[t].concat(Object.keys(s).map(n=>{let a=s[n];return Array.isArray(a)||(a=[a]),a.map(r=>r===!0?n:`${n}=${r}`).join("; ")})).join("; ")).join(", ")}).join(", ")}Vr.exports={format:Mc,parse:Ic}});var Dn=qe((qu,io)=>{"use strict";var Lc=require("events"),Fc=require("https"),Oc=require("http"),Jr=require("net"),Nc=require("tls"),{randomBytes:Bc,createHash:Uc}=require("crypto"),{Duplex:Wu,Readable:Hu}=require("stream"),{URL:Ia}=require("url"),xt=Yt(),$c=Aa(),jc=Ra(),{isBlob:Wc}=Kt(),{BINARY_TYPES:Yr,CLOSE_TIMEOUT:Hc,EMPTY_BUFFER:En,GUID:qc,kForOnEventAttribute:Ma,kListener:zc,kStatusCode:Gc,kWebSocket:Fe,NOOP:Xr}=pt(),{EventTarget:{addEventListener:Vc,removeEventListener:Yc}}=Gr(),{format:Kc,parse:Jc}=An(),{toBuffer:Xc}=xs(),Qr=Symbol("kAborted"),La=[8,13],gt=["CONNECTING","OPEN","CLOSING","CLOSED"],Qc=/^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/,be=class i extends Lc{constructor(t,e,s){super(),this._binaryType=Yr[0],this._closeCode=1006,this._closeFrameReceived=!1,this._closeFrameSent=!1,this._closeMessage=En,this._closeTimer=null,this._errorEmitted=!1,this._extensions={},this._paused=!1,this._protocol="",this._readyState=i.CONNECTING,this._receiver=null,this._sender=null,this._socket=null,t!==null?(this._bufferedAmount=0,this._isServer=!1,this._redirects=0,e===void 0?e=[]:Array.isArray(e)||(typeof e=="object"&&e!==null?(s=e,e=[]):e=[e]),Zr(this,t,e,s)):(this._autoPong=s.autoPong,this._closeTimeout=s.closeTimeout,this._isServer=!0)}get binaryType(){return this._binaryType}set binaryType(t){Yr.includes(t)&&(this._binaryType=t,this._receiver&&(this._receiver._binaryType=t))}get bufferedAmount(){return this._socket?this._socket._writableState.length+this._sender._bufferedBytes:this._bufferedAmount}get extensions(){return Object.keys(this._extensions).join()}get isPaused(){return this._paused}get onclose(){return null}get onerror(){return null}get onopen(){return null}get onmessage(){return null}get protocol(){return this._protocol}get readyState(){return this._readyState}get url(){return this._url}setSocket(t,e,s){let n=new $c({allowSynchronousEvents:s.allowSynchronousEvents,binaryType:this.binaryType,extensions:this._extensions,isServer:this._isServer,maxPayload:s.maxPayload,skipUTF8Validation:s.skipUTF8Validation}),a=new jc(t,this._extensions,s.generateMask);this._receiver=n,this._sender=a,this._socket=t,n[Fe]=this,a[Fe]=this,t[Fe]=this,n.on("conclude",td),n.on("drain",sd),n.on("error",nd),n.on("message",ad),n.on("ping",id),n.on("pong",rd),a.onerror=od,t.setTimeout&&t.setTimeout(0),t.setNoDelay&&t.setNoDelay(),e.length>0&&t.unshift(e),t.on("close",so),t.on("data",Rn),t.on("end",no),t.on("error",ao),this._readyState=i.OPEN,this.emit("open")}emitClose(){if(!this._socket){this._readyState=i.CLOSED,this.emit("close",this._closeCode,this._closeMessage);return}this._extensions[xt.extensionName]&&this._extensions[xt.extensionName].cleanup(),this._receiver.removeAllListeners(),this._readyState=i.CLOSED,this.emit("close",this._closeCode,this._closeMessage)}close(t,e){if(this.readyState!==i.CLOSED){if(this.readyState===i.CONNECTING){Ke(this,this._req,"WebSocket was closed before the connection was established");return}if(this.readyState===i.CLOSING){this._closeFrameSent&&(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end();return}this._readyState=i.CLOSING,this._sender.close(t,e,!this._isServer,s=>{s||(this._closeFrameSent=!0,(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end())}),to(this)}}pause(){this.readyState===i.CONNECTING||this.readyState===i.CLOSED||(this._paused=!0,this._socket.pause())}ping(t,e,s){if(this.readyState===i.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof t=="function"?(s=t,t=e=void 0):typeof e=="function"&&(s=e,e=void 0),typeof t=="number"&&(t=t.toString()),this.readyState!==i.OPEN){Fa(this,t,s);return}e===void 0&&(e=!this._isServer),this._sender.ping(t||En,e,s)}pong(t,e,s){if(this.readyState===i.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof t=="function"?(s=t,t=e=void 0):typeof e=="function"&&(s=e,e=void 0),typeof t=="number"&&(t=t.toString()),this.readyState!==i.OPEN){Fa(this,t,s);return}e===void 0&&(e=!this._isServer),this._sender.pong(t||En,e,s)}resume(){this.readyState===i.CONNECTING||this.readyState===i.CLOSED||(this._paused=!1,this._receiver._writableState.needDrain||this._socket.resume())}send(t,e,s){if(this.readyState===i.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof e=="function"&&(s=e,e={}),typeof t=="number"&&(t=t.toString()),this.readyState!==i.OPEN){Fa(this,t,s);return}let n={binary:typeof t!="string",mask:!this._isServer,compress:!0,fin:!0,...e};this._extensions[xt.extensionName]||(n.compress=!1),this._sender.send(t||En,n,s)}terminate(){if(this.readyState!==i.CLOSED){if(this.readyState===i.CONNECTING){Ke(this,this._req,"WebSocket was closed before the connection was established");return}this._socket&&(this._readyState=i.CLOSING,this._socket.destroy())}}};Object.defineProperty(be,"CONNECTING",{enumerable:!0,value:gt.indexOf("CONNECTING")});Object.defineProperty(be.prototype,"CONNECTING",{enumerable:!0,value:gt.indexOf("CONNECTING")});Object.defineProperty(be,"OPEN",{enumerable:!0,value:gt.indexOf("OPEN")});Object.defineProperty(be.prototype,"OPEN",{enumerable:!0,value:gt.indexOf("OPEN")});Object.defineProperty(be,"CLOSING",{enumerable:!0,value:gt.indexOf("CLOSING")});Object.defineProperty(be.prototype,"CLOSING",{enumerable:!0,value:gt.indexOf("CLOSING")});Object.defineProperty(be,"CLOSED",{enumerable:!0,value:gt.indexOf("CLOSED")});Object.defineProperty(be.prototype,"CLOSED",{enumerable:!0,value:gt.indexOf("CLOSED")});["binaryType","bufferedAmount","extensions","isPaused","protocol","readyState","url"].forEach(i=>{Object.defineProperty(be.prototype,i,{enumerable:!0})});["open","error","close","message"].forEach(i=>{Object.defineProperty(be.prototype,`on${i}`,{enumerable:!0,get(){for(let t of this.listeners(i))if(t[Ma])return t[zc];return null},set(t){for(let e of this.listeners(i))if(e[Ma]){this.removeListener(i,e);break}typeof t=="function"&&this.addEventListener(i,t,{[Ma]:!0})}})});be.prototype.addEventListener=Vc;be.prototype.removeEventListener=Yc;io.exports=be;function Zr(i,t,e,s){let n={allowSynchronousEvents:!0,autoPong:!0,closeTimeout:Hc,protocolVersion:La[1],maxPayload:104857600,skipUTF8Validation:!1,perMessageDeflate:!0,followRedirects:!1,maxRedirects:10,...s,socketPath:void 0,hostname:void 0,protocol:void 0,timeout:void 0,method:"GET",host:void 0,path:void 0,port:void 0};if(i._autoPong=n.autoPong,i._closeTimeout=n.closeTimeout,!La.includes(n.protocolVersion))throw new RangeError(`Unsupported protocol version: ${n.protocolVersion} (supported versions: ${La.join(", ")})`);let a;if(t instanceof Ia)a=t;else try{a=new Ia(t)}catch{throw new SyntaxError(`Invalid URL: ${t}`)}a.protocol==="http:"?a.protocol="ws:":a.protocol==="https:"&&(a.protocol="wss:"),i._url=a.href;let r=a.protocol==="wss:",o=a.protocol==="ws+unix:",c;if(a.protocol!=="ws:"&&!r&&!o?c=`The URL's protocol must be one of "ws:", "wss:", "http:", "https:", or "ws+unix:"`:o&&!a.pathname?c="The URL's pathname is empty":a.hash&&(c="The URL contains a fragment identifier"),c){let m=new SyntaxError(c);if(i._redirects===0)throw m;Pn(i,m);return}let l=r?443:80,d=Bc(16).toString("base64"),h=r?Fc.request:Oc.request,u=new Set,p;if(n.createConnection=n.createConnection||(r?ed:Zc),n.defaultPort=n.defaultPort||l,n.port=a.port||l,n.host=a.hostname.startsWith("[")?a.hostname.slice(1,-1):a.hostname,n.headers={...n.headers,"Sec-WebSocket-Version":n.protocolVersion,"Sec-WebSocket-Key":d,Connection:"Upgrade",Upgrade:"websocket"},n.path=a.pathname+a.search,n.timeout=n.handshakeTimeout,n.perMessageDeflate&&(p=new xt({...n.perMessageDeflate,isServer:!1,maxPayload:n.maxPayload}),n.headers["Sec-WebSocket-Extensions"]=Kc({[xt.extensionName]:p.offer()})),e.length){for(let m of e){if(typeof m!="string"||!Qc.test(m)||u.has(m))throw new SyntaxError("An invalid or duplicated subprotocol was specified");u.add(m)}n.headers["Sec-WebSocket-Protocol"]=e.join(",")}if(n.origin&&(n.protocolVersion<13?n.headers["Sec-WebSocket-Origin"]=n.origin:n.headers.Origin=n.origin),(a.username||a.password)&&(n.auth=`${a.username}:${a.password}`),o){let m=n.path.split(":");n.socketPath=m[0],n.path=m[1]}let f;if(n.followRedirects){if(i._redirects===0){i._originalIpc=o,i._originalSecure=r,i._originalHostOrSocketPath=o?n.socketPath:a.host;let m=s&&s.headers;if(s={...s,headers:{}},m)for(let[g,v]of Object.entries(m))s.headers[g.toLowerCase()]=v}else if(i.listenerCount("redirect")===0){let m=o?i._originalIpc?n.socketPath===i._originalHostOrSocketPath:!1:i._originalIpc?!1:a.host===i._originalHostOrSocketPath;(!m||i._originalSecure&&!r)&&(delete n.headers.authorization,delete n.headers.cookie,m||delete n.headers.host,n.auth=void 0)}n.auth&&!s.headers.authorization&&(s.headers.authorization="Basic "+Buffer.from(n.auth).toString("base64")),f=i._req=h(n),i._redirects&&i.emit("redirect",i.url,f)}else f=i._req=h(n);n.timeout&&f.on("timeout",()=>{Ke(i,f,"Opening handshake has timed out")}),f.on("error",m=>{f===null||f[Qr]||(f=i._req=null,Pn(i,m))}),f.on("response",m=>{let g=m.headers.location,v=m.statusCode;if(g&&n.followRedirects&&v>=300&&v<400){if(++i._redirects>n.maxRedirects){Ke(i,f,"Maximum redirects exceeded");return}f.abort();let k;try{k=new Ia(g,t)}catch{let y=new SyntaxError(`Invalid URL: ${g}`);Pn(i,y);return}Zr(i,k,e,s)}else i.emit("unexpected-response",f,m)||Ke(i,f,`Unexpected server response: ${m.statusCode}`)}),f.on("upgrade",(m,g,v)=>{if(i.emit("upgrade",m),i.readyState!==be.CONNECTING)return;f=i._req=null;let k=m.headers.upgrade;if(k===void 0||k.toLowerCase()!=="websocket"){Ke(i,g,"Invalid Upgrade header");return}let w=Uc("sha1").update(d+qc).digest("base64");if(m.headers["sec-websocket-accept"]!==w){Ke(i,g,"Invalid Sec-WebSocket-Accept header");return}let y=m.headers["sec-websocket-protocol"],C;if(y!==void 0?u.size?u.has(y)||(C="Server sent an invalid subprotocol"):C="Server sent a subprotocol but none was requested":u.size&&(C="Server sent no subprotocol"),C){Ke(i,g,C);return}y&&(i._protocol=y);let T=m.headers["sec-websocket-extensions"];if(T!==void 0){if(!p){Ke(i,g,"Server sent a Sec-WebSocket-Extensions header but no extension was requested");return}let _;try{_=Jc(T)}catch{Ke(i,g,"Invalid Sec-WebSocket-Extensions header");return}let O=Object.keys(_);if(O.length!==1||O[0]!==xt.extensionName){Ke(i,g,"Server indicated an extension that was not requested");return}try{p.accept(_[xt.extensionName])}catch{Ke(i,g,"Invalid Sec-WebSocket-Extensions header");return}i._extensions[xt.extensionName]=p}i.setSocket(g,v,{allowSynchronousEvents:n.allowSynchronousEvents,generateMask:n.generateMask,maxPayload:n.maxPayload,skipUTF8Validation:n.skipUTF8Validation})}),n.finishRequest?n.finishRequest(f,i):f.end()}function Pn(i,t){i._readyState=be.CLOSING,i._errorEmitted=!0,i.emit("error",t),i.emitClose()}function Zc(i){return i.path=i.socketPath,Jr.connect(i)}function ed(i){return i.path=void 0,!i.servername&&i.servername!==""&&(i.servername=Jr.isIP(i.host)?"":i.host),Nc.connect(i)}function Ke(i,t,e){i._readyState=be.CLOSING;let s=new Error(e);Error.captureStackTrace(s,Ke),t.setHeader?(t[Qr]=!0,t.abort(),t.socket&&!t.socket.destroyed&&t.socket.destroy(),process.nextTick(Pn,i,s)):(t.destroy(s),t.once("error",i.emit.bind(i,"error")),t.once("close",i.emitClose.bind(i)))}function Fa(i,t,e){if(t){let s=Wc(t)?t.size:Xc(t).length;i._socket?i._sender._bufferedBytes+=s:i._bufferedAmount+=s}if(e){let s=new Error(`WebSocket is not open: readyState ${i.readyState} (${gt[i.readyState]})`);process.nextTick(e,s)}}function td(i,t){let e=this[Fe];e._closeFrameReceived=!0,e._closeMessage=t,e._closeCode=i,e._socket[Fe]!==void 0&&(e._socket.removeListener("data",Rn),process.nextTick(eo,e._socket),i===1005?e.close():e.close(i,t))}function sd(){let i=this[Fe];i.isPaused||i._socket.resume()}function nd(i){let t=this[Fe];t._socket[Fe]!==void 0&&(t._socket.removeListener("data",Rn),process.nextTick(eo,t._socket),t.close(i[Gc])),t._errorEmitted||(t._errorEmitted=!0,t.emit("error",i))}function Kr(){this[Fe].emitClose()}function ad(i,t){this[Fe].emit("message",i,t)}function id(i){let t=this[Fe];t._autoPong&&t.pong(i,!this._isServer,Xr),t.emit("ping",i)}function rd(i){this[Fe].emit("pong",i)}function eo(i){i.resume()}function od(i){let t=this[Fe];t.readyState!==be.CLOSED&&(t.readyState===be.OPEN&&(t._readyState=be.CLOSING,to(t)),this._socket.end(),t._errorEmitted||(t._errorEmitted=!0,t.emit("error",i)))}function to(i){i._closeTimer=setTimeout(i._socket.destroy.bind(i._socket),i._closeTimeout)}function so(){let i=this[Fe];if(this.removeListener("close",so),this.removeListener("data",Rn),this.removeListener("end",no),i._readyState=be.CLOSING,!this._readableState.endEmitted&&!i._closeFrameReceived&&!i._receiver._writableState.errorEmitted&&this._readableState.length!==0){let t=this.read(this._readableState.length);i._receiver.write(t)}i._receiver.end(),this[Fe]=void 0,clearTimeout(i._closeTimer),i._receiver._writableState.finished||i._receiver._writableState.errorEmitted?i.emitClose():(i._receiver.on("error",Kr),i._receiver.on("finish",Kr))}function Rn(i){this[Fe]._receiver.write(i)||this.pause()}function no(){let i=this[Fe];i._readyState=be.CLOSING,i._receiver.end(),this.end()}function ao(){let i=this[Fe];this.removeListener("error",ao),this.on("error",Xr),i&&(i._readyState=be.CLOSING,this.destroy())}});var co=qe((Gu,lo)=>{"use strict";var zu=Dn(),{Duplex:ld}=require("stream");function ro(i){i.emit("close")}function cd(){!this.destroyed&&this._writableState.finished&&this.destroy()}function oo(i){this.removeListener("error",oo),this.destroy(),this.listenerCount("error")===0&&this.emit("error",i)}function dd(i,t){let e=!0,s=new ld({...t,autoDestroy:!1,emitClose:!1,objectMode:!1,writableObjectMode:!1});return i.on("message",function(a,r){let o=!r&&s._readableState.objectMode?a.toString():a;s.push(o)||i.pause()}),i.once("error",function(a){s.destroyed||(e=!1,s.destroy(a))}),i.once("close",function(){s.destroyed||s.push(null)}),s._destroy=function(n,a){if(i.readyState===i.CLOSED){a(n),process.nextTick(ro,s);return}let r=!1;i.once("error",function(c){r=!0,a(c)}),i.once("close",function(){r||a(n),process.nextTick(ro,s)}),e&&i.terminate()},s._final=function(n){if(i.readyState===i.CONNECTING){i.once("open",function(){s._final(n)});return}i._socket!==null&&(i._socket._writableState.finished?(n(),s._readableState.endEmitted&&s.destroy()):(i._socket.once("finish",function(){n()}),i.close()))},s._read=function(){i.isPaused&&i.resume()},s._write=function(n,a,r){if(i.readyState===i.CONNECTING){i.once("open",function(){s._write(n,a,r)});return}i.send(n,r)},s.on("end",cd),s.on("error",oo),s}lo.exports=dd});var Oa=qe((Vu,ho)=>{"use strict";var{tokenChars:hd}=Kt();function ud(i){let t=new Set,e=-1,s=-1,n=0;for(n;n<i.length;n++){let r=i.charCodeAt(n);if(s===-1&&hd[r]===1)e===-1&&(e=n);else if(n!==0&&(r===32||r===9))s===-1&&e!==-1&&(s=n);else if(r===44){if(e===-1)throw new SyntaxError(`Unexpected character at index ${n}`);s===-1&&(s=n);let o=i.slice(e,s);if(t.has(o))throw new SyntaxError(`The "${o}" subprotocol is duplicated`);t.add(o),e=s=-1}else throw new SyntaxError(`Unexpected character at index ${n}`)}if(e===-1||s!==-1)throw new SyntaxError("Unexpected end of input");let a=i.slice(e,n);if(t.has(a))throw new SyntaxError(`The "${a}" subprotocol is duplicated`);return t.add(a),t}ho.exports={parse:ud}});var vo=qe((Ku,yo)=>{"use strict";var pd=require("events"),In=require("http"),{Duplex:Yu}=require("stream"),{createHash:md}=require("crypto"),uo=An(),Mt=Yt(),fd=Oa(),gd=Dn(),{CLOSE_TIMEOUT:yd,GUID:vd,kWebSocket:bd}=pt(),wd=/^[+/0-9A-Za-z]{22}==$/,po=0,mo=1,go=2,Na=class extends pd{constructor(t,e){if(super(),t={allowSynchronousEvents:!0,autoPong:!0,maxPayload:100*1024*1024,skipUTF8Validation:!1,perMessageDeflate:!1,handleProtocols:null,clientTracking:!0,closeTimeout:yd,verifyClient:null,noServer:!1,backlog:null,server:null,host:null,path:null,port:null,WebSocket:gd,...t},t.port==null&&!t.server&&!t.noServer||t.port!=null&&(t.server||t.noServer)||t.server&&t.noServer)throw new TypeError('One and only one of the "port", "server", or "noServer" options must be specified');if(t.port!=null?(this._server=In.createServer((s,n)=>{let a=In.STATUS_CODES[426];n.writeHead(426,{"Content-Length":a.length,"Content-Type":"text/plain"}),n.end(a)}),this._server.listen(t.port,t.host,t.backlog,e)):t.server&&(this._server=t.server),this._server){let s=this.emit.bind(this,"connection");this._removeListeners=kd(this._server,{listening:this.emit.bind(this,"listening"),error:this.emit.bind(this,"error"),upgrade:(n,a,r)=>{this.handleUpgrade(n,a,r,s)}})}t.perMessageDeflate===!0&&(t.perMessageDeflate={}),t.clientTracking&&(this.clients=new Set,this._shouldEmitClose=!1),this.options=t,this._state=po}address(){if(this.options.noServer)throw new Error('The server is operating in "noServer" mode');return this._server?this._server.address():null}close(t){if(this._state===go){t&&this.once("close",()=>{t(new Error("The server is not running"))}),process.nextTick(As,this);return}if(t&&this.once("close",t),this._state!==mo)if(this._state=mo,this.options.noServer||this.options.server)this._server&&(this._removeListeners(),this._removeListeners=this._server=null),this.clients?this.clients.size?this._shouldEmitClose=!0:process.nextTick(As,this):process.nextTick(As,this);else{let e=this._server;this._removeListeners(),this._removeListeners=this._server=null,e.close(()=>{As(this)})}}shouldHandle(t){if(this.options.path){let e=t.url.indexOf("?");if((e!==-1?t.url.slice(0,e):t.url)!==this.options.path)return!1}return!0}handleUpgrade(t,e,s,n){e.on("error",fo);let a=t.headers["sec-websocket-key"],r=t.headers.upgrade,o=+t.headers["sec-websocket-version"];if(t.method!=="GET"){Lt(this,t,e,405,"Invalid HTTP method");return}if(r===void 0||r.toLowerCase()!=="websocket"){Lt(this,t,e,400,"Invalid Upgrade header");return}if(a===void 0||!wd.test(a)){Lt(this,t,e,400,"Missing or invalid Sec-WebSocket-Key header");return}if(o!==13&&o!==8){Lt(this,t,e,400,"Missing or invalid Sec-WebSocket-Version header",{"Sec-WebSocket-Version":"13, 8"});return}if(!this.shouldHandle(t)){Es(e,400);return}let c=t.headers["sec-websocket-protocol"],l=new Set;if(c!==void 0)try{l=fd.parse(c)}catch{Lt(this,t,e,400,"Invalid Sec-WebSocket-Protocol header");return}let d=t.headers["sec-websocket-extensions"],h={};if(this.options.perMessageDeflate&&d!==void 0){let u=new Mt({...this.options.perMessageDeflate,isServer:!0,maxPayload:this.options.maxPayload});try{let p=uo.parse(d);p[Mt.extensionName]&&(u.accept(p[Mt.extensionName]),h[Mt.extensionName]=u)}catch{Lt(this,t,e,400,"Invalid or unacceptable Sec-WebSocket-Extensions header");return}}if(this.options.verifyClient){let u={origin:t.headers[`${o===8?"sec-websocket-origin":"origin"}`],secure:!!(t.socket.authorized||t.socket.encrypted),req:t};if(this.options.verifyClient.length===2){this.options.verifyClient(u,(p,f,m,g)=>{if(!p)return Es(e,f||401,m,g);this.completeUpgrade(h,a,l,t,e,s,n)});return}if(!this.options.verifyClient(u))return Es(e,401)}this.completeUpgrade(h,a,l,t,e,s,n)}completeUpgrade(t,e,s,n,a,r,o){if(!a.readable||!a.writable)return a.destroy();if(a[bd])throw new Error("server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration");if(this._state>po)return Es(a,503);let l=["HTTP/1.1 101 Switching Protocols","Upgrade: websocket","Connection: Upgrade",`Sec-WebSocket-Accept: ${md("sha1").update(e+vd).digest("base64")}`],d=new this.options.WebSocket(null,void 0,this.options);if(s.size){let h=this.options.handleProtocols?this.options.handleProtocols(s,n):s.values().next().value;h&&(l.push(`Sec-WebSocket-Protocol: ${h}`),d._protocol=h)}if(t[Mt.extensionName]){let h=t[Mt.extensionName].params,u=uo.format({[Mt.extensionName]:[h]});l.push(`Sec-WebSocket-Extensions: ${u}`),d._extensions=t}this.emit("headers",l,n),a.write(l.concat(`\r
1
+ "use strict";var jo=Object.create;var Ns=Object.defineProperty;var Wo=Object.getOwnPropertyDescriptor;var Ho=Object.getOwnPropertyNames;var qo=Object.getPrototypeOf,zo=Object.prototype.hasOwnProperty;var qe=(i,t)=>()=>(t||i((t={exports:{}}).exports,t),t.exports),Go=(i,t)=>{for(var e in t)Ns(i,e,{get:t[e],enumerable:!0})},Va=(i,t,e,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let n of Ho(t))!zo.call(i,n)&&n!==e&&Ns(i,n,{get:()=>t[n],enumerable:!(s=Wo(t,n))||s.enumerable});return i};var ze=(i,t,e)=>(e=i!=null?jo(qo(i)):{},Va(t||!i||!i.__esModule?Ns(e,"default",{value:i,enumerable:!0}):e,i)),Vo=i=>Va(Ns({},"__esModule",{value:!0}),i);var mt=qe((Mu,vr)=>{"use strict";var gr=["nodebuffer","arraybuffer","fragments"],yr=typeof Blob<"u";yr&&gr.push("blob");vr.exports={BINARY_TYPES:gr,CLOSE_TIMEOUT:3e4,EMPTY_BUFFER:Buffer.alloc(0),GUID:"258EAFA5-E914-47DA-95CA-C5AB0DC85B11",hasBlob:yr,kForOnEventAttribute:Symbol("kIsForOnEventAttribute"),kListener:Symbol("kListener"),kStatusCode:Symbol("status-code"),kWebSocket:Symbol("websocket"),NOOP:()=>{}}});var xs=qe((Lu,wn)=>{"use strict";var{EMPTY_BUFFER:ac}=mt(),ya=Buffer[Symbol.species];function ic(i,t){if(i.length===0)return ac;if(i.length===1)return i[0];let e=Buffer.allocUnsafe(t),s=0;for(let n=0;n<i.length;n++){let a=i[n];e.set(a,s),s+=a.length}return s<t?new ya(e.buffer,e.byteOffset,s):e}function wr(i,t,e,s,n){for(let a=0;a<n;a++)e[s+a]=i[a]^t[a&3]}function br(i,t){for(let e=0;e<i.length;e++)i[e]^=t[e&3]}function rc(i){return i.length===i.buffer.byteLength?i.buffer:i.buffer.slice(i.byteOffset,i.byteOffset+i.length)}function va(i){if(va.readOnly=!0,Buffer.isBuffer(i))return i;let t;return i instanceof ArrayBuffer?t=new ya(i):ArrayBuffer.isView(i)?t=new ya(i.buffer,i.byteOffset,i.byteLength):(t=Buffer.from(i),va.readOnly=!1),t}wn.exports={concat:ic,mask:wr,toArrayBuffer:rc,toBuffer:va,unmask:br};if(!process.env.WS_NO_BUFFER_UTIL)try{let i=require("bufferutil");wn.exports.mask=function(t,e,s,n,a){a<48?wr(t,e,s,n,a):i.mask(t,e,s,n,a)},wn.exports.unmask=function(t,e){t.length<32?br(t,e):i.unmask(t,e)}}catch{}});var Sr=qe((Fu,xr)=>{"use strict";var kr=Symbol("kDone"),wa=Symbol("kRun"),ba=class{constructor(t){this[kr]=()=>{this.pending--,this[wa]()},this.concurrency=t||1/0,this.jobs=[],this.pending=0}add(t){this.jobs.push(t),this[wa]()}[wa](){if(this.pending!==this.concurrency&&this.jobs.length){let t=this.jobs.shift();this.pending++,t(this[kr])}}};xr.exports=ba});var Kt=qe((Ou,Ar)=>{"use strict";var Ss=require("zlib"),Cr=xs(),oc=Sr(),{kStatusCode:Tr}=mt(),lc=Buffer[Symbol.species],cc=Buffer.from([0,0,255,255]),kn=Symbol("permessage-deflate"),ft=Symbol("total-length"),Vt=Symbol("callback"),kt=Symbol("buffers"),Yt=Symbol("error"),bn,ka=class{constructor(t){if(this._options=t||{},this._threshold=this._options.threshold!==void 0?this._options.threshold:1024,this._maxPayload=this._options.maxPayload|0,this._isServer=!!this._options.isServer,this._deflate=null,this._inflate=null,this.params=null,!bn){let e=this._options.concurrencyLimit!==void 0?this._options.concurrencyLimit:10;bn=new oc(e)}}static get extensionName(){return"permessage-deflate"}offer(){let t={};return this._options.serverNoContextTakeover&&(t.server_no_context_takeover=!0),this._options.clientNoContextTakeover&&(t.client_no_context_takeover=!0),this._options.serverMaxWindowBits&&(t.server_max_window_bits=this._options.serverMaxWindowBits),this._options.clientMaxWindowBits?t.client_max_window_bits=this._options.clientMaxWindowBits:this._options.clientMaxWindowBits==null&&(t.client_max_window_bits=!0),t}accept(t){return t=this.normalizeParams(t),this.params=this._isServer?this.acceptAsServer(t):this.acceptAsClient(t),this.params}cleanup(){if(this._inflate&&(this._inflate.close(),this._inflate=null),this._deflate){let t=this._deflate[Vt];this._deflate.close(),this._deflate=null,t&&t(new Error("The deflate stream was closed while data was being processed"))}}acceptAsServer(t){let e=this._options,s=t.find(n=>!(e.serverNoContextTakeover===!1&&n.server_no_context_takeover||n.server_max_window_bits&&(e.serverMaxWindowBits===!1||typeof e.serverMaxWindowBits=="number"&&e.serverMaxWindowBits>n.server_max_window_bits)||typeof e.clientMaxWindowBits=="number"&&!n.client_max_window_bits));if(!s)throw new Error("None of the extension offers can be accepted");return e.serverNoContextTakeover&&(s.server_no_context_takeover=!0),e.clientNoContextTakeover&&(s.client_no_context_takeover=!0),typeof e.serverMaxWindowBits=="number"&&(s.server_max_window_bits=e.serverMaxWindowBits),typeof e.clientMaxWindowBits=="number"?s.client_max_window_bits=e.clientMaxWindowBits:(s.client_max_window_bits===!0||e.clientMaxWindowBits===!1)&&delete s.client_max_window_bits,s}acceptAsClient(t){let e=t[0];if(this._options.clientNoContextTakeover===!1&&e.client_no_context_takeover)throw new Error('Unexpected parameter "client_no_context_takeover"');if(!e.client_max_window_bits)typeof this._options.clientMaxWindowBits=="number"&&(e.client_max_window_bits=this._options.clientMaxWindowBits);else if(this._options.clientMaxWindowBits===!1||typeof this._options.clientMaxWindowBits=="number"&&e.client_max_window_bits>this._options.clientMaxWindowBits)throw new Error('Unexpected or invalid parameter "client_max_window_bits"');return e}normalizeParams(t){return t.forEach(e=>{Object.keys(e).forEach(s=>{let n=e[s];if(n.length>1)throw new Error(`Parameter "${s}" must have only a single value`);if(n=n[0],s==="client_max_window_bits"){if(n!==!0){let a=+n;if(!Number.isInteger(a)||a<8||a>15)throw new TypeError(`Invalid value for parameter "${s}": ${n}`);n=a}else if(!this._isServer)throw new TypeError(`Invalid value for parameter "${s}": ${n}`)}else if(s==="server_max_window_bits"){let a=+n;if(!Number.isInteger(a)||a<8||a>15)throw new TypeError(`Invalid value for parameter "${s}": ${n}`);n=a}else if(s==="client_no_context_takeover"||s==="server_no_context_takeover"){if(n!==!0)throw new TypeError(`Invalid value for parameter "${s}": ${n}`)}else throw new Error(`Unknown parameter "${s}"`);e[s]=n})}),t}decompress(t,e,s){bn.add(n=>{this._decompress(t,e,(a,r)=>{n(),s(a,r)})})}compress(t,e,s){bn.add(n=>{this._compress(t,e,(a,r)=>{n(),s(a,r)})})}_decompress(t,e,s){let n=this._isServer?"client":"server";if(!this._inflate){let a=`${n}_max_window_bits`,r=typeof this.params[a]!="number"?Ss.Z_DEFAULT_WINDOWBITS:this.params[a];this._inflate=Ss.createInflateRaw({...this._options.zlibInflateOptions,windowBits:r}),this._inflate[kn]=this,this._inflate[ft]=0,this._inflate[kt]=[],this._inflate.on("error",hc),this._inflate.on("data",_r)}this._inflate[Vt]=s,this._inflate.write(t),e&&this._inflate.write(cc),this._inflate.flush(()=>{let a=this._inflate[Yt];if(a){this._inflate.close(),this._inflate=null,s(a);return}let r=Cr.concat(this._inflate[kt],this._inflate[ft]);this._inflate._readableState.endEmitted?(this._inflate.close(),this._inflate=null):(this._inflate[ft]=0,this._inflate[kt]=[],e&&this.params[`${n}_no_context_takeover`]&&this._inflate.reset()),s(null,r)})}_compress(t,e,s){let n=this._isServer?"server":"client";if(!this._deflate){let a=`${n}_max_window_bits`,r=typeof this.params[a]!="number"?Ss.Z_DEFAULT_WINDOWBITS:this.params[a];this._deflate=Ss.createDeflateRaw({...this._options.zlibDeflateOptions,windowBits:r}),this._deflate[ft]=0,this._deflate[kt]=[],this._deflate.on("data",dc)}this._deflate[Vt]=s,this._deflate.write(t),this._deflate.flush(Ss.Z_SYNC_FLUSH,()=>{if(!this._deflate)return;let a=Cr.concat(this._deflate[kt],this._deflate[ft]);e&&(a=new lc(a.buffer,a.byteOffset,a.length-4)),this._deflate[Vt]=null,this._deflate[ft]=0,this._deflate[kt]=[],e&&this.params[`${n}_no_context_takeover`]&&this._deflate.reset(),s(null,a)})}};Ar.exports=ka;function dc(i){this[kt].push(i),this[ft]+=i.length}function _r(i){if(this[ft]+=i.length,this[kn]._maxPayload<1||this[ft]<=this[kn]._maxPayload){this[kt].push(i);return}this[Yt]=new RangeError("Max payload size exceeded"),this[Yt].code="WS_ERR_UNSUPPORTED_MESSAGE_LENGTH",this[Yt][Tr]=1009,this.removeListener("data",_r),this.reset()}function hc(i){if(this[kn]._inflate=null,this[Yt]){this[Vt](this[Yt]);return}i[Tr]=1007,this[Vt](i)}});var Jt=qe((Nu,xn)=>{"use strict";var{isUtf8:Er}=require("buffer"),{hasBlob:uc}=mt(),pc=[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,1,1,1,1,0,0,1,1,0,1,1,0,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,1,0];function mc(i){return i>=1e3&&i<=1014&&i!==1004&&i!==1005&&i!==1006||i>=3e3&&i<=4999}function xa(i){let t=i.length,e=0;for(;e<t;)if((i[e]&128)===0)e++;else if((i[e]&224)===192){if(e+1===t||(i[e+1]&192)!==128||(i[e]&254)===192)return!1;e+=2}else if((i[e]&240)===224){if(e+2>=t||(i[e+1]&192)!==128||(i[e+2]&192)!==128||i[e]===224&&(i[e+1]&224)===128||i[e]===237&&(i[e+1]&224)===160)return!1;e+=3}else if((i[e]&248)===240){if(e+3>=t||(i[e+1]&192)!==128||(i[e+2]&192)!==128||(i[e+3]&192)!==128||i[e]===240&&(i[e+1]&240)===128||i[e]===244&&i[e+1]>143||i[e]>244)return!1;e+=4}else return!1;return!0}function fc(i){return uc&&typeof i=="object"&&typeof i.arrayBuffer=="function"&&typeof i.type=="string"&&typeof i.stream=="function"&&(i[Symbol.toStringTag]==="Blob"||i[Symbol.toStringTag]==="File")}xn.exports={isBlob:fc,isValidStatusCode:mc,isValidUTF8:xa,tokenChars:pc};if(Er)xn.exports.isValidUTF8=function(i){return i.length<24?xa(i):Er(i)};else if(!process.env.WS_NO_UTF_8_VALIDATE)try{let i=require("utf-8-validate");xn.exports.isValidUTF8=function(t){return t.length<32?xa(t):i(t)}}catch{}});var Aa=qe((Bu,Fr)=>{"use strict";var{Writable:gc}=require("stream"),Pr=Kt(),{BINARY_TYPES:yc,EMPTY_BUFFER:Rr,kStatusCode:vc,kWebSocket:wc}=mt(),{concat:Sa,toArrayBuffer:bc,unmask:kc}=xs(),{isValidStatusCode:xc,isValidUTF8:Dr}=Jt(),Sn=Buffer[Symbol.species],Xe=0,Ir=1,Mr=2,Lr=3,Ca=4,Ta=5,Cn=6,_a=class extends gc{constructor(t={}){super(),this._allowSynchronousEvents=t.allowSynchronousEvents!==void 0?t.allowSynchronousEvents:!0,this._binaryType=t.binaryType||yc[0],this._extensions=t.extensions||{},this._isServer=!!t.isServer,this._maxPayload=t.maxPayload|0,this._skipUTF8Validation=!!t.skipUTF8Validation,this[wc]=void 0,this._bufferedBytes=0,this._buffers=[],this._compressed=!1,this._payloadLength=0,this._mask=void 0,this._fragmented=0,this._masked=!1,this._fin=!1,this._opcode=0,this._totalPayloadLength=0,this._messageLength=0,this._fragments=[],this._errored=!1,this._loop=!1,this._state=Xe}_write(t,e,s){if(this._opcode===8&&this._state==Xe)return s();this._bufferedBytes+=t.length,this._buffers.push(t),this.startLoop(s)}consume(t){if(this._bufferedBytes-=t,t===this._buffers[0].length)return this._buffers.shift();if(t<this._buffers[0].length){let s=this._buffers[0];return this._buffers[0]=new Sn(s.buffer,s.byteOffset+t,s.length-t),new Sn(s.buffer,s.byteOffset,t)}let e=Buffer.allocUnsafe(t);do{let s=this._buffers[0],n=e.length-t;t>=s.length?e.set(this._buffers.shift(),n):(e.set(new Uint8Array(s.buffer,s.byteOffset,t),n),this._buffers[0]=new Sn(s.buffer,s.byteOffset+t,s.length-t)),t-=s.length}while(t>0);return e}startLoop(t){this._loop=!0;do switch(this._state){case Xe:this.getInfo(t);break;case Ir:this.getPayloadLength16(t);break;case Mr:this.getPayloadLength64(t);break;case Lr:this.getMask();break;case Ca:this.getData(t);break;case Ta:case Cn:this._loop=!1;return}while(this._loop);this._errored||t()}getInfo(t){if(this._bufferedBytes<2){this._loop=!1;return}let e=this.consume(2);if((e[0]&48)!==0){let n=this.createError(RangeError,"RSV2 and RSV3 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_2_3");t(n);return}let s=(e[0]&64)===64;if(s&&!this._extensions[Pr.extensionName]){let n=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");t(n);return}if(this._fin=(e[0]&128)===128,this._opcode=e[0]&15,this._payloadLength=e[1]&127,this._opcode===0){if(s){let n=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");t(n);return}if(!this._fragmented){let n=this.createError(RangeError,"invalid opcode 0",!0,1002,"WS_ERR_INVALID_OPCODE");t(n);return}this._opcode=this._fragmented}else if(this._opcode===1||this._opcode===2){if(this._fragmented){let n=this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,"WS_ERR_INVALID_OPCODE");t(n);return}this._compressed=s}else if(this._opcode>7&&this._opcode<11){if(!this._fin){let n=this.createError(RangeError,"FIN must be set",!0,1002,"WS_ERR_EXPECTED_FIN");t(n);return}if(s){let n=this.createError(RangeError,"RSV1 must be clear",!0,1002,"WS_ERR_UNEXPECTED_RSV_1");t(n);return}if(this._payloadLength>125||this._opcode===8&&this._payloadLength===1){let n=this.createError(RangeError,`invalid payload length ${this._payloadLength}`,!0,1002,"WS_ERR_INVALID_CONTROL_PAYLOAD_LENGTH");t(n);return}}else{let n=this.createError(RangeError,`invalid opcode ${this._opcode}`,!0,1002,"WS_ERR_INVALID_OPCODE");t(n);return}if(!this._fin&&!this._fragmented&&(this._fragmented=this._opcode),this._masked=(e[1]&128)===128,this._isServer){if(!this._masked){let n=this.createError(RangeError,"MASK must be set",!0,1002,"WS_ERR_EXPECTED_MASK");t(n);return}}else if(this._masked){let n=this.createError(RangeError,"MASK must be clear",!0,1002,"WS_ERR_UNEXPECTED_MASK");t(n);return}this._payloadLength===126?this._state=Ir:this._payloadLength===127?this._state=Mr:this.haveLength(t)}getPayloadLength16(t){if(this._bufferedBytes<2){this._loop=!1;return}this._payloadLength=this.consume(2).readUInt16BE(0),this.haveLength(t)}getPayloadLength64(t){if(this._bufferedBytes<8){this._loop=!1;return}let e=this.consume(8),s=e.readUInt32BE(0);if(s>Math.pow(2,21)-1){let n=this.createError(RangeError,"Unsupported WebSocket frame: payload length > 2^53 - 1",!1,1009,"WS_ERR_UNSUPPORTED_DATA_PAYLOAD_LENGTH");t(n);return}this._payloadLength=s*Math.pow(2,32)+e.readUInt32BE(4),this.haveLength(t)}haveLength(t){if(this._payloadLength&&this._opcode<8&&(this._totalPayloadLength+=this._payloadLength,this._totalPayloadLength>this._maxPayload&&this._maxPayload>0)){let e=this.createError(RangeError,"Max payload size exceeded",!1,1009,"WS_ERR_UNSUPPORTED_MESSAGE_LENGTH");t(e);return}this._masked?this._state=Lr:this._state=Ca}getMask(){if(this._bufferedBytes<4){this._loop=!1;return}this._mask=this.consume(4),this._state=Ca}getData(t){let e=Rr;if(this._payloadLength){if(this._bufferedBytes<this._payloadLength){this._loop=!1;return}e=this.consume(this._payloadLength),this._masked&&(this._mask[0]|this._mask[1]|this._mask[2]|this._mask[3])!==0&&kc(e,this._mask)}if(this._opcode>7){this.controlMessage(e,t);return}if(this._compressed){this._state=Ta,this.decompress(e,t);return}e.length&&(this._messageLength=this._totalPayloadLength,this._fragments.push(e)),this.dataMessage(t)}decompress(t,e){this._extensions[Pr.extensionName].decompress(t,this._fin,(n,a)=>{if(n)return e(n);if(a.length){if(this._messageLength+=a.length,this._messageLength>this._maxPayload&&this._maxPayload>0){let r=this.createError(RangeError,"Max payload size exceeded",!1,1009,"WS_ERR_UNSUPPORTED_MESSAGE_LENGTH");e(r);return}this._fragments.push(a)}this.dataMessage(e),this._state===Xe&&this.startLoop(e)})}dataMessage(t){if(!this._fin){this._state=Xe;return}let e=this._messageLength,s=this._fragments;if(this._totalPayloadLength=0,this._messageLength=0,this._fragmented=0,this._fragments=[],this._opcode===2){let n;this._binaryType==="nodebuffer"?n=Sa(s,e):this._binaryType==="arraybuffer"?n=bc(Sa(s,e)):this._binaryType==="blob"?n=new Blob(s):n=s,this._allowSynchronousEvents?(this.emit("message",n,!0),this._state=Xe):(this._state=Cn,setImmediate(()=>{this.emit("message",n,!0),this._state=Xe,this.startLoop(t)}))}else{let n=Sa(s,e);if(!this._skipUTF8Validation&&!Dr(n)){let a=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");t(a);return}this._state===Ta||this._allowSynchronousEvents?(this.emit("message",n,!1),this._state=Xe):(this._state=Cn,setImmediate(()=>{this.emit("message",n,!1),this._state=Xe,this.startLoop(t)}))}}controlMessage(t,e){if(this._opcode===8){if(t.length===0)this._loop=!1,this.emit("conclude",1005,Rr),this.end();else{let s=t.readUInt16BE(0);if(!xc(s)){let a=this.createError(RangeError,`invalid status code ${s}`,!0,1002,"WS_ERR_INVALID_CLOSE_CODE");e(a);return}let n=new Sn(t.buffer,t.byteOffset+2,t.length-2);if(!this._skipUTF8Validation&&!Dr(n)){let a=this.createError(Error,"invalid UTF-8 sequence",!0,1007,"WS_ERR_INVALID_UTF8");e(a);return}this._loop=!1,this.emit("conclude",s,n),this.end()}this._state=Xe;return}this._allowSynchronousEvents?(this.emit(this._opcode===9?"ping":"pong",t),this._state=Xe):(this._state=Cn,setImmediate(()=>{this.emit(this._opcode===9?"ping":"pong",t),this._state=Xe,this.startLoop(e)}))}createError(t,e,s,n,a){this._loop=!1,this._errored=!0;let r=new t(s?`Invalid WebSocket frame: ${e}`:e);return Error.captureStackTrace(r,this.createError),r.code=a,r[vc]=n,r}};Fr.exports=_a});var Ra=qe(($u,Br)=>{"use strict";var{Duplex:Uu}=require("stream"),{randomFillSync:Sc}=require("crypto"),Or=Kt(),{EMPTY_BUFFER:Cc,kWebSocket:Tc,NOOP:_c}=mt(),{isBlob:Xt,isValidStatusCode:Ac}=Jt(),{mask:Nr,toBuffer:Rt}=xs(),Qe=Symbol("kByteLength"),Ec=Buffer.alloc(4),Tn=8*1024,Dt,Qt=Tn,rt=0,Pc=1,Rc=2,Ea=class i{constructor(t,e,s){this._extensions=e||{},s&&(this._generateMask=s,this._maskBuffer=Buffer.alloc(4)),this._socket=t,this._firstFragment=!0,this._compress=!1,this._bufferedBytes=0,this._queue=[],this._state=rt,this.onerror=_c,this[Tc]=void 0}static frame(t,e){let s,n=!1,a=2,r=!1;e.mask&&(s=e.maskBuffer||Ec,e.generateMask?e.generateMask(s):(Qt===Tn&&(Dt===void 0&&(Dt=Buffer.alloc(Tn)),Sc(Dt,0,Tn),Qt=0),s[0]=Dt[Qt++],s[1]=Dt[Qt++],s[2]=Dt[Qt++],s[3]=Dt[Qt++]),r=(s[0]|s[1]|s[2]|s[3])===0,a=6);let o;typeof t=="string"?(!e.mask||r)&&e[Qe]!==void 0?o=e[Qe]:(t=Buffer.from(t),o=t.length):(o=t.length,n=e.mask&&e.readOnly&&!r);let c=o;o>=65536?(a+=8,c=127):o>125&&(a+=2,c=126);let l=Buffer.allocUnsafe(n?o+a:a);return l[0]=e.fin?e.opcode|128:e.opcode,e.rsv1&&(l[0]|=64),l[1]=c,c===126?l.writeUInt16BE(o,2):c===127&&(l[2]=l[3]=0,l.writeUIntBE(o,4,6)),e.mask?(l[1]|=128,l[a-4]=s[0],l[a-3]=s[1],l[a-2]=s[2],l[a-1]=s[3],r?[l,t]:n?(Nr(t,s,l,a,o),[l]):(Nr(t,s,t,0,o),[l,t])):[l,t]}close(t,e,s,n){let a;if(t===void 0)a=Cc;else{if(typeof t!="number"||!Ac(t))throw new TypeError("First argument must be a valid error code number");if(e===void 0||!e.length)a=Buffer.allocUnsafe(2),a.writeUInt16BE(t,0);else{let o=Buffer.byteLength(e);if(o>123)throw new RangeError("The message must not be greater than 123 bytes");a=Buffer.allocUnsafe(2+o),a.writeUInt16BE(t,0),typeof e=="string"?a.write(e,2):a.set(e,2)}}let r={[Qe]:a.length,fin:!0,generateMask:this._generateMask,mask:s,maskBuffer:this._maskBuffer,opcode:8,readOnly:!1,rsv1:!1};this._state!==rt?this.enqueue([this.dispatch,a,!1,r,n]):this.sendFrame(i.frame(a,r),n)}ping(t,e,s){let n,a;if(typeof t=="string"?(n=Buffer.byteLength(t),a=!1):Xt(t)?(n=t.size,a=!1):(t=Rt(t),n=t.length,a=Rt.readOnly),n>125)throw new RangeError("The data size must not be greater than 125 bytes");let r={[Qe]:n,fin:!0,generateMask:this._generateMask,mask:e,maskBuffer:this._maskBuffer,opcode:9,readOnly:a,rsv1:!1};Xt(t)?this._state!==rt?this.enqueue([this.getBlobData,t,!1,r,s]):this.getBlobData(t,!1,r,s):this._state!==rt?this.enqueue([this.dispatch,t,!1,r,s]):this.sendFrame(i.frame(t,r),s)}pong(t,e,s){let n,a;if(typeof t=="string"?(n=Buffer.byteLength(t),a=!1):Xt(t)?(n=t.size,a=!1):(t=Rt(t),n=t.length,a=Rt.readOnly),n>125)throw new RangeError("The data size must not be greater than 125 bytes");let r={[Qe]:n,fin:!0,generateMask:this._generateMask,mask:e,maskBuffer:this._maskBuffer,opcode:10,readOnly:a,rsv1:!1};Xt(t)?this._state!==rt?this.enqueue([this.getBlobData,t,!1,r,s]):this.getBlobData(t,!1,r,s):this._state!==rt?this.enqueue([this.dispatch,t,!1,r,s]):this.sendFrame(i.frame(t,r),s)}send(t,e,s){let n=this._extensions[Or.extensionName],a=e.binary?2:1,r=e.compress,o,c;typeof t=="string"?(o=Buffer.byteLength(t),c=!1):Xt(t)?(o=t.size,c=!1):(t=Rt(t),o=t.length,c=Rt.readOnly),this._firstFragment?(this._firstFragment=!1,r&&n&&n.params[n._isServer?"server_no_context_takeover":"client_no_context_takeover"]&&(r=o>=n._threshold),this._compress=r):(r=!1,a=0),e.fin&&(this._firstFragment=!0);let l={[Qe]:o,fin:e.fin,generateMask:this._generateMask,mask:e.mask,maskBuffer:this._maskBuffer,opcode:a,readOnly:c,rsv1:r};Xt(t)?this._state!==rt?this.enqueue([this.getBlobData,t,this._compress,l,s]):this.getBlobData(t,this._compress,l,s):this._state!==rt?this.enqueue([this.dispatch,t,this._compress,l,s]):this.dispatch(t,this._compress,l,s)}getBlobData(t,e,s,n){this._bufferedBytes+=s[Qe],this._state=Rc,t.arrayBuffer().then(a=>{if(this._socket.destroyed){let o=new Error("The socket was closed while the blob was being read");process.nextTick(Pa,this,o,n);return}this._bufferedBytes-=s[Qe];let r=Rt(a);e?this.dispatch(r,e,s,n):(this._state=rt,this.sendFrame(i.frame(r,s),n),this.dequeue())}).catch(a=>{process.nextTick(Dc,this,a,n)})}dispatch(t,e,s,n){if(!e){this.sendFrame(i.frame(t,s),n);return}let a=this._extensions[Or.extensionName];this._bufferedBytes+=s[Qe],this._state=Pc,a.compress(t,s.fin,(r,o)=>{if(this._socket.destroyed){let c=new Error("The socket was closed while data was being compressed");Pa(this,c,n);return}this._bufferedBytes-=s[Qe],this._state=rt,s.readOnly=!1,this.sendFrame(i.frame(o,s),n),this.dequeue()})}dequeue(){for(;this._state===rt&&this._queue.length;){let t=this._queue.shift();this._bufferedBytes-=t[3][Qe],Reflect.apply(t[0],this,t.slice(1))}}enqueue(t){this._bufferedBytes+=t[3][Qe],this._queue.push(t)}sendFrame(t,e){t.length===2?(this._socket.cork(),this._socket.write(t[0]),this._socket.write(t[1],e),this._socket.uncork()):this._socket.write(t[0],e)}};Br.exports=Ea;function Pa(i,t,e){typeof e=="function"&&e(t);for(let s=0;s<i._queue.length;s++){let n=i._queue[s],a=n[n.length-1];typeof a=="function"&&a(t)}}function Dc(i,t,e){Pa(i,t,e),i.onerror(t)}});var Vr=qe((ju,Gr)=>{"use strict";var{kForOnEventAttribute:Cs,kListener:Da}=mt(),Ur=Symbol("kCode"),$r=Symbol("kData"),jr=Symbol("kError"),Wr=Symbol("kMessage"),Hr=Symbol("kReason"),Zt=Symbol("kTarget"),qr=Symbol("kType"),zr=Symbol("kWasClean"),gt=class{constructor(t){this[Zt]=null,this[qr]=t}get target(){return this[Zt]}get type(){return this[qr]}};Object.defineProperty(gt.prototype,"target",{enumerable:!0});Object.defineProperty(gt.prototype,"type",{enumerable:!0});var It=class extends gt{constructor(t,e={}){super(t),this[Ur]=e.code===void 0?0:e.code,this[Hr]=e.reason===void 0?"":e.reason,this[zr]=e.wasClean===void 0?!1:e.wasClean}get code(){return this[Ur]}get reason(){return this[Hr]}get wasClean(){return this[zr]}};Object.defineProperty(It.prototype,"code",{enumerable:!0});Object.defineProperty(It.prototype,"reason",{enumerable:!0});Object.defineProperty(It.prototype,"wasClean",{enumerable:!0});var es=class extends gt{constructor(t,e={}){super(t),this[jr]=e.error===void 0?null:e.error,this[Wr]=e.message===void 0?"":e.message}get error(){return this[jr]}get message(){return this[Wr]}};Object.defineProperty(es.prototype,"error",{enumerable:!0});Object.defineProperty(es.prototype,"message",{enumerable:!0});var Ts=class extends gt{constructor(t,e={}){super(t),this[$r]=e.data===void 0?null:e.data}get data(){return this[$r]}};Object.defineProperty(Ts.prototype,"data",{enumerable:!0});var Ic={addEventListener(i,t,e={}){for(let n of this.listeners(i))if(!e[Cs]&&n[Da]===t&&!n[Cs])return;let s;if(i==="message")s=function(a,r){let o=new Ts("message",{data:r?a:a.toString()});o[Zt]=this,_n(t,this,o)};else if(i==="close")s=function(a,r){let o=new It("close",{code:a,reason:r.toString(),wasClean:this._closeFrameReceived&&this._closeFrameSent});o[Zt]=this,_n(t,this,o)};else if(i==="error")s=function(a){let r=new es("error",{error:a,message:a.message});r[Zt]=this,_n(t,this,r)};else if(i==="open")s=function(){let a=new gt("open");a[Zt]=this,_n(t,this,a)};else return;s[Cs]=!!e[Cs],s[Da]=t,e.once?this.once(i,s):this.on(i,s)},removeEventListener(i,t){for(let e of this.listeners(i))if(e[Da]===t&&!e[Cs]){this.removeListener(i,e);break}}};Gr.exports={CloseEvent:It,ErrorEvent:es,Event:gt,EventTarget:Ic,MessageEvent:Ts};function _n(i,t,e){typeof i=="object"&&i.handleEvent?i.handleEvent.call(i,e):i.call(t,e)}});var An=qe((Wu,Yr)=>{"use strict";var{tokenChars:_s}=Jt();function ht(i,t,e){i[t]===void 0?i[t]=[e]:i[t].push(e)}function Mc(i){let t=Object.create(null),e=Object.create(null),s=!1,n=!1,a=!1,r,o,c=-1,l=-1,h=-1,d=0;for(;d<i.length;d++)if(l=i.charCodeAt(d),r===void 0)if(h===-1&&_s[l]===1)c===-1&&(c=d);else if(d!==0&&(l===32||l===9))h===-1&&c!==-1&&(h=d);else if(l===59||l===44){if(c===-1)throw new SyntaxError(`Unexpected character at index ${d}`);h===-1&&(h=d);let p=i.slice(c,h);l===44?(ht(t,p,e),e=Object.create(null)):r=p,c=h=-1}else throw new SyntaxError(`Unexpected character at index ${d}`);else if(o===void 0)if(h===-1&&_s[l]===1)c===-1&&(c=d);else if(l===32||l===9)h===-1&&c!==-1&&(h=d);else if(l===59||l===44){if(c===-1)throw new SyntaxError(`Unexpected character at index ${d}`);h===-1&&(h=d),ht(e,i.slice(c,h),!0),l===44&&(ht(t,r,e),e=Object.create(null),r=void 0),c=h=-1}else if(l===61&&c!==-1&&h===-1)o=i.slice(c,d),c=h=-1;else throw new SyntaxError(`Unexpected character at index ${d}`);else if(n){if(_s[l]!==1)throw new SyntaxError(`Unexpected character at index ${d}`);c===-1?c=d:s||(s=!0),n=!1}else if(a)if(_s[l]===1)c===-1&&(c=d);else if(l===34&&c!==-1)a=!1,h=d;else if(l===92)n=!0;else throw new SyntaxError(`Unexpected character at index ${d}`);else if(l===34&&i.charCodeAt(d-1)===61)a=!0;else if(h===-1&&_s[l]===1)c===-1&&(c=d);else if(c!==-1&&(l===32||l===9))h===-1&&(h=d);else if(l===59||l===44){if(c===-1)throw new SyntaxError(`Unexpected character at index ${d}`);h===-1&&(h=d);let p=i.slice(c,h);s&&(p=p.replace(/\\/g,""),s=!1),ht(e,o,p),l===44&&(ht(t,r,e),e=Object.create(null),r=void 0),o=void 0,c=h=-1}else throw new SyntaxError(`Unexpected character at index ${d}`);if(c===-1||a||l===32||l===9)throw new SyntaxError("Unexpected end of input");h===-1&&(h=d);let u=i.slice(c,h);return r===void 0?ht(t,u,e):(o===void 0?ht(e,u,!0):s?ht(e,o,u.replace(/\\/g,"")):ht(e,o,u),ht(t,r,e)),t}function Lc(i){return Object.keys(i).map(t=>{let e=i[t];return Array.isArray(e)||(e=[e]),e.map(s=>[t].concat(Object.keys(s).map(n=>{let a=s[n];return Array.isArray(a)||(a=[a]),a.map(r=>r===!0?n:`${n}=${r}`).join("; ")})).join("; ")).join(", ")}).join(", ")}Yr.exports={format:Lc,parse:Mc}});var Dn=qe((zu,ro)=>{"use strict";var Fc=require("events"),Oc=require("https"),Nc=require("http"),Xr=require("net"),Bc=require("tls"),{randomBytes:Uc,createHash:$c}=require("crypto"),{Duplex:Hu,Readable:qu}=require("stream"),{URL:Ia}=require("url"),xt=Kt(),jc=Aa(),Wc=Ra(),{isBlob:Hc}=Jt(),{BINARY_TYPES:Kr,CLOSE_TIMEOUT:qc,EMPTY_BUFFER:En,GUID:zc,kForOnEventAttribute:Ma,kListener:Gc,kStatusCode:Vc,kWebSocket:Ie,NOOP:Qr}=mt(),{EventTarget:{addEventListener:Yc,removeEventListener:Kc}}=Vr(),{format:Jc,parse:Xc}=An(),{toBuffer:Qc}=xs(),Zr=Symbol("kAborted"),La=[8,13],yt=["CONNECTING","OPEN","CLOSING","CLOSED"],Zc=/^[!#$%&'*+\-.0-9A-Z^_`|a-z~]+$/,be=class i extends Fc{constructor(t,e,s){super(),this._binaryType=Kr[0],this._closeCode=1006,this._closeFrameReceived=!1,this._closeFrameSent=!1,this._closeMessage=En,this._closeTimer=null,this._errorEmitted=!1,this._extensions={},this._paused=!1,this._protocol="",this._readyState=i.CONNECTING,this._receiver=null,this._sender=null,this._socket=null,t!==null?(this._bufferedAmount=0,this._isServer=!1,this._redirects=0,e===void 0?e=[]:Array.isArray(e)||(typeof e=="object"&&e!==null?(s=e,e=[]):e=[e]),eo(this,t,e,s)):(this._autoPong=s.autoPong,this._closeTimeout=s.closeTimeout,this._isServer=!0)}get binaryType(){return this._binaryType}set binaryType(t){Kr.includes(t)&&(this._binaryType=t,this._receiver&&(this._receiver._binaryType=t))}get bufferedAmount(){return this._socket?this._socket._writableState.length+this._sender._bufferedBytes:this._bufferedAmount}get extensions(){return Object.keys(this._extensions).join()}get isPaused(){return this._paused}get onclose(){return null}get onerror(){return null}get onopen(){return null}get onmessage(){return null}get protocol(){return this._protocol}get readyState(){return this._readyState}get url(){return this._url}setSocket(t,e,s){let n=new jc({allowSynchronousEvents:s.allowSynchronousEvents,binaryType:this.binaryType,extensions:this._extensions,isServer:this._isServer,maxPayload:s.maxPayload,skipUTF8Validation:s.skipUTF8Validation}),a=new Wc(t,this._extensions,s.generateMask);this._receiver=n,this._sender=a,this._socket=t,n[Ie]=this,a[Ie]=this,t[Ie]=this,n.on("conclude",sd),n.on("drain",nd),n.on("error",ad),n.on("message",id),n.on("ping",rd),n.on("pong",od),a.onerror=ld,t.setTimeout&&t.setTimeout(0),t.setNoDelay&&t.setNoDelay(),e.length>0&&t.unshift(e),t.on("close",no),t.on("data",Rn),t.on("end",ao),t.on("error",io),this._readyState=i.OPEN,this.emit("open")}emitClose(){if(!this._socket){this._readyState=i.CLOSED,this.emit("close",this._closeCode,this._closeMessage);return}this._extensions[xt.extensionName]&&this._extensions[xt.extensionName].cleanup(),this._receiver.removeAllListeners(),this._readyState=i.CLOSED,this.emit("close",this._closeCode,this._closeMessage)}close(t,e){if(this.readyState!==i.CLOSED){if(this.readyState===i.CONNECTING){Ke(this,this._req,"WebSocket was closed before the connection was established");return}if(this.readyState===i.CLOSING){this._closeFrameSent&&(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end();return}this._readyState=i.CLOSING,this._sender.close(t,e,!this._isServer,s=>{s||(this._closeFrameSent=!0,(this._closeFrameReceived||this._receiver._writableState.errorEmitted)&&this._socket.end())}),so(this)}}pause(){this.readyState===i.CONNECTING||this.readyState===i.CLOSED||(this._paused=!0,this._socket.pause())}ping(t,e,s){if(this.readyState===i.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof t=="function"?(s=t,t=e=void 0):typeof e=="function"&&(s=e,e=void 0),typeof t=="number"&&(t=t.toString()),this.readyState!==i.OPEN){Fa(this,t,s);return}e===void 0&&(e=!this._isServer),this._sender.ping(t||En,e,s)}pong(t,e,s){if(this.readyState===i.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof t=="function"?(s=t,t=e=void 0):typeof e=="function"&&(s=e,e=void 0),typeof t=="number"&&(t=t.toString()),this.readyState!==i.OPEN){Fa(this,t,s);return}e===void 0&&(e=!this._isServer),this._sender.pong(t||En,e,s)}resume(){this.readyState===i.CONNECTING||this.readyState===i.CLOSED||(this._paused=!1,this._receiver._writableState.needDrain||this._socket.resume())}send(t,e,s){if(this.readyState===i.CONNECTING)throw new Error("WebSocket is not open: readyState 0 (CONNECTING)");if(typeof e=="function"&&(s=e,e={}),typeof t=="number"&&(t=t.toString()),this.readyState!==i.OPEN){Fa(this,t,s);return}let n={binary:typeof t!="string",mask:!this._isServer,compress:!0,fin:!0,...e};this._extensions[xt.extensionName]||(n.compress=!1),this._sender.send(t||En,n,s)}terminate(){if(this.readyState!==i.CLOSED){if(this.readyState===i.CONNECTING){Ke(this,this._req,"WebSocket was closed before the connection was established");return}this._socket&&(this._readyState=i.CLOSING,this._socket.destroy())}}};Object.defineProperty(be,"CONNECTING",{enumerable:!0,value:yt.indexOf("CONNECTING")});Object.defineProperty(be.prototype,"CONNECTING",{enumerable:!0,value:yt.indexOf("CONNECTING")});Object.defineProperty(be,"OPEN",{enumerable:!0,value:yt.indexOf("OPEN")});Object.defineProperty(be.prototype,"OPEN",{enumerable:!0,value:yt.indexOf("OPEN")});Object.defineProperty(be,"CLOSING",{enumerable:!0,value:yt.indexOf("CLOSING")});Object.defineProperty(be.prototype,"CLOSING",{enumerable:!0,value:yt.indexOf("CLOSING")});Object.defineProperty(be,"CLOSED",{enumerable:!0,value:yt.indexOf("CLOSED")});Object.defineProperty(be.prototype,"CLOSED",{enumerable:!0,value:yt.indexOf("CLOSED")});["binaryType","bufferedAmount","extensions","isPaused","protocol","readyState","url"].forEach(i=>{Object.defineProperty(be.prototype,i,{enumerable:!0})});["open","error","close","message"].forEach(i=>{Object.defineProperty(be.prototype,`on${i}`,{enumerable:!0,get(){for(let t of this.listeners(i))if(t[Ma])return t[Gc];return null},set(t){for(let e of this.listeners(i))if(e[Ma]){this.removeListener(i,e);break}typeof t=="function"&&this.addEventListener(i,t,{[Ma]:!0})}})});be.prototype.addEventListener=Yc;be.prototype.removeEventListener=Kc;ro.exports=be;function eo(i,t,e,s){let n={allowSynchronousEvents:!0,autoPong:!0,closeTimeout:qc,protocolVersion:La[1],maxPayload:104857600,skipUTF8Validation:!1,perMessageDeflate:!0,followRedirects:!1,maxRedirects:10,...s,socketPath:void 0,hostname:void 0,protocol:void 0,timeout:void 0,method:"GET",host:void 0,path:void 0,port:void 0};if(i._autoPong=n.autoPong,i._closeTimeout=n.closeTimeout,!La.includes(n.protocolVersion))throw new RangeError(`Unsupported protocol version: ${n.protocolVersion} (supported versions: ${La.join(", ")})`);let a;if(t instanceof Ia)a=t;else try{a=new Ia(t)}catch{throw new SyntaxError(`Invalid URL: ${t}`)}a.protocol==="http:"?a.protocol="ws:":a.protocol==="https:"&&(a.protocol="wss:"),i._url=a.href;let r=a.protocol==="wss:",o=a.protocol==="ws+unix:",c;if(a.protocol!=="ws:"&&!r&&!o?c=`The URL's protocol must be one of "ws:", "wss:", "http:", "https:", or "ws+unix:"`:o&&!a.pathname?c="The URL's pathname is empty":a.hash&&(c="The URL contains a fragment identifier"),c){let f=new SyntaxError(c);if(i._redirects===0)throw f;Pn(i,f);return}let l=r?443:80,h=Uc(16).toString("base64"),d=r?Oc.request:Nc.request,u=new Set,p;if(n.createConnection=n.createConnection||(r?td:ed),n.defaultPort=n.defaultPort||l,n.port=a.port||l,n.host=a.hostname.startsWith("[")?a.hostname.slice(1,-1):a.hostname,n.headers={...n.headers,"Sec-WebSocket-Version":n.protocolVersion,"Sec-WebSocket-Key":h,Connection:"Upgrade",Upgrade:"websocket"},n.path=a.pathname+a.search,n.timeout=n.handshakeTimeout,n.perMessageDeflate&&(p=new xt({...n.perMessageDeflate,isServer:!1,maxPayload:n.maxPayload}),n.headers["Sec-WebSocket-Extensions"]=Jc({[xt.extensionName]:p.offer()})),e.length){for(let f of e){if(typeof f!="string"||!Zc.test(f)||u.has(f))throw new SyntaxError("An invalid or duplicated subprotocol was specified");u.add(f)}n.headers["Sec-WebSocket-Protocol"]=e.join(",")}if(n.origin&&(n.protocolVersion<13?n.headers["Sec-WebSocket-Origin"]=n.origin:n.headers.Origin=n.origin),(a.username||a.password)&&(n.auth=`${a.username}:${a.password}`),o){let f=n.path.split(":");n.socketPath=f[0],n.path=f[1]}let m;if(n.followRedirects){if(i._redirects===0){i._originalIpc=o,i._originalSecure=r,i._originalHostOrSocketPath=o?n.socketPath:a.host;let f=s&&s.headers;if(s={...s,headers:{}},f)for(let[g,v]of Object.entries(f))s.headers[g.toLowerCase()]=v}else if(i.listenerCount("redirect")===0){let f=o?i._originalIpc?n.socketPath===i._originalHostOrSocketPath:!1:i._originalIpc?!1:a.host===i._originalHostOrSocketPath;(!f||i._originalSecure&&!r)&&(delete n.headers.authorization,delete n.headers.cookie,f||delete n.headers.host,n.auth=void 0)}n.auth&&!s.headers.authorization&&(s.headers.authorization="Basic "+Buffer.from(n.auth).toString("base64")),m=i._req=d(n),i._redirects&&i.emit("redirect",i.url,m)}else m=i._req=d(n);n.timeout&&m.on("timeout",()=>{Ke(i,m,"Opening handshake has timed out")}),m.on("error",f=>{m===null||m[Zr]||(m=i._req=null,Pn(i,f))}),m.on("response",f=>{let g=f.headers.location,v=f.statusCode;if(g&&n.followRedirects&&v>=300&&v<400){if(++i._redirects>n.maxRedirects){Ke(i,m,"Maximum redirects exceeded");return}m.abort();let b;try{b=new Ia(g,t)}catch{let y=new SyntaxError(`Invalid URL: ${g}`);Pn(i,y);return}eo(i,b,e,s)}else i.emit("unexpected-response",m,f)||Ke(i,m,`Unexpected server response: ${f.statusCode}`)}),m.on("upgrade",(f,g,v)=>{if(i.emit("upgrade",f),i.readyState!==be.CONNECTING)return;m=i._req=null;let b=f.headers.upgrade;if(b===void 0||b.toLowerCase()!=="websocket"){Ke(i,g,"Invalid Upgrade header");return}let k=$c("sha1").update(h+zc).digest("base64");if(f.headers["sec-websocket-accept"]!==k){Ke(i,g,"Invalid Sec-WebSocket-Accept header");return}let y=f.headers["sec-websocket-protocol"],S;if(y!==void 0?u.size?u.has(y)||(S="Server sent an invalid subprotocol"):S="Server sent a subprotocol but none was requested":u.size&&(S="Server sent no subprotocol"),S){Ke(i,g,S);return}y&&(i._protocol=y);let T=f.headers["sec-websocket-extensions"];if(T!==void 0){if(!p){Ke(i,g,"Server sent a Sec-WebSocket-Extensions header but no extension was requested");return}let _;try{_=Xc(T)}catch{Ke(i,g,"Invalid Sec-WebSocket-Extensions header");return}let D=Object.keys(_);if(D.length!==1||D[0]!==xt.extensionName){Ke(i,g,"Server indicated an extension that was not requested");return}try{p.accept(_[xt.extensionName])}catch{Ke(i,g,"Invalid Sec-WebSocket-Extensions header");return}i._extensions[xt.extensionName]=p}i.setSocket(g,v,{allowSynchronousEvents:n.allowSynchronousEvents,generateMask:n.generateMask,maxPayload:n.maxPayload,skipUTF8Validation:n.skipUTF8Validation})}),n.finishRequest?n.finishRequest(m,i):m.end()}function Pn(i,t){i._readyState=be.CLOSING,i._errorEmitted=!0,i.emit("error",t),i.emitClose()}function ed(i){return i.path=i.socketPath,Xr.connect(i)}function td(i){return i.path=void 0,!i.servername&&i.servername!==""&&(i.servername=Xr.isIP(i.host)?"":i.host),Bc.connect(i)}function Ke(i,t,e){i._readyState=be.CLOSING;let s=new Error(e);Error.captureStackTrace(s,Ke),t.setHeader?(t[Zr]=!0,t.abort(),t.socket&&!t.socket.destroyed&&t.socket.destroy(),process.nextTick(Pn,i,s)):(t.destroy(s),t.once("error",i.emit.bind(i,"error")),t.once("close",i.emitClose.bind(i)))}function Fa(i,t,e){if(t){let s=Hc(t)?t.size:Qc(t).length;i._socket?i._sender._bufferedBytes+=s:i._bufferedAmount+=s}if(e){let s=new Error(`WebSocket is not open: readyState ${i.readyState} (${yt[i.readyState]})`);process.nextTick(e,s)}}function sd(i,t){let e=this[Ie];e._closeFrameReceived=!0,e._closeMessage=t,e._closeCode=i,e._socket[Ie]!==void 0&&(e._socket.removeListener("data",Rn),process.nextTick(to,e._socket),i===1005?e.close():e.close(i,t))}function nd(){let i=this[Ie];i.isPaused||i._socket.resume()}function ad(i){let t=this[Ie];t._socket[Ie]!==void 0&&(t._socket.removeListener("data",Rn),process.nextTick(to,t._socket),t.close(i[Vc])),t._errorEmitted||(t._errorEmitted=!0,t.emit("error",i))}function Jr(){this[Ie].emitClose()}function id(i,t){this[Ie].emit("message",i,t)}function rd(i){let t=this[Ie];t._autoPong&&t.pong(i,!this._isServer,Qr),t.emit("ping",i)}function od(i){this[Ie].emit("pong",i)}function to(i){i.resume()}function ld(i){let t=this[Ie];t.readyState!==be.CLOSED&&(t.readyState===be.OPEN&&(t._readyState=be.CLOSING,so(t)),this._socket.end(),t._errorEmitted||(t._errorEmitted=!0,t.emit("error",i)))}function so(i){i._closeTimer=setTimeout(i._socket.destroy.bind(i._socket),i._closeTimeout)}function no(){let i=this[Ie];if(this.removeListener("close",no),this.removeListener("data",Rn),this.removeListener("end",ao),i._readyState=be.CLOSING,!this._readableState.endEmitted&&!i._closeFrameReceived&&!i._receiver._writableState.errorEmitted&&this._readableState.length!==0){let t=this.read(this._readableState.length);i._receiver.write(t)}i._receiver.end(),this[Ie]=void 0,clearTimeout(i._closeTimer),i._receiver._writableState.finished||i._receiver._writableState.errorEmitted?i.emitClose():(i._receiver.on("error",Jr),i._receiver.on("finish",Jr))}function Rn(i){this[Ie]._receiver.write(i)||this.pause()}function ao(){let i=this[Ie];i._readyState=be.CLOSING,i._receiver.end(),this.end()}function io(){let i=this[Ie];this.removeListener("error",io),this.on("error",Qr),i&&(i._readyState=be.CLOSING,this.destroy())}});var ho=qe((Vu,co)=>{"use strict";var Gu=Dn(),{Duplex:cd}=require("stream");function oo(i){i.emit("close")}function dd(){!this.destroyed&&this._writableState.finished&&this.destroy()}function lo(i){this.removeListener("error",lo),this.destroy(),this.listenerCount("error")===0&&this.emit("error",i)}function hd(i,t){let e=!0,s=new cd({...t,autoDestroy:!1,emitClose:!1,objectMode:!1,writableObjectMode:!1});return i.on("message",function(a,r){let o=!r&&s._readableState.objectMode?a.toString():a;s.push(o)||i.pause()}),i.once("error",function(a){s.destroyed||(e=!1,s.destroy(a))}),i.once("close",function(){s.destroyed||s.push(null)}),s._destroy=function(n,a){if(i.readyState===i.CLOSED){a(n),process.nextTick(oo,s);return}let r=!1;i.once("error",function(c){r=!0,a(c)}),i.once("close",function(){r||a(n),process.nextTick(oo,s)}),e&&i.terminate()},s._final=function(n){if(i.readyState===i.CONNECTING){i.once("open",function(){s._final(n)});return}i._socket!==null&&(i._socket._writableState.finished?(n(),s._readableState.endEmitted&&s.destroy()):(i._socket.once("finish",function(){n()}),i.close()))},s._read=function(){i.isPaused&&i.resume()},s._write=function(n,a,r){if(i.readyState===i.CONNECTING){i.once("open",function(){s._write(n,a,r)});return}i.send(n,r)},s.on("end",dd),s.on("error",lo),s}co.exports=hd});var Oa=qe((Yu,uo)=>{"use strict";var{tokenChars:ud}=Jt();function pd(i){let t=new Set,e=-1,s=-1,n=0;for(n;n<i.length;n++){let r=i.charCodeAt(n);if(s===-1&&ud[r]===1)e===-1&&(e=n);else if(n!==0&&(r===32||r===9))s===-1&&e!==-1&&(s=n);else if(r===44){if(e===-1)throw new SyntaxError(`Unexpected character at index ${n}`);s===-1&&(s=n);let o=i.slice(e,s);if(t.has(o))throw new SyntaxError(`The "${o}" subprotocol is duplicated`);t.add(o),e=s=-1}else throw new SyntaxError(`Unexpected character at index ${n}`)}if(e===-1||s!==-1)throw new SyntaxError("Unexpected end of input");let a=i.slice(e,n);if(t.has(a))throw new SyntaxError(`The "${a}" subprotocol is duplicated`);return t.add(a),t}uo.exports={parse:pd}});var wo=qe((Ju,vo)=>{"use strict";var md=require("events"),In=require("http"),{Duplex:Ku}=require("stream"),{createHash:fd}=require("crypto"),po=An(),Mt=Kt(),gd=Oa(),yd=Dn(),{CLOSE_TIMEOUT:vd,GUID:wd,kWebSocket:bd}=mt(),kd=/^[+/0-9A-Za-z]{22}==$/,mo=0,fo=1,yo=2,Na=class extends md{constructor(t,e){if(super(),t={allowSynchronousEvents:!0,autoPong:!0,maxPayload:100*1024*1024,skipUTF8Validation:!1,perMessageDeflate:!1,handleProtocols:null,clientTracking:!0,closeTimeout:vd,verifyClient:null,noServer:!1,backlog:null,server:null,host:null,path:null,port:null,WebSocket:yd,...t},t.port==null&&!t.server&&!t.noServer||t.port!=null&&(t.server||t.noServer)||t.server&&t.noServer)throw new TypeError('One and only one of the "port", "server", or "noServer" options must be specified');if(t.port!=null?(this._server=In.createServer((s,n)=>{let a=In.STATUS_CODES[426];n.writeHead(426,{"Content-Length":a.length,"Content-Type":"text/plain"}),n.end(a)}),this._server.listen(t.port,t.host,t.backlog,e)):t.server&&(this._server=t.server),this._server){let s=this.emit.bind(this,"connection");this._removeListeners=xd(this._server,{listening:this.emit.bind(this,"listening"),error:this.emit.bind(this,"error"),upgrade:(n,a,r)=>{this.handleUpgrade(n,a,r,s)}})}t.perMessageDeflate===!0&&(t.perMessageDeflate={}),t.clientTracking&&(this.clients=new Set,this._shouldEmitClose=!1),this.options=t,this._state=mo}address(){if(this.options.noServer)throw new Error('The server is operating in "noServer" mode');return this._server?this._server.address():null}close(t){if(this._state===yo){t&&this.once("close",()=>{t(new Error("The server is not running"))}),process.nextTick(As,this);return}if(t&&this.once("close",t),this._state!==fo)if(this._state=fo,this.options.noServer||this.options.server)this._server&&(this._removeListeners(),this._removeListeners=this._server=null),this.clients?this.clients.size?this._shouldEmitClose=!0:process.nextTick(As,this):process.nextTick(As,this);else{let e=this._server;this._removeListeners(),this._removeListeners=this._server=null,e.close(()=>{As(this)})}}shouldHandle(t){if(this.options.path){let e=t.url.indexOf("?");if((e!==-1?t.url.slice(0,e):t.url)!==this.options.path)return!1}return!0}handleUpgrade(t,e,s,n){e.on("error",go);let a=t.headers["sec-websocket-key"],r=t.headers.upgrade,o=+t.headers["sec-websocket-version"];if(t.method!=="GET"){Lt(this,t,e,405,"Invalid HTTP method");return}if(r===void 0||r.toLowerCase()!=="websocket"){Lt(this,t,e,400,"Invalid Upgrade header");return}if(a===void 0||!kd.test(a)){Lt(this,t,e,400,"Missing or invalid Sec-WebSocket-Key header");return}if(o!==13&&o!==8){Lt(this,t,e,400,"Missing or invalid Sec-WebSocket-Version header",{"Sec-WebSocket-Version":"13, 8"});return}if(!this.shouldHandle(t)){Es(e,400);return}let c=t.headers["sec-websocket-protocol"],l=new Set;if(c!==void 0)try{l=gd.parse(c)}catch{Lt(this,t,e,400,"Invalid Sec-WebSocket-Protocol header");return}let h=t.headers["sec-websocket-extensions"],d={};if(this.options.perMessageDeflate&&h!==void 0){let u=new Mt({...this.options.perMessageDeflate,isServer:!0,maxPayload:this.options.maxPayload});try{let p=po.parse(h);p[Mt.extensionName]&&(u.accept(p[Mt.extensionName]),d[Mt.extensionName]=u)}catch{Lt(this,t,e,400,"Invalid or unacceptable Sec-WebSocket-Extensions header");return}}if(this.options.verifyClient){let u={origin:t.headers[`${o===8?"sec-websocket-origin":"origin"}`],secure:!!(t.socket.authorized||t.socket.encrypted),req:t};if(this.options.verifyClient.length===2){this.options.verifyClient(u,(p,m,f,g)=>{if(!p)return Es(e,m||401,f,g);this.completeUpgrade(d,a,l,t,e,s,n)});return}if(!this.options.verifyClient(u))return Es(e,401)}this.completeUpgrade(d,a,l,t,e,s,n)}completeUpgrade(t,e,s,n,a,r,o){if(!a.readable||!a.writable)return a.destroy();if(a[bd])throw new Error("server.handleUpgrade() was called more than once with the same socket, possibly due to a misconfiguration");if(this._state>mo)return Es(a,503);let l=["HTTP/1.1 101 Switching Protocols","Upgrade: websocket","Connection: Upgrade",`Sec-WebSocket-Accept: ${fd("sha1").update(e+wd).digest("base64")}`],h=new this.options.WebSocket(null,void 0,this.options);if(s.size){let d=this.options.handleProtocols?this.options.handleProtocols(s,n):s.values().next().value;d&&(l.push(`Sec-WebSocket-Protocol: ${d}`),h._protocol=d)}if(t[Mt.extensionName]){let d=t[Mt.extensionName].params,u=po.format({[Mt.extensionName]:[d]});l.push(`Sec-WebSocket-Extensions: ${u}`),h._extensions=t}this.emit("headers",l,n),a.write(l.concat(`\r
2
2
  `).join(`\r
3
- `)),a.removeListener("error",fo),d.setSocket(a,r,{allowSynchronousEvents:this.options.allowSynchronousEvents,maxPayload:this.options.maxPayload,skipUTF8Validation:this.options.skipUTF8Validation}),this.clients&&(this.clients.add(d),d.on("close",()=>{this.clients.delete(d),this._shouldEmitClose&&!this.clients.size&&process.nextTick(As,this)})),o(d,n)}};yo.exports=Na;function kd(i,t){for(let e of Object.keys(t))i.on(e,t[e]);return function(){for(let s of Object.keys(t))i.removeListener(s,t[s])}}function As(i){i._state=go,i.emit("close")}function fo(){this.destroy()}function Es(i,t,e,s){e=e||In.STATUS_CODES[t],s={Connection:"close","Content-Type":"text/html","Content-Length":Buffer.byteLength(e),...s},i.once("finish",i.destroy),i.end(`HTTP/1.1 ${t} ${In.STATUS_CODES[t]}\r
3
+ `)),a.removeListener("error",go),h.setSocket(a,r,{allowSynchronousEvents:this.options.allowSynchronousEvents,maxPayload:this.options.maxPayload,skipUTF8Validation:this.options.skipUTF8Validation}),this.clients&&(this.clients.add(h),h.on("close",()=>{this.clients.delete(h),this._shouldEmitClose&&!this.clients.size&&process.nextTick(As,this)})),o(h,n)}};vo.exports=Na;function xd(i,t){for(let e of Object.keys(t))i.on(e,t[e]);return function(){for(let s of Object.keys(t))i.removeListener(s,t[s])}}function As(i){i._state=yo,i.emit("close")}function go(){this.destroy()}function Es(i,t,e,s){e=e||In.STATUS_CODES[t],s={Connection:"close","Content-Type":"text/html","Content-Length":Buffer.byteLength(e),...s},i.once("finish",i.destroy),i.end(`HTTP/1.1 ${t} ${In.STATUS_CODES[t]}\r
4
4
  `+Object.keys(s).map(n=>`${n}: ${s[n]}`).join(`\r
5
5
  `)+`\r
6
6
  \r
7
- `+e)}function Lt(i,t,e,s,n,a){if(i.listenerCount("wsClientError")){let r=new Error(n);Error.captureStackTrace(r,Lt),i.emit("wsClientError",r,e,t)}else Es(e,s,n,a)}});var Wd={};zo(Wd,{default:()=>jn});module.exports=Go(Wd);var Is=require("fs"),ja=require("os"),Wa=require("path"),xe=require("obsidian");var Ct="agent-fleet-agents";var vt="agent-fleet-dashboard",Xe="agent-fleet-chat",at={fleetFolder:"_fleet",claudeCliPath:"claude",codexCliPath:"codex",defaultModel:"default",awsRegion:"us-east-1",maxConcurrentRuns:2,runLogRetentionDays:30,catchUpMissedTasks:!0,notificationLevel:"all",showStatusBar:!0,mcpApiKeys:{},mcpTokens:{},channelCredentials:{},maxConcurrentChannelSessions:5,channelIdleTimeoutMinutes:15,channelRateLimitPerConversation:20,channelRateLimitWindowMinutes:5,chatWatchdogMinutes:10,defaultFileHashes:{}},Va=["agents","skills","tasks","runs","memory","channels","mcp"],Bs=1500,Ya="0 3 * * *",Ka=3;var wi=require("path"),x=require("obsidian");var qn=[{path:"agents/fleet-orchestrator/CONTEXT.md",content:`---
7
+ `+e)}function Lt(i,t,e,s,n,a){if(i.listenerCount("wsClientError")){let r=new Error(n);Error.captureStackTrace(r,Lt),i.emit("wsClientError",r,e,t)}else Es(e,s,n,a)}});var Hd={};Go(Hd,{default:()=>jn});module.exports=Vo(Hd);var Is=require("fs"),Wa=require("os"),Ha=require("path"),Ce=require("obsidian");var Ut="agent-fleet-agents";var Ct="agent-fleet-dashboard",nt="agent-fleet-chat",at={fleetFolder:"_fleet",claudeCliPath:"claude",codexCliPath:"codex",defaultModel:"default",awsRegion:"us-east-1",maxConcurrentRuns:2,runLogRetentionDays:30,catchUpMissedTasks:!0,notificationLevel:"all",showStatusBar:!0,mcpApiKeys:{},mcpTokens:{},channelCredentials:{},maxConcurrentChannelSessions:5,channelIdleTimeoutMinutes:15,channelRateLimitPerConversation:20,channelRateLimitWindowMinutes:5,chatWatchdogMinutes:10,defaultFileHashes:{}},Ya=["agents","skills","tasks","runs","memory","channels","mcp"],Bs=1500,Ka="0 3 * * *",Ja=3;var ki=require("path"),x=require("obsidian");var qn=[{path:"agents/fleet-orchestrator/CONTEXT.md",content:`---
8
8
  {}
9
9
  ---
10
10
 
@@ -11694,29 +11694,29 @@ python scripts/office/validate.py <path> [--original <original_file>] [--auto-re
11694
11694
 
11695
11695
  - \`paraId\`/\`durableId\` values that exceed OOXML limits
11696
11696
  - Missing \`xml:space="preserve"\` on \`w:t\` elements with whitespace
11697
- `}];var Us=require("obsidian");function Q(i){let t=i.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);if(!t)return{frontmatter:{},body:i.trim()};let e=t[1]??"",s=t[2]??"",n;try{n=(0,Us.parseYaml)(e)??{}}catch(a){console.warn("Agent Fleet: malformed YAML frontmatter, treating as empty",a),n={}}return{frontmatter:n,body:s.trim()}}function H(i,t){let e=(0,Us.stringifyYaml)(i).trim(),s=t.trim();return`---
11697
+ `}];var Us=require("obsidian");function J(i){let t=i.match(/^---\n([\s\S]*?)\n---\n?([\s\S]*)$/);if(!t)return{frontmatter:{},body:i.trim()};let e=t[1]??"",s=t[2]??"",n;try{n=(0,Us.parseYaml)(e)??{}}catch(a){console.warn("Agent Fleet: malformed YAML frontmatter, treating as empty",a),n={}}return{frontmatter:n,body:s.trim()}}function W(i,t){let e=(0,Us.stringifyYaml)(i).trim(),s=t.trim();return`---
11698
11698
  ${e}
11699
11699
  ---
11700
11700
 
11701
11701
  ${s}
11702
- `}function ae(i){return i.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/(^-|-$)/g,"")}function Ut(i,t){return i.length<=t?i:`${i.slice(0,t-1)}\u2026`}var $s=2,Qa=["Preferences","Procedures","Observations","Recent"],Za="Recent",Gn=/\[REMEMBER(?::([a-zA-Z]+))?\]([\s\S]*?)\[\/REMEMBER\]/g;function Vo(i){switch((i??"").toLowerCase()){case"pin":case"preference":case"preferences":return{pinned:!0,section:"Preferences"};case"procedure":case"procedures":return{pinned:!1,section:"Procedures"};case"observation":case"observations":return{pinned:!1,section:"Observations"};default:return{pinned:!1}}}function js(i){let t=[];for(let e of i.matchAll(Gn)){let s=(e[2]??"").trim();if(!s)continue;let n=Vo(e[1]);t.push({text:s,pinned:n.pinned,section:n.section})}return t}function ls(i){return i.replace(Gn,"").replace(/[ \t]+\n/g,`
11702
+ `}function oe(i){return i.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/(^-|-$)/g,"")}function $t(i,t){return i.length<=t?i:`${i.slice(0,t-1)}\u2026`}var $s=2,Za=["Preferences","Procedures","Observations","Recent"],ei="Recent",Gn=/\[REMEMBER(?::([a-zA-Z]+))?\]([\s\S]*?)\[\/REMEMBER\]/g;function Yo(i){switch((i??"").toLowerCase()){case"pin":case"preference":case"preferences":return{pinned:!0,section:"Preferences"};case"procedure":case"procedures":return{pinned:!1,section:"Procedures"};case"observation":case"observations":return{pinned:!1,section:"Observations"};default:return{pinned:!1}}}function js(i){let t=[];for(let e of i.matchAll(Gn)){let s=(e[2]??"").trim();if(!s)continue;let n=Yo(e[1]);t.push({text:s,pinned:n.pinned,section:n.section})}return t}function ls(i){return i.replace(Gn,"").replace(/[ \t]+\n/g,`
11703
11703
  `).replace(/\n{3,}/g,`
11704
11704
 
11705
- `).trim()}function ei(i){let t=i.replace(Gn,""),e=t.match(/\[REMEMBER(?::[a-zA-Z]+)?\][\s\S]*$/i);if(e&&e.index!==void 0)return t.slice(0,e.index);let s=t.match(/\[(?:R(?:E(?:M(?:E(?:M(?:B(?:E(?:R(?::[a-zA-Z]*)?)?)?)?)?)?)?)?)?$/i);return s&&s.index!==void 0?t.slice(0,s.index):t}var Yo={Preferences:"Preferences",Procedures:"Procedures",Observations:"Observations",Recent:"Recent (uncurated)"};function Ko(i){let t=i.trim().toLowerCase();return t.startsWith("preference")?"Preferences":t.startsWith("procedure")?"Procedures":t.startsWith("observation")?"Observations":t.startsWith("recent")?"Recent":"Observations"}function cs(i){return Math.ceil(i.length/4)}var Ja=500;function ti(i){let t=i.replace(/\s+/g," ").trim();return t.length<=Ja?t:`${t.slice(0,Ja-1).trimEnd()}\u2026`}function zn(i){return typeof i=="string"?i:void 0}function Jo(i,t){return typeof i=="number"&&Number.isFinite(i)?i:t}function si(i,t){return{filePath:i,agent:t,schema:$s,tokenEstimate:0,sections:[]}}var Xo=/\s*<!--\s*([\s\S]*?)\s*-->\s*$/,Xa=/^\[pin\]\s+/i;function Qo(i){let t=i.match(/^[-*]\s+(.*)$/);if(!t)return null;let e=(t[1]??"").trim();if(!e)return null;let s,n,a=e.match(Xo);if(a){e=e.slice(0,a.index).trim();let o=(a[1]??"").trim(),c=o.match(/^src:(\S+)(?:\s+(.+))?$/);c?(s=c[1],n=c[2]?.trim()||void 0):o&&(n=o)}let r=!1;return Xa.test(e)&&(r=!0,e=e.replace(Xa,"").trim()),e?{text:e,source:s,date:n,pinned:r}:null}function ni(i){let t=i.pinned?"[pin] ":"",e="";if(i.source||i.date){let s=[];i.source&&s.push(`src:${i.source}`),i.date&&s.push(i.date),e=` <!-- ${s.join(" ")} -->`}return`- ${t}${i.text}${e}`}function Ge(i){return Zo(i).map(e=>{let s=e.entries.map(ni).join(`
11706
- `);return`## ${Yo[e.name]}
11705
+ `).trim()}function ti(i){let t=i.replace(Gn,""),e=t.match(/\[REMEMBER(?::[a-zA-Z]+)?\][\s\S]*$/i);if(e&&e.index!==void 0)return t.slice(0,e.index);let s=t.match(/\[(?:R(?:E(?:M(?:E(?:M(?:B(?:E(?:R(?::[a-zA-Z]*)?)?)?)?)?)?)?)?)?$/i);return s&&s.index!==void 0?t.slice(0,s.index):t}var Ko={Preferences:"Preferences",Procedures:"Procedures",Observations:"Observations",Recent:"Recent (uncurated)"};function Jo(i){let t=i.trim().toLowerCase();return t.startsWith("preference")?"Preferences":t.startsWith("procedure")?"Procedures":t.startsWith("observation")?"Observations":t.startsWith("recent")?"Recent":"Observations"}function cs(i){return Math.ceil(i.length/4)}var Xa=500;function si(i){let t=i.replace(/\s+/g," ").trim();return t.length<=Xa?t:`${t.slice(0,Xa-1).trimEnd()}\u2026`}function zn(i){return typeof i=="string"?i:void 0}function Xo(i,t){return typeof i=="number"&&Number.isFinite(i)?i:t}function ni(i,t){return{filePath:i,agent:t,schema:$s,tokenEstimate:0,sections:[]}}var Qo=/\s*<!--\s*([\s\S]*?)\s*-->\s*$/,Qa=/^\[pin\]\s+/i;function Zo(i){let t=i.match(/^[-*]\s+(.*)$/);if(!t)return null;let e=(t[1]??"").trim();if(!e)return null;let s,n,a=e.match(Qo);if(a){e=e.slice(0,a.index).trim();let o=(a[1]??"").trim(),c=o.match(/^src:(\S+)(?:\s+(.+))?$/);c?(s=c[1],n=c[2]?.trim()||void 0):o&&(n=o)}let r=!1;return Qa.test(e)&&(r=!0,e=e.replace(Qa,"").trim()),e?{text:e,source:s,date:n,pinned:r}:null}function ai(i){let t=i.pinned?"[pin] ":"",e="";if(i.source||i.date){let s=[];i.source&&s.push(`src:${i.source}`),i.date&&s.push(i.date),e=` <!-- ${s.join(" ")} -->`}return`- ${t}${i.text}${e}`}function Ge(i){return el(i).map(e=>{let s=e.entries.map(ai).join(`
11706
+ `);return`## ${Ko[e.name]}
11707
11707
  ${s}`}).join(`
11708
11708
 
11709
- `)}function Zo(i){let t=[];for(let e of Qa){let s=i.find(n=>n.name===e);s&&s.entries.length>0&&t.push(s)}return t}function ai(i,t,e){let{frontmatter:s,body:n}=Q(i),a=Ws(n);return{filePath:t,agent:zn(s.agent)??e,schema:Jo(s.schema,$s),lastUpdated:zn(s.last_updated),lastReflection:zn(s.last_reflection),tokenEstimate:cs(Ge(a)),sections:a}}function Ws(i){let t=new Map,e=(a,r)=>{let o=t.get(a)??[];o.push(r),t.set(a,o)},s="Observations";for(let a of i.split(`
11710
- `)){let r=a.match(/^#{1,6}\s+(.+?)\s*$/);if(r){s=Ko(r[1]??"");continue}let o=Qo(a);o&&e(s,o)}let n=[];for(let a of Qa){let r=t.get(a);r&&r.length&&n.push({name:a,entries:r})}return n}function ii(i){let t=Ge(i.sections),e={agent:i.agent,schema:i.schema||$s,last_updated:i.lastUpdated??"",token_estimate:cs(t)};return i.lastReflection&&(e.last_reflection=i.lastReflection),H(e,t||"## Observations")}function ri(i,t,e,s){if(t.length===0)return i;let n=i.sections.map(o=>({name:o.name,entries:[...o.entries]})),a=n.find(o=>o.name===e);return a||(a={name:e,entries:[]},n.push(a)),a.entries.push(...t),{...i,sections:n,lastUpdated:s??i.lastUpdated,tokenEstimate:cs(Ge(n))}}var el=["Recent","Observations","Procedures"];function oi(i,t){if(i.tokenEstimate<=t)return{wm:i,spilled:[]};let e=i.sections.map(o=>({name:o.name,entries:[...o.entries]})),s=[],n=Ge(e).length,a=()=>Math.ceil(n/4)>t;for(let o of el){if(!a())break;let c=e.find(l=>l.name===o);if(c)for(;c.entries.length>0&&a();){let l=c.entries.findIndex(h=>!h.pinned);if(l===-1)break;let d=c.entries.splice(l,1)[0];d&&(s.push(d),n-=ni(d).length+1)}}let r=e.filter(o=>o.entries.length>0);return{wm:{...i,sections:r,tokenEstimate:cs(Ge(r))},spilled:s}}function Vn(i,t,e,s){let n=Ws(i);return{filePath:t,agent:e,schema:$s,lastUpdated:s,tokenEstimate:cs(Ge(n)),sections:n}}function li(i,t){let e=(i?.sections??[]).flatMap(o=>o.entries).filter(o=>o.pinned);if(e.length===0)return t;let s=new Set(t.flatMap(o=>o.entries).map(o=>o.text.trim().toLowerCase())),n=e.filter(o=>!s.has(o.text.trim().toLowerCase()));if(n.length===0)return t;let a=t.map(o=>({name:o.name,entries:[...o.entries]})),r=a.find(o=>o.name==="Preferences");return r||(r={name:"Preferences",entries:[]},a.unshift(r)),r.entries.unshift(...n),a}var tl="When you learn a durable fact about the user, their preferences, or how to do your work better, save it to memory. Prefer the `remember` tool \u2014 call remember(fact, pin?, section?); it is the reliable way to record a memory. If that tool is not available, fall back to writing [REMEMBER] <one concise fact> [/REMEMBER] in your reply (use [REMEMBER:pin] for standing preferences and hard constraints). Record only durable, reusable facts \u2014 not transient task details. These notes persist into your future runs.";function Hs(i,t){if(!i.memory)return"";let s=(t?Ge(t.sections).trim():"")||"Nothing yet \u2014 this is a fresh agent.";return`## Memory
11711
- ${tl}
11709
+ `)}function el(i){let t=[];for(let e of Za){let s=i.find(n=>n.name===e);s&&s.entries.length>0&&t.push(s)}return t}function ii(i,t,e){let{frontmatter:s,body:n}=J(i),a=Ws(n);return{filePath:t,agent:zn(s.agent)??e,schema:Xo(s.schema,$s),lastUpdated:zn(s.last_updated),lastReflection:zn(s.last_reflection),tokenEstimate:cs(Ge(a)),sections:a}}function Ws(i){let t=new Map,e=(a,r)=>{let o=t.get(a)??[];o.push(r),t.set(a,o)},s="Observations";for(let a of i.split(`
11710
+ `)){let r=a.match(/^#{1,6}\s+(.+?)\s*$/);if(r){s=Jo(r[1]??"");continue}let o=Zo(a);o&&e(s,o)}let n=[];for(let a of Za){let r=t.get(a);r&&r.length&&n.push({name:a,entries:r})}return n}function ri(i){let t=Ge(i.sections),e={agent:i.agent,schema:i.schema||$s,last_updated:i.lastUpdated??"",token_estimate:cs(t)};return i.lastReflection&&(e.last_reflection=i.lastReflection),W(e,t||"## Observations")}function oi(i,t,e,s){if(t.length===0)return i;let n=i.sections.map(o=>({name:o.name,entries:[...o.entries]})),a=n.find(o=>o.name===e);return a||(a={name:e,entries:[]},n.push(a)),a.entries.push(...t),{...i,sections:n,lastUpdated:s??i.lastUpdated,tokenEstimate:cs(Ge(n))}}var tl=["Recent","Observations","Procedures"];function li(i,t){if(i.tokenEstimate<=t)return{wm:i,spilled:[]};let e=i.sections.map(o=>({name:o.name,entries:[...o.entries]})),s=[],n=Ge(e).length,a=()=>Math.ceil(n/4)>t;for(let o of tl){if(!a())break;let c=e.find(l=>l.name===o);if(c)for(;c.entries.length>0&&a();){let l=c.entries.findIndex(d=>!d.pinned);if(l===-1)break;let h=c.entries.splice(l,1)[0];h&&(s.push(h),n-=ai(h).length+1)}}let r=e.filter(o=>o.entries.length>0);return{wm:{...i,sections:r,tokenEstimate:cs(Ge(r))},spilled:s}}function Vn(i,t,e,s){let n=Ws(i);return{filePath:t,agent:e,schema:$s,lastUpdated:s,tokenEstimate:cs(Ge(n)),sections:n}}function ci(i,t){let e=(i?.sections??[]).flatMap(o=>o.entries).filter(o=>o.pinned);if(e.length===0)return t;let s=new Set(t.flatMap(o=>o.entries).map(o=>o.text.trim().toLowerCase())),n=e.filter(o=>!s.has(o.text.trim().toLowerCase()));if(n.length===0)return t;let a=t.map(o=>({name:o.name,entries:[...o.entries]})),r=a.find(o=>o.name==="Preferences");return r||(r={name:"Preferences",entries:[]},a.unshift(r)),r.entries.unshift(...n),a}var sl="When you learn a durable fact about the user, their preferences, or how to do your work better, save it to memory. Prefer the `remember` tool \u2014 call remember(fact, pin?, section?); it is the reliable way to record a memory. If that tool is not available, fall back to writing [REMEMBER] <one concise fact> [/REMEMBER] in your reply (use [REMEMBER:pin] for standing preferences and hard constraints). Record only durable, reusable facts \u2014 not transient task details. These notes persist into your future runs.";function Hs(i,t){if(!i.memory)return"";let s=(t?Ge(t.sections).trim():"")||"Nothing yet \u2014 this is a fresh agent.";return`## Memory
11711
+ ${sl}
11712
11712
 
11713
11713
  ### What you've learned so far
11714
- ${s}`}var ht=require("child_process"),ci=require("fs"),zs=require("os"),Tt=require("path");function Yn(){return(0,zs.homedir)()}function di(){if(process.platform==="darwin")return"/bin/zsh";for(let i of["/bin/bash","/bin/zsh","/bin/sh"])if((0,ci.existsSync)(i))return i;return"/bin/sh"}function sl(i){return`'${i.replace(/'/g,"'\\''")}'`}function ot(i,t,e){let s={cwd:e?.cwd,env:e?.env};if(process.platform==="win32")return(0,ht.spawn)(i,t,s);let n=di(),a=[i,...t].map(sl).join(" ");return(0,ht.spawn)(n,["-l","-c",a],s)}function hi(i,t){let e={cwd:t?.cwd,env:t?.env,stdio:["pipe","pipe","pipe"]};if(process.platform==="win32")return(0,ht.spawn)(i,[],{...e,shell:!0});let s=di();return(0,ht.spawn)(s,["-l","-c",i],e)}function ui(i){try{require("electron").shell.openExternal(i)}catch{switch(process.platform){case"darwin":(0,ht.spawn)("open",[i],{stdio:"ignore"});break;case"win32":(0,ht.spawn)("cmd.exe",["/c","start","",i.replace(/&/g,"^&")],{stdio:"ignore"});break;default:(0,ht.spawn)("xdg-open",[i],{stdio:"ignore"});break}}}function pe(i){return i.split(/\r?\n/)}function pi(i){let t=(0,zs.homedir)();if(process.platform==="win32")return[i,(0,Tt.join)(process.env.APPDATA??"","Claude","claude.exe"),(0,Tt.join)(process.env.LOCALAPPDATA??"","Claude","claude.exe"),(0,Tt.join)(t,".local","bin","claude.exe"),"claude.exe","claude"].filter(s=>!!s&&qs(s));let e=[i,(0,Tt.join)(t,".local","bin","claude")];return process.platform==="darwin"&&e.push("/opt/homebrew/bin/claude"),e.push("/usr/local/bin/claude","/usr/bin/claude","claude"),e.filter(s=>!!s&&qs(s))}function Kn(i){let t=(0,zs.homedir)();if(process.platform==="win32")return[i,(0,Tt.join)(t,".local","bin","codex.exe"),"codex.exe","codex"].filter(s=>!!s&&qs(s));let e=[i,(0,Tt.join)(t,".local","bin","codex")];return process.platform==="darwin"&&e.push("/opt/homebrew/bin/codex"),e.push("/usr/local/bin/codex","/usr/bin/codex","codex"),e.filter(s=>!!s&&qs(s))}function qs(i){return!i||/[\n\r\0]/.test(i)?!1:i.startsWith("/")?/^[\w/.@+-]+$/.test(i):i.startsWith("~")?/^~[\w/.@+-]*$/.test(i):/^[a-zA-Z]:[\\/]/.test(i)?/^[a-zA-Z]:[\\/][\w\\/. @+-]+$/.test(i):i.startsWith("\\\\")?/^\\\\[\w\\/. @+-]+$/.test(i):!i.includes("/")&&!i.includes("\\")?/^[\w.@+-]+$/.test(i):!1}function Jn(i){return!!(i.includes("/")||i.includes("\\"))}function $t(i){return typeof i=="object"&&i!==null}function A(i){return typeof i=="string"?i:void 0}function Be(i,t){return typeof i=="boolean"?i:t}function Le(i,t){return typeof i=="number"&&Number.isFinite(i)?i:t}function le(i){return Array.isArray(i)?i.filter(t=>typeof t=="string"):[]}function mi(i){if(!$t(i))return;let t={};for(let[e,s]of Object.entries(i))typeof s=="string"&&(t[e]=s);return Object.keys(t).length>0?t:void 0}var fi=!1;function gi(i,t={}){let e=i.memory_token_budget??t.memory_token_budget;return e!==void 0?Le(e,Bs):((i.memory_max_entries??t.memory_max_entries)!==void 0&&!fi&&(fi=!0,console.info(`Agent Fleet: \`memory_max_entries\` is deprecated and no longer enforced; memory is now bounded by \`memory_token_budget\` (default ${Bs}). Set that field to tune memory size.`)),Bs)}function yi(i,t={}){let e=s=>i[s]??t[s];return{enabled:Be(e("reflection_enabled"),!1),schedule:A(e("reflection_schedule"))??Ya,recurrenceThreshold:Le(e("reflection_recurrence_threshold"),Ka),proposeSkills:Be(e("reflection_propose_skills"),!1),model:A(e("reflection_model"))}}function vi(i){return(0,x.normalizePath)(i.replace(/\.md$/,".permissions.json"))}function bi(i){let t=0;for(let e=0;e<i.length;e++){let s=i.charCodeAt(e);t=(t<<5)-t+s|0}return t.toString(36)}var ds=class{constructor(t,e){this.vault=t;this.settings=e}agents=new Map;skills=new Map;tasks=new Map;channels=new Map;mcpServers=new Map;validationIssues=new Map;channelCredentialGetter;warnedFolderAgentModelConflict=new Set;warnedLegacyPerms=new Set;migratingMemory=new Set;setChannelCredentialGetter(t){this.channelCredentialGetter=t}getVaultBasePath(){let t=this.vault.adapter;return t instanceof x.FileSystemAdapter?t.getBasePath():void 0}getFleetRoot(){return(0,x.normalizePath)(this.settings.fleetFolder)}getSubfolder(t){return(0,x.normalizePath)(`${this.getFleetRoot()}/${t}`)}async ensureFleetStructure(){let t=this.getFleetRoot(),e=!this.vault.getAbstractFileByPath(t);await this.ensureFolder(t);for(let s of Va)await this.ensureFolder(this.getSubfolder(s));return e}async ensureSamples(){let t=this.getFleetRoot();for(let e of qn){let s=(0,x.normalizePath)(`${t}/${e.path}`),n=s.substring(0,s.lastIndexOf("/"));await this.ensureFolder(n),await this.createFileIfMissing(s,e.content)}}async updateDefaults(t){let e=this.getFleetRoot(),s={...t};for(let n of qn){let a=(0,x.normalizePath)(`${e}/${n.path}`),r=bi(n.content),o=t[n.path];if(o===r)continue;let c=this.vault.getAbstractFileByPath(a);if(!(c instanceof x.TFile)){let h=a.substring(0,a.lastIndexOf("/"));await this.ensureFolder(h),await this.createFileIfMissing(a,n.content),s[n.path]=r;continue}let l=await this.vault.cachedRead(c),d=bi(l);(!o||d===o)&&(await this.vault.modify(c,n.content),s[n.path]=r)}return s}async loadAll(){this.agents.clear(),this.skills.clear(),this.tasks.clear(),this.channels.clear(),this.mcpServers.clear(),this.validationIssues.clear(),await this.loadFolderAgents(),await this.loadFolderSkills();let t=this.vault.getMarkdownFiles().filter(e=>e.path.startsWith(`${this.getFleetRoot()}/`));for(let e of t)await this.loadFile(e);return this.validateReferences(),this.getSnapshot()}async loadFile(t){let e=typeof t=="string"?this.vault.getAbstractFileByPath(t):t;if(!(e instanceof x.TFile)||e.extension!=="md")return;if(this.isInsideAgentFolder(e.path)){await this.reloadFolderAgentContaining(e.path);return}if(this.isInsideSkillFolder(e.path)){await this.reloadFolderSkillContaining(e.path);return}this.clearStoredFile(e.path);let s=`${this.getSubfolder("channels")}/`;if(e.path.startsWith(s)){if(!e.path.slice(s.length).includes("/")){let c=await this.vault.cachedRead(e),l=this.parseChannelFile(e.path,c);l&&this.channels.set(e.path,l)}return}let n=`${this.getSubfolder("mcp")}/`;if(e.path.startsWith(n)){if(!e.path.slice(n.length).includes("/")){let c=await this.vault.cachedRead(e),l=this.parseMcpServerFile(e.path,c);l&&this.mcpServers.set(e.path,l)}return}let a=await this.vault.cachedRead(e),r=this.parseFile(e.path,a);if(r)if("taskId"in r)this.tasks.set(e.path,r);else if("model"in r){if(!r.isFolder){let o=vi(e.path),c=this.vault.getAbstractFileByPath(o);if(c instanceof x.TFile)try{let l=await this.vault.cachedRead(c),d=JSON.parse(l);r.permissionRules={allow:le(d.allow),deny:le(d.deny)}}catch{}}this.agents.set(e.path,r)}else this.skills.set(e.path,r)}async reloadFolderAgentContaining(t){let e=`${this.getSubfolder("agents")}/`,n=t.slice(e.length).split("/")[0];if(!n)return;let a=(0,x.normalizePath)(`${e}${n}`),r=(0,x.normalizePath)(`${a}/agent.md`);if(this.agents.delete(r),!(this.vault.getAbstractFileByPath(a)instanceof x.TFolder))return;let c=this.vault.getAbstractFileByPath(r);if(!(c instanceof x.TFile))return;let l=await this.loadFolderAgent(a,c);l&&this.agents.set(r,l)}isInsideAgentFolder(t){let e=`${this.getSubfolder("agents")}/`;return t.startsWith(e)?t.slice(e.length).includes("/"):!1}isInsideSkillFolder(t){let e=`${this.getSubfolder("skills")}/`;return t.startsWith(e)?t.slice(e.length).includes("/"):!1}async reloadFolderSkillContaining(t){let e=`${this.getSubfolder("skills")}/`,n=t.slice(e.length).split("/")[0];if(!n)return;let a=(0,x.normalizePath)(`${e}${n}`),r=(0,x.normalizePath)(`${a}/skill.md`);if(this.skills.delete(r),!(this.vault.getAbstractFileByPath(a)instanceof x.TFolder))return;let c=this.vault.getAbstractFileByPath(r);if(!(c instanceof x.TFile))return;let l=await this.loadFolderSkill(a,c);l&&this.skills.set(r,l)}async loadFolderSkills(){let t=this.vault.getAbstractFileByPath(this.getSubfolder("skills"));if(t instanceof x.TFolder)for(let e of t.children){if(!(e instanceof x.TFolder))continue;let s=(0,x.normalizePath)(`${e.path}/skill.md`),n=this.vault.getAbstractFileByPath(s);if(!(n instanceof x.TFile))continue;let a=await this.loadFolderSkill(e.path,n);a&&this.skills.set(s,a)}}async loadFolderSkill(t,e){let s=await this.vault.cachedRead(e),{frontmatter:n,body:a}=Q(s),r=A(n.name);if(!r)return this.setIssue(e.path,"Folder skill skill.md requires string field `name`."),null;let o=async c=>{let l=(0,x.normalizePath)(`${t}/${c}`),d=this.vault.getAbstractFileByPath(l);if(!(d instanceof x.TFile))return"";let h=await this.vault.cachedRead(d);return Q(h).body};return{filePath:e.path,name:r,description:A(n.description),tags:le(n.tags),body:a,toolsBody:await o("tools.md"),referencesBody:await o("references.md"),examplesBody:await o("examples.md"),isFolder:!0}}async loadFolderAgents(){let t=this.vault.getAbstractFileByPath(this.getSubfolder("agents"));if(t instanceof x.TFolder)for(let e of t.children){if(!(e instanceof x.TFolder))continue;let s=(0,x.normalizePath)(`${e.path}/agent.md`),n=this.vault.getAbstractFileByPath(s);if(!(n instanceof x.TFile))continue;let a=await this.loadFolderAgent(e.path,n);a&&this.agents.set(s,a)}}async loadFolderAgent(t,e){let s=await this.vault.cachedRead(e),{frontmatter:n,body:a}=Q(s),r=A(n.name);if(!r)return this.setIssue(e.path,"Folder agent agent.md requires string field `name`."),null;let o={},c=(0,x.normalizePath)(`${t}/config.md`),l=this.vault.getAbstractFileByPath(c);if(l instanceof x.TFile){let N=await this.vault.cachedRead(l);o=Q(N).frontmatter}let d={allow:[],deny:[]},h=(0,x.normalizePath)(`${t}/permissions.json`),u=this.vault.getAbstractFileByPath(h);if(u instanceof x.TFile)try{let N=await this.vault.cachedRead(u),L=JSON.parse(N);d={allow:le(L.allow),deny:le(L.deny)}}catch{}if(d.allow.length===0&&d.deny.length===0){let N=le(o.allowed_tools),L=le(o.blocked_tools);(N.length>0||L.length>0)&&(d={allow:N,deny:L},this.warnedLegacyPerms.has(r)||(this.warnedLegacyPerms.add(r),console.warn(`Agent Fleet: "${r}" still uses legacy allowed_tools/blocked_tools in config.md. Permission rules now live in permissions.json. Open this agent in Edit and Save to migrate.`)))}let p="",f=(0,x.normalizePath)(`${t}/SKILLS.md`),m=this.vault.getAbstractFileByPath(f);if(m instanceof x.TFile){let N=await this.vault.cachedRead(m);p=Q(N).body}let g="",v=(0,x.normalizePath)(`${t}/CONTEXT.md`),k=this.vault.getAbstractFileByPath(v);if(k instanceof x.TFile){let N=await this.vault.cachedRead(k);g=Q(N).body}let w=!1,y="",C="",T=!0,_="",O=(0,x.normalizePath)(`${t}/HEARTBEAT.md`),E=this.vault.getAbstractFileByPath(O);if(E instanceof x.TFile){let N=await this.vault.cachedRead(E),L=Q(N);w=Be(L.frontmatter.enabled,!1),y=A(L.frontmatter.schedule)??"",T=Be(L.frontmatter.notify,!0),_=A(L.frontmatter.channel)??"",C=L.body}let S=A(n.model),P=A(o.model);S&&P&&S!==P&&(this.warnedFolderAgentModelConflict.has(r)||(this.warnedFolderAgentModelConflict.add(r),console.warn(`Agent Fleet: "${r}" has conflicting model fields \u2014 agent.md says "${S}", config.md says "${P}". config.md wins. Remove agent.md's model field or sync the values to silence this warning.`)));let R=P??S??this.settings.defaultModel;return{filePath:e.path,name:r,description:A(n.description),model:R,adapter:A(o.adapter)??"claude-code",permissionMode:A(o.permission_mode)??"bypassPermissions",effort:A(o.effort),maxRetries:Le(o.max_retries,1),skills:le(n.skills),mcpServers:le(n.mcp_servers),cwd:A(o.cwd)||A(n.cwd),enabled:Be(n.enabled,!0),timeout:Le(o.timeout,Le(n.timeout,300)),approvalRequired:le(o.approval_required),memory:Be(o.memory,Be(n.memory,!1)),memoryMaxEntries:Le(o.memory_max_entries,100),memoryTokenBudget:gi(o,n),reflection:yi(o,n),autoCompactThreshold:Le(o.auto_compact_threshold??n.auto_compact_threshold,85),tags:le(n.tags),avatar:A(n.avatar)??"",body:a,contextBody:g,skillsBody:p,env:this.parseEnvMap(o.env),permissionRules:d,isFolder:!0,heartbeatEnabled:w,heartbeatSchedule:y,heartbeatBody:C,heartbeatNotify:T,heartbeatChannel:_,wikiKeeper:this.parseWikiKeeperConfig(o.wiki_keeper??n.wiki_keeper),wikiReferences:this.parseWikiReferences(o.wiki_references??n.wiki_references)}}parseWikiReferences(t){if(!Array.isArray(t))return;let e=[];for(let s of t)if(typeof s=="string"&&s.trim())e.push({agent:s.trim()});else if(s&&typeof s=="object"){let n=s.agent;typeof n=="string"&&n.trim()&&e.push({agent:n.trim()})}return e.length>0?e:void 0}parseWikiKeeperConfig(t){if(!t||typeof t!="object")return;let e=t;return{scopeRoot:A(e.scope_root)??"",inboxPath:A(e.inbox_path)??"_sources/inbox",archivePath:A(e.archive_path)??"_sources/archive",failedPath:A(e.failed_path)??"_sources/failed",topicsRoot:A(e.topics_root)??"_topics",indexPath:A(e.index_path)??"index.md",logPath:A(e.log_path)??"log.md",watchedFolders:le(e.watched_folders),excludePatterns:le(e.exclude_patterns),watchedSince:A(e.watched_since)??"",fileSubstantiveAnswers:Be(e.file_substantive_answers,!0),obsidianUrlScheme:Be(e.obsidian_url_scheme,!0),maxTokensPerIngest:Le(e.max_tokens_per_ingest,6e4),maxTokensPerRefresh:Le(e.max_tokens_per_refresh,3e4),indexSplitThreshold:Le(e.index_split_threshold,100),dedupSimilarityThreshold:Le(e.dedup_similarity_threshold,.82),summaryStaleDays:Le(e.summary_stale_days,30),stateFile:A(e.state_file)??".wiki-keeper-state.json"}}removeFile(t){this.clearStoredFile(t)}getSnapshot(){return{agents:Array.from(this.agents.values()).sort((t,e)=>t.name.localeCompare(e.name)),skills:Array.from(this.skills.values()).sort((t,e)=>t.name.localeCompare(e.name)),tasks:Array.from(this.tasks.values()).sort((t,e)=>t.taskId.localeCompare(e.taskId)),channels:Array.from(this.channels.values()).sort((t,e)=>t.name.localeCompare(e.name)),mcpServers:Array.from(this.mcpServers.values()).sort((t,e)=>t.name.localeCompare(e.name)),validationIssues:Array.from(this.validationIssues.values()).flat()}}getAgentByName(t){return Array.from(this.agents.values()).find(e=>e.name===t)}getSkillByName(t){return Array.from(this.skills.values()).find(e=>e.name===t)}getTaskById(t){return Array.from(this.tasks.values()).find(e=>e.taskId===t)}getTasksForAgent(t){return Array.from(this.tasks.values()).filter(e=>e.agent===t)}getChannelByName(t){return Array.from(this.channels.values()).find(e=>e.name===t)}getChannelsForAgent(t){return Array.from(this.channels.values()).filter(e=>e.defaultAgent===t)}getMcpServers(){return Array.from(this.mcpServers.values()).sort((t,e)=>t.name.localeCompare(e.name))}getMcpServerByName(t){return Array.from(this.mcpServers.values()).find(e=>e.name===t)}getRunsRoot(){return this.getSubfolder("runs")}getMemoryPath(t){return(0,x.normalizePath)(`${this.getSubfolder("memory")}/${ae(t)}.md`)}getMemoryDir(t){return(0,x.normalizePath)(`${this.getSubfolder("memory")}/${ae(t)}`)}getWorkingMemoryPath(t){return(0,x.normalizePath)(`${this.getMemoryDir(t)}/working.md`)}getRawMemoryPath(t,e){let s=e.slice(0,10);return(0,x.normalizePath)(`${this.getMemoryDir(t)}/raw/${s}.md`)}async readWorkingMemory(t){let e=this.getWorkingMemoryPath(t),s=this.vault.getAbstractFileByPath(e);if(s instanceof x.TFile){let r=await this.vault.cachedRead(s);return ai(r,e,t)}let n=this.getMemoryPath(t),a=this.vault.getAbstractFileByPath(n);if(a instanceof x.TFile){let r=await this.vault.cachedRead(a),{body:o}=Q(r);return Vn(o,e,t)}return null}async writeWorkingMemory(t,e){let s=this.getWorkingMemoryPath(t);await this.ensureFolder(this.getMemoryDir(t));let n=ii(e),a=this.vault.getAbstractFileByPath(s);a instanceof x.TFile?await this.vault.modify(a,n):await this.createFileIfMissing(s,n);let r=this.getMemoryPath(t);r!==s&&this.vault.getAbstractFileByPath(r)&&await this.trashFile(r)}async migrateLegacyMemory(t){let e=this.getWorkingMemoryPath(t);if(this.vault.getAbstractFileByPath(e))return;let s=this.getMemoryPath(t),n=this.vault.getAbstractFileByPath(s);if(n instanceof x.TFile&&!this.migratingMemory.has(t)){this.migratingMemory.add(t);try{let a=await this.vault.cachedRead(n),{body:r}=Q(a),o=new Date().toISOString(),c=r.split(`
11715
- `).map(h=>h.replace(/^\s*[-*]\s+/,"").trim()).filter(h=>h.length>0&&!/^#{1,6}\s/.test(h)),l=[`- ${o} [migrated] Imported ${c.length} legacy memory entr${c.length===1?"y":"ies"} (pre-v2).`,...c.map(h=>`- ${o} [migrated] ${h}`)];await this.appendRawMemory(t,l,o);let d=Vn(r,e,t,o);await this.writeWorkingMemory(t,d)}finally{this.migratingMemory.delete(t)}}}async migrateAllLegacyMemory(){for(let t of this.getSnapshot().agents)if(t.memory)try{await this.migrateLegacyMemory(t.name)}catch(e){console.warn(`Agent Fleet: legacy memory migration failed for "${t.name}"`,e)}}getPendingDir(t){return(0,x.normalizePath)(`${this.getMemoryDir(t)}/pending`)}getPendingDirAbsolutePath(t){let e=this.vault.adapter;return e instanceof x.FileSystemAdapter?(0,wi.join)(e.getBasePath(),this.getPendingDir(t)):null}async ensureMemoryDir(t){await this.ensureFolder(this.getMemoryDir(t))}async readAndClearPending(t){let e=this.vault.adapter,s=this.getPendingDir(t),n;try{if(!await e.exists(s))return[];n=(await e.list(s)).files}catch{return[]}let a=[];for(let r of n)if(r.endsWith(".json"))try{let o=await e.read(r);await e.remove(r);for(let c of o.split(`
11714
+ ${s}`}var ut=require("child_process"),di=require("fs"),zs=require("os"),Tt=require("path");function Yn(){return(0,zs.homedir)()}function hi(){if(process.platform==="darwin")return"/bin/zsh";for(let i of["/bin/bash","/bin/zsh","/bin/sh"])if((0,di.existsSync)(i))return i;return"/bin/sh"}function nl(i){return`'${i.replace(/'/g,"'\\''")}'`}function lt(i,t,e){let s={cwd:e?.cwd,env:e?.env};if(process.platform==="win32")return(0,ut.spawn)(i,t,s);let n=hi(),a=[i,...t].map(nl).join(" ");return(0,ut.spawn)(n,["-l","-c",a],s)}function ui(i,t){let e={cwd:t?.cwd,env:t?.env,stdio:["pipe","pipe","pipe"]};if(process.platform==="win32")return(0,ut.spawn)(i,[],{...e,shell:!0});let s=hi();return(0,ut.spawn)(s,["-l","-c",i],e)}function pi(i){try{require("electron").shell.openExternal(i)}catch{switch(process.platform){case"darwin":(0,ut.spawn)("open",[i],{stdio:"ignore"});break;case"win32":(0,ut.spawn)("cmd.exe",["/c","start","",i.replace(/&/g,"^&")],{stdio:"ignore"});break;default:(0,ut.spawn)("xdg-open",[i],{stdio:"ignore"});break}}}function ge(i){return i.split(/\r?\n/)}function mi(i){let t=(0,zs.homedir)();if(process.platform==="win32")return[i,(0,Tt.join)(process.env.APPDATA??"","Claude","claude.exe"),(0,Tt.join)(process.env.LOCALAPPDATA??"","Claude","claude.exe"),(0,Tt.join)(t,".local","bin","claude.exe"),"claude.exe","claude"].filter(s=>!!s&&qs(s));let e=[i,(0,Tt.join)(t,".local","bin","claude")];return process.platform==="darwin"&&e.push("/opt/homebrew/bin/claude"),e.push("/usr/local/bin/claude","/usr/bin/claude","claude"),e.filter(s=>!!s&&qs(s))}function Kn(i){let t=(0,zs.homedir)();if(process.platform==="win32")return[i,(0,Tt.join)(t,".local","bin","codex.exe"),"codex.exe","codex"].filter(s=>!!s&&qs(s));let e=[i,(0,Tt.join)(t,".local","bin","codex")];return process.platform==="darwin"&&e.push("/opt/homebrew/bin/codex"),e.push("/usr/local/bin/codex","/usr/bin/codex","codex"),e.filter(s=>!!s&&qs(s))}function qs(i){return!i||/[\n\r\0]/.test(i)?!1:i.startsWith("/")?/^[\w/.@+-]+$/.test(i):i.startsWith("~")?/^~[\w/.@+-]*$/.test(i):/^[a-zA-Z]:[\\/]/.test(i)?/^[a-zA-Z]:[\\/][\w\\/. @+-]+$/.test(i):i.startsWith("\\\\")?/^\\\\[\w\\/. @+-]+$/.test(i):!i.includes("/")&&!i.includes("\\")?/^[\w.@+-]+$/.test(i):!1}function Jn(i){return!!(i.includes("/")||i.includes("\\"))}function jt(i){return typeof i=="object"&&i!==null}function A(i){return typeof i=="string"?i:void 0}function Be(i,t){return typeof i=="boolean"?i:t}function De(i,t){return typeof i=="number"&&Number.isFinite(i)?i:t}function ue(i){return Array.isArray(i)?i.filter(t=>typeof t=="string"):[]}function fi(i){if(!jt(i))return;let t={};for(let[e,s]of Object.entries(i))typeof s=="string"&&(t[e]=s);return Object.keys(t).length>0?t:void 0}var gi=!1;function yi(i,t={}){let e=i.memory_token_budget??t.memory_token_budget;return e!==void 0?De(e,Bs):((i.memory_max_entries??t.memory_max_entries)!==void 0&&!gi&&(gi=!0,console.info(`Agent Fleet: \`memory_max_entries\` is deprecated and no longer enforced; memory is now bounded by \`memory_token_budget\` (default ${Bs}). Set that field to tune memory size.`)),Bs)}function vi(i,t={}){let e=s=>i[s]??t[s];return{enabled:Be(e("reflection_enabled"),!1),schedule:A(e("reflection_schedule"))??Ka,recurrenceThreshold:De(e("reflection_recurrence_threshold"),Ja),proposeSkills:Be(e("reflection_propose_skills"),!1),model:A(e("reflection_model"))}}function wi(i){return(0,x.normalizePath)(i.replace(/\.md$/,".permissions.json"))}function bi(i){let t=0;for(let e=0;e<i.length;e++){let s=i.charCodeAt(e);t=(t<<5)-t+s|0}return t.toString(36)}var ds=class{constructor(t,e){this.app=t;this.settings=e;this.vault=t.vault}agents=new Map;skills=new Map;tasks=new Map;channels=new Map;mcpServers=new Map;validationIssues=new Map;channelCredentialGetter;warnedFolderAgentModelConflict=new Set;warnedLegacyPerms=new Set;migratingMemory=new Set;vault;setChannelCredentialGetter(t){this.channelCredentialGetter=t}getVaultBasePath(){let t=this.vault.adapter;return t instanceof x.FileSystemAdapter?t.getBasePath():void 0}getFleetRoot(){return(0,x.normalizePath)(this.settings.fleetFolder)}getSubfolder(t){return(0,x.normalizePath)(`${this.getFleetRoot()}/${t}`)}async ensureFleetStructure(){let t=this.getFleetRoot(),e=!this.vault.getAbstractFileByPath(t);await this.ensureFolder(t);for(let s of Ya)await this.ensureFolder(this.getSubfolder(s));return e}async ensureSamples(){let t=this.getFleetRoot();for(let e of qn){let s=(0,x.normalizePath)(`${t}/${e.path}`),n=s.substring(0,s.lastIndexOf("/"));await this.ensureFolder(n),await this.createFileIfMissing(s,e.content)}}async updateDefaults(t){let e=this.getFleetRoot(),s={...t};for(let n of qn){let a=(0,x.normalizePath)(`${e}/${n.path}`),r=bi(n.content),o=t[n.path];if(o===r)continue;let c=this.vault.getAbstractFileByPath(a);if(!(c instanceof x.TFile)){let d=a.substring(0,a.lastIndexOf("/"));await this.ensureFolder(d),await this.createFileIfMissing(a,n.content),s[n.path]=r;continue}let l=await this.vault.cachedRead(c),h=bi(l);(!o||h===o)&&(await this.vault.modify(c,n.content),s[n.path]=r)}return s}async loadAll(){this.agents.clear(),this.skills.clear(),this.tasks.clear(),this.channels.clear(),this.mcpServers.clear(),this.validationIssues.clear(),await this.loadFolderAgents(),await this.loadFolderSkills();let t=this.vault.getMarkdownFiles().filter(e=>e.path.startsWith(`${this.getFleetRoot()}/`));for(let e of t)await this.loadFile(e);return this.validateReferences(),this.getSnapshot()}async loadFile(t){let e=typeof t=="string"?this.vault.getAbstractFileByPath(t):t;if(!(e instanceof x.TFile)||e.extension!=="md")return;if(this.isInsideAgentFolder(e.path)){await this.reloadFolderAgentContaining(e.path);return}if(this.isInsideSkillFolder(e.path)){await this.reloadFolderSkillContaining(e.path);return}this.clearStoredFile(e.path);let s=`${this.getSubfolder("channels")}/`;if(e.path.startsWith(s)){if(!e.path.slice(s.length).includes("/")){let c=await this.vault.cachedRead(e),l=this.parseChannelFile(e.path,c);l&&this.channels.set(e.path,l)}return}let n=`${this.getSubfolder("mcp")}/`;if(e.path.startsWith(n)){if(!e.path.slice(n.length).includes("/")){let c=await this.vault.cachedRead(e),l=this.parseMcpServerFile(e.path,c);l&&this.mcpServers.set(e.path,l)}return}let a=await this.vault.cachedRead(e),r=this.parseFile(e.path,a);if(r)if("taskId"in r)this.tasks.set(e.path,r);else if("model"in r){if(!r.isFolder){let o=wi(e.path),c=this.vault.getAbstractFileByPath(o);if(c instanceof x.TFile)try{let l=await this.vault.cachedRead(c),h=JSON.parse(l);r.permissionRules={allow:ue(h.allow),deny:ue(h.deny)}}catch{}}this.agents.set(e.path,r)}else this.skills.set(e.path,r)}async reloadFolderAgentContaining(t){let e=`${this.getSubfolder("agents")}/`,n=t.slice(e.length).split("/")[0];if(!n)return;let a=(0,x.normalizePath)(`${e}${n}`),r=(0,x.normalizePath)(`${a}/agent.md`);if(this.agents.delete(r),!(this.vault.getAbstractFileByPath(a)instanceof x.TFolder))return;let c=this.vault.getAbstractFileByPath(r);if(!(c instanceof x.TFile))return;let l=await this.loadFolderAgent(a,c);l&&this.agents.set(r,l)}isInsideAgentFolder(t){let e=`${this.getSubfolder("agents")}/`;return t.startsWith(e)?t.slice(e.length).includes("/"):!1}isInsideSkillFolder(t){let e=`${this.getSubfolder("skills")}/`;return t.startsWith(e)?t.slice(e.length).includes("/"):!1}async reloadFolderSkillContaining(t){let e=`${this.getSubfolder("skills")}/`,n=t.slice(e.length).split("/")[0];if(!n)return;let a=(0,x.normalizePath)(`${e}${n}`),r=(0,x.normalizePath)(`${a}/skill.md`);if(this.skills.delete(r),!(this.vault.getAbstractFileByPath(a)instanceof x.TFolder))return;let c=this.vault.getAbstractFileByPath(r);if(!(c instanceof x.TFile))return;let l=await this.loadFolderSkill(a,c);l&&this.skills.set(r,l)}async loadFolderSkills(){let t=this.vault.getAbstractFileByPath(this.getSubfolder("skills"));if(t instanceof x.TFolder)for(let e of t.children){if(!(e instanceof x.TFolder))continue;let s=(0,x.normalizePath)(`${e.path}/skill.md`),n=this.vault.getAbstractFileByPath(s);if(!(n instanceof x.TFile))continue;let a=await this.loadFolderSkill(e.path,n);a&&this.skills.set(s,a)}}async loadFolderSkill(t,e){let s=await this.vault.cachedRead(e),{frontmatter:n,body:a}=J(s),r=A(n.name);if(!r)return this.setIssue(e.path,"Folder skill skill.md requires string field `name`."),null;let o=async c=>{let l=(0,x.normalizePath)(`${t}/${c}`),h=this.vault.getAbstractFileByPath(l);if(!(h instanceof x.TFile))return"";let d=await this.vault.cachedRead(h);return J(d).body};return{filePath:e.path,name:r,description:A(n.description),tags:ue(n.tags),body:a,toolsBody:await o("tools.md"),referencesBody:await o("references.md"),examplesBody:await o("examples.md"),isFolder:!0}}async loadFolderAgents(){let t=this.vault.getAbstractFileByPath(this.getSubfolder("agents"));if(t instanceof x.TFolder)for(let e of t.children){if(!(e instanceof x.TFolder))continue;let s=(0,x.normalizePath)(`${e.path}/agent.md`),n=this.vault.getAbstractFileByPath(s);if(!(n instanceof x.TFile))continue;let a=await this.loadFolderAgent(e.path,n);a&&this.agents.set(s,a)}}async loadFolderAgent(t,e){let s=await this.vault.cachedRead(e),{frontmatter:n,body:a}=J(s),r=A(n.name);if(!r)return this.setIssue(e.path,"Folder agent agent.md requires string field `name`."),null;let o={},c=(0,x.normalizePath)(`${t}/config.md`),l=this.vault.getAbstractFileByPath(c);if(l instanceof x.TFile){let L=await this.vault.cachedRead(l);o=J(L).frontmatter}let h={allow:[],deny:[]},d=(0,x.normalizePath)(`${t}/permissions.json`),u=this.vault.getAbstractFileByPath(d);if(u instanceof x.TFile)try{let L=await this.vault.cachedRead(u),F=JSON.parse(L);h={allow:ue(F.allow),deny:ue(F.deny)}}catch{}if(h.allow.length===0&&h.deny.length===0){let L=ue(o.allowed_tools),F=ue(o.blocked_tools);(L.length>0||F.length>0)&&(h={allow:L,deny:F},this.warnedLegacyPerms.has(r)||(this.warnedLegacyPerms.add(r),console.warn(`Agent Fleet: "${r}" still uses legacy allowed_tools/blocked_tools in config.md. Permission rules now live in permissions.json. Open this agent in Edit and Save to migrate.`)))}let p="",m=(0,x.normalizePath)(`${t}/SKILLS.md`),f=this.vault.getAbstractFileByPath(m);if(f instanceof x.TFile){let L=await this.vault.cachedRead(f);p=J(L).body}let g="",v=(0,x.normalizePath)(`${t}/CONTEXT.md`),b=this.vault.getAbstractFileByPath(v);if(b instanceof x.TFile){let L=await this.vault.cachedRead(b);g=J(L).body}let k=!1,y="",S="",T=!0,_="",D=(0,x.normalizePath)(`${t}/HEARTBEAT.md`),M=this.vault.getAbstractFileByPath(D);if(M instanceof x.TFile){let L=await this.vault.cachedRead(M),F=J(L);k=Be(F.frontmatter.enabled,!1),y=A(F.frontmatter.schedule)??"",T=Be(F.frontmatter.notify,!0),_=A(F.frontmatter.channel)??"",S=F.body}let C=A(n.model),I=A(o.model);C&&I&&C!==I&&(this.warnedFolderAgentModelConflict.has(r)||(this.warnedFolderAgentModelConflict.add(r),console.warn(`Agent Fleet: "${r}" has conflicting model fields \u2014 agent.md says "${C}", config.md says "${I}". config.md wins. Remove agent.md's model field or sync the values to silence this warning.`)));let P=I??C??this.settings.defaultModel;return{filePath:e.path,name:r,description:A(n.description),model:P,adapter:A(o.adapter)??"claude-code",permissionMode:A(o.permission_mode)??"bypassPermissions",effort:A(o.effort),maxRetries:De(o.max_retries,1),skills:ue(n.skills),mcpServers:ue(n.mcp_servers),cwd:A(o.cwd)||A(n.cwd),enabled:Be(n.enabled,!0),timeout:De(o.timeout,De(n.timeout,300)),approvalRequired:ue(o.approval_required),memory:Be(o.memory,Be(n.memory,!1)),memoryMaxEntries:De(o.memory_max_entries,100),memoryTokenBudget:yi(o,n),reflection:vi(o,n),autoCompactThreshold:De(o.auto_compact_threshold??n.auto_compact_threshold,85),tags:ue(n.tags),avatar:A(n.avatar)??"",body:a,contextBody:g,skillsBody:p,env:this.parseEnvMap(o.env),permissionRules:h,isFolder:!0,heartbeatEnabled:k,heartbeatSchedule:y,heartbeatBody:S,heartbeatNotify:T,heartbeatChannel:_,wikiKeeper:this.parseWikiKeeperConfig(o.wiki_keeper??n.wiki_keeper),wikiReferences:this.parseWikiReferences(o.wiki_references??n.wiki_references)}}parseWikiReferences(t){if(!Array.isArray(t))return;let e=[];for(let s of t)if(typeof s=="string"&&s.trim())e.push({agent:s.trim()});else if(s&&typeof s=="object"){let n=s.agent;typeof n=="string"&&n.trim()&&e.push({agent:n.trim()})}return e.length>0?e:void 0}parseWikiKeeperConfig(t){if(!t||typeof t!="object")return;let e=t;return{scopeRoot:A(e.scope_root)??"",inboxPath:A(e.inbox_path)??"_sources/inbox",archivePath:A(e.archive_path)??"_sources/archive",failedPath:A(e.failed_path)??"_sources/failed",topicsRoot:A(e.topics_root)??"_topics",indexPath:A(e.index_path)??"index.md",logPath:A(e.log_path)??"log.md",watchedFolders:ue(e.watched_folders),excludePatterns:ue(e.exclude_patterns),watchedSince:A(e.watched_since)??"",fileSubstantiveAnswers:Be(e.file_substantive_answers,!0),obsidianUrlScheme:Be(e.obsidian_url_scheme,!0),maxTokensPerIngest:De(e.max_tokens_per_ingest,6e4),maxTokensPerRefresh:De(e.max_tokens_per_refresh,3e4),indexSplitThreshold:De(e.index_split_threshold,100),dedupSimilarityThreshold:De(e.dedup_similarity_threshold,.82),summaryStaleDays:De(e.summary_stale_days,30),stateFile:A(e.state_file)??".wiki-keeper-state.json"}}removeFile(t){this.clearStoredFile(t)}getSnapshot(){return{agents:Array.from(this.agents.values()).sort((t,e)=>t.name.localeCompare(e.name)),skills:Array.from(this.skills.values()).sort((t,e)=>t.name.localeCompare(e.name)),tasks:Array.from(this.tasks.values()).sort((t,e)=>t.taskId.localeCompare(e.taskId)),channels:Array.from(this.channels.values()).sort((t,e)=>t.name.localeCompare(e.name)),mcpServers:Array.from(this.mcpServers.values()).sort((t,e)=>t.name.localeCompare(e.name)),validationIssues:Array.from(this.validationIssues.values()).flat()}}getAgentByName(t){return Array.from(this.agents.values()).find(e=>e.name===t)}getSkillByName(t){return Array.from(this.skills.values()).find(e=>e.name===t)}getTaskById(t){return Array.from(this.tasks.values()).find(e=>e.taskId===t)}getTasksForAgent(t){return Array.from(this.tasks.values()).filter(e=>e.agent===t)}getChannelByName(t){return Array.from(this.channels.values()).find(e=>e.name===t)}getChannelsForAgent(t){return Array.from(this.channels.values()).filter(e=>e.defaultAgent===t)}getMcpServers(){return Array.from(this.mcpServers.values()).sort((t,e)=>t.name.localeCompare(e.name))}getMcpServerByName(t){return Array.from(this.mcpServers.values()).find(e=>e.name===t)}getRunsRoot(){return this.getSubfolder("runs")}getMemoryPath(t){return(0,x.normalizePath)(`${this.getSubfolder("memory")}/${oe(t)}.md`)}getMemoryDir(t){return(0,x.normalizePath)(`${this.getSubfolder("memory")}/${oe(t)}`)}getWorkingMemoryPath(t){return(0,x.normalizePath)(`${this.getMemoryDir(t)}/working.md`)}getRawMemoryPath(t,e){let s=e.slice(0,10);return(0,x.normalizePath)(`${this.getMemoryDir(t)}/raw/${s}.md`)}async readWorkingMemory(t){let e=this.getWorkingMemoryPath(t),s=this.vault.getAbstractFileByPath(e);if(s instanceof x.TFile){let r=await this.vault.cachedRead(s);return ii(r,e,t)}let n=this.getMemoryPath(t),a=this.vault.getAbstractFileByPath(n);if(a instanceof x.TFile){let r=await this.vault.cachedRead(a),{body:o}=J(r);return Vn(o,e,t)}return null}async writeWorkingMemory(t,e){let s=this.getWorkingMemoryPath(t);await this.ensureFolder(this.getMemoryDir(t));let n=ri(e),a=this.vault.getAbstractFileByPath(s);a instanceof x.TFile?await this.vault.modify(a,n):await this.createFileIfMissing(s,n);let r=this.getMemoryPath(t);r!==s&&this.vault.getAbstractFileByPath(r)&&await this.trashFile(r)}async migrateLegacyMemory(t){let e=this.getWorkingMemoryPath(t);if(this.vault.getAbstractFileByPath(e))return;let s=this.getMemoryPath(t),n=this.vault.getAbstractFileByPath(s);if(n instanceof x.TFile&&!this.migratingMemory.has(t)){this.migratingMemory.add(t);try{let a=await this.vault.cachedRead(n),{body:r}=J(a),o=new Date().toISOString(),c=r.split(`
11715
+ `).map(d=>d.replace(/^\s*[-*]\s+/,"").trim()).filter(d=>d.length>0&&!/^#{1,6}\s/.test(d)),l=[`- ${o} [migrated] Imported ${c.length} legacy memory entr${c.length===1?"y":"ies"} (pre-v2).`,...c.map(d=>`- ${o} [migrated] ${d}`)];await this.appendRawMemory(t,l,o);let h=Vn(r,e,t,o);await this.writeWorkingMemory(t,h)}finally{this.migratingMemory.delete(t)}}}async migrateAllLegacyMemory(){for(let t of this.getSnapshot().agents)if(t.memory)try{await this.migrateLegacyMemory(t.name)}catch(e){console.warn(`Agent Fleet: legacy memory migration failed for "${t.name}"`,e)}}getPendingDir(t){return(0,x.normalizePath)(`${this.getMemoryDir(t)}/pending`)}getPendingDirAbsolutePath(t){let e=this.vault.adapter;return e instanceof x.FileSystemAdapter?(0,ki.join)(e.getBasePath(),this.getPendingDir(t)):null}async ensureMemoryDir(t){await this.ensureFolder(this.getMemoryDir(t))}async readAndClearPending(t){let e=this.vault.adapter,s=this.getPendingDir(t),n;try{if(!await e.exists(s))return[];n=(await e.list(s)).files}catch{return[]}let a=[];for(let r of n)if(r.endsWith(".json"))try{let o=await e.read(r);await e.remove(r);for(let c of o.split(`
11716
11716
  `))c.trim().length>0&&a.push(c)}catch{}return a}async readRecentRaw(t,e=2){let s=(0,x.normalizePath)(`${this.getMemoryDir(t)}/raw`),n=this.vault.getAbstractFileByPath(s);if(!(n instanceof x.TFolder))return"";let a=n.children.filter(o=>o instanceof x.TFile&&o.extension==="md").sort((o,c)=>c.name.localeCompare(o.name)).slice(0,e),r=[];for(let o of a.reverse())r.push(`### ${o.basename}
11717
11717
  ${await this.vault.cachedRead(o)}`);return r.join(`
11718
11718
 
11719
- `)}getCandidatesPath(t){return(0,x.normalizePath)(`${this.getMemoryDir(t)}/candidates.json`)}async readCandidates(t){let e=this.getCandidatesPath(t),s=this.vault.getAbstractFileByPath(e);if(!(s instanceof x.TFile))return[];try{let n=JSON.parse(await this.vault.cachedRead(s));return Array.isArray(n)?n:[]}catch{return[]}}async writeCandidates(t,e){let s=this.getCandidatesPath(t);await this.ensureFolder(this.getMemoryDir(t));let n=JSON.stringify(e,null,2),a=this.vault.getAbstractFileByPath(s);a instanceof x.TFile?await this.vault.modify(a,n):await this.createFileIfMissing(s,n)}getProposalsDir(){return(0,x.normalizePath)(`${this.getFleetRoot()}/proposals`)}async listProposals(){let t=this.vault.getAbstractFileByPath(this.getProposalsDir());if(!(t instanceof x.TFolder))return[];let e=[];for(let s of t.children){if(!(s instanceof x.TFile)||s.extension!=="md")continue;let n=await this.readProposal(s.basename);n&&e.push(n)}return e.sort((s,n)=>n.created.localeCompare(s.created)),e}async readProposal(t){let e=(0,x.normalizePath)(`${this.getProposalsDir()}/${t}.md`),s=this.vault.getAbstractFileByPath(e);if(!(s instanceof x.TFile))return null;let{frontmatter:n,body:a}=Q(await this.vault.cachedRead(s)),r=n.type==="skill_modify"?"skill_modify":"skill_create",o=n.status==="accepted"||n.status==="rejected"?n.status:"pending";return{id:t,type:r,agent:A(n.agent)??"",status:o,created:A(n.created)??"",targetSkill:A(n.target_skill),candidate:A(n.candidate),evidence:le(n.evidence),rationale:A(n.rationale)??"",body:a}}async writeProposal(t){await this.ensureFolder(this.getProposalsDir());let e=(0,x.normalizePath)(`${this.getProposalsDir()}/${t.id}.md`),s={id:t.id,type:t.type,agent:t.agent,status:t.status,created:t.created,target_skill:t.targetSkill||void 0,candidate:t.candidate||void 0,evidence:t.evidence.length?t.evidence:void 0,rationale:t.rationale||void 0},n=H(s,t.body||""),a=this.vault.getAbstractFileByPath(e);a instanceof x.TFile?await this.vault.modify(a,n):await this.createFileIfMissing(e,n)}async setProposalStatus(t,e){let s=await this.readProposal(t);s&&(s.status=e,await this.writeProposal(s))}async applyProposal(t){if(t.type==="skill_create"){let e=t.targetSkill||`learned-${ae(t.rationale).slice(0,24)||"skill"}`,s=await this.getAvailablePath(this.getSubfolder("skills"),ae(e)),a={name:s.split("/").pop()?.replace(/\.md$/,"")||ae(e),description:t.rationale||`Auto-proposed from recurring pattern for ${t.agent}.`,tags:["proposed"]};return await this.vault.create(s,H(a,t.body||"Skill instructions go here.")),s}if(t.targetSkill){let e=this.getSkillByName(t.targetSkill);if(e){let s=this.vault.getAbstractFileByPath(e.filePath);if(s instanceof x.TFile){let n=await this.vault.cachedRead(s),a=`
11719
+ `)}getCandidatesPath(t){return(0,x.normalizePath)(`${this.getMemoryDir(t)}/candidates.json`)}async readCandidates(t){let e=this.getCandidatesPath(t),s=this.vault.getAbstractFileByPath(e);if(!(s instanceof x.TFile))return[];try{let n=JSON.parse(await this.vault.cachedRead(s));return Array.isArray(n)?n:[]}catch{return[]}}async writeCandidates(t,e){let s=this.getCandidatesPath(t);await this.ensureFolder(this.getMemoryDir(t));let n=JSON.stringify(e,null,2),a=this.vault.getAbstractFileByPath(s);a instanceof x.TFile?await this.vault.modify(a,n):await this.createFileIfMissing(s,n)}getProposalsDir(){return(0,x.normalizePath)(`${this.getFleetRoot()}/proposals`)}async listProposals(){let t=this.vault.getAbstractFileByPath(this.getProposalsDir());if(!(t instanceof x.TFolder))return[];let e=[];for(let s of t.children){if(!(s instanceof x.TFile)||s.extension!=="md")continue;let n=await this.readProposal(s.basename);n&&e.push(n)}return e.sort((s,n)=>n.created.localeCompare(s.created)),e}async readProposal(t){let e=(0,x.normalizePath)(`${this.getProposalsDir()}/${t}.md`),s=this.vault.getAbstractFileByPath(e);if(!(s instanceof x.TFile))return null;let{frontmatter:n,body:a}=J(await this.vault.cachedRead(s)),r=n.type==="skill_modify"?"skill_modify":"skill_create",o=n.status==="accepted"||n.status==="rejected"?n.status:"pending";return{id:t,type:r,agent:A(n.agent)??"",status:o,created:A(n.created)??"",targetSkill:A(n.target_skill),candidate:A(n.candidate),evidence:ue(n.evidence),rationale:A(n.rationale)??"",body:a}}async writeProposal(t){await this.ensureFolder(this.getProposalsDir());let e=(0,x.normalizePath)(`${this.getProposalsDir()}/${t.id}.md`),s={id:t.id,type:t.type,agent:t.agent,status:t.status,created:t.created,target_skill:t.targetSkill||void 0,candidate:t.candidate||void 0,evidence:t.evidence.length?t.evidence:void 0,rationale:t.rationale||void 0},n=W(s,t.body||""),a=this.vault.getAbstractFileByPath(e);a instanceof x.TFile?await this.vault.modify(a,n):await this.createFileIfMissing(e,n)}async setProposalStatus(t,e){let s=await this.readProposal(t);s&&(s.status=e,await this.writeProposal(s))}async applyProposal(t){if(t.type==="skill_create"){let e=t.targetSkill||`learned-${oe(t.rationale).slice(0,24)||"skill"}`,s=await this.getAvailablePath(this.getSubfolder("skills"),oe(e)),a={name:s.split("/").pop()?.replace(/\.md$/,"")||oe(e),description:t.rationale||`Auto-proposed from recurring pattern for ${t.agent}.`,tags:["proposed"]};return await this.vault.create(s,W(a,t.body||"Skill instructions go here.")),s}if(t.targetSkill){let e=this.getSkillByName(t.targetSkill);if(e){let s=this.vault.getAbstractFileByPath(e.filePath);if(s instanceof x.TFile){let n=await this.vault.cachedRead(s),a=`
11720
11720
 
11721
11721
  ## Proposed update (${new Date().toISOString().slice(0,10)})
11722
11722
  ${t.body}`;return await this.vault.modify(s,`${n.trimEnd()}${a}
@@ -11724,14 +11724,14 @@ ${t.body}`;return await this.vault.modify(s,`${n.trimEnd()}${a}
11724
11724
  `),r=this.vault.getAbstractFileByPath(n);if(r instanceof x.TFile){let o=await this.vault.cachedRead(r);await this.vault.modify(r,`${o.trimEnd()}
11725
11725
  ${a}
11726
11726
  `)}else await this.createFileIfMissing(n,`${a}
11727
- `)}getConversationsDir(t){if(t.isFolder){let s=t.filePath.replace(/\/agent\.md$/,"");return(0,x.normalizePath)(`${s}/conversations`)}let e=this.getMemoryPath(t.name).replace(/\/[^/]+$/,"");return(0,x.normalizePath)(`${e}/${t.name}-conversations`)}getConversationPath(t,e){let s=this.getConversationsDir(t),n=ae(e)||"conversation";return(0,x.normalizePath)(`${s}/${n}.json`)}async listConversations(t){let e=[],s=this.getConversationsDir(t),n=this.vault.getAbstractFileByPath(s);if(n instanceof x.TFolder)for(let a of n.children){if(!(a instanceof x.TFile)||a.extension!=="json")continue;let r=a.basename,o=await this.readConversationMeta(a,r);o&&e.push(o)}return e.sort((a,r)=>r.lastActive.localeCompare(a.lastActive)),e}async readConversationMeta(t,e){try{let s=await this.vault.cachedRead(t),n=JSON.parse(s);return{id:e,name:n.name?.trim()||"Untitled",lastActive:n.lastActive??new Date(t.stat.mtime).toISOString(),messageCount:Array.isArray(n.messages)?n.messages.length:0}}catch{return null}}async createConversation(t,e,s){let n=this.getConversationPath(t,e);if(this.vault.getAbstractFileByPath(n)instanceof x.TFile)return;let r=n.replace(/\/[^/]+$/,"");await this.ensureFolder(r);let o=new Date().toISOString(),c={sessionId:null,messages:[],lastActive:o,createdAt:o,name:s.trim()};await this.vault.create(n,JSON.stringify(c,null,2))}async renameConversation(t,e,s){let n=this.getConversationPath(t,e),a=this.vault.getAbstractFileByPath(n);if(!(a instanceof x.TFile))return;let r=await this.vault.cachedRead(a),o;try{o=JSON.parse(r)}catch{return}o.name=s.trim(),await this.vault.modify(a,JSON.stringify(o,null,2))}async deleteConversation(t,e){let s=this.getConversationPath(t,e),n=this.vault.getAbstractFileByPath(s);n instanceof x.TFile&&await this.vault.delete(n);let a=s.replace(/\.json$/,".threads"),r=this.vault.getAbstractFileByPath(a);r instanceof x.TFolder&&await this.vault.delete(r,!0);let o=this.getConversationsDir(t),c=this.vault.getAbstractFileByPath(o);c instanceof x.TFolder&&c.children.length===0&&await this.vault.delete(c,!0)}async getMemory(t){let e=await this.readWorkingMemory(t);return e?{filePath:e.filePath,agent:e.agent,lastUpdated:e.lastUpdated,body:Ge(e.sections)}:null}async appendMemory(t,e){if(e.length===0)return;let s=this.getMemoryPath(t),n=this.vault.getAbstractFileByPath(s),a=new Date().toISOString(),r=e.map(o=>`- ${o.trim()}`).join(`
11727
+ `)}getConversationsDir(t){if(t.isFolder){let s=t.filePath.replace(/\/agent\.md$/,"");return(0,x.normalizePath)(`${s}/conversations`)}let e=this.getMemoryPath(t.name).replace(/\/[^/]+$/,"");return(0,x.normalizePath)(`${e}/${t.name}-conversations`)}getConversationPath(t,e){let s=this.getConversationsDir(t),n=oe(e)||"conversation";return(0,x.normalizePath)(`${s}/${n}.json`)}async listConversations(t){let e=[],s=this.getConversationsDir(t),n=this.vault.getAbstractFileByPath(s);if(n instanceof x.TFolder)for(let a of n.children){if(!(a instanceof x.TFile)||a.extension!=="json")continue;let r=a.basename,o=await this.readConversationMeta(a,r);o&&e.push(o)}return e.sort((a,r)=>r.lastActive.localeCompare(a.lastActive)),e}async readConversationMeta(t,e){try{let s=await this.vault.cachedRead(t),n=JSON.parse(s);return{id:e,name:n.name?.trim()||"Untitled",lastActive:n.lastActive??new Date(t.stat.mtime).toISOString(),messageCount:Array.isArray(n.messages)?n.messages.length:0}}catch{return null}}async createConversation(t,e,s){let n=this.getConversationPath(t,e);if(this.vault.getAbstractFileByPath(n)instanceof x.TFile)return;let r=n.replace(/\/[^/]+$/,"");await this.ensureFolder(r);let o=new Date().toISOString(),c={sessionId:null,messages:[],lastActive:o,createdAt:o,name:s.trim()};await this.vault.create(n,JSON.stringify(c,null,2))}async renameConversation(t,e,s){let n=this.getConversationPath(t,e),a=this.vault.getAbstractFileByPath(n);if(!(a instanceof x.TFile))return;let r=await this.vault.cachedRead(a),o;try{o=JSON.parse(r)}catch{return}o.name=s.trim(),await this.vault.modify(a,JSON.stringify(o,null,2))}async deleteConversation(t,e){let s=this.getConversationPath(t,e),n=this.vault.getAbstractFileByPath(s);n instanceof x.TFile&&await this.app.fileManager.trashFile(n);let a=s.replace(/\.json$/,".threads"),r=this.vault.getAbstractFileByPath(a);r instanceof x.TFolder&&await this.app.fileManager.trashFile(r);let o=this.getConversationsDir(t),c=this.vault.getAbstractFileByPath(o);c instanceof x.TFolder&&c.children.length===0&&await this.app.fileManager.trashFile(c)}async getMemory(t){let e=await this.readWorkingMemory(t);return e?{filePath:e.filePath,agent:e.agent,lastUpdated:e.lastUpdated,body:Ge(e.sections)}:null}async appendMemory(t,e){if(e.length===0)return;let s=this.getMemoryPath(t),n=this.vault.getAbstractFileByPath(s),a=new Date().toISOString(),r=e.map(o=>`- ${o.trim()}`).join(`
11728
11728
  `);if(n instanceof x.TFile){let c=`${(await this.getMemory(t))?.body.trim()||"## Learned Context"}
11729
11729
 
11730
- ${r}`.trim();await this.vault.modify(n,H({agent:t,last_updated:a},c));return}await this.createFileIfMissing(s,H({agent:t,last_updated:a},`## Learned Context
11730
+ ${r}`.trim();await this.vault.modify(n,W({agent:t,last_updated:a},c));return}await this.createFileIfMissing(s,W({agent:t,last_updated:a},`## Learned Context
11731
11731
 
11732
- ${r}`))}async listRecentRuns(t=50){let e=this.vault.getAbstractFileByPath(this.getRunsRoot());if(!(e instanceof x.TFolder))return[];let s=[];this.collectMarkdownChildren(e,s),s.sort((r,o)=>o.path.localeCompare(r.path));let n=s.slice(0,t),a=[];for(let r of n){let o=await this.readRunLog(r);o&&a.push(o)}return a.sort((r,o)=>o.started.localeCompare(r.started))}async listRunsSince(t){let e=this.vault.getAbstractFileByPath(this.getRunsRoot());if(!(e instanceof x.TFolder))return[];let s=`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")}`,n=[];for(let r of e.children)r instanceof x.TFolder&&(r.name<s||this.collectMarkdownChildren(r,n));let a=[];for(let r of n){let o=await this.readRunLog(r);o&&a.push(o)}return a.sort((r,o)=>o.started.localeCompare(r.started))}async readRunLog(t){let e=await this.vault.cachedRead(t),{frontmatter:s,body:n}=Q(e),a=n.match(/## Prompt\n([\s\S]*?)(?:\n## Result\n|\n## Output\n|$)/),r=n.match(/## Result\n([\s\S]*?)(?:\n## Output\n|$)/),o=n.match(/## Output\n([\s\S]*?)(?:\n## Tools Used\n|$)/),c=n.match(/## Tools Used\n([\s\S]*?)(?:\n## STDERR\n|$)/);return{filePath:t.path,runId:A(s.run_id)??t.basename,agent:A(s.agent)??"unknown",task:A(s.task)??"unknown",status:A(s.status)??"failure",started:A(s.started)??new Date(t.stat.ctime).toISOString(),completed:A(s.completed),durationSeconds:Le(s.duration_seconds,0),tokensUsed:typeof s.tokens_used=="number"?s.tokens_used:void 0,costUsd:typeof s.cost_usd=="number"?s.cost_usd:void 0,model:A(s.model)??at.defaultModel,modelSource:(()=>{let l=A(s.model_source);if(l==="task"||l==="agent"||l==="settings"||l==="cli-default")return l})(),concreteModel:A(s.resolved_concrete_model),exitCode:typeof s.exit_code=="number"?s.exit_code:null,tags:le(s.tags),prompt:a?.[1]?.trim()??"",output:o?.[1]?.trim()??"",finalResult:r?.[1]?.trim()||void 0,toolsUsed:c?.[1]?pe(c[1]).map(l=>l.replace(/^- /,"").trim()).filter(Boolean):[],approvals:this.parseApprovals(s.approvals)}}async writeRunLog(t){let e=new Date(t.started),s=(0,x.normalizePath)(`${this.getRunsRoot()}/${e.toISOString().slice(0,10)}`);await this.ensureFolder(s);let n=`${e.toISOString().slice(11,19).replace(/:/g,"")}-${ae(t.agent)}-${ae(t.task)}.md`,a=(0,x.normalizePath)(`${s}/${n}`),r=H({run_id:t.runId,agent:t.agent,task:t.task,status:t.status,started:t.started,completed:t.completed,duration_seconds:t.durationSeconds,tokens_used:t.tokensUsed,cost_usd:t.costUsd,model:t.model,model_source:t.modelSource,resolved_concrete_model:t.concreteModel,exit_code:t.exitCode,tags:t.tags,approvals:t.approvals},["## Prompt","",t.prompt.trim(),"",...t.finalResult&&t.finalResult.trim()?["## Result","",t.finalResult.trim(),""]:[],"## Output","",t.output.trim()||"(no output)","","## Tools Used","",...t.toolsUsed.length>0?t.toolsUsed.map(c=>`- ${c}`):["- none"],...t.stderr?["","## STDERR","",t.stderr.trim()]:[]].join(`
11733
- `)),o=this.vault.getAbstractFileByPath(a);return o instanceof x.TFile?await this.vault.modify(o,r):await this.vault.create(a,r),a}async updateTaskRunMetadata(t,e){let s=this.vault.getAbstractFileByPath(t.filePath);if(!(s instanceof x.TFile))return;let n=await this.vault.cachedRead(s),{frontmatter:a,body:r}=Q(n),o={...a,last_run:e.lastRun??t.lastRun,next_run:e.nextRun??t.nextRun,run_count:e.runCount??t.runCount};await this.vault.modify(s,H(o,r)),await this.loadFile(s)}async setApprovalDecision(t,e,s){let n=this.vault.getAbstractFileByPath(t);if(!(n instanceof x.TFile))return;let a=await this.vault.cachedRead(n),{frontmatter:r,body:o}=Q(a),c=(this.parseApprovals(r.approvals)??[]).map(l=>l.tool===e?{...l,status:s,resolvedAt:new Date().toISOString()}:l);await this.vault.modify(n,H({...r,approvals:c},o))}async createAgentTemplate(t){let e=await this.getAvailablePath(this.getSubfolder("agents"),ae(t)),s=`---
11734
- name: ${ae(t)}
11732
+ ${r}`))}async listRecentRuns(t=50){let e=this.vault.getAbstractFileByPath(this.getRunsRoot());if(!(e instanceof x.TFolder))return[];let s=[];this.collectMarkdownChildren(e,s),s.sort((r,o)=>o.path.localeCompare(r.path));let n=s.slice(0,t),a=[];for(let r of n){let o=await this.readRunLog(r);o&&a.push(o)}return a.sort((r,o)=>o.started.localeCompare(r.started))}async listRunsSince(t){let e=this.vault.getAbstractFileByPath(this.getRunsRoot());if(!(e instanceof x.TFolder))return[];let s=`${t.getFullYear()}-${String(t.getMonth()+1).padStart(2,"0")}-${String(t.getDate()).padStart(2,"0")}`,n=[];for(let r of e.children)r instanceof x.TFolder&&(r.name<s||this.collectMarkdownChildren(r,n));let a=[];for(let r of n){let o=await this.readRunLog(r);o&&a.push(o)}return a.sort((r,o)=>o.started.localeCompare(r.started))}async readRunLog(t){let e=await this.vault.cachedRead(t),{frontmatter:s,body:n}=J(e),a=n.match(/## Prompt\n([\s\S]*?)(?:\n## Result\n|\n## Output\n|$)/),r=n.match(/## Result\n([\s\S]*?)(?:\n## Output\n|$)/),o=n.match(/## Output\n([\s\S]*?)(?:\n## Tools Used\n|$)/),c=n.match(/## Tools Used\n([\s\S]*?)(?:\n## STDERR\n|$)/);return{filePath:t.path,runId:A(s.run_id)??t.basename,agent:A(s.agent)??"unknown",task:A(s.task)??"unknown",status:A(s.status)??"failure",started:A(s.started)??new Date(t.stat.ctime).toISOString(),completed:A(s.completed),durationSeconds:De(s.duration_seconds,0),tokensUsed:typeof s.tokens_used=="number"?s.tokens_used:void 0,costUsd:typeof s.cost_usd=="number"?s.cost_usd:void 0,model:A(s.model)??at.defaultModel,modelSource:(()=>{let l=A(s.model_source);if(l==="task"||l==="agent"||l==="settings"||l==="cli-default")return l})(),concreteModel:A(s.resolved_concrete_model),exitCode:typeof s.exit_code=="number"?s.exit_code:null,tags:ue(s.tags),prompt:a?.[1]?.trim()??"",output:o?.[1]?.trim()??"",finalResult:r?.[1]?.trim()||void 0,toolsUsed:c?.[1]?ge(c[1]).map(l=>l.replace(/^- /,"").trim()).filter(Boolean):[],approvals:this.parseApprovals(s.approvals)}}async writeRunLog(t){let e=new Date(t.started),s=(0,x.normalizePath)(`${this.getRunsRoot()}/${e.toISOString().slice(0,10)}`);await this.ensureFolder(s);let n=`${e.toISOString().slice(11,19).replace(/:/g,"")}-${oe(t.agent)}-${oe(t.task)}.md`,a=(0,x.normalizePath)(`${s}/${n}`),r=W({run_id:t.runId,agent:t.agent,task:t.task,status:t.status,started:t.started,completed:t.completed,duration_seconds:t.durationSeconds,tokens_used:t.tokensUsed,cost_usd:t.costUsd,model:t.model,model_source:t.modelSource,resolved_concrete_model:t.concreteModel,exit_code:t.exitCode,tags:t.tags,approvals:t.approvals},["## Prompt","",t.prompt.trim(),"",...t.finalResult&&t.finalResult.trim()?["## Result","",t.finalResult.trim(),""]:[],"## Output","",t.output.trim()||"(no output)","","## Tools Used","",...t.toolsUsed.length>0?t.toolsUsed.map(c=>`- ${c}`):["- none"],...t.stderr?["","## STDERR","",t.stderr.trim()]:[]].join(`
11733
+ `)),o=this.vault.getAbstractFileByPath(a);return o instanceof x.TFile?await this.vault.modify(o,r):await this.vault.create(a,r),a}async updateTaskRunMetadata(t,e){let s=this.vault.getAbstractFileByPath(t.filePath);if(!(s instanceof x.TFile))return;let n=await this.vault.cachedRead(s),{frontmatter:a,body:r}=J(n),o={...a,last_run:e.lastRun??t.lastRun,next_run:e.nextRun??t.nextRun,run_count:e.runCount??t.runCount};await this.vault.modify(s,W(o,r)),await this.loadFile(s)}async setApprovalDecision(t,e,s){let n=this.vault.getAbstractFileByPath(t);if(!(n instanceof x.TFile))return;let a=await this.vault.cachedRead(n),{frontmatter:r,body:o}=J(a),c=(this.parseApprovals(r.approvals)??[]).map(l=>l.tool===e?{...l,status:s,resolvedAt:new Date().toISOString()}:l);await this.vault.modify(n,W({...r,approvals:c},o))}async createAgentTemplate(t){let e=await this.getAvailablePath(this.getSubfolder("agents"),oe(t)),s=`---
11734
+ name: ${oe(t)}
11735
11735
  description:
11736
11736
  enabled: true
11737
11737
  skills: []
@@ -11739,23 +11739,23 @@ tags: []
11739
11739
  ---
11740
11740
 
11741
11741
  Agent instructions go here.
11742
- `;return await this.vault.create(e,s)}async createAgentFolder(t){let e=ae(t.name),s=(0,x.normalizePath)(`${this.getSubfolder("agents")}/${e}`);await this.ensureFolder(s);let n={name:t.name,description:t.description||void 0,avatar:t.avatar||void 0,enabled:t.enabled??!0,tags:t.tags,skills:t.skills,mcp_servers:t.mcpServers?.length?t.mcpServers:void 0};t.model&&t.model!=="default"&&(n.model=t.model);let a=(0,x.normalizePath)(`${s}/agent.md`);await this.vault.create(a,H(n,t.systemPrompt||""));let r={model:t.model||"default",adapter:t.adapter||"claude-code",timeout:t.timeout,max_retries:1,cwd:t.cwd||"",permission_mode:t.permissionMode||"bypassPermissions",effort:t.effort||void 0,approval_required:t.approvalRequired,memory:t.memory,memory_max_entries:t.memoryMaxEntries};typeof t.autoCompactThreshold=="number"&&(r.auto_compact_threshold=t.autoCompactThreshold),t.wikiReferences&&t.wikiReferences.length>0&&(r.wiki_references=t.wikiReferences.map(h=>({agent:h})));let o=(0,x.normalizePath)(`${s}/config.md`);await this.vault.create(o,H(r,""));let c=(0,x.normalizePath)(`${s}/SKILLS.md`);await this.vault.create(c,H({},t.skillsBody||""));let l=(0,x.normalizePath)(`${s}/CONTEXT.md`);await this.vault.create(l,H({},t.contextBody||""));let d=t.permissionRules;if(d&&(d.allow.length>0||d.deny.length>0)){let h=(0,x.normalizePath)(`${s}/permissions.json`);await this.vault.create(h,JSON.stringify(d,null,2)+`
11743
- `)}return a}async createSkillTemplate(t){let e=await this.getAvailablePath(this.getSubfolder("skills"),ae(t)),s=`---
11744
- name: ${ae(t)}
11742
+ `;return await this.vault.create(e,s)}async createAgentFolder(t){let e=oe(t.name),s=(0,x.normalizePath)(`${this.getSubfolder("agents")}/${e}`);await this.ensureFolder(s);let n={name:t.name,description:t.description||void 0,avatar:t.avatar||void 0,enabled:t.enabled??!0,tags:t.tags,skills:t.skills,mcp_servers:t.mcpServers?.length?t.mcpServers:void 0};t.model&&t.model!=="default"&&(n.model=t.model);let a=(0,x.normalizePath)(`${s}/agent.md`);await this.vault.create(a,W(n,t.systemPrompt||""));let r={model:t.model||"default",adapter:t.adapter||"claude-code",timeout:t.timeout,max_retries:1,cwd:t.cwd||"",permission_mode:t.permissionMode||"bypassPermissions",effort:t.effort||void 0,approval_required:t.approvalRequired,memory:t.memory,memory_max_entries:t.memoryMaxEntries};typeof t.autoCompactThreshold=="number"&&(r.auto_compact_threshold=t.autoCompactThreshold),t.wikiReferences&&t.wikiReferences.length>0&&(r.wiki_references=t.wikiReferences.map(d=>({agent:d})));let o=(0,x.normalizePath)(`${s}/config.md`);await this.vault.create(o,W(r,""));let c=(0,x.normalizePath)(`${s}/SKILLS.md`);await this.vault.create(c,W({},t.skillsBody||""));let l=(0,x.normalizePath)(`${s}/CONTEXT.md`);await this.vault.create(l,W({},t.contextBody||""));let h=t.permissionRules;if(h&&(h.allow.length>0||h.deny.length>0)){let d=(0,x.normalizePath)(`${s}/permissions.json`);await this.vault.create(d,JSON.stringify(h,null,2)+`
11743
+ `)}return a}async createSkillTemplate(t){let e=await this.getAvailablePath(this.getSubfolder("skills"),oe(t)),s=`---
11744
+ name: ${oe(t)}
11745
11745
  description:
11746
11746
  tags: []
11747
11747
  ---
11748
11748
 
11749
11749
  Skill instructions go here.
11750
- `;return await this.vault.create(e,s)}async createSkillFolder(t){let e=(0,x.normalizePath)(`${this.getSubfolder("skills")}/${ae(t.name)}`);await this.ensureFolder(e);let s={name:t.name,description:t.description||void 0,tags:t.tags.length>0?t.tags:void 0},n=(0,x.normalizePath)(`${e}/skill.md`);if(await this.createFileIfMissing(n,H(s,t.body||"Skill instructions go here.")),t.toolsBody){let a=(0,x.normalizePath)(`${e}/tools.md`);await this.createFileIfMissing(a,`# Tools
11750
+ `;return await this.vault.create(e,s)}async createSkillFolder(t){let e=(0,x.normalizePath)(`${this.getSubfolder("skills")}/${oe(t.name)}`);await this.ensureFolder(e);let s={name:t.name,description:t.description||void 0,tags:t.tags.length>0?t.tags:void 0},n=(0,x.normalizePath)(`${e}/skill.md`);if(await this.createFileIfMissing(n,W(s,t.body||"Skill instructions go here.")),t.toolsBody){let a=(0,x.normalizePath)(`${e}/tools.md`);await this.createFileIfMissing(a,`# Tools
11751
11751
 
11752
11752
  ${t.toolsBody}`)}if(t.referencesBody){let a=(0,x.normalizePath)(`${e}/references.md`);await this.createFileIfMissing(a,`# References
11753
11753
 
11754
11754
  ${t.referencesBody}`)}if(t.examplesBody){let a=(0,x.normalizePath)(`${e}/examples.md`);await this.createFileIfMissing(a,`# Examples
11755
11755
 
11756
- ${t.examplesBody}`)}}async updateAgent(t,e){let s=this.getAgentByName(t);if(s)if(s.isFolder){let n=(0,x.normalizePath)(s.filePath.replace(/\/agent\.md$/,"")),a=this.vault.getAbstractFileByPath(s.filePath);if(a instanceof x.TFile){let c=await this.vault.cachedRead(a),{frontmatter:l,body:d}=Q(c);e.description!==void 0&&(l.description=e.description||void 0),e.avatar!==void 0&&(l.avatar=e.avatar||void 0),e.tags!==void 0&&(l.tags=e.tags),e.skills!==void 0&&(l.skills=e.skills),e.mcpServers!==void 0&&(l.mcp_servers=e.mcpServers.length>0?e.mcpServers:void 0),e.enabled!==void 0&&(l.enabled=e.enabled),e.model!==void 0&&e.model!=="default"&&(l.model=e.model);let h=e.systemPrompt!==void 0?e.systemPrompt:d;await this.vault.modify(a,H(l,h))}let r=(0,x.normalizePath)(`${n}/config.md`),o=this.vault.getAbstractFileByPath(r);if(o instanceof x.TFile){let c=await this.vault.cachedRead(o),{frontmatter:l,body:d}=Q(c);e.model!==void 0&&(l.model=e.model),e.adapter!==void 0&&(l.adapter=e.adapter),e.timeout!==void 0&&(l.timeout=e.timeout),e.cwd!==void 0&&(l.cwd=e.cwd),e.permissionMode!==void 0&&(l.permission_mode=e.permissionMode),e.effort!==void 0&&(l.effort=e.effort||void 0),e.approvalRequired!==void 0&&(l.approval_required=e.approvalRequired),e.memory!==void 0&&(l.memory=e.memory),e.memoryTokenBudget!==void 0&&(l.memory_token_budget=e.memoryTokenBudget),e.reflectionEnabled!==void 0&&(l.reflection_enabled=e.reflectionEnabled),e.reflectionSchedule!==void 0&&(l.reflection_schedule=e.reflectionSchedule),e.reflectionProposeSkills!==void 0&&(l.reflection_propose_skills=e.reflectionProposeSkills),e.autoCompactThreshold!==void 0&&(l.auto_compact_threshold=e.autoCompactThreshold),e.wikiReferences!==void 0&&(l.wiki_references=e.wikiReferences.length>0?e.wikiReferences.map(h=>({agent:h})):void 0),delete l.allowed_tools,delete l.blocked_tools,await this.vault.modify(o,H(l,d))}if(e.skillsBody!==void 0){let c=(0,x.normalizePath)(`${n}/SKILLS.md`),l=this.vault.getAbstractFileByPath(c);l instanceof x.TFile?await this.vault.modify(l,H({},e.skillsBody)):await this.vault.create(c,H({},e.skillsBody))}if(e.contextBody!==void 0){let c=(0,x.normalizePath)(`${n}/CONTEXT.md`),l=this.vault.getAbstractFileByPath(c);l instanceof x.TFile?await this.vault.modify(l,H({},e.contextBody)):await this.vault.create(c,H({},e.contextBody))}if(e.permissionRules!==void 0){let c=(0,x.normalizePath)(`${n}/permissions.json`),l=this.vault.getAbstractFileByPath(c),d=e.permissionRules;if(d.allow.length>0||d.deny.length>0){let h=JSON.stringify(d,null,2)+`
11757
- `;l instanceof x.TFile?await this.vault.modify(l,h):await this.vault.create(c,h)}else l instanceof x.TFile&&await this.vault.trash(l,!0)}}else{let n=this.vault.getAbstractFileByPath(s.filePath);if(!(n instanceof x.TFile))return;let a=await this.vault.cachedRead(n),{frontmatter:r,body:o}=Q(a);e.description!==void 0&&(r.description=e.description||void 0),e.avatar!==void 0&&(r.avatar=e.avatar||void 0),e.tags!==void 0&&(r.tags=e.tags),e.skills!==void 0&&(r.skills=e.skills),e.mcpServers!==void 0&&(r.mcp_servers=e.mcpServers.length>0?e.mcpServers:void 0),e.enabled!==void 0&&(r.enabled=e.enabled),e.model!==void 0&&(r.model=e.model),e.adapter!==void 0&&(r.adapter=e.adapter),e.timeout!==void 0&&(r.timeout=e.timeout),e.cwd!==void 0&&(r.cwd=e.cwd),e.permissionMode!==void 0&&(r.permission_mode=e.permissionMode),e.effort!==void 0&&(r.effort=e.effort||void 0),e.approvalRequired!==void 0&&(r.approval_required=e.approvalRequired),e.memory!==void 0&&(r.memory=e.memory),e.autoCompactThreshold!==void 0&&(r.auto_compact_threshold=e.autoCompactThreshold),e.wikiReferences!==void 0&&(r.wiki_references=e.wikiReferences.length>0?e.wikiReferences.map(l=>({agent:l})):void 0),delete r.allowed_tools,delete r.blocked_tools;let c=e.systemPrompt!==void 0?e.systemPrompt:o;if(await this.vault.modify(n,H(r,c)),e.permissionRules!==void 0){let l=vi(s.filePath),d=this.vault.getAbstractFileByPath(l),h=e.permissionRules;if(h.allow.length>0||h.deny.length>0){let u=JSON.stringify(h,null,2)+`
11758
- `;d instanceof x.TFile?await this.vault.modify(d,u):await this.vault.create(l,u)}else d instanceof x.TFile&&await this.vault.trash(d,!0)}}}async updateTask(t,e){let s=this.getTaskById(t);if(!s)return;let n=this.vault.getAbstractFileByPath(s.filePath);if(!(n instanceof x.TFile))return;let a=await this.vault.cachedRead(n),{frontmatter:r,body:o}=Q(a);e.agent!==void 0&&(r.agent=e.agent),e.type!==void 0&&(r.type=e.type),e.schedule!==void 0&&(r.schedule=e.schedule||void 0),e.runAt!==void 0&&(r.run_at=e.runAt||void 0),e.enabled!==void 0&&(r.enabled=e.enabled),e.priority!==void 0&&(r.priority=e.priority),e.catch_up!==void 0&&(r.catch_up=e.catch_up),e.effort!==void 0&&(r.effort=e.effort||void 0),e.model!==void 0&&(r.model=e.model||void 0),e.tags!==void 0&&(r.tags=e.tags);let c=e.body!==void 0?e.body:o;await this.vault.modify(n,H(r,c))}async updateSkill(t,e){let s=this.getSkillByName(t);if(s)if(s.isFolder){let n=(0,x.normalizePath)(s.filePath.replace(/\/skill\.md$/,"")),a=this.vault.getAbstractFileByPath(s.filePath);if(a instanceof x.TFile){let r=await this.vault.cachedRead(a),{frontmatter:o,body:c}=Q(r);e.description!==void 0&&(o.description=e.description||void 0),e.tags!==void 0&&(o.tags=e.tags.length>0?e.tags:void 0);let l=e.body!==void 0?e.body:c;await this.vault.modify(a,H(o,l))}if(e.toolsBody!==void 0){let r=(0,x.normalizePath)(`${n}/tools.md`),o=this.vault.getAbstractFileByPath(r);e.toolsBody&&(o instanceof x.TFile?await this.vault.modify(o,`# Tools
11756
+ ${t.examplesBody}`)}}async updateAgent(t,e){let s=this.getAgentByName(t);if(s)if(s.isFolder){let n=(0,x.normalizePath)(s.filePath.replace(/\/agent\.md$/,"")),a=this.vault.getAbstractFileByPath(s.filePath);if(a instanceof x.TFile){let c=await this.vault.cachedRead(a),{frontmatter:l,body:h}=J(c);e.description!==void 0&&(l.description=e.description||void 0),e.avatar!==void 0&&(l.avatar=e.avatar||void 0),e.tags!==void 0&&(l.tags=e.tags),e.skills!==void 0&&(l.skills=e.skills),e.mcpServers!==void 0&&(l.mcp_servers=e.mcpServers.length>0?e.mcpServers:void 0),e.enabled!==void 0&&(l.enabled=e.enabled),e.model!==void 0&&e.model!=="default"&&(l.model=e.model);let d=e.systemPrompt!==void 0?e.systemPrompt:h;await this.vault.modify(a,W(l,d))}let r=(0,x.normalizePath)(`${n}/config.md`),o=this.vault.getAbstractFileByPath(r);if(o instanceof x.TFile){let c=await this.vault.cachedRead(o),{frontmatter:l,body:h}=J(c);e.model!==void 0&&(l.model=e.model),e.adapter!==void 0&&(l.adapter=e.adapter),e.timeout!==void 0&&(l.timeout=e.timeout),e.cwd!==void 0&&(l.cwd=e.cwd),e.permissionMode!==void 0&&(l.permission_mode=e.permissionMode),e.effort!==void 0&&(l.effort=e.effort||void 0),e.approvalRequired!==void 0&&(l.approval_required=e.approvalRequired),e.memory!==void 0&&(l.memory=e.memory),e.memoryTokenBudget!==void 0&&(l.memory_token_budget=e.memoryTokenBudget),e.reflectionEnabled!==void 0&&(l.reflection_enabled=e.reflectionEnabled),e.reflectionSchedule!==void 0&&(l.reflection_schedule=e.reflectionSchedule),e.reflectionProposeSkills!==void 0&&(l.reflection_propose_skills=e.reflectionProposeSkills),e.autoCompactThreshold!==void 0&&(l.auto_compact_threshold=e.autoCompactThreshold),e.wikiReferences!==void 0&&(l.wiki_references=e.wikiReferences.length>0?e.wikiReferences.map(d=>({agent:d})):void 0),delete l.allowed_tools,delete l.blocked_tools,await this.vault.modify(o,W(l,h))}if(e.skillsBody!==void 0){let c=(0,x.normalizePath)(`${n}/SKILLS.md`),l=this.vault.getAbstractFileByPath(c);l instanceof x.TFile?await this.vault.modify(l,W({},e.skillsBody)):await this.vault.create(c,W({},e.skillsBody))}if(e.contextBody!==void 0){let c=(0,x.normalizePath)(`${n}/CONTEXT.md`),l=this.vault.getAbstractFileByPath(c);l instanceof x.TFile?await this.vault.modify(l,W({},e.contextBody)):await this.vault.create(c,W({},e.contextBody))}if(e.permissionRules!==void 0){let c=(0,x.normalizePath)(`${n}/permissions.json`),l=this.vault.getAbstractFileByPath(c),h=e.permissionRules;if(h.allow.length>0||h.deny.length>0){let d=JSON.stringify(h,null,2)+`
11757
+ `;l instanceof x.TFile?await this.vault.modify(l,d):await this.vault.create(c,d)}else l instanceof x.TFile&&await this.app.fileManager.trashFile(l)}}else{let n=this.vault.getAbstractFileByPath(s.filePath);if(!(n instanceof x.TFile))return;let a=await this.vault.cachedRead(n),{frontmatter:r,body:o}=J(a);e.description!==void 0&&(r.description=e.description||void 0),e.avatar!==void 0&&(r.avatar=e.avatar||void 0),e.tags!==void 0&&(r.tags=e.tags),e.skills!==void 0&&(r.skills=e.skills),e.mcpServers!==void 0&&(r.mcp_servers=e.mcpServers.length>0?e.mcpServers:void 0),e.enabled!==void 0&&(r.enabled=e.enabled),e.model!==void 0&&(r.model=e.model),e.adapter!==void 0&&(r.adapter=e.adapter),e.timeout!==void 0&&(r.timeout=e.timeout),e.cwd!==void 0&&(r.cwd=e.cwd),e.permissionMode!==void 0&&(r.permission_mode=e.permissionMode),e.effort!==void 0&&(r.effort=e.effort||void 0),e.approvalRequired!==void 0&&(r.approval_required=e.approvalRequired),e.memory!==void 0&&(r.memory=e.memory),e.autoCompactThreshold!==void 0&&(r.auto_compact_threshold=e.autoCompactThreshold),e.wikiReferences!==void 0&&(r.wiki_references=e.wikiReferences.length>0?e.wikiReferences.map(l=>({agent:l})):void 0),delete r.allowed_tools,delete r.blocked_tools;let c=e.systemPrompt!==void 0?e.systemPrompt:o;if(await this.vault.modify(n,W(r,c)),e.permissionRules!==void 0){let l=wi(s.filePath),h=this.vault.getAbstractFileByPath(l),d=e.permissionRules;if(d.allow.length>0||d.deny.length>0){let u=JSON.stringify(d,null,2)+`
11758
+ `;h instanceof x.TFile?await this.vault.modify(h,u):await this.vault.create(l,u)}else h instanceof x.TFile&&await this.app.fileManager.trashFile(h)}}}async updateTask(t,e){let s=this.getTaskById(t);if(!s)return;let n=this.vault.getAbstractFileByPath(s.filePath);if(!(n instanceof x.TFile))return;let a=await this.vault.cachedRead(n),{frontmatter:r,body:o}=J(a);e.agent!==void 0&&(r.agent=e.agent),e.type!==void 0&&(r.type=e.type),e.schedule!==void 0&&(r.schedule=e.schedule||void 0),e.runAt!==void 0&&(r.run_at=e.runAt||void 0),e.enabled!==void 0&&(r.enabled=e.enabled),e.priority!==void 0&&(r.priority=e.priority),e.catch_up!==void 0&&(r.catch_up=e.catch_up),e.effort!==void 0&&(r.effort=e.effort||void 0),e.model!==void 0&&(r.model=e.model||void 0),e.tags!==void 0&&(r.tags=e.tags);let c=e.body!==void 0?e.body:o;await this.vault.modify(n,W(r,c))}async updateSkill(t,e){let s=this.getSkillByName(t);if(s)if(s.isFolder){let n=(0,x.normalizePath)(s.filePath.replace(/\/skill\.md$/,"")),a=this.vault.getAbstractFileByPath(s.filePath);if(a instanceof x.TFile){let r=await this.vault.cachedRead(a),{frontmatter:o,body:c}=J(r);e.description!==void 0&&(o.description=e.description||void 0),e.tags!==void 0&&(o.tags=e.tags.length>0?e.tags:void 0);let l=e.body!==void 0?e.body:c;await this.vault.modify(a,W(o,l))}if(e.toolsBody!==void 0){let r=(0,x.normalizePath)(`${n}/tools.md`),o=this.vault.getAbstractFileByPath(r);e.toolsBody&&(o instanceof x.TFile?await this.vault.modify(o,`# Tools
11759
11759
 
11760
11760
  ${e.toolsBody}`):await this.vault.create(r,`# Tools
11761
11761
 
@@ -11767,7 +11767,7 @@ ${e.referencesBody}`))}if(e.examplesBody!==void 0){let r=(0,x.normalizePath)(`${
11767
11767
 
11768
11768
  ${e.examplesBody}`):await this.vault.create(r,`# Examples
11769
11769
 
11770
- ${e.examplesBody}`))}}else{let n=this.vault.getAbstractFileByPath(s.filePath);if(!(n instanceof x.TFile))return;let a=await this.vault.cachedRead(n),{frontmatter:r,body:o}=Q(a);e.description!==void 0&&(r.description=e.description||void 0),e.tags!==void 0&&(r.tags=e.tags.length>0?e.tags:void 0);let c=e.body!==void 0?e.body:o;await this.vault.modify(n,H(r,c))}}async deleteSkill(t){let e=this.getSkillByName(t);if(e)if(e.isFolder){let s=(0,x.normalizePath)(e.filePath.replace(/\/skill\.md$/,"")),n=this.vault.getAbstractFileByPath(s);n instanceof x.TFolder&&await this.vault.trash(n,!0)}else await this.trashFile(e.filePath)}async deleteTask(t){let e=this.getTaskById(t);e&&await this.trashFile(e.filePath)}async updateChannel(t,e){let s=this.getChannelByName(t);if(!s)return;let n=this.vault.getAbstractFileByPath(s.filePath);if(!(n instanceof x.TFile))return;let a=await this.vault.cachedRead(n),{frontmatter:r,body:o}=Q(a);e.default_agent!==void 0&&(r.default_agent=e.default_agent,delete r.agent),e.allowed_agents!==void 0&&(r.allowed_agents=e.allowed_agents),e.enabled!==void 0&&(r.enabled=e.enabled),e.credential_ref!==void 0&&(r.credential_ref=e.credential_ref),e.allowed_users!==void 0&&(r.allowed_users=e.allowed_users),e.per_user_sessions!==void 0&&(r.per_user_sessions=e.per_user_sessions),e.channel_context!==void 0&&(r.channel_context=e.channel_context||void 0),e.tags!==void 0&&(r.tags=e.tags),e.type!==void 0&&(r.type=e.type),e.transport!==void 0&&(r.transport=e.transport);let c=e.body!==void 0?e.body:o;await this.vault.modify(n,H(r,c))}async deleteChannel(t){let e=this.getChannelByName(t);if(!e)return;await this.trashFile(e.filePath);let s=(0,x.normalizePath)(`${this.getSubfolder("channels")}/${ae(t)}/sessions`),n=this.vault.getAbstractFileByPath(s);n instanceof x.TFolder&&await this.vault.trash(n,!0)}mcpServerFrontmatter(t){let e={name:t.name,transport:t.type,enabled:t.enabled};return t.source&&(e.source=t.source),t.type==="stdio"?(t.command&&(e.command=t.command),t.args&&t.args.length>0&&(e.args=t.args),t.env&&Object.keys(t.env).length>0&&(e.env=t.env),t.envSecretKeys&&t.envSecretKeys.length>0&&(e.env_secret_keys=t.envSecretKeys)):(t.url&&(e.url=t.url),t.headers&&Object.keys(t.headers).length>0&&(e.headers=t.headers),t.auth&&(e.auth=t.auth),t.oauth&&(t.oauth.clientId||t.oauth.resource||(t.oauth.scopes?.length??0)>0)&&(e.oauth={client_id:t.oauth.clientId||void 0,resource:t.oauth.resource||void 0,scopes:t.oauth.scopes&&t.oauth.scopes.length>0?t.oauth.scopes:void 0})),e}async saveMcpServer(t,e=""){let s=this.mcpServerFrontmatter(t),n=H(s,e.trim()),a=t.filePath?this.vault.getAbstractFileByPath(t.filePath):null;if(a instanceof x.TFile)return await this.vault.modify(a,n),a.path;let r=await this.getAvailablePath(this.getSubfolder("mcp"),ae(t.name));return await this.ensureFolder(this.getSubfolder("mcp")),await this.vault.create(r,n),r}async setMcpServerEnabled(t,e){let s=this.getMcpServerByName(t);if(!s?.filePath)return;let n=this.vault.getAbstractFileByPath(s.filePath);if(!(n instanceof x.TFile))return;let a=await this.vault.cachedRead(n),{frontmatter:r,body:o}=Q(a);r.enabled=e,await this.vault.modify(n,H(r,o))}async deleteMcpServer(t){let e=this.getMcpServerByName(t);e?.filePath&&await this.trashFile(e.filePath)}async updateHeartbeat(t,e){let s=this.getAgentByName(t);if(!s||!s.isFolder)return;let n=(0,x.normalizePath)(s.filePath.replace(/\/agent\.md$/,"")),a=(0,x.normalizePath)(`${n}/HEARTBEAT.md`),r=this.vault.getAbstractFileByPath(a);if(r instanceof x.TFile){let o=await this.vault.cachedRead(r),{frontmatter:c,body:l}=Q(o);e.enabled!==void 0&&(c.enabled=e.enabled),e.schedule!==void 0&&(c.schedule=e.schedule||void 0),e.notify!==void 0&&(c.notify=e.notify),e.channel!==void 0&&(c.channel=e.channel||void 0);let d=e.body!==void 0?e.body:l;await this.vault.modify(r,H(c,d))}else{let o={enabled:e.enabled??!1};e.schedule&&(o.schedule=e.schedule),e.notify!==void 0&&(o.notify=e.notify),e.channel&&(o.channel=e.channel);let c=e.body??"";await this.vault.create(a,H(o,c))}}async deleteAgent(t,e){let s=[],n=this.getAgentByName(t);if(!n)return{trashedFiles:s};if(n.isFolder){let c=(0,x.normalizePath)(n.filePath.replace(/\/agent\.md$/,"")),l=this.vault.getAbstractFileByPath(c);if(l instanceof x.TFolder){let d=[];this.collectMarkdownChildren(l,d);for(let h of d)s.push(h.path);await this.vault.trash(l,!0)}}else await this.trashFile(n.filePath),s.push(n.filePath);let a=this.getMemoryPath(t);this.vault.getAbstractFileByPath(a)&&(await this.trashFile(a),s.push(a));let r=this.getMemoryDir(t),o=this.vault.getAbstractFileByPath(r);if(o instanceof x.TFolder&&(await this.vault.trash(o,!0),s.push(r)),e){let c=this.getTasksForAgent(t);for(let l of c)await this.trashFile(l.filePath),s.push(l.filePath)}return{trashedFiles:s}}async trashFile(t){let e=this.vault.getAbstractFileByPath(t);e&&await this.vault.trash(e,!0)}async ensureFolder(t){if(!this.vault.getAbstractFileByPath(t))try{await this.vault.createFolder(t)}catch(e){if(!(e instanceof Error?e.message:String(e)).includes("Folder already exists"))throw e}}async getAvailablePath(t,e){let s=0;for(;;){let n=s===0?"":`-${s+1}`,a=(0,x.normalizePath)(`${t}/${e}${n}.md`);if(!this.vault.getAbstractFileByPath(a))return a;s+=1}}async createFileIfMissing(t,e){if(!this.vault.getAbstractFileByPath(t))try{await this.vault.create(t,e)}catch(s){if(!(s instanceof Error?s.message:String(s)).includes("File already exists"))throw s}}collectMarkdownChildren(t,e){for(let s of t.children)s instanceof x.TFile&&s.extension==="md"&&e.push(s),s instanceof x.TFolder&&this.collectMarkdownChildren(s,e)}clearStoredFile(t){this.agents.delete(t),this.skills.delete(t),this.tasks.delete(t),this.channels.delete(t),this.mcpServers.delete(t),this.validationIssues.delete(t)}setIssue(t,e){let s=this.validationIssues.get(t)??[];s.push({path:t,message:e}),this.validationIssues.set(t,s)}parseFile(t,e){return t.startsWith(`${this.getSubfolder("agents")}/`)?this.parseAgent(t,e):t.startsWith(`${this.getSubfolder("skills")}/`)?this.parseSkill(t,e):t.startsWith(`${this.getSubfolder("tasks")}/`)?this.parseTask(t,e):null}parseAgent(t,e){let{frontmatter:s,body:n}=Q(e);if(!$t(s))return this.setIssue(t,"Invalid frontmatter."),null;let a=A(s.name),r=A(s.model)??this.settings.defaultModel;if(!a||!r)return this.setIssue(t,"Agent requires string field `name` and a valid model or default model setting."),null;let o=le(s.allowed_tools),c=le(s.blocked_tools);return(o.length>0||c.length>0)&&!this.warnedLegacyPerms.has(a)&&(this.warnedLegacyPerms.add(a),console.warn(`Agent Fleet: "${a}" still uses legacy allowed_tools/blocked_tools in its frontmatter. Permission rules now live in <name>.permissions.json beside the .md. Open Edit and Save to migrate.`)),{filePath:t,name:a,description:A(s.description),model:r,adapter:A(s.adapter)??"claude-code",permissionMode:A(s.permission_mode)??"bypassPermissions",effort:A(s.effort),maxRetries:Le(s.max_retries,1),skills:le(s.skills),mcpServers:le(s.mcp_servers),cwd:A(s.cwd),enabled:Be(s.enabled,!0),timeout:Le(s.timeout,300),approvalRequired:le(s.approval_required),memory:Be(s.memory,!1),memoryMaxEntries:Le(s.memory_max_entries,100),memoryTokenBudget:gi(s),reflection:yi(s),autoCompactThreshold:Le(s.auto_compact_threshold,85),tags:le(s.tags),avatar:A(s.avatar)??"",body:n,contextBody:"",skillsBody:"",env:this.parseEnvMap(s.env),permissionRules:{allow:o,deny:c},isFolder:!1,heartbeatEnabled:!1,heartbeatSchedule:"",heartbeatBody:"",heartbeatNotify:!0,heartbeatChannel:""}}parseSkill(t,e){let{frontmatter:s,body:n}=Q(e),a=A(s.name);return a?{filePath:t,name:a,description:A(s.description),tags:le(s.tags),body:n,toolsBody:"",referencesBody:"",examplesBody:"",isFolder:!1}:(this.setIssue(t,"Skill requires string field `name`."),null)}parseTask(t,e){let{frontmatter:s,body:n}=Q(e),a=A(s.task_id),r=A(s.agent),o=A(s.type);if(!a||!r||!o)return this.setIssue(t,"Task requires `task_id`, `agent`, and `type`."),null;if(o==="recurring"&&!A(s.schedule))return this.setIssue(t,"Recurring task requires `schedule`."),null;if(o==="once"&&!A(s.run_at))return this.setIssue(t,"One-time task requires `run_at`."),null;let c=A(s.priority),d=c&&["low","medium","high","critical"].includes(c)?c:"medium";return{filePath:t,taskId:a,agent:r,schedule:A(s.schedule),runAt:A(s.run_at),type:o,priority:d,enabled:Be(s.enabled,!0),created:A(s.created)??new Date().toISOString(),lastRun:A(s.last_run),nextRun:A(s.next_run),runCount:Le(s.run_count,0),catchUp:Be(s.catch_up,this.settings.catchUpMissedTasks),effort:A(s.effort),model:A(s.model),tags:le(s.tags),body:n}}parseChannelFile(t,e){let{frontmatter:s,body:n}=Q(e),a=A(s.name);if(!a)return this.setIssue(t,"Channel requires string field `name`."),null;let r=A(s.type),o=["slack","telegram"];if(!r||!o.includes(r))return this.setIssue(t,`Channel \`${a}\` requires \`type\` to be one of: ${o.join(", ")}.`),null;let c=r,l=A(s.default_agent)??A(s.agent);if(!l)return this.setIssue(t,`Channel \`${a}\` requires \`default_agent\` (or \`agent\`).`),null;let d=le(s.allowed_agents),h=A(s.credential_ref);if(!h)return this.setIssue(t,`Channel \`${a}\` requires \`credential_ref\` pointing at a configured credential.`),null;let u=$t(s.transport)?s.transport:{};return{filePath:t,name:a,type:c,defaultAgent:l,allowedAgents:d,enabled:Be(s.enabled,!0),credentialRef:h,allowedUsers:le(s.allowed_users),perUserSessions:Be(s.per_user_sessions,!0),channelContext:A(s.channel_context)??"",transport:u,tags:le(s.tags),body:n}}parseMcpServerFile(t,e){let{frontmatter:s,body:n}=Q(e),a=A(s.name);if(!a)return this.setIssue(t,"MCP server requires string field `name`."),null;let r=(A(s.transport)??A(s.type)??"").toLowerCase(),o=["stdio","http","sse"];if(!o.includes(r))return this.setIssue(t,`MCP server \`${a}\` requires \`transport\` to be one of: ${o.join(", ")}.`),null;let c=r;if(c==="stdio"){if(!A(s.command))return this.setIssue(t,`MCP server \`${a}\` (stdio) requires a \`command\`.`),null}else if(!A(s.url))return this.setIssue(t,`MCP server \`${a}\` (${c}) requires a \`url\`.`),null;let l=(A(s.auth)??"").toLowerCase(),d=l==="bearer"||l==="oauth"||l==="none"?l:void 0,h;if($t(s.oauth)){let u=s.oauth;h={clientId:A(u.client_id)??A(u.clientId),resource:A(u.resource),scopes:le(u.scopes)}}return{name:a,filePath:t,type:c,enabled:Be(s.enabled,!0),description:A(s.description)??(n.trim()||void 0),source:A(s.source)==="imported"?"imported":"manual",command:A(s.command),args:le(s.args),env:mi(s.env),envSecretKeys:le(s.env_secret_keys),url:A(s.url),headers:mi(s.headers),auth:d,oauth:h,status:"disconnected",scope:"user",tools:[],toolDetails:[]}}validateReferences(){let t=new Set;for(let o of this.skills.values())t.has(o.name)&&this.setIssue(o.filePath,`Duplicate skill name \`${o.name}\`.`),t.add(o.name);let e=new Set;for(let o of this.agents.values()){e.has(o.name)&&this.setIssue(o.filePath,`Duplicate agent name \`${o.name}\`.`),e.add(o.name);for(let c of o.skills)t.has(c)||this.setIssue(o.filePath,`Agent references missing skill \`${c}\`.`)}for(let o of this.tasks.values())e.has(o.agent)||this.setIssue(o.filePath,`Task references missing agent \`${o.agent}\`.`);let s=new Set,n=new Map;for(let o of this.agents.values())n.set(o.name,o);let a=this.channelCredentialGetter?.()??this.settings.channelCredentials??{};for(let o of this.channels.values()){s.has(o.name)&&this.setIssue(o.filePath,`Duplicate channel name \`${o.name}\`.`),s.add(o.name);let c=n.get(o.defaultAgent);c?c.approvalRequired.length>0&&this.setIssue(o.filePath,`Channel \`${o.name}\` cannot bind to agent \`${c.name}\` because the agent has \`approval_required\` set (${c.approvalRequired.join(", ")}). Clear the approval list on the agent or pick a different agent.`):this.setIssue(o.filePath,`Channel \`${o.name}\` references missing agent \`${o.defaultAgent}\`.`);let l=a[o.credentialRef];l?l.type!==o.type&&this.setIssue(o.filePath,`Channel \`${o.name}\` is type \`${o.type}\` but credential \`${o.credentialRef}\` is type \`${l.type}\`.`):this.setIssue(o.filePath,`Channel \`${o.name}\` references missing credential \`${o.credentialRef}\`. Add it under Settings \u2192 Channel Credentials.`)}let r=new Set;for(let o of this.mcpServers.values())r.has(o.name)&&this.setIssue(o.filePath??o.name,`Duplicate MCP server name \`${o.name}\`.`),r.add(o.name)}parseEnvMap(t){if(!$t(t))return{};let e={};for(let[s,n]of Object.entries(t))typeof n=="string"?e[s]=n:(typeof n=="number"||typeof n=="boolean")&&(e[s]=String(n));return e}parseApprovals(t){if(Array.isArray(t))return t.flatMap(e=>{if(!$t(e)||!A(e.tool))return[];let s=A(e.tool);return s?[{tool:s,command:A(e.command),reason:A(e.reason),status:A(e.status)??"pending",resolvedAt:A(e.resolvedAt),note:A(e.note)}]:[]})}};var _t=require("obsidian"),Gs=class extends _t.Modal{constructor(e,s,n){super(e);this.info=s;this.onConfirm=n}deleteTasks=!0;onOpen(){let{contentEl:e}=this;e.empty(),e.addClass("af-confirm-delete-modal");let s=e.createDiv({cls:"af-delete-header"}),n=s.createSpan({cls:"af-delete-header-icon"});(0,_t.setIcon)(n,"alert-triangle"),s.createEl("h3",{text:`Delete agent "${this.info.agentName}"?`});let a=e.createDiv({cls:"af-delete-summary"});a.createDiv({text:"This action will:"});let r=a.createEl("ul",{cls:"af-delete-impact-list"});r.createEl("li",{text:"Move the agent definition to trash"}),this.info.hasMemory&&r.createEl("li",{text:"Move the agent's memory file to trash"}),this.info.taskCount>0&&r.createEl("li").setText(`${this.info.taskCount} task${this.info.taskCount!==1?"s":""} reference this agent`),this.info.runCount>0&&r.createEl("li",{cls:"af-delete-preserved"}).setText(`${this.info.runCount} run log${this.info.runCount!==1?"s":""} will be preserved`),e.createDiv({cls:"af-delete-note",text:"Files are moved to your system trash and can be recovered."}),this.info.taskCount>0&&new _t.Setting(e).setName("Also delete associated tasks").setDesc(`Delete ${this.info.taskCount} task${this.info.taskCount!==1?"s":""} that reference this agent`).addToggle(h=>{h.setValue(this.deleteTasks),h.onChange(u=>{this.deleteTasks=u})});let o=e.createDiv({cls:"af-delete-actions"}),c=o.createEl("button",{text:"Cancel"});c.onclick=()=>this.close();let l=o.createEl("button",{cls:"af-delete-confirm-btn",text:"Delete Agent"}),d=l.createSpan({cls:"af-delete-btn-icon"});(0,_t.setIcon)(d,"trash-2"),l.onclick=()=>{this.onConfirm(this.deleteTasks),this.close()}}};var F=require("obsidian");var Ys=[{value:"opus",label:"opus \u2014 latest Opus"},{value:"sonnet",label:"sonnet \u2014 latest Sonnet"},{value:"haiku",label:"haiku \u2014 latest Haiku"},{value:"opusplan",label:"opusplan \u2014 plan-mode Opus"}],Ks=[{value:"gpt-5.5",label:"gpt-5.5 \u2014 frontier"},{value:"gpt-5.4",label:"gpt-5.4"},{value:"gpt-5.4-mini",label:"gpt-5.4-mini \u2014 fast"},{value:"gpt-5.3-codex",label:"gpt-5.3-codex"}],Vs="__custom__";function ki(i){let t=(i??"").trim().toLowerCase();return t==="codex"||t==="openai-codex"}function xi(i){return ki(i)?Ks:Ys}function nl(i,t){let e=i.trim();return!e||e==="default"||e==="subscription"?"inherit":xi(t).some(s=>s.value===e)?"alias":"custom"}function At(i,t){i.empty(),i.addClass("af-model-picker");let e=ki(t.adapter),s=xi(t.adapter),n=nl(t.value,t.adapter),a=i.createEl("select",{cls:"af-form-select af-mp-select"}),r=t.allowInherit?t.inheritPlaceholder??"Inherit from agent":e?"Default (let Codex pick)":"Default (let Claude Code pick)";a.createEl("option",{text:r,attr:{value:""}});let o=a.createEl("optgroup",{attr:{label:e?"Codex models":"Aliases (any backend)"}});for(let l of s)o.createEl("option",{text:l.label,attr:{value:l.value}});a.createEl("option",{text:"Custom\u2026",attr:{value:Vs}});let c=i.createEl("input",{cls:"af-form-input af-mp-custom-input",attr:{type:"text",placeholder:e?"e.g. gpt-5.5 \xB7 gpt-5.4-mini":"e.g. claude-opus-4-7 \xB7 us.anthropic.claude-opus-4-7 \xB7 claude-opus-4-7@20251101",spellcheck:"false"}});n==="inherit"?(a.value="",c.value="",c.style.display="none"):n==="alias"?(a.value=t.value.trim(),c.value="",c.style.display="none"):(a.value=Vs,c.value=t.value.trim(),c.style.display=""),a.addEventListener("change",()=>{a.value===Vs?(c.style.display="",c.focus(),t.onChange(c.value.trim())):(c.style.display="none",t.onChange(a.value))}),c.addEventListener("input",()=>{a.value===Vs&&t.onChange(c.value.trim())})}var ue=require("obsidian");function al(){let i=new Date,t=i.getFullYear(),e=String(i.getMonth()+1).padStart(2,"0"),s=String(i.getDate()).padStart(2,"0");return`${t}-${e}-${s}`}var il="0 3 * * *",rl="0 9 * * 0";function Xn(){return{scopeSlug:"",scopeRoot:"",inboxPath:"_sources/inbox",archivePath:"_sources/archive",topicsRoot:"_topics",indexPath:"index.md",logPath:"log.md",watchedFolders:[],excludePatterns:[],watchedSince:al(),heartbeatChannel:"",fileSubstantiveAnswers:!0,obsidianUrlScheme:!0,maxTokensPerIngest:6e4,maxTokensPerRefresh:3e4,indexSplitThreshold:100,dedupSimilarityThreshold:.82,summaryStaleDays:30,failedPath:"_sources/failed",stateFile:".wiki-keeper-state.json"}}var Ti=Xn();function Qn(i){let t=ae(i).trim();return t?`wiki-keeper-${t}`:"wiki-keeper"}function ol(i,t){let e=t||"the whole vault",s={name:i,description:`Cultivates ${e} as a self-maintaining wiki. Ingests new sources, extracts durable claims from watched folders, answers questions with citations, and periodically lints.`,avatar:"library",enabled:!0,skills:["wiki-ingest","wiki-query","wiki-lint","wiki-refresh"],tags:t?["wiki-keeper",`scope:${ae(t)}`]:["wiki-keeper"]},n=`You are the Wiki Keeper for the \`${e}\` scope. Maintain it as a persistent, interlinked knowledge base (Karpathy's "LLM wiki" pattern).
11770
+ ${e.examplesBody}`))}}else{let n=this.vault.getAbstractFileByPath(s.filePath);if(!(n instanceof x.TFile))return;let a=await this.vault.cachedRead(n),{frontmatter:r,body:o}=J(a);e.description!==void 0&&(r.description=e.description||void 0),e.tags!==void 0&&(r.tags=e.tags.length>0?e.tags:void 0);let c=e.body!==void 0?e.body:o;await this.vault.modify(n,W(r,c))}}async deleteSkill(t){let e=this.getSkillByName(t);if(e)if(e.isFolder){let s=(0,x.normalizePath)(e.filePath.replace(/\/skill\.md$/,"")),n=this.vault.getAbstractFileByPath(s);n instanceof x.TFolder&&await this.app.fileManager.trashFile(n)}else await this.trashFile(e.filePath)}async deleteTask(t){let e=this.getTaskById(t);e&&await this.trashFile(e.filePath)}async updateChannel(t,e){let s=this.getChannelByName(t);if(!s)return;let n=this.vault.getAbstractFileByPath(s.filePath);if(!(n instanceof x.TFile))return;let a=await this.vault.cachedRead(n),{frontmatter:r,body:o}=J(a);e.default_agent!==void 0&&(r.default_agent=e.default_agent,delete r.agent),e.allowed_agents!==void 0&&(r.allowed_agents=e.allowed_agents),e.enabled!==void 0&&(r.enabled=e.enabled),e.credential_ref!==void 0&&(r.credential_ref=e.credential_ref),e.allowed_users!==void 0&&(r.allowed_users=e.allowed_users),e.per_user_sessions!==void 0&&(r.per_user_sessions=e.per_user_sessions),e.channel_context!==void 0&&(r.channel_context=e.channel_context||void 0),e.tags!==void 0&&(r.tags=e.tags),e.type!==void 0&&(r.type=e.type),e.transport!==void 0&&(r.transport=e.transport);let c=e.body!==void 0?e.body:o;await this.vault.modify(n,W(r,c))}async deleteChannel(t){let e=this.getChannelByName(t);if(!e)return;await this.trashFile(e.filePath);let s=(0,x.normalizePath)(`${this.getSubfolder("channels")}/${oe(t)}/sessions`),n=this.vault.getAbstractFileByPath(s);n instanceof x.TFolder&&await this.app.fileManager.trashFile(n)}mcpServerFrontmatter(t){let e={name:t.name,transport:t.type,enabled:t.enabled};return t.source&&(e.source=t.source),t.type==="stdio"?(t.command&&(e.command=t.command),t.args&&t.args.length>0&&(e.args=t.args),t.env&&Object.keys(t.env).length>0&&(e.env=t.env),t.envSecretKeys&&t.envSecretKeys.length>0&&(e.env_secret_keys=t.envSecretKeys)):(t.url&&(e.url=t.url),t.headers&&Object.keys(t.headers).length>0&&(e.headers=t.headers),t.auth&&(e.auth=t.auth),t.oauth&&(t.oauth.clientId||t.oauth.resource||(t.oauth.scopes?.length??0)>0)&&(e.oauth={client_id:t.oauth.clientId||void 0,resource:t.oauth.resource||void 0,scopes:t.oauth.scopes&&t.oauth.scopes.length>0?t.oauth.scopes:void 0})),e}async saveMcpServer(t,e=""){let s=this.mcpServerFrontmatter(t),n=W(s,e.trim()),a=t.filePath?this.vault.getAbstractFileByPath(t.filePath):null;if(a instanceof x.TFile)return await this.vault.modify(a,n),a.path;let r=await this.getAvailablePath(this.getSubfolder("mcp"),oe(t.name));return await this.ensureFolder(this.getSubfolder("mcp")),await this.vault.create(r,n),r}async setMcpServerEnabled(t,e){let s=this.getMcpServerByName(t);if(!s?.filePath)return;let n=this.vault.getAbstractFileByPath(s.filePath);if(!(n instanceof x.TFile))return;let a=await this.vault.cachedRead(n),{frontmatter:r,body:o}=J(a);r.enabled=e,await this.vault.modify(n,W(r,o))}async deleteMcpServer(t){let e=this.getMcpServerByName(t);e?.filePath&&await this.trashFile(e.filePath)}async updateHeartbeat(t,e){let s=this.getAgentByName(t);if(!s||!s.isFolder)return;let n=(0,x.normalizePath)(s.filePath.replace(/\/agent\.md$/,"")),a=(0,x.normalizePath)(`${n}/HEARTBEAT.md`),r=this.vault.getAbstractFileByPath(a);if(r instanceof x.TFile){let o=await this.vault.cachedRead(r),{frontmatter:c,body:l}=J(o);e.enabled!==void 0&&(c.enabled=e.enabled),e.schedule!==void 0&&(c.schedule=e.schedule||void 0),e.notify!==void 0&&(c.notify=e.notify),e.channel!==void 0&&(c.channel=e.channel||void 0);let h=e.body!==void 0?e.body:l;await this.vault.modify(r,W(c,h))}else{let o={enabled:e.enabled??!1};e.schedule&&(o.schedule=e.schedule),e.notify!==void 0&&(o.notify=e.notify),e.channel&&(o.channel=e.channel);let c=e.body??"";await this.vault.create(a,W(o,c))}}async deleteAgent(t,e){let s=[],n=this.getAgentByName(t);if(!n)return{trashedFiles:s};if(n.isFolder){let c=(0,x.normalizePath)(n.filePath.replace(/\/agent\.md$/,"")),l=this.vault.getAbstractFileByPath(c);if(l instanceof x.TFolder){let h=[];this.collectMarkdownChildren(l,h);for(let d of h)s.push(d.path);await this.app.fileManager.trashFile(l)}}else await this.trashFile(n.filePath),s.push(n.filePath);let a=this.getMemoryPath(t);this.vault.getAbstractFileByPath(a)&&(await this.trashFile(a),s.push(a));let r=this.getMemoryDir(t),o=this.vault.getAbstractFileByPath(r);if(o instanceof x.TFolder&&(await this.app.fileManager.trashFile(o),s.push(r)),e){let c=this.getTasksForAgent(t);for(let l of c)await this.trashFile(l.filePath),s.push(l.filePath)}return{trashedFiles:s}}async trashFile(t){let e=this.vault.getAbstractFileByPath(t);e&&await this.app.fileManager.trashFile(e)}async ensureFolder(t){if(!this.vault.getAbstractFileByPath(t))try{await this.vault.createFolder(t)}catch(e){if(!(e instanceof Error?e.message:String(e)).includes("Folder already exists"))throw e}}async getAvailablePath(t,e){let s=0;for(;;){let n=s===0?"":`-${s+1}`,a=(0,x.normalizePath)(`${t}/${e}${n}.md`);if(!this.vault.getAbstractFileByPath(a))return a;s+=1}}async createFileIfMissing(t,e){if(!this.vault.getAbstractFileByPath(t))try{await this.vault.create(t,e)}catch(s){if(!(s instanceof Error?s.message:String(s)).includes("File already exists"))throw s}}collectMarkdownChildren(t,e){for(let s of t.children)s instanceof x.TFile&&s.extension==="md"&&e.push(s),s instanceof x.TFolder&&this.collectMarkdownChildren(s,e)}clearStoredFile(t){this.agents.delete(t),this.skills.delete(t),this.tasks.delete(t),this.channels.delete(t),this.mcpServers.delete(t),this.validationIssues.delete(t)}setIssue(t,e){let s=this.validationIssues.get(t)??[];s.push({path:t,message:e}),this.validationIssues.set(t,s)}parseFile(t,e){return t.startsWith(`${this.getSubfolder("agents")}/`)?this.parseAgent(t,e):t.startsWith(`${this.getSubfolder("skills")}/`)?this.parseSkill(t,e):t.startsWith(`${this.getSubfolder("tasks")}/`)?this.parseTask(t,e):null}parseAgent(t,e){let{frontmatter:s,body:n}=J(e);if(!jt(s))return this.setIssue(t,"Invalid frontmatter."),null;let a=A(s.name),r=A(s.model)??this.settings.defaultModel;if(!a||!r)return this.setIssue(t,"Agent requires string field `name` and a valid model or default model setting."),null;let o=ue(s.allowed_tools),c=ue(s.blocked_tools);return(o.length>0||c.length>0)&&!this.warnedLegacyPerms.has(a)&&(this.warnedLegacyPerms.add(a),console.warn(`Agent Fleet: "${a}" still uses legacy allowed_tools/blocked_tools in its frontmatter. Permission rules now live in <name>.permissions.json beside the .md. Open Edit and Save to migrate.`)),{filePath:t,name:a,description:A(s.description),model:r,adapter:A(s.adapter)??"claude-code",permissionMode:A(s.permission_mode)??"bypassPermissions",effort:A(s.effort),maxRetries:De(s.max_retries,1),skills:ue(s.skills),mcpServers:ue(s.mcp_servers),cwd:A(s.cwd),enabled:Be(s.enabled,!0),timeout:De(s.timeout,300),approvalRequired:ue(s.approval_required),memory:Be(s.memory,!1),memoryMaxEntries:De(s.memory_max_entries,100),memoryTokenBudget:yi(s),reflection:vi(s),autoCompactThreshold:De(s.auto_compact_threshold,85),tags:ue(s.tags),avatar:A(s.avatar)??"",body:n,contextBody:"",skillsBody:"",env:this.parseEnvMap(s.env),permissionRules:{allow:o,deny:c},isFolder:!1,heartbeatEnabled:!1,heartbeatSchedule:"",heartbeatBody:"",heartbeatNotify:!0,heartbeatChannel:""}}parseSkill(t,e){let{frontmatter:s,body:n}=J(e),a=A(s.name);return a?{filePath:t,name:a,description:A(s.description),tags:ue(s.tags),body:n,toolsBody:"",referencesBody:"",examplesBody:"",isFolder:!1}:(this.setIssue(t,"Skill requires string field `name`."),null)}parseTask(t,e){let{frontmatter:s,body:n}=J(e),a=A(s.task_id),r=A(s.agent),o=A(s.type);if(!a||!r||!o)return this.setIssue(t,"Task requires `task_id`, `agent`, and `type`."),null;if(o==="recurring"&&!A(s.schedule))return this.setIssue(t,"Recurring task requires `schedule`."),null;if(o==="once"&&!A(s.run_at))return this.setIssue(t,"One-time task requires `run_at`."),null;let c=A(s.priority),h=c&&["low","medium","high","critical"].includes(c)?c:"medium";return{filePath:t,taskId:a,agent:r,schedule:A(s.schedule),runAt:A(s.run_at),type:o,priority:h,enabled:Be(s.enabled,!0),created:A(s.created)??new Date().toISOString(),lastRun:A(s.last_run),nextRun:A(s.next_run),runCount:De(s.run_count,0),catchUp:Be(s.catch_up,this.settings.catchUpMissedTasks),effort:A(s.effort),model:A(s.model),tags:ue(s.tags),body:n}}parseChannelFile(t,e){let{frontmatter:s,body:n}=J(e),a=A(s.name);if(!a)return this.setIssue(t,"Channel requires string field `name`."),null;let r=A(s.type),o=["slack","telegram"];if(!r||!o.includes(r))return this.setIssue(t,`Channel \`${a}\` requires \`type\` to be one of: ${o.join(", ")}.`),null;let c=r,l=A(s.default_agent)??A(s.agent);if(!l)return this.setIssue(t,`Channel \`${a}\` requires \`default_agent\` (or \`agent\`).`),null;let h=ue(s.allowed_agents),d=A(s.credential_ref);if(!d)return this.setIssue(t,`Channel \`${a}\` requires \`credential_ref\` pointing at a configured credential.`),null;let u=jt(s.transport)?s.transport:{};return{filePath:t,name:a,type:c,defaultAgent:l,allowedAgents:h,enabled:Be(s.enabled,!0),credentialRef:d,allowedUsers:ue(s.allowed_users),perUserSessions:Be(s.per_user_sessions,!0),channelContext:A(s.channel_context)??"",transport:u,tags:ue(s.tags),body:n}}parseMcpServerFile(t,e){let{frontmatter:s,body:n}=J(e),a=A(s.name);if(!a)return this.setIssue(t,"MCP server requires string field `name`."),null;let r=(A(s.transport)??A(s.type)??"").toLowerCase(),o=["stdio","http","sse"];if(!o.includes(r))return this.setIssue(t,`MCP server \`${a}\` requires \`transport\` to be one of: ${o.join(", ")}.`),null;let c=r;if(c==="stdio"){if(!A(s.command))return this.setIssue(t,`MCP server \`${a}\` (stdio) requires a \`command\`.`),null}else if(!A(s.url))return this.setIssue(t,`MCP server \`${a}\` (${c}) requires a \`url\`.`),null;let l=(A(s.auth)??"").toLowerCase(),h=l==="bearer"||l==="oauth"||l==="none"?l:void 0,d;if(jt(s.oauth)){let u=s.oauth;d={clientId:A(u.client_id)??A(u.clientId),resource:A(u.resource),scopes:ue(u.scopes)}}return{name:a,filePath:t,type:c,enabled:Be(s.enabled,!0),description:A(s.description)??(n.trim()||void 0),source:A(s.source)==="imported"?"imported":"manual",command:A(s.command),args:ue(s.args),env:fi(s.env),envSecretKeys:ue(s.env_secret_keys),url:A(s.url),headers:fi(s.headers),auth:h,oauth:d,status:"disconnected",scope:"user",tools:[],toolDetails:[]}}validateReferences(){let t=new Set;for(let o of this.skills.values())t.has(o.name)&&this.setIssue(o.filePath,`Duplicate skill name \`${o.name}\`.`),t.add(o.name);let e=new Set;for(let o of this.agents.values()){e.has(o.name)&&this.setIssue(o.filePath,`Duplicate agent name \`${o.name}\`.`),e.add(o.name);for(let c of o.skills)t.has(c)||this.setIssue(o.filePath,`Agent references missing skill \`${c}\`.`)}for(let o of this.tasks.values())e.has(o.agent)||this.setIssue(o.filePath,`Task references missing agent \`${o.agent}\`.`);let s=new Set,n=new Map;for(let o of this.agents.values())n.set(o.name,o);let a=this.channelCredentialGetter?.()??this.settings.channelCredentials??{};for(let o of this.channels.values()){s.has(o.name)&&this.setIssue(o.filePath,`Duplicate channel name \`${o.name}\`.`),s.add(o.name);let c=n.get(o.defaultAgent);c?c.approvalRequired.length>0&&this.setIssue(o.filePath,`Channel \`${o.name}\` cannot bind to agent \`${c.name}\` because the agent has \`approval_required\` set (${c.approvalRequired.join(", ")}). Clear the approval list on the agent or pick a different agent.`):this.setIssue(o.filePath,`Channel \`${o.name}\` references missing agent \`${o.defaultAgent}\`.`);let l=a[o.credentialRef];l?l.type!==o.type&&this.setIssue(o.filePath,`Channel \`${o.name}\` is type \`${o.type}\` but credential \`${o.credentialRef}\` is type \`${l.type}\`.`):this.setIssue(o.filePath,`Channel \`${o.name}\` references missing credential \`${o.credentialRef}\`. Add it under Settings \u2192 Channel Credentials.`)}let r=new Set;for(let o of this.mcpServers.values())r.has(o.name)&&this.setIssue(o.filePath??o.name,`Duplicate MCP server name \`${o.name}\`.`),r.add(o.name)}parseEnvMap(t){if(!jt(t))return{};let e={};for(let[s,n]of Object.entries(t))typeof n=="string"?e[s]=n:(typeof n=="number"||typeof n=="boolean")&&(e[s]=String(n));return e}parseApprovals(t){if(Array.isArray(t))return t.flatMap(e=>{if(!jt(e)||!A(e.tool))return[];let s=A(e.tool);return s?[{tool:s,command:A(e.command),reason:A(e.reason),status:A(e.status)??"pending",resolvedAt:A(e.resolvedAt),note:A(e.note)}]:[]})}};var _t=require("obsidian"),Gs=class extends _t.Modal{constructor(e,s,n){super(e);this.info=s;this.onConfirm=n}deleteTasks=!0;onOpen(){let{contentEl:e}=this;e.empty(),e.addClass("af-confirm-delete-modal");let s=e.createDiv({cls:"af-delete-header"}),n=s.createSpan({cls:"af-delete-header-icon"});(0,_t.setIcon)(n,"alert-triangle"),s.createEl("h3",{text:`Delete agent "${this.info.agentName}"?`});let a=e.createDiv({cls:"af-delete-summary"});a.createDiv({text:"This action will:"});let r=a.createEl("ul",{cls:"af-delete-impact-list"});r.createEl("li",{text:"Move the agent definition to trash"}),this.info.hasMemory&&r.createEl("li",{text:"Move the agent's memory file to trash"}),this.info.taskCount>0&&r.createEl("li").setText(`${this.info.taskCount} task${this.info.taskCount!==1?"s":""} reference this agent`),this.info.runCount>0&&r.createEl("li",{cls:"af-delete-preserved"}).setText(`${this.info.runCount} run log${this.info.runCount!==1?"s":""} will be preserved`),e.createDiv({cls:"af-delete-note",text:"Files are moved to your system trash and can be recovered."}),this.info.taskCount>0&&new _t.Setting(e).setName("Also delete associated tasks").setDesc(`Delete ${this.info.taskCount} task${this.info.taskCount!==1?"s":""} that reference this agent`).addToggle(d=>{d.setValue(this.deleteTasks),d.onChange(u=>{this.deleteTasks=u})});let o=e.createDiv({cls:"af-delete-actions"}),c=o.createEl("button",{text:"Cancel"});c.onclick=()=>this.close();let l=o.createEl("button",{cls:"af-delete-confirm-btn",text:"Delete Agent"}),h=l.createSpan({cls:"af-delete-btn-icon"});(0,_t.setIcon)(h,"trash-2"),l.onclick=()=>{this.onConfirm(this.deleteTasks),this.close()}}};var N=require("obsidian");var Ys=[{value:"opus",label:"opus \u2014 latest Opus"},{value:"sonnet",label:"sonnet \u2014 latest Sonnet"},{value:"haiku",label:"haiku \u2014 latest Haiku"},{value:"opusplan",label:"opusplan \u2014 plan-mode Opus"}],Ks=[{value:"gpt-5.5",label:"gpt-5.5 \u2014 frontier"},{value:"gpt-5.4",label:"gpt-5.4"},{value:"gpt-5.4-mini",label:"gpt-5.4-mini \u2014 fast"},{value:"gpt-5.3-codex",label:"gpt-5.3-codex"}],Vs="__custom__";function xi(i){let t=(i??"").trim().toLowerCase();return t==="codex"||t==="openai-codex"}function Si(i){return xi(i)?Ks:Ys}function al(i,t){let e=i.trim();return!e||e==="default"||e==="subscription"?"inherit":Si(t).some(s=>s.value===e)?"alias":"custom"}function At(i,t){i.empty(),i.addClass("af-model-picker");let e=xi(t.adapter),s=Si(t.adapter),n=al(t.value,t.adapter),a=i.createEl("select",{cls:"af-form-select af-mp-select"}),r=t.allowInherit?t.inheritPlaceholder??"Inherit from agent":e?"Default (let Codex pick)":"Default (let Claude Code pick)";a.createEl("option",{text:r,attr:{value:""}});let o=a.createEl("optgroup",{attr:{label:e?"Codex models":"Aliases (any backend)"}});for(let l of s)o.createEl("option",{text:l.label,attr:{value:l.value}});a.createEl("option",{text:"Custom\u2026",attr:{value:Vs}});let c=i.createEl("input",{cls:"af-form-input af-mp-custom-input",attr:{type:"text",placeholder:e?"e.g. gpt-5.5 \xB7 gpt-5.4-mini":"e.g. claude-opus-4-7 \xB7 us.anthropic.claude-opus-4-7 \xB7 claude-opus-4-7@20251101",spellcheck:"false"}});n==="inherit"?(a.value="",c.value="",c.setCssStyles({display:"none"})):n==="alias"?(a.value=t.value.trim(),c.value="",c.setCssStyles({display:"none"})):(a.value=Vs,c.value=t.value.trim(),c.setCssStyles({display:""})),a.addEventListener("change",()=>{a.value===Vs?(c.setCssStyles({display:""}),c.focus(),t.onChange(c.value.trim())):(c.setCssStyles({display:"none"}),t.onChange(a.value))}),c.addEventListener("input",()=>{a.value===Vs&&t.onChange(c.value.trim())})}var fe=require("obsidian");function il(){let i=new Date,t=i.getFullYear(),e=String(i.getMonth()+1).padStart(2,"0"),s=String(i.getDate()).padStart(2,"0");return`${t}-${e}-${s}`}var rl="0 3 * * *",ol="0 9 * * 0";function Xn(){return{scopeSlug:"",scopeRoot:"",inboxPath:"_sources/inbox",archivePath:"_sources/archive",topicsRoot:"_topics",indexPath:"index.md",logPath:"log.md",watchedFolders:[],excludePatterns:[],watchedSince:il(),heartbeatChannel:"",fileSubstantiveAnswers:!0,obsidianUrlScheme:!0,maxTokensPerIngest:6e4,maxTokensPerRefresh:3e4,indexSplitThreshold:100,dedupSimilarityThreshold:.82,summaryStaleDays:30,failedPath:"_sources/failed",stateFile:".wiki-keeper-state.json"}}var _i=Xn();function Qn(i){let t=oe(i).trim();return t?`wiki-keeper-${t}`:"wiki-keeper"}function ll(i,t){let e=t||"the whole vault",s={name:i,description:`Cultivates ${e} as a self-maintaining wiki. Ingests new sources, extracts durable claims from watched folders, answers questions with citations, and periodically lints.`,avatar:"library",enabled:!0,skills:["wiki-ingest","wiki-query","wiki-lint","wiki-refresh"],tags:t?["wiki-keeper",`scope:${oe(t)}`]:["wiki-keeper"]},n=`You are the Wiki Keeper for the \`${e}\` scope. Maintain it as a persistent, interlinked knowledge base (Karpathy's "LLM wiki" pattern).
11771
11771
 
11772
11772
  ## Scope isolation
11773
11773
 
@@ -11809,7 +11809,7 @@ Use \`memory\` for procedural learning ("user prefers concept pages under sub-fo
11809
11809
  - Never write outside the scope root.
11810
11810
  - Never edit \`## Claims\` history (append only).
11811
11811
  - Never edit \`## Summary\` blocks by hand \u2014 \`wiki-refresh\` owns them.
11812
- `;return H(s,n)}function ll(i){let t={model:"opus",adapter:"claude-code",timeout:900,max_retries:1,cwd:"",permission_mode:"acceptEdits",approval_required:["Write"],memory:!0,memory_max_entries:200,wiki_keeper:{scope_root:i.scopeRoot,inbox_path:i.inboxPath,archive_path:i.archivePath,failed_path:i.failedPath,topics_root:i.topicsRoot,index_path:i.indexPath,log_path:i.logPath,watched_folders:i.watchedFolders,exclude_patterns:i.excludePatterns,watched_since:i.watchedSince,file_substantive_answers:i.fileSubstantiveAnswers,obsidian_url_scheme:i.obsidianUrlScheme,max_tokens_per_ingest:i.maxTokensPerIngest,max_tokens_per_refresh:i.maxTokensPerRefresh,index_split_threshold:i.indexSplitThreshold,dedup_similarity_threshold:i.dedupSimilarityThreshold,summary_stale_days:i.summaryStaleDays,state_file:i.stateFile}};return H(t,"")}function cl(i){let t={enabled:!0,schedule:il,notify:!0};return i.heartbeatChannel&&(t.channel=i.heartbeatChannel),H(t,`Run wiki-ingest in both modes:
11812
+ `;return W(s,n)}function cl(i){let t={model:"opus",adapter:"claude-code",timeout:900,max_retries:1,cwd:"",permission_mode:"acceptEdits",approval_required:["Write"],memory:!0,memory_max_entries:200,wiki_keeper:{scope_root:i.scopeRoot,inbox_path:i.inboxPath,archive_path:i.archivePath,failed_path:i.failedPath,topics_root:i.topicsRoot,index_path:i.indexPath,log_path:i.logPath,watched_folders:i.watchedFolders,exclude_patterns:i.excludePatterns,watched_since:i.watchedSince,file_substantive_answers:i.fileSubstantiveAnswers,obsidian_url_scheme:i.obsidianUrlScheme,max_tokens_per_ingest:i.maxTokensPerIngest,max_tokens_per_refresh:i.maxTokensPerRefresh,index_split_threshold:i.indexSplitThreshold,dedup_similarity_threshold:i.dedupSimilarityThreshold,summary_stale_days:i.summaryStaleDays,state_file:i.stateFile}};return W(t,"")}function dl(i){let t={enabled:!0,schedule:rl,notify:!0};return i.heartbeatChannel&&(t.channel=i.heartbeatChannel),W(t,`Run wiki-ingest in both modes:
11813
11813
 
11814
11814
  1. Drain every unprocessed file in the configured inbox (inbox mode).
11815
11815
  2. Diff watched folders against the state file; process changed or new files (watched mode).
@@ -11817,38 +11817,38 @@ Use \`memory\` for procedural learning ("user prefers concept pages under sub-fo
11817
11817
  Lint runs on its own schedule via the sibling \`*-lint\` task.
11818
11818
 
11819
11819
  Change the schedule by editing this file's \`schedule:\` frontmatter directly, or via the agent editor in the dashboard.
11820
- `)}function _i(i){let e={task_id:`${i}-lint`,agent:i,type:"recurring",schedule:rl,priority:"low",enabled:!0,created:new Date().toISOString(),run_count:0,catch_up:!1,tags:["wiki-keeper","lint"]};return H(e,"Run the `wiki-lint` skill on the current scope.\n\nWrite the report as a new `## Lint YYYY-MM-DD` section inside the fenced block in log.md.\n")}function Zn(i,t){return(0,ue.normalizePath)(`${i}/tasks/${t}-lint.md`)}var dl="# Wiki Schema\n\n## Page types\n\n- **Entity pages** \u2014 people, orgs, products. Frontmatter: `type: entity`.\n- **Concept pages** \u2014 ideas, techniques, patterns. `type: concept`.\n- **Event pages** \u2014 meetings, releases, decisions. `type: event, date: YYYY-MM-DD`.\n- **Summary pages** (inbox-mode only) \u2014 one per ingested inbox source. `type: summary, source: <filename>`.\n- **Synthesis pages** \u2014 filed answers from `wiki-query` substantive responses. `type: synthesis, question: <q>, refreshed: <ISO>`. Live under `_topics/syntheses/`.\n\nTopic pages of type entity/concept/event SHOULD also carry:\n- `summary_refreshed: <ISO>` \u2014 last time `wiki-refresh` regenerated this page's summary block. Empty string on creation.\n- `claims_at_refresh: <int>` \u2014 how many claims existed at last refresh. Drives the staleness threshold.\n\n## Page anatomy\n\nEvery entity/concept/event page has this structure:\n\n```markdown\n---\ntype: entity\nname: Vendor X\nsummary_refreshed: 2026-04-26\nclaims_at_refresh: 14\n---\n\n<!-- wiki-keeper:summary:begin -->\n## Summary\n\n- 3-7 bullet synthesis maintained by wiki-refresh.\n- Forward-links to other topics with [[wikilinks]].\n<!-- wiki-keeper:summary:end -->\n\n## Claims\n\n- 2026-04-18 [meeting]: from [[meetings/2026-04-18-vendor-sync|vendor-sync]]: Vendor X raised prices 15%\n- 2026-04-12 [doc]: from [[summaries/2026-04-12-renewal-brief|renewal-brief]]: contract auto-renews 2026-12-01\n\n## Contradictions\n\n(only present when contradictions exist)\n```\n\nThe fenced summary block is auto-managed by `wiki-refresh`. The `## Claims` section is append-only history written by `wiki-ingest` and `wiki-query` compounding. `## Contradictions` is created on demand. **Anything outside these structures is user-authored** and must be preserved.\n\n## Source-type tags\n\nEvery dated bullet in `## Claims` carries a tag indicating the source type:\n\n- `[doc]` \u2014 PDF, DOCX, XLSX, or other document\n- `[meeting]` \u2014 meeting note or transcript\n- `[email]` \u2014 email forward\n- `[note]` \u2014 markdown daily note or in-vault note\n- `[web]` \u2014 web clipping or URL drop\n- `[synthesis]` \u2014 bullet emitted by `wiki-query` compounding (links to a synthesis page)\n- `[other]` \u2014 fallback\n\nTags help `wiki-query` weight evidence quality and help `wiki-lint` identify drift.\n\n## Naming\n\n- Slug-case filenames: `vendor-x.md`, not `Vendor X.md`.\n- Group by type under `_topics/<type>/` when there are >5 pages of a type.\n\n## Links\n\n- Every entity/concept page MUST have \u22651 inbound link from `index.md` (or a sub-MOC) or a sibling.\n- Summary pages MUST forward-link to every entity/concept they mention.\n- Watched-mode extractions append dated entries to topic pages; forward-link to the source file path so readers can find the raw note.\n- Synthesis pages forward-link to every cited topic and earn their place that way (lint exempts them from orphan flagging if they have any outbound links to topics).\n\n## Index split\n\nWhen the topic count exceeds the `index_split_threshold` config value (default 100) or any single type exceeds 30 pages, `index.md` becomes a hub of hubs and per-type sub-MOCs live at `<scope>/index/<type>.md`. After split, new topic-page entries go into the matching sub-MOC, not the root index.\n\n## Conflict resolution\n\n- New claim contradicts existing? Add a `## Contradictions` section with a dated entry. Do NOT overwrite.\n- Flag in `log.md` for user review.\n- `wiki-refresh` reflects unresolved contradictions in the summary so query-time readers see them.\n\n## Failed sources\n\nFiles that fail ingest 3 times in a row are quarantined to `<failed_path>/` (default `_sources/failed/`) with a sidecar `.error.md`. Lint surfaces the quarantine count weekly.\n",hl=["Read","Write","Edit","Glob","Grep","Bash(mv *)","Bash(mkdir *)"],ul=["Bash(rm -rf *)","Bash(git push *)","Bash(rm -rf /*)","Bash(mv * /*)","Bash(cp -r * /*)"];async function Ai(i,t){let e=(0,ue.normalizePath)(`${t}/permissions.json`),s=i.getAbstractFileByPath(e),n={allow:[],deny:[]};if(s instanceof ue.TFile)try{let o=await i.cachedRead(s),c=JSON.parse(o),l=Array.isArray(c.allow)?c.allow.filter(h=>typeof h=="string"):[],d=Array.isArray(c.deny)?c.deny.filter(h=>typeof h=="string"):[];n={allow:l,deny:d}}catch{}let a={allow:Si(n.allow,hl),deny:Si(n.deny,ul)},r=JSON.stringify(a,null,2)+`
11821
- `;return s instanceof ue.TFile?await i.modify(s,r):await i.create(e,r),a}function Si(i,t){let e=new Set,s=[];for(let n of i)e.has(n)||(e.add(n),s.push(n));for(let n of t)e.has(n)||(e.add(n),s.push(n));return s}async function Ei(i,t,e){let s=Qn(e.scopeSlug||e.scopeRoot),n=(0,ue.normalizePath)(`${t}/agents/${s}`);if(await jt(i,n),i.getAbstractFileByPath((0,ue.normalizePath)(`${n}/agent.md`)))throw new Error(`Wiki Keeper agent already exists at ${n}. Delete it first or choose a different scope slug.`);await i.create((0,ue.normalizePath)(`${n}/agent.md`),ol(s,e.scopeRoot)),await i.create((0,ue.normalizePath)(`${n}/config.md`),ll(e)),await i.create((0,ue.normalizePath)(`${n}/HEARTBEAT.md`),cl(e)),await i.create((0,ue.normalizePath)(`${n}/CONTEXT.md`),dl),await Ai(i,n);let r=Zn(t,s);i.getAbstractFileByPath(r)||(await jt(i,(0,ue.normalizePath)(`${t}/tasks`)),await i.create(r,_i(s)));let o=e.scopeRoot.trim(),c=o?`${o}/`:"";return await jt(i,(0,ue.normalizePath)(`${c}${e.inboxPath}`)),await jt(i,(0,ue.normalizePath)(`${c}${e.topicsRoot}`)),await Ci(i,(0,ue.normalizePath)(`${c}${e.indexPath}`),`# Index
11820
+ `)}function Ai(i){let e={task_id:`${i}-lint`,agent:i,type:"recurring",schedule:ol,priority:"low",enabled:!0,created:new Date().toISOString(),run_count:0,catch_up:!1,tags:["wiki-keeper","lint"]};return W(e,"Run the `wiki-lint` skill on the current scope.\n\nWrite the report as a new `## Lint YYYY-MM-DD` section inside the fenced block in log.md.\n")}function Zn(i,t){return(0,fe.normalizePath)(`${i}/tasks/${t}-lint.md`)}var hl="# Wiki Schema\n\n## Page types\n\n- **Entity pages** \u2014 people, orgs, products. Frontmatter: `type: entity`.\n- **Concept pages** \u2014 ideas, techniques, patterns. `type: concept`.\n- **Event pages** \u2014 meetings, releases, decisions. `type: event, date: YYYY-MM-DD`.\n- **Summary pages** (inbox-mode only) \u2014 one per ingested inbox source. `type: summary, source: <filename>`.\n- **Synthesis pages** \u2014 filed answers from `wiki-query` substantive responses. `type: synthesis, question: <q>, refreshed: <ISO>`. Live under `_topics/syntheses/`.\n\nTopic pages of type entity/concept/event SHOULD also carry:\n- `summary_refreshed: <ISO>` \u2014 last time `wiki-refresh` regenerated this page's summary block. Empty string on creation.\n- `claims_at_refresh: <int>` \u2014 how many claims existed at last refresh. Drives the staleness threshold.\n\n## Page anatomy\n\nEvery entity/concept/event page has this structure:\n\n```markdown\n---\ntype: entity\nname: Vendor X\nsummary_refreshed: 2026-04-26\nclaims_at_refresh: 14\n---\n\n<!-- wiki-keeper:summary:begin -->\n## Summary\n\n- 3-7 bullet synthesis maintained by wiki-refresh.\n- Forward-links to other topics with [[wikilinks]].\n<!-- wiki-keeper:summary:end -->\n\n## Claims\n\n- 2026-04-18 [meeting]: from [[meetings/2026-04-18-vendor-sync|vendor-sync]]: Vendor X raised prices 15%\n- 2026-04-12 [doc]: from [[summaries/2026-04-12-renewal-brief|renewal-brief]]: contract auto-renews 2026-12-01\n\n## Contradictions\n\n(only present when contradictions exist)\n```\n\nThe fenced summary block is auto-managed by `wiki-refresh`. The `## Claims` section is append-only history written by `wiki-ingest` and `wiki-query` compounding. `## Contradictions` is created on demand. **Anything outside these structures is user-authored** and must be preserved.\n\n## Source-type tags\n\nEvery dated bullet in `## Claims` carries a tag indicating the source type:\n\n- `[doc]` \u2014 PDF, DOCX, XLSX, or other document\n- `[meeting]` \u2014 meeting note or transcript\n- `[email]` \u2014 email forward\n- `[note]` \u2014 markdown daily note or in-vault note\n- `[web]` \u2014 web clipping or URL drop\n- `[synthesis]` \u2014 bullet emitted by `wiki-query` compounding (links to a synthesis page)\n- `[other]` \u2014 fallback\n\nTags help `wiki-query` weight evidence quality and help `wiki-lint` identify drift.\n\n## Naming\n\n- Slug-case filenames: `vendor-x.md`, not `Vendor X.md`.\n- Group by type under `_topics/<type>/` when there are >5 pages of a type.\n\n## Links\n\n- Every entity/concept page MUST have \u22651 inbound link from `index.md` (or a sub-MOC) or a sibling.\n- Summary pages MUST forward-link to every entity/concept they mention.\n- Watched-mode extractions append dated entries to topic pages; forward-link to the source file path so readers can find the raw note.\n- Synthesis pages forward-link to every cited topic and earn their place that way (lint exempts them from orphan flagging if they have any outbound links to topics).\n\n## Index split\n\nWhen the topic count exceeds the `index_split_threshold` config value (default 100) or any single type exceeds 30 pages, `index.md` becomes a hub of hubs and per-type sub-MOCs live at `<scope>/index/<type>.md`. After split, new topic-page entries go into the matching sub-MOC, not the root index.\n\n## Conflict resolution\n\n- New claim contradicts existing? Add a `## Contradictions` section with a dated entry. Do NOT overwrite.\n- Flag in `log.md` for user review.\n- `wiki-refresh` reflects unresolved contradictions in the summary so query-time readers see them.\n\n## Failed sources\n\nFiles that fail ingest 3 times in a row are quarantined to `<failed_path>/` (default `_sources/failed/`) with a sidecar `.error.md`. Lint surfaces the quarantine count weekly.\n",ul=["Read","Write","Edit","Glob","Grep","Bash(mv *)","Bash(mkdir *)"],pl=["Bash(rm -rf *)","Bash(git push *)","Bash(rm -rf /*)","Bash(mv * /*)","Bash(cp -r * /*)"];async function Ei(i,t){let e=(0,fe.normalizePath)(`${t}/permissions.json`),s=i.getAbstractFileByPath(e),n={allow:[],deny:[]};if(s instanceof fe.TFile)try{let o=await i.cachedRead(s),c=JSON.parse(o),l=Array.isArray(c.allow)?c.allow.filter(d=>typeof d=="string"):[],h=Array.isArray(c.deny)?c.deny.filter(d=>typeof d=="string"):[];n={allow:l,deny:h}}catch{}let a={allow:Ci(n.allow,ul),deny:Ci(n.deny,pl)},r=JSON.stringify(a,null,2)+`
11821
+ `;return s instanceof fe.TFile?await i.modify(s,r):await i.create(e,r),a}function Ci(i,t){let e=new Set,s=[];for(let n of i)e.has(n)||(e.add(n),s.push(n));for(let n of t)e.has(n)||(e.add(n),s.push(n));return s}async function Pi(i,t,e){let s=Qn(e.scopeSlug||e.scopeRoot),n=(0,fe.normalizePath)(`${t}/agents/${s}`);if(await Wt(i,n),i.getAbstractFileByPath((0,fe.normalizePath)(`${n}/agent.md`)))throw new Error(`Wiki Keeper agent already exists at ${n}. Delete it first or choose a different scope slug.`);await i.create((0,fe.normalizePath)(`${n}/agent.md`),ll(s,e.scopeRoot)),await i.create((0,fe.normalizePath)(`${n}/config.md`),cl(e)),await i.create((0,fe.normalizePath)(`${n}/HEARTBEAT.md`),dl(e)),await i.create((0,fe.normalizePath)(`${n}/CONTEXT.md`),hl),await Ei(i,n);let r=Zn(t,s);i.getAbstractFileByPath(r)||(await Wt(i,(0,fe.normalizePath)(`${t}/tasks`)),await i.create(r,Ai(s)));let o=e.scopeRoot.trim(),c=o?`${o}/`:"";return await Wt(i,(0,fe.normalizePath)(`${c}${e.inboxPath}`)),await Wt(i,(0,fe.normalizePath)(`${c}${e.topicsRoot}`)),await Ti(i,(0,fe.normalizePath)(`${c}${e.indexPath}`),`# Index
11822
11822
 
11823
11823
  <!-- wiki-keeper:begin -->
11824
11824
  <!-- wiki-keeper:end -->
11825
- `),await Ci(i,(0,ue.normalizePath)(`${c}${e.logPath}`),`# Log
11825
+ `),await Ti(i,(0,fe.normalizePath)(`${c}${e.logPath}`),`# Log
11826
11826
 
11827
11827
  <!-- wiki-keeper:begin -->
11828
11828
  <!-- wiki-keeper:end -->
11829
- `),{path:n,name:s}}async function jt(i,t){if(i.getAbstractFileByPath(t))return;let e=t.split("/"),s="";for(let n of e)if(s=s?`${s}/${n}`:n,!i.getAbstractFileByPath(s))try{await i.createFolder(s)}catch(a){if(!(a instanceof Error?a.message:String(a)).includes("already exists"))throw a}}async function Ci(i,t,e){if(i.getAbstractFileByPath(t))return;let s=t.replace(/\/[^/]+$/,"");s&&s!==t&&await jt(i,s),await i.create(t,e)}async function Pi(i,t,e,s){let n=(0,ue.normalizePath)(`${t}/agents/${e}`),a=(0,ue.normalizePath)(`${n}/config.md`),r=i.getAbstractFileByPath(a);if(!(r instanceof ue.TFile))throw new Error(`Config file not found for ${e} at ${a}`);let o=await i.cachedRead(r),{frontmatter:c,body:l}=Q(o),d=c.wiki_keeper??{};d.watched_folders=s.watchedFolders,d.exclude_patterns=s.excludePatterns,s.watchedSince?d.watched_since=s.watchedSince:delete d.watched_since,delete d.ingest_schedule,delete d.lint_schedule,delete d.lint_day,d.file_substantive_answers=s.fileSubstantiveAnswers,d.obsidian_url_scheme=s.obsidianUrlScheme,d.max_tokens_per_ingest=s.maxTokensPerIngest,d.max_tokens_per_refresh=s.maxTokensPerRefresh,d.index_split_threshold=s.indexSplitThreshold,d.dedup_similarity_threshold=s.dedupSimilarityThreshold,d.summary_stale_days=s.summaryStaleDays,(typeof d.failed_path!="string"||!d.failed_path)&&(d.failed_path="_sources/failed"),c.wiki_keeper=d,delete c.allowed_tools,delete c.blocked_tools,await i.modify(r,H(c,l)),await Ai(i,n);let h=(0,ue.normalizePath)(`${n}/HEARTBEAT.md`),u=i.getAbstractFileByPath(h);if(u instanceof ue.TFile){let m=await i.cachedRead(u),{frontmatter:g,body:v}=Q(m);s.heartbeatChannel?g.channel=s.heartbeatChannel:delete g.channel,await i.modify(u,H(g,v))}let p=Zn(t,e);i.getAbstractFileByPath(p)instanceof ue.TFile||(await jt(i,(0,ue.normalizePath)(`${t}/tasks`)),await i.create(p,_i(e)))}async function Ri(i,t,e){let s=(0,ue.normalizePath)(`${t}/agents/${e}`),n=i.getAbstractFileByPath(s);if(!n)return;if(!(n instanceof ue.TFolder))throw new Error(`Expected folder at ${s}`);await i.adapter.rmdir(s,!0);let a=Zn(t,e),r=i.getAbstractFileByPath(a);r instanceof ue.TFile&&await i.delete(r)}var Js=class extends F.PluginSettingTab{constructor(e){super(e.app,e);this.plugin=e}display(){let{containerEl:e}=this;e.empty(),e.createEl("h2",{text:"Agent Fleet Settings"}),new F.Setting(e).setName("Fleet folder").addText(a=>a.setValue(this.plugin.settings.fleetFolder).onChange(async r=>{this.plugin.settings.fleetFolder=r.trim()||at.fleetFolder,await this.plugin.saveSettings()})),new F.Setting(e).setName("Claude CLI path").addText(a=>a.setValue(this.plugin.settings.claudeCliPath).onChange(async r=>{this.plugin.settings.claudeCliPath=r.trim()||at.claudeCliPath,await this.plugin.saveSettings()})),new F.Setting(e).setName("Codex CLI path").setDesc("Used by agents with adapter \u201Ccodex\u201D. Install via `npm i -g @openai/codex` and authenticate with `codex login` in a terminal first.").addText(a=>a.setValue(this.plugin.settings.codexCliPath).onChange(async r=>{this.plugin.settings.codexCliPath=r.trim()||at.codexCliPath,await this.plugin.saveSettings()}));let n=new F.Setting(e).setName("Default model").setDesc("Fallback for agents that don\u2019t set their own. Aliases (opus/sonnet/haiku) work on any backend; use Custom for pinned IDs or Bedrock/Vertex/Foundry.").controlEl.createDiv();At(n,{value:this.plugin.settings.defaultModel,onChange:async a=>{this.plugin.settings.defaultModel=a||at.defaultModel,await this.plugin.saveSettings()}}),new F.Setting(e).setName("AWS region").addText(a=>a.setValue(this.plugin.settings.awsRegion).onChange(async r=>{this.plugin.settings.awsRegion=r.trim()||at.awsRegion,await this.plugin.saveSettings()})),new F.Setting(e).setName("Max concurrent runs").addSlider(a=>a.setLimits(1,10,1).setValue(this.plugin.settings.maxConcurrentRuns).setDynamicTooltip().onChange(async r=>{this.plugin.settings.maxConcurrentRuns=r,await this.plugin.saveSettings()})),new F.Setting(e).setName("Run log retention").setDesc("Days to keep run logs before auto-prune.").addSlider(a=>a.setLimits(1,365,1).setValue(this.plugin.settings.runLogRetentionDays).setDynamicTooltip().onChange(async r=>{this.plugin.settings.runLogRetentionDays=r,await this.plugin.saveSettings()})),new F.Setting(e).setName("Catch up missed tasks").addToggle(a=>a.setValue(this.plugin.settings.catchUpMissedTasks).onChange(async r=>{this.plugin.settings.catchUpMissedTasks=r,await this.plugin.saveSettings()})),new F.Setting(e).setName("Notification level").addDropdown(a=>a.addOption("all","All").addOption("failures-only","Failures only").addOption("none","None").setValue(this.plugin.settings.notificationLevel).onChange(async r=>{this.plugin.settings.notificationLevel=r,await this.plugin.saveSettings()})),new F.Setting(e).setName("Status bar").addToggle(a=>a.setValue(this.plugin.settings.showStatusBar).onChange(async r=>{this.plugin.settings.showStatusBar=r,await this.plugin.saveSettings(),this.plugin.refreshStatusBar()})),new F.Setting(e).setName("Chat watchdog timeout (minutes)").setDesc("How long a chat session waits for any output from the Claude CLI before killing the subprocess and surfacing a timeout error. Raise this if your agents run long tools (e.g. large web fetches, builds) and you're seeing spurious 'no response' errors.").addSlider(a=>a.setLimits(1,60,1).setValue(this.plugin.settings.chatWatchdogMinutes).setDynamicTooltip().onChange(async r=>{this.plugin.settings.chatWatchdogMinutes=r,await this.plugin.saveSettings()})),new F.Setting(e).setName("Verify Claude CLI").setDesc("Checks that the configured binary is reachable.").addButton(a=>a.setButtonText("Verify").onClick(async()=>{let r=await this.plugin.verifyClaudeCli();new F.Notice(r?"Claude CLI detected.":"Claude CLI check failed. See console for details.")})),new F.Setting(e).setName("Verify Codex CLI").setDesc("Checks that the configured Codex binary is reachable.").addButton(a=>a.setButtonText("Verify").onClick(async()=>{let r=await this.plugin.verifyCodexCli();new F.Notice(r?"Codex CLI detected.":"Codex CLI check failed. See console for details.")})),this.renderWikiKeepersSection(e),this.renderChannelsSection(e)}renderChannelsSection(e){e.createEl("h3",{text:"Channels"});let s=e.createDiv({cls:"af-settings-warning"});s.style.padding="12px",s.style.margin="8px 0 16px 0",s.style.border="1px solid var(--background-modifier-border)",s.style.borderRadius="6px",s.style.background="var(--background-secondary)",s.createEl("strong",{text:"Credential storage: "}),s.createSpan({text:"Channel credentials are stored in this plugin's data.json inside your vault's .obsidian folder. If you sync your .obsidian folder across devices, credentials will sync with it. Do not commit this file to a public git repository."}),new F.Setting(e).setName("Max concurrent channel sessions").setDesc("Hard cap on live claude subprocesses across all channels. Oldest idle session is hibernated when exceeded.").addSlider(l=>l.setLimits(1,20,1).setValue(this.plugin.settings.maxConcurrentChannelSessions).setDynamicTooltip().onChange(async d=>{this.plugin.settings.maxConcurrentChannelSessions=d,await this.plugin.saveSettings()})),new F.Setting(e).setName("Idle timeout (minutes)").setDesc("Channel sessions with no activity for this long get their subprocess hibernated. State is preserved and the next message resumes transparently.").addSlider(l=>l.setLimits(1,120,1).setValue(this.plugin.settings.channelIdleTimeoutMinutes).setDynamicTooltip().onChange(async d=>{this.plugin.settings.channelIdleTimeoutMinutes=d,await this.plugin.saveSettings()})),new F.Setting(e).setName("Rate limit per conversation").setDesc("Maximum messages allowed per external conversation within the rolling window.").addSlider(l=>l.setLimits(1,100,1).setValue(this.plugin.settings.channelRateLimitPerConversation).setDynamicTooltip().onChange(async d=>{this.plugin.settings.channelRateLimitPerConversation=d,await this.plugin.saveSettings()})),new F.Setting(e).setName("Rate limit window (minutes)").addSlider(l=>l.setLimits(1,60,1).setValue(this.plugin.settings.channelRateLimitWindowMinutes).setDynamicTooltip().onChange(async d=>{this.plugin.settings.channelRateLimitWindowMinutes=d,await this.plugin.saveSettings()})),e.createEl("h4",{text:"Channel credentials"});let n=e.createDiv({cls:"af-channel-credentials"});this.renderCredentialList(n);let a=e.createDiv({cls:"af-channel-credential-add"});a.style.marginTop="12px",a.style.padding="12px",a.style.border="1px dashed var(--background-modifier-border)",a.style.borderRadius="6px",a.createEl("strong",{text:"Add a channel credential"});let r={ref:"",type:"slack",botToken:"",appToken:""};new F.Setting(a).setName("Reference name").setDesc("Used by `credential_ref` in _fleet/channels/*.md files.").addText(l=>l.setPlaceholder("my-creds").onChange(d=>{r.ref=d.trim()})),new F.Setting(a).setName("Type").addDropdown(l=>l.addOption("slack","Slack").addOption("telegram","Telegram").setValue("slack").onChange(d=>{r.type=d,o.style.display=d==="slack"?"":"none",c.style.display=d==="telegram"?"":"none"}));let o=a.createDiv();new F.Setting(o).setName("Bot token (xoxb-...)").addText(l=>{l.inputEl.type="password",l.setPlaceholder("xoxb-...").onChange(d=>{r.botToken=d.trim()})}),new F.Setting(o).setName("App-level token (xapp-...)").setDesc("Generated in your Slack app's Basic Information \u2192 App-Level Tokens.").addText(l=>{l.inputEl.type="password",l.setPlaceholder("xapp-...").onChange(d=>{r.appToken=d.trim()})});let c=a.createDiv();c.style.display="none",new F.Setting(c).setName("Bot token").setDesc("From @BotFather on Telegram.").addText(l=>{l.inputEl.type="password",l.setPlaceholder("123456:ABC-DEF1234...").onChange(d=>{r.botToken=d.trim()})}),new F.Setting(a).addButton(l=>l.setButtonText("Add credential").setCta().onClick(async()=>{if(!r.ref||!r.botToken){new F.Notice("Fill in the reference name and bot token.");return}let d;if(r.type==="telegram")d={type:"telegram",botToken:r.botToken};else{if(!r.appToken){new F.Notice("Slack requires both bot token and app-level token.");return}d={type:"slack",botToken:r.botToken,appToken:r.appToken}}this.plugin.channelCredentials.set(r.ref,d),new F.Notice(`Added credential \`${r.ref}\`.`),this.display()}))}renderCredentialList(e){let s=this.plugin.channelCredentials.list();if(s.length===0){e.createDiv({text:"No channel credentials configured yet.",cls:"af-muted"}).style.color="var(--text-muted)";return}for(let{ref:n,entry:a}of s){let r=e.createDiv({cls:"af-channel-credential-row"});r.style.display="flex",r.style.justifyContent="space-between",r.style.alignItems="center",r.style.padding="8px 12px",r.style.border="1px solid var(--background-modifier-border)",r.style.borderRadius="6px",r.style.marginBottom="6px";let o=r.createDiv();o.createEl("strong",{text:n}),o.createEl("span",{text:` \xB7 ${a.type} \xB7 ${ml(pl(a))}`,cls:"af-muted"}).style.color="var(--text-muted)";let c=r.createEl("button",{text:"Remove"});c.onclick=()=>{this.plugin.channelCredentials.delete(n),new F.Notice(`Removed credential \`${n}\`.`),this.display()}}}renderWikiKeepersSection(e){e.createEl("h3",{text:"Wiki Keepers"});let s=e.createEl("p",{cls:"af-settings-hint",text:"Per-scope wiki agents. Each runs its own inbox + watched folders + topics + heartbeat. All fields on the Add form are optional \u2014 click Create with everything blank to get a whole-vault keeper with defaults."});s.style.color="var(--af-text-secondary)",s.style.fontSize="12px";let a=this.plugin.runtime.getSnapshot().agents.filter(o=>o.wikiKeeper!==void 0),r=e.createDiv({cls:"af-wk-list"});if(a.length===0)r.createDiv({cls:"af-wk-empty",text:"No Wiki Keepers yet. Click Add to create one."});else for(let o of a){let c=r.createDiv({cls:"af-wk-row"}),l=c.createDiv({cls:"af-wk-row-left"});l.createSpan({cls:"af-wk-name",text:o.name});let d=o.wikiKeeper.scopeRoot||"(whole vault)";l.createSpan({cls:"af-wk-scope",text:`scope: ${d}`});let h=c.createDiv({cls:"af-wk-row-actions"}),u=h.createEl("button",{text:"Edit",cls:"af-wk-row-btn"});u.onclick=()=>{new ta(this.plugin,o,()=>{this.scheduleRerender()}).open()};let p=h.createEl("button",{text:"Delete",cls:"af-wk-row-btn af-wk-row-btn-danger"});p.onclick=async()=>{if(confirm(`Delete Wiki Keeper "${o.name}"?
11829
+ `),{path:n,name:s}}async function Wt(i,t){if(i.getAbstractFileByPath(t))return;let e=t.split("/"),s="";for(let n of e)if(s=s?`${s}/${n}`:n,!i.getAbstractFileByPath(s))try{await i.createFolder(s)}catch(a){if(!(a instanceof Error?a.message:String(a)).includes("already exists"))throw a}}async function Ti(i,t,e){if(i.getAbstractFileByPath(t))return;let s=t.replace(/\/[^/]+$/,"");s&&s!==t&&await Wt(i,s),await i.create(t,e)}async function Ri(i,t,e,s){let n=(0,fe.normalizePath)(`${t}/agents/${e}`),a=(0,fe.normalizePath)(`${n}/config.md`),r=i.getAbstractFileByPath(a);if(!(r instanceof fe.TFile))throw new Error(`Config file not found for ${e} at ${a}`);let o=await i.cachedRead(r),{frontmatter:c,body:l}=J(o),h=c.wiki_keeper??{};h.watched_folders=s.watchedFolders,h.exclude_patterns=s.excludePatterns,s.watchedSince?h.watched_since=s.watchedSince:delete h.watched_since,delete h.ingest_schedule,delete h.lint_schedule,delete h.lint_day,h.file_substantive_answers=s.fileSubstantiveAnswers,h.obsidian_url_scheme=s.obsidianUrlScheme,h.max_tokens_per_ingest=s.maxTokensPerIngest,h.max_tokens_per_refresh=s.maxTokensPerRefresh,h.index_split_threshold=s.indexSplitThreshold,h.dedup_similarity_threshold=s.dedupSimilarityThreshold,h.summary_stale_days=s.summaryStaleDays,(typeof h.failed_path!="string"||!h.failed_path)&&(h.failed_path="_sources/failed"),c.wiki_keeper=h,delete c.allowed_tools,delete c.blocked_tools,await i.modify(r,W(c,l)),await Ei(i,n);let d=(0,fe.normalizePath)(`${n}/HEARTBEAT.md`),u=i.getAbstractFileByPath(d);if(u instanceof fe.TFile){let f=await i.cachedRead(u),{frontmatter:g,body:v}=J(f);s.heartbeatChannel?g.channel=s.heartbeatChannel:delete g.channel,await i.modify(u,W(g,v))}let p=Zn(t,e);i.getAbstractFileByPath(p)instanceof fe.TFile||(await Wt(i,(0,fe.normalizePath)(`${t}/tasks`)),await i.create(p,Ai(e)))}async function Di(i,t,e){let s=i.vault,n=(0,fe.normalizePath)(`${t}/agents/${e}`),a=s.getAbstractFileByPath(n);if(!a)return;if(!(a instanceof fe.TFolder))throw new Error(`Expected folder at ${n}`);await i.fileManager.trashFile(a);let r=Zn(t,e),o=s.getAbstractFileByPath(r);o instanceof fe.TFile&&await i.fileManager.trashFile(o)}var Js=class extends N.PluginSettingTab{constructor(e){super(e.app,e);this.plugin=e}display(){let{containerEl:e}=this;e.empty(),new N.Setting(e).setName("Fleet folder").addText(a=>a.setValue(this.plugin.settings.fleetFolder).onChange(async r=>{this.plugin.settings.fleetFolder=r.trim()||at.fleetFolder,await this.plugin.saveSettings()})),new N.Setting(e).setName("Claude CLI path").addText(a=>a.setValue(this.plugin.settings.claudeCliPath).onChange(async r=>{this.plugin.settings.claudeCliPath=r.trim()||at.claudeCliPath,await this.plugin.saveSettings()})),new N.Setting(e).setName("Codex CLI path").setDesc("Used by agents with adapter \u201Ccodex\u201D. Install via `npm i -g @openai/codex` and authenticate with `codex login` in a terminal first.").addText(a=>a.setValue(this.plugin.settings.codexCliPath).onChange(async r=>{this.plugin.settings.codexCliPath=r.trim()||at.codexCliPath,await this.plugin.saveSettings()}));let n=new N.Setting(e).setName("Default model").setDesc("Fallback for agents that don\u2019t set their own. Aliases (opus/sonnet/haiku) work on any backend; use Custom for pinned IDs or Bedrock/Vertex/Foundry.").controlEl.createDiv();At(n,{value:this.plugin.settings.defaultModel,onChange:async a=>{this.plugin.settings.defaultModel=a||at.defaultModel,await this.plugin.saveSettings()}}),new N.Setting(e).setName("AWS region").addText(a=>a.setValue(this.plugin.settings.awsRegion).onChange(async r=>{this.plugin.settings.awsRegion=r.trim()||at.awsRegion,await this.plugin.saveSettings()})),new N.Setting(e).setName("Max concurrent runs").addSlider(a=>a.setLimits(1,10,1).setValue(this.plugin.settings.maxConcurrentRuns).setDynamicTooltip().onChange(async r=>{this.plugin.settings.maxConcurrentRuns=r,await this.plugin.saveSettings()})),new N.Setting(e).setName("Run log retention").setDesc("Days to keep run logs before auto-prune.").addSlider(a=>a.setLimits(1,365,1).setValue(this.plugin.settings.runLogRetentionDays).setDynamicTooltip().onChange(async r=>{this.plugin.settings.runLogRetentionDays=r,await this.plugin.saveSettings()})),new N.Setting(e).setName("Catch up missed tasks").addToggle(a=>a.setValue(this.plugin.settings.catchUpMissedTasks).onChange(async r=>{this.plugin.settings.catchUpMissedTasks=r,await this.plugin.saveSettings()})),new N.Setting(e).setName("Notification level").addDropdown(a=>a.addOption("all","All").addOption("failures-only","Failures only").addOption("none","None").setValue(this.plugin.settings.notificationLevel).onChange(async r=>{this.plugin.settings.notificationLevel=r,await this.plugin.saveSettings()})),new N.Setting(e).setName("Status bar").addToggle(a=>a.setValue(this.plugin.settings.showStatusBar).onChange(async r=>{this.plugin.settings.showStatusBar=r,await this.plugin.saveSettings(),this.plugin.refreshStatusBar()})),new N.Setting(e).setName("Chat watchdog timeout (minutes)").setDesc("How long a chat session waits for any output from the Claude CLI before killing the subprocess and surfacing a timeout error. Raise this if your agents run long tools (e.g. large web fetches, builds) and you're seeing spurious 'no response' errors.").addSlider(a=>a.setLimits(1,60,1).setValue(this.plugin.settings.chatWatchdogMinutes).setDynamicTooltip().onChange(async r=>{this.plugin.settings.chatWatchdogMinutes=r,await this.plugin.saveSettings()})),new N.Setting(e).setName("Verify Claude CLI").setDesc("Checks that the configured binary is reachable.").addButton(a=>a.setButtonText("Verify").onClick(async()=>{let r=await this.plugin.verifyClaudeCli();new N.Notice(r?"Claude CLI detected.":"Claude CLI check failed. See console for details.")})),new N.Setting(e).setName("Verify Codex CLI").setDesc("Checks that the configured Codex binary is reachable.").addButton(a=>a.setButtonText("Verify").onClick(async()=>{let r=await this.plugin.verifyCodexCli();new N.Notice(r?"Codex CLI detected.":"Codex CLI check failed. See console for details.")})),this.renderWikiKeepersSection(e),this.renderChannelsSection(e)}renderChannelsSection(e){new N.Setting(e).setName("Channels").setHeading();let s=e.createDiv({cls:"af-settings-warning"});s.setCssStyles({padding:"12px"}),s.setCssStyles({margin:"8px 0 16px 0"}),s.setCssStyles({border:"1px solid var(--background-modifier-border)"}),s.setCssStyles({borderRadius:"6px"}),s.setCssStyles({background:"var(--background-secondary)"}),s.createEl("strong",{text:"Credential storage: "});let n=this.plugin.app.vault.configDir;s.createSpan({text:`Channel credentials are stored in this plugin's data.json inside your vault's ${n} folder. If you sync your ${n} folder across devices, credentials will sync with it. Do not commit this file to a public git repository.`}),new N.Setting(e).setName("Max concurrent channel sessions").setDesc("Hard cap on live claude subprocesses across all channels. Oldest idle session is hibernated when exceeded.").addSlider(h=>h.setLimits(1,20,1).setValue(this.plugin.settings.maxConcurrentChannelSessions).setDynamicTooltip().onChange(async d=>{this.plugin.settings.maxConcurrentChannelSessions=d,await this.plugin.saveSettings()})),new N.Setting(e).setName("Idle timeout (minutes)").setDesc("Channel sessions with no activity for this long get their subprocess hibernated. State is preserved and the next message resumes transparently.").addSlider(h=>h.setLimits(1,120,1).setValue(this.plugin.settings.channelIdleTimeoutMinutes).setDynamicTooltip().onChange(async d=>{this.plugin.settings.channelIdleTimeoutMinutes=d,await this.plugin.saveSettings()})),new N.Setting(e).setName("Rate limit per conversation").setDesc("Maximum messages allowed per external conversation within the rolling window.").addSlider(h=>h.setLimits(1,100,1).setValue(this.plugin.settings.channelRateLimitPerConversation).setDynamicTooltip().onChange(async d=>{this.plugin.settings.channelRateLimitPerConversation=d,await this.plugin.saveSettings()})),new N.Setting(e).setName("Rate limit window (minutes)").addSlider(h=>h.setLimits(1,60,1).setValue(this.plugin.settings.channelRateLimitWindowMinutes).setDynamicTooltip().onChange(async d=>{this.plugin.settings.channelRateLimitWindowMinutes=d,await this.plugin.saveSettings()})),new N.Setting(e).setName("Channel credentials").setHeading();let a=e.createDiv({cls:"af-channel-credentials"});this.renderCredentialList(a);let r=e.createDiv({cls:"af-channel-credential-add"});r.setCssStyles({marginTop:"12px"}),r.setCssStyles({padding:"12px"}),r.setCssStyles({border:"1px dashed var(--background-modifier-border)"}),r.setCssStyles({borderRadius:"6px"}),r.createEl("strong",{text:"Add a channel credential"});let o={ref:"",type:"slack",botToken:"",appToken:""};new N.Setting(r).setName("Reference name").setDesc("Used by `credential_ref` in _fleet/channels/*.md files.").addText(h=>h.setPlaceholder("my-creds").onChange(d=>{o.ref=d.trim()})),new N.Setting(r).setName("Type").addDropdown(h=>h.addOption("slack","Slack").addOption("telegram","Telegram").setValue("slack").onChange(d=>{o.type=d,c.setCssStyles({display:d==="slack"?"":"none"}),l.setCssStyles({display:d==="telegram"?"":"none"})}));let c=r.createDiv();new N.Setting(c).setName("Bot token (xoxb-...)").addText(h=>{h.inputEl.type="password",h.setPlaceholder("xoxb-...").onChange(d=>{o.botToken=d.trim()})}),new N.Setting(c).setName("App-level token (xapp-...)").setDesc("Generated in your Slack app's Basic Information \u2192 App-Level Tokens.").addText(h=>{h.inputEl.type="password",h.setPlaceholder("xapp-...").onChange(d=>{o.appToken=d.trim()})});let l=r.createDiv();l.setCssStyles({display:"none"}),new N.Setting(l).setName("Bot token").setDesc("From @BotFather on Telegram.").addText(h=>{h.inputEl.type="password",h.setPlaceholder("123456:ABC-DEF1234...").onChange(d=>{o.botToken=d.trim()})}),new N.Setting(r).addButton(h=>h.setButtonText("Add credential").setCta().onClick(async()=>{if(!o.ref||!o.botToken){new N.Notice("Fill in the reference name and bot token.");return}let d;if(o.type==="telegram")d={type:"telegram",botToken:o.botToken};else{if(!o.appToken){new N.Notice("Slack requires both bot token and app-level token.");return}d={type:"slack",botToken:o.botToken,appToken:o.appToken}}this.plugin.channelCredentials.set(o.ref,d),new N.Notice(`Added credential \`${o.ref}\`.`),this.display()}))}renderCredentialList(e){let s=this.plugin.channelCredentials.list();if(s.length===0){e.createDiv({text:"No channel credentials configured yet.",cls:"af-muted"}).setCssStyles({color:"var(--text-muted)"});return}for(let{ref:n,entry:a}of s){let r=e.createDiv({cls:"af-channel-credential-row"});r.setCssStyles({display:"flex"}),r.setCssStyles({justifyContent:"space-between"}),r.setCssStyles({alignItems:"center"}),r.setCssStyles({padding:"8px 12px"}),r.setCssStyles({border:"1px solid var(--background-modifier-border)"}),r.setCssStyles({borderRadius:"6px"}),r.setCssStyles({marginBottom:"6px"});let o=r.createDiv();o.createEl("strong",{text:n}),o.createEl("span",{text:` \xB7 ${a.type} \xB7 ${fl(ml(a))}`,cls:"af-muted"}).setCssStyles({color:"var(--text-muted)"});let c=r.createEl("button",{text:"Remove"});c.onclick=()=>{this.plugin.channelCredentials.delete(n),new N.Notice(`Removed credential \`${n}\`.`),this.display()}}}renderWikiKeepersSection(e){new N.Setting(e).setName("Wiki Keepers").setHeading();let s=e.createEl("p",{cls:"af-settings-hint",text:"Per-scope wiki agents. Each runs its own inbox + watched folders + topics + heartbeat. All fields on the Add form are optional \u2014 click Create with everything blank to get a whole-vault keeper with defaults."});s.setCssStyles({color:"var(--af-text-secondary)"}),s.setCssStyles({fontSize:"12px"});let a=this.plugin.runtime.getSnapshot().agents.filter(o=>o.wikiKeeper!==void 0),r=e.createDiv({cls:"af-wk-list"});if(a.length===0)r.createDiv({cls:"af-wk-empty",text:"No Wiki Keepers yet. Click Add to create one."});else for(let o of a){let c=r.createDiv({cls:"af-wk-row"}),l=c.createDiv({cls:"af-wk-row-left"});l.createSpan({cls:"af-wk-name",text:o.name});let h=o.wikiKeeper.scopeRoot||"(whole vault)";l.createSpan({cls:"af-wk-scope",text:`scope: ${h}`});let d=c.createDiv({cls:"af-wk-row-actions"}),u=d.createEl("button",{text:"Edit",cls:"af-wk-row-btn"});u.onclick=()=>{new ta(this.plugin,o,()=>{this.scheduleRerender()}).open()};let p=d.createEl("button",{text:"Delete",cls:"af-wk-row-btn af-wk-row-btn-danger"});p.onclick=async()=>{if(confirm(`Delete Wiki Keeper "${o.name}"?
11830
11830
 
11831
11831
  This removes the agent folder at _fleet/agents/${o.name}/.
11832
- Your scope's inbox, topics, index, and log are NOT deleted.`))try{await Ri(this.plugin.app.vault,this.plugin.settings.fleetFolder,o.name),await this.plugin.refreshFromVault(),new F.Notice(`Wiki Keeper "${o.name}" deleted.`),this.scheduleRerender()}catch(m){let g=m instanceof Error?m.message:String(m);new F.Notice(`Failed to delete: ${g}`)}}}new F.Setting(e).setName("Add Wiki Keeper").setDesc("Create a new scoped wiki agent. All fields optional.").addButton(o=>o.setButtonText("+ Add").onClick(()=>{new ea(this.plugin,()=>{this.scheduleRerender()}).open()}))}scheduleRerender(){window.setTimeout(async()=>{try{await this.plugin.refreshFromVault()}catch{}this.display()},600)}},ea=class extends F.Modal{constructor(e,s){super(e.app);this.plugin=e;this.onCreated=s;this.input=Xn()}input;onOpen(){let{contentEl:e}=this;e.empty(),e.addClass("af-wk-modal"),e.createEl("h2",{text:"Add Wiki Keeper"});let s=e.createDiv({cls:"af-wk-banner"});s.createEl("strong",{text:"All fields are optional. "}),s.createSpan({text:"Click Create with everything blank and you'll get a whole-vault keeper with sensible defaults (inbox at _sources/inbox, topics at topics/, nightly ingest at 3am, Sunday lint)."}),e.createEl("h3",{text:"Scope",cls:"af-wk-section-h"}),new F.Setting(e).setName("Scope folder").setDesc("Optional. Vault-relative path. Empty = whole vault.").addText(d=>d.setPlaceholder("(empty = whole vault)").setValue(this.input.scopeRoot).onChange(h=>{this.input.scopeRoot=h.trim(),this.renderPreview()})),new F.Setting(e).setName("Slug").setDesc("Optional. Agent name suffix. Default: derived from scope folder name, or 'wiki-keeper' for whole-vault.").addText(d=>d.setPlaceholder("(auto)").setValue(this.input.scopeSlug).onChange(h=>{this.input.scopeSlug=h.trim(),this.renderPreview()})),this.renderPreview(),e.createEl("h3",{text:"Sources",cls:"af-wk-section-h"}),new F.Setting(e).setName("Watched folders").setDesc("Optional. Comma- or newline-separated vault-relative paths. Read-only \u2014 claims are extracted but files are never moved. Leave empty for inbox-only mode (you drop files into _sources/inbox/ and they get archived after processing).").addTextArea(d=>d.setPlaceholder("(empty = inbox-only)").setValue(this.input.watchedFolders.join(", ")).onChange(h=>{this.input.watchedFolders=h.split(/[,\n]/).map(u=>u.trim()).filter(Boolean)})),new F.Setting(e).setName("Exclude patterns").setDesc("Optional. Glob patterns to skip. Leave empty to process everything under watched + inbox.").addTextArea(d=>d.setPlaceholder("(empty = no excludes)").setValue(this.input.excludePatterns.join(", ")).onChange(h=>{this.input.excludePatterns=h.split(/[,\n]/).map(u=>u.trim()).filter(Boolean)})),new F.Setting(e).setName("Watch files modified since").setDesc("Watched mode only \u2014 files whose last modification date is before this are skipped. Defaults to today so an established vault doesn't flood the keeper on first run. Clear the field to process everything.").addText(d=>{d.inputEl.type="date",d.setValue(this.input.watchedSince).onChange(h=>{this.input.watchedSince=h.trim()})});let n=this.plugin.runtime.getSnapshot().channels.map(d=>d.name);new F.Setting(e).setName("Heartbeat channel").setDesc("Optional. Slack/Telegram channel for ingest + lint summaries. Leave as (none) to disable.").addDropdown(d=>{d.addOption("","(none)");for(let h of n)d.addOption(h,h);d.setValue(this.input.heartbeatChannel).onChange(h=>{this.input.heartbeatChannel=h})}),e.createEl("h3",{text:"Advanced",cls:"af-wk-section-h"}),new F.Setting(e).setName("Max tokens per ingest").setDesc("Hard cap on token spend per run. Unprocessed files resume next cycle.").addText(d=>d.setValue(String(this.input.maxTokensPerIngest)).onChange(h=>{let u=parseInt(h,10);!isNaN(u)&&u>0&&(this.input.maxTokensPerIngest=u)})),new F.Setting(e).setName("File substantive answers").setDesc("If on, wiki-query files long answers under _topics/syntheses/. Off = answers live only in chat.").addToggle(d=>d.setValue(this.input.fileSubstantiveAnswers).onChange(h=>{this.input.fileSubstantiveAnswers=h})),new F.Setting(e).setName("Obsidian URL scheme for citations").setDesc("If on, external-channel (Slack/Telegram) replies rewrite [[wikilinks]] as obsidian:// URLs.").addToggle(d=>d.setValue(this.input.obsidianUrlScheme).onChange(h=>{this.input.obsidianUrlScheme=h}));let a=e.createEl("h3",{text:"Paths (expert)",cls:"af-wk-section-h"});a.title="Paths are relative to scope_root. Defaults work for almost everyone. Override only if your vault layout demands it \u2014 these cannot be changed after creation.";let r=(d,h,u)=>{new F.Setting(e).setName(d).setDesc(h).addText(p=>p.setPlaceholder(String(this.input[u]??"")).setValue(String(this.input[u]??"")).onChange(f=>{this.input[u]=f.trim()||Ti[u]}))};r("Inbox path","Where one-off source drops land.","inboxPath"),r("Archive path","Where processed inbox files are moved after summarization.","archivePath"),r("Topics root","Folder under scope_root that holds the generated topic pages.","topicsRoot"),r("Index path","Relative file path for the curated index.","indexPath"),r("Log path","Relative file path for the keeper's activity log.","logPath"),r("State file","Hidden JSON file that tracks watched-source mtimes.","stateFile");let o=e.createDiv({cls:"af-wk-modal-footer"}),c=o.createEl("button",{text:"Cancel"});c.onclick=()=>this.close();let l=o.createEl("button",{text:"Create",cls:"mod-cta"});l.onclick=async()=>{l.setText("Creating\u2026"),l.disabled=!0;try{let{name:d}=await Ei(this.app.vault,this.plugin.settings.fleetFolder,this.input);await this.plugin.refreshFromVault(),this.close(),new F.Notice(`Wiki Keeper "${d}" created.`),this.onCreated()}catch(d){let h=d instanceof Error?d.message:String(d);new F.Notice(`Failed to create Wiki Keeper: ${h}`),l.setText("Create"),l.disabled=!1}}}renderPreview(){let e=this.contentEl.querySelector(".af-wk-name-preview");e||(e=this.contentEl.createDiv({cls:"af-wk-name-preview"}));let s=this.input.scopeSlug||this.input.scopeRoot;e.setText(`\u2192 Will create agent: ${Qn(s)}`)}onClose(){this.contentEl.empty()}},ta=class extends F.Modal{constructor(e,s,n){super(e.app);this.plugin=e;this.agent=s;this.onSaved=n;let a=s.wikiKeeper;this.edit={watchedFolders:[...a.watchedFolders],excludePatterns:[...a.excludePatterns],watchedSince:a.watchedSince,heartbeatChannel:s.heartbeatChannel??"",fileSubstantiveAnswers:a.fileSubstantiveAnswers,obsidianUrlScheme:a.obsidianUrlScheme,maxTokensPerIngest:a.maxTokensPerIngest,maxTokensPerRefresh:a.maxTokensPerRefresh,indexSplitThreshold:a.indexSplitThreshold,dedupSimilarityThreshold:a.dedupSimilarityThreshold,summaryStaleDays:a.summaryStaleDays}}edit;onOpen(){let{contentEl:e}=this;e.empty(),e.addClass("af-wk-modal"),e.createEl("h2",{text:`Edit ${this.agent.name}`});let s=e.createDiv({cls:"af-wk-banner"}),n=this.agent.wikiKeeper.scopeRoot||"(whole vault)";s.createEl("strong",{text:"Scope: "}),s.createSpan({text:n}),s.createEl("br"),s.createSpan({text:"Scope and paths are fixed after creation \u2014 changing them would orphan existing topic pages. To move a Wiki Keeper, delete this one and create a new one at the new scope."}),e.createEl("h3",{text:"Sources",cls:"af-wk-section-h"}),new F.Setting(e).setName("Watched folders").setDesc("Comma- or newline-separated vault-relative paths.").addTextArea(l=>l.setValue(this.edit.watchedFolders.join(", ")).onChange(d=>{this.edit.watchedFolders=d.split(/[,\n]/).map(h=>h.trim()).filter(Boolean)})),new F.Setting(e).setName("Exclude patterns").setDesc("Glob patterns to skip.").addTextArea(l=>l.setValue(this.edit.excludePatterns.join(", ")).onChange(d=>{this.edit.excludePatterns=d.split(/[,\n]/).map(h=>h.trim()).filter(Boolean)})),new F.Setting(e).setName("Watch files modified since").setDesc("Watched mode skips files older than this date. Clear to process everything.").addText(l=>{l.inputEl.type="date",l.setValue(this.edit.watchedSince).onChange(d=>{this.edit.watchedSince=d.trim()})});let a=this.plugin.runtime.getSnapshot().channels.map(l=>l.name);new F.Setting(e).setName("Heartbeat channel").addDropdown(l=>{l.addOption("","(none)");for(let d of a)l.addOption(d,d);l.setValue(this.edit.heartbeatChannel).onChange(d=>{this.edit.heartbeatChannel=d})}),e.createEl("h3",{text:"Advanced",cls:"af-wk-section-h"}),new F.Setting(e).setName("Max tokens per ingest").addText(l=>l.setValue(String(this.edit.maxTokensPerIngest)).onChange(d=>{let h=parseInt(d,10);!isNaN(h)&&h>0&&(this.edit.maxTokensPerIngest=h)})),new F.Setting(e).setName("Max tokens per refresh").setDesc("Separate budget for the synthesis-refresh phase that regenerates topic-page summaries.").addText(l=>l.setValue(String(this.edit.maxTokensPerRefresh)).onChange(d=>{let h=parseInt(d,10);!isNaN(h)&&h>0&&(this.edit.maxTokensPerRefresh=h)})),new F.Setting(e).setName("Index split threshold").setDesc("Topic-page count above which index.md splits into per-type sub-MOCs.").addText(l=>l.setValue(String(this.edit.indexSplitThreshold)).onChange(d=>{let h=parseInt(d,10);!isNaN(h)&&h>0&&(this.edit.indexSplitThreshold=h)})),new F.Setting(e).setName("Summary stale (days)").setDesc("Lint flags topic-page summaries older than this and chains wiki-refresh.").addText(l=>l.setValue(String(this.edit.summaryStaleDays)).onChange(d=>{let h=parseInt(d,10);!isNaN(h)&&h>0&&(this.edit.summaryStaleDays=h)})),new F.Setting(e).setName("Dedup similarity threshold").setDesc("Levenshtein-ratio above which lint proposes merging two same-type pages (0.0\u20131.0).").addText(l=>l.setValue(String(this.edit.dedupSimilarityThreshold)).onChange(d=>{let h=parseFloat(d);!isNaN(h)&&h>0&&h<=1&&(this.edit.dedupSimilarityThreshold=h)})),new F.Setting(e).setName("File substantive answers").setDesc("Compounding: wiki-query files long answers under _topics/syntheses/ and bullets each cited topic page. Default ON.").addToggle(l=>l.setValue(this.edit.fileSubstantiveAnswers).onChange(d=>{this.edit.fileSubstantiveAnswers=d})),new F.Setting(e).setName("Obsidian URL scheme for citations").setDesc("Rewrite [[wikilinks]] as obsidian:// URLs when replying via Slack/Telegram.").addToggle(l=>l.setValue(this.edit.obsidianUrlScheme).onChange(d=>{this.edit.obsidianUrlScheme=d}));let r=e.createDiv({cls:"af-wk-modal-footer"}),o=r.createEl("button",{text:"Cancel"});o.onclick=()=>this.close();let c=r.createEl("button",{text:"Save",cls:"mod-cta"});c.onclick=async()=>{c.setText("Saving\u2026"),c.disabled=!0;try{await Pi(this.app.vault,this.plugin.settings.fleetFolder,this.agent.name,this.edit),await this.plugin.refreshFromVault(),this.close(),new F.Notice("Saved."),this.onSaved()}catch(l){let d=l instanceof Error?l.message:String(l);new F.Notice(`Failed to save: ${d}`),c.setText("Save"),c.disabled=!1}}}onClose(){this.contentEl.empty()}};function pl(i){return i.type==="slack",i.botToken}function ml(i){return i.length<=10?"***":`${i.slice(0,6)}\u2026${i.slice(-4)}`}var rr=require("crypto");function je(i,t,e,s,n,a,r,o){return je.fromTZ(je.tp(i,t,e,s,n,a,r),o)}je.fromTZISO=(i,t,e)=>je.fromTZ(fl(i,t),e);je.fromTZ=function(i,t){let e=new Date(Date.UTC(i.y,i.m-1,i.d,i.h,i.i,i.s)),s=sa(i.tz,e),n=new Date(e.getTime()-s),a=sa(i.tz,n);if(a-s===0)return n;{let r=new Date(e.getTime()-a),o=sa(i.tz,r);if(o-a===0)return r;if(!t&&o-a>0)return r;if(t)throw new Error("Invalid date passed to fromTZ()");return n}};je.toTZ=function(i,t){let e=i.toLocaleString("en-US",{timeZone:t}).replace(/[\u202f]/," "),s=new Date(e);return{y:s.getFullYear(),m:s.getMonth()+1,d:s.getDate(),h:s.getHours(),i:s.getMinutes(),s:s.getSeconds(),tz:t}};je.tp=(i,t,e,s,n,a,r)=>({y:i,m:t,d:e,h:s,i:n,s:a,tz:r});function sa(i,t=new Date){let e=t.toLocaleString("en-US",{timeZone:i,timeZoneName:"shortOffset"}).split(" ").slice(-1)[0],s=t.toLocaleString("en-US").replace(/[\u202f]/," ");return Date.parse(`${s} GMT`)-Date.parse(`${s} ${e}`)}function fl(i,t){let e=new Date(Date.parse(i));if(isNaN(e))throw new Error("minitz: Invalid ISO8601 passed to parser.");let s=i.substring(9);return i.includes("Z")||s.includes("-")||s.includes("+")?je.tp(e.getUTCFullYear(),e.getUTCMonth()+1,e.getUTCDate(),e.getUTCHours(),e.getUTCMinutes(),e.getUTCSeconds(),"Etc/UTC"):je.tp(e.getFullYear(),e.getMonth()+1,e.getDate(),e.getHours(),e.getMinutes(),e.getSeconds(),t)}je.minitz=je;function gl(i){if(i===void 0&&(i={}),delete i.name,i.legacyMode=i.legacyMode===void 0?!0:i.legacyMode,i.paused=i.paused===void 0?!1:i.paused,i.maxRuns=i.maxRuns===void 0?1/0:i.maxRuns,i.catch=i.catch===void 0?!1:i.catch,i.interval=i.interval===void 0?0:parseInt(i.interval,10),i.utcOffset=i.utcOffset===void 0?void 0:parseInt(i.utcOffset,10),i.unref=i.unref===void 0?!1:i.unref,i.startAt&&(i.startAt=new _e(i.startAt,i.timezone)),i.stopAt&&(i.stopAt=new _e(i.stopAt,i.timezone)),i.interval!==null){if(isNaN(i.interval))throw new Error("CronOptions: Supplied value for interval is not a number");if(i.interval<0)throw new Error("CronOptions: Supplied value for interval can not be negative")}if(i.utcOffset!==void 0){if(isNaN(i.utcOffset))throw new Error("CronOptions: Invalid value passed for utcOffset, should be number representing minutes offset from UTC.");if(i.utcOffset<-870||i.utcOffset>870)throw new Error("CronOptions: utcOffset out of bounds.");if(i.utcOffset!==void 0&&i.timezone)throw new Error("CronOptions: Combining 'utcOffset' with 'timezone' is not allowed.")}if(i.unref!==!0&&i.unref!==!1)throw new Error("CronOptions: Unref should be either true, false or undefined(false).");return i}var na=32,hs=31|na,Ii=[1,2,4,8,16];function He(i,t){this.pattern=i,this.timezone=t,this.second=Array(60).fill(0),this.minute=Array(60).fill(0),this.hour=Array(24).fill(0),this.day=Array(31).fill(0),this.month=Array(12).fill(0),this.dayOfWeek=Array(7).fill(0),this.lastDayOfMonth=!1,this.starDOM=!1,this.starDOW=!1,this.parse()}He.prototype.parse=function(){if(!(typeof this.pattern=="string"||this.pattern.constructor===String))throw new TypeError("CronPattern: Pattern has to be of type string.");this.pattern.indexOf("@")>=0&&(this.pattern=this.handleNicknames(this.pattern).trim());let i=this.pattern.replace(/\s+/g," ").split(" ");if(i.length<5||i.length>6)throw new TypeError("CronPattern: invalid configuration format ('"+this.pattern+"'), exactly five or six space separated parts are required.");if(i.length===5&&i.unshift("0"),i[3].indexOf("L")>=0&&(i[3]=i[3].replace("L",""),this.lastDayOfMonth=!0),i[3]=="*"&&(this.starDOM=!0),i[4].length>=3&&(i[4]=this.replaceAlphaMonths(i[4])),i[5].length>=3&&(i[5]=this.replaceAlphaDays(i[5])),i[5]=="*"&&(this.starDOW=!0),this.pattern.indexOf("?")>=0){let t=new _e(new Date,this.timezone).getDate(!0);i[0]=i[0].replace("?",t.getSeconds()),i[1]=i[1].replace("?",t.getMinutes()),i[2]=i[2].replace("?",t.getHours()),this.starDOM||(i[3]=i[3].replace("?",t.getDate())),i[4]=i[4].replace("?",t.getMonth()+1),this.starDOW||(i[5]=i[5].replace("?",t.getDay()))}this.throwAtIllegalCharacters(i),this.partToArray("second",i[0],0,1),this.partToArray("minute",i[1],0,1),this.partToArray("hour",i[2],0,1),this.partToArray("day",i[3],-1,1),this.partToArray("month",i[4],-1,1),this.partToArray("dayOfWeek",i[5],0,hs),this.dayOfWeek[7]&&(this.dayOfWeek[0]=this.dayOfWeek[7])};He.prototype.partToArray=function(i,t,e,s){let n=this[i],a=i==="day"&&this.lastDayOfMonth;if(t===""&&!a)throw new TypeError("CronPattern: configuration entry "+i+" ("+t+") is empty, check for trailing spaces.");if(t==="*")return n.fill(s);let r=t.split(",");if(r.length>1)for(let o=0;o<r.length;o++)this.partToArray(i,r[o],e,s);else t.indexOf("-")!==-1&&t.indexOf("/")!==-1?this.handleRangeWithStepping(t,i,e,s):t.indexOf("-")!==-1?this.handleRange(t,i,e,s):t.indexOf("/")!==-1?this.handleStepping(t,i,e,s):t!==""&&this.handleNumber(t,i,e,s)};He.prototype.throwAtIllegalCharacters=function(i){for(let t=0;t<i.length;t++)if((t===5?/[^/*0-9,\-#L]+/:/[^/*0-9,-]+/).test(i[t]))throw new TypeError("CronPattern: configuration entry "+t+" ("+i[t]+") contains illegal characters.")};He.prototype.handleNumber=function(i,t,e,s){let n=this.extractNth(i,t),a=parseInt(n[0],10)+e;if(isNaN(a))throw new TypeError("CronPattern: "+t+" is not a number: '"+i+"'");this.setPart(t,a,n[1]||s)};He.prototype.setPart=function(i,t,e){if(!Object.prototype.hasOwnProperty.call(this,i))throw new TypeError("CronPattern: Invalid part specified: "+i);if(i==="dayOfWeek"){if(t===7&&(t=0),(t<0||t>6)&&t!=="L")throw new RangeError("CronPattern: Invalid value for dayOfWeek: "+t);this.setNthWeekdayOfMonth(t,e);return}if(i==="second"||i==="minute"){if(t<0||t>=60)throw new RangeError("CronPattern: Invalid value for "+i+": "+t)}else if(i==="hour"){if(t<0||t>=24)throw new RangeError("CronPattern: Invalid value for "+i+": "+t)}else if(i==="day"){if(t<0||t>=31)throw new RangeError("CronPattern: Invalid value for "+i+": "+t)}else if(i==="month"&&(t<0||t>=12))throw new RangeError("CronPattern: Invalid value for "+i+": "+t);this[i][t]=e};He.prototype.handleRangeWithStepping=function(i,t,e,s){let n=this.extractNth(i,t),a=n[0].match(/^(\d+)-(\d+)\/(\d+)$/);if(a===null)throw new TypeError("CronPattern: Syntax error, illegal range with stepping: '"+i+"'");let[,r,o,c]=a;if(r=parseInt(r,10)+e,o=parseInt(o,10)+e,c=parseInt(c,10),isNaN(r))throw new TypeError("CronPattern: Syntax error, illegal lower range (NaN)");if(isNaN(o))throw new TypeError("CronPattern: Syntax error, illegal upper range (NaN)");if(isNaN(c))throw new TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(c===0)throw new TypeError("CronPattern: Syntax error, illegal stepping: 0");if(c>this[t].length)throw new TypeError("CronPattern: Syntax error, steps cannot be greater than maximum value of part ("+this[t].length+")");if(r>o)throw new TypeError("CronPattern: From value is larger than to value: '"+i+"'");for(let l=r;l<=o;l+=c)this.setPart(t,l,n[1]||s)};He.prototype.extractNth=function(i,t){let e=i,s;if(e.includes("#")){if(t!=="dayOfWeek")throw new Error("CronPattern: nth (#) only allowed in day-of-week field");s=e.split("#")[1],e=e.split("#")[0]}return[e,s]};He.prototype.handleRange=function(i,t,e,s){let n=this.extractNth(i,t),a=n[0].split("-");if(a.length!==2)throw new TypeError("CronPattern: Syntax error, illegal range: '"+i+"'");let r=parseInt(a[0],10)+e,o=parseInt(a[1],10)+e;if(isNaN(r))throw new TypeError("CronPattern: Syntax error, illegal lower range (NaN)");if(isNaN(o))throw new TypeError("CronPattern: Syntax error, illegal upper range (NaN)");if(r>o)throw new TypeError("CronPattern: From value is larger than to value: '"+i+"'");for(let c=r;c<=o;c++)this.setPart(t,c,n[1]||s)};He.prototype.handleStepping=function(i,t,e,s){let n=this.extractNth(i,t),a=n[0].split("/");if(a.length!==2)throw new TypeError("CronPattern: Syntax error, illegal stepping: '"+i+"'");let r=0;a[0]!=="*"&&(r=parseInt(a[0],10)+e);let o=parseInt(a[1],10);if(isNaN(o))throw new TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(o===0)throw new TypeError("CronPattern: Syntax error, illegal stepping: 0");if(o>this[t].length)throw new TypeError("CronPattern: Syntax error, max steps for part is ("+this[t].length+")");for(let c=r;c<this[t].length;c+=o)this.setPart(t,c,n[1]||s)};He.prototype.replaceAlphaDays=function(i){return i.replace(/-sun/gi,"-7").replace(/sun/gi,"0").replace(/mon/gi,"1").replace(/tue/gi,"2").replace(/wed/gi,"3").replace(/thu/gi,"4").replace(/fri/gi,"5").replace(/sat/gi,"6")};He.prototype.replaceAlphaMonths=function(i){return i.replace(/jan/gi,"1").replace(/feb/gi,"2").replace(/mar/gi,"3").replace(/apr/gi,"4").replace(/may/gi,"5").replace(/jun/gi,"6").replace(/jul/gi,"7").replace(/aug/gi,"8").replace(/sep/gi,"9").replace(/oct/gi,"10").replace(/nov/gi,"11").replace(/dec/gi,"12")};He.prototype.handleNicknames=function(i){let t=i.trim().toLowerCase();return t==="@yearly"||t==="@annually"?"0 0 1 1 *":t==="@monthly"?"0 0 1 * *":t==="@weekly"?"0 0 * * 0":t==="@daily"?"0 0 * * *":t==="@hourly"?"0 * * * *":i};He.prototype.setNthWeekdayOfMonth=function(i,t){if(t==="L")this.dayOfWeek[i]=this.dayOfWeek[i]|na;else if(t<6&&t>0)this.dayOfWeek[i]=this.dayOfWeek[i]|Ii[t-1];else if(t===hs)this.dayOfWeek[i]=hs;else throw new TypeError(`CronPattern: nth weekday of of range, should be 1-5 or L. Value: ${t}`)};var Mi=[31,28,31,30,31,30,31,31,30,31,30,31],ut=[["month","year",0],["day","month",-1],["hour","day",0],["minute","hour",0],["second","minute",0]];function _e(i,t){if(this.tz=t,i&&i instanceof Date)if(!isNaN(i))this.fromDate(i);else throw new TypeError("CronDate: Invalid date passed to CronDate constructor");else if(i===void 0)this.fromDate(new Date);else if(i&&typeof i=="string")this.fromString(i);else if(i instanceof _e)this.fromCronDate(i);else throw new TypeError("CronDate: Invalid type ("+typeof i+") passed to CronDate constructor")}_e.prototype.isNthWeekdayOfMonth=function(i,t,e,s){let a=new Date(Date.UTC(i,t,e)).getUTCDay(),r=0;for(let o=1;o<=e;o++)new Date(Date.UTC(i,t,o)).getUTCDay()===a&&r++;if(s&hs&&Ii[r-1]&s)return!0;if(s&na){let o=new Date(Date.UTC(i,t+1,0)).getUTCDate();for(let c=e+1;c<=o;c++)if(new Date(Date.UTC(i,t,c)).getUTCDay()===a)return!1;return!0}return!1};_e.prototype.fromDate=function(i){if(this.tz!==void 0)if(typeof this.tz=="number")this.ms=i.getUTCMilliseconds(),this.second=i.getUTCSeconds(),this.minute=i.getUTCMinutes()+this.tz,this.hour=i.getUTCHours(),this.day=i.getUTCDate(),this.month=i.getUTCMonth(),this.year=i.getUTCFullYear(),this.apply();else{let t=je.toTZ(i,this.tz);this.ms=i.getMilliseconds(),this.second=t.s,this.minute=t.i,this.hour=t.h,this.day=t.d,this.month=t.m-1,this.year=t.y}else this.ms=i.getMilliseconds(),this.second=i.getSeconds(),this.minute=i.getMinutes(),this.hour=i.getHours(),this.day=i.getDate(),this.month=i.getMonth(),this.year=i.getFullYear()};_e.prototype.fromCronDate=function(i){this.tz=i.tz,this.year=i.year,this.month=i.month,this.day=i.day,this.hour=i.hour,this.minute=i.minute,this.second=i.second,this.ms=i.ms};_e.prototype.apply=function(){if(this.month>11||this.day>Mi[this.month]||this.hour>59||this.minute>59||this.second>59||this.hour<0||this.minute<0||this.second<0){let i=new Date(Date.UTC(this.year,this.month,this.day,this.hour,this.minute,this.second,this.ms));return this.ms=i.getUTCMilliseconds(),this.second=i.getUTCSeconds(),this.minute=i.getUTCMinutes(),this.hour=i.getUTCHours(),this.day=i.getUTCDate(),this.month=i.getUTCMonth(),this.year=i.getUTCFullYear(),!0}else return!1};_e.prototype.fromString=function(i){if(typeof this.tz=="number"){let t=je.fromTZISO(i);this.ms=t.getUTCMilliseconds(),this.second=t.getUTCSeconds(),this.minute=t.getUTCMinutes(),this.hour=t.getUTCHours(),this.day=t.getUTCDate(),this.month=t.getUTCMonth(),this.year=t.getUTCFullYear(),this.apply()}else return this.fromDate(je.fromTZISO(i,this.tz))};_e.prototype.findNext=function(i,t,e,s){let n=this[t],a;e.lastDayOfMonth&&(this.month!==1?a=Mi[this.month]:a=new Date(Date.UTC(this.year,this.month+1,0,0,0,0,0)).getUTCDate());let r=!e.starDOW&&t=="day"?new Date(Date.UTC(this.year,this.month,1,0,0,0,0)).getUTCDay():void 0;for(let o=this[t]+s;o<e[t].length;o++){let c=e[t][o];if(t==="day"&&e.lastDayOfMonth&&o-s==a&&(c=!0),t==="day"&&!e.starDOW){let l=e.dayOfWeek[(r+(o-s-1))%7];if(l&&l&hs)l=this.isNthWeekdayOfMonth(this.year,this.month,o-s,l);else if(l)throw new Error(`CronDate: Invalid value for dayOfWeek encountered. ${l}`);i.legacyMode&&!e.starDOM?c=c||l:c=c&&l}if(c)return this[t]=o-s,n!==this[t]?2:1}return 3};_e.prototype.recurse=function(i,t,e){let s=this.findNext(t,ut[e][0],i,ut[e][2]);if(s>1){let n=e+1;for(;n<ut.length;)this[ut[n][0]]=-ut[n][2],n++;if(s===3)return this[ut[e][1]]++,this[ut[e][0]]=-ut[e][2],this.apply(),this.recurse(i,t,0);if(this.apply())return this.recurse(i,t,e-1)}return e+=1,e>=ut.length?this:this.year>=3e3?null:this.recurse(i,t,e)};_e.prototype.increment=function(i,t,e){return this.second+=t.interval>1&&e?t.interval:1,this.ms=0,this.apply(),this.recurse(i,t,0)};_e.prototype.getDate=function(i){return i||this.tz===void 0?new Date(this.year,this.month,this.day,this.hour,this.minute,this.second,this.ms):typeof this.tz=="number"?new Date(Date.UTC(this.year,this.month,this.day,this.hour,this.minute-this.tz,this.second,this.ms)):je(this.year,this.month+1,this.day,this.hour,this.minute,this.second,this.tz)};_e.prototype.getTime=function(){return this.getDate().getTime()};function Xs(i){return Object.prototype.toString.call(i)==="[object Function]"||typeof i=="function"||i instanceof Function}function yl(i){typeof Deno<"u"&&typeof Deno.unrefTimer<"u"?Deno.unrefTimer(i):i&&typeof i.unref<"u"&&i.unref()}var Di=30*1e3,us=[];function ce(i,t,e){if(!(this instanceof ce))return new ce(i,t,e);let s,n;if(Xs(t))n=t;else if(typeof t=="object")s=t;else if(t!==void 0)throw new Error("Cron: Invalid argument passed for optionsIn. Should be one of function, or object (options).");if(Xs(e))n=e;else if(typeof e=="object")s=e;else if(e!==void 0)throw new Error("Cron: Invalid argument passed for funcIn. Should be one of function, or object (options).");if(this.name=s?s.name:void 0,this.options=gl(s),this._states={kill:!1,blocking:!1,previousRun:void 0,currentRun:void 0,once:void 0,currentTimeout:void 0,maxRuns:s?s.maxRuns:void 0,paused:s?s.paused:!1,pattern:void 0},i&&(i instanceof Date||typeof i=="string"&&i.indexOf(":")>0)?this._states.once=new _e(i,this.options.timezone||this.options.utcOffset):this._states.pattern=new He(i,this.options.timezone),this.name){if(us.find(r=>r.name===this.name))throw new Error("Cron: Tried to initialize new named job '"+this.name+"', but name already taken.");us.push(this)}return n!==void 0&&(this.fn=n,this.schedule()),this}ce.prototype.nextRun=function(i){let t=this._next(i);return t?t.getDate():null};ce.prototype.nextRuns=function(i,t){i>this._states.maxRuns&&(i=this._states.maxRuns);let e=[],s=t||this._states.currentRun;for(;i--&&(s=this.nextRun(s));)e.push(s);return e};ce.prototype.getPattern=function(){return this._states.pattern?this._states.pattern.pattern:void 0};ce.prototype.isRunning=function(){let i=this.nextRun(this._states.currentRun),t=!this._states.paused,e=this.fn!==void 0,s=!this._states.kill;return t&&e&&s&&i!==null};ce.prototype.isStopped=function(){return this._states.kill};ce.prototype.isBusy=function(){return this._states.blocking};ce.prototype.currentRun=function(){return this._states.currentRun?this._states.currentRun.getDate():null};ce.prototype.previousRun=function(){return this._states.previousRun?this._states.previousRun.getDate():null};ce.prototype.msToNext=function(i){i=i||new Date;let t=this._next(i);return t?t.getTime()-i.getTime():null};ce.prototype.stop=function(){this._states.kill=!0,this._states.currentTimeout&&clearTimeout(this._states.currentTimeout);let i=us.indexOf(this);i>=0&&us.splice(i,1)};ce.prototype.pause=function(){return this._states.paused=!0,!this._states.kill};ce.prototype.resume=function(){return this._states.paused=!1,!this._states.kill};ce.prototype.schedule=function(i){if(i&&this.fn)throw new Error("Cron: It is not allowed to schedule two functions using the same Croner instance.");i&&(this.fn=i);let t=this.msToNext(),e=this.nextRun(this._states.currentRun);return t==null||isNaN(t)||e===null?this:(t>Di&&(t=Di),this._states.currentTimeout=setTimeout(()=>this._checkTrigger(e),t),this._states.currentTimeout&&this.options.unref&&yl(this._states.currentTimeout),this)};ce.prototype._trigger=async function(i){if(this._states.blocking=!0,this._states.currentRun=new _e(void 0,this.options.timezone||this.options.utcOffset),this.options.catch)try{await this.fn(this,this.options.context)}catch(t){Xs(this.options.catch)&&this.options.catch(t,this)}else await this.fn(this,this.options.context);this._states.previousRun=new _e(i,this.options.timezone||this.options.utcOffset),this._states.blocking=!1};ce.prototype.trigger=async function(){await this._trigger()};ce.prototype._checkTrigger=function(i){let t=new Date,e=!this._states.paused&&t.getTime()>=i,s=this._states.blocking&&this.options.protect;e&&!s?(this._states.maxRuns--,this._trigger()):e&&s&&Xs(this.options.protect)&&setTimeout(()=>this.options.protect(this),0),this.schedule()};ce.prototype._next=function(i){let t=!!(i||this._states.currentRun),e=!1;!i&&this.options.startAt&&this.options.interval&&([i,t]=this._calculatePreviousRun(i,t),e=!i),i=new _e(i,this.options.timezone||this.options.utcOffset),this.options.startAt&&i&&i.getTime()<this.options.startAt.getTime()&&(i=this.options.startAt);let s=this._states.once||new _e(i,this.options.timezone||this.options.utcOffset);return!e&&s!==this._states.once&&(s=s.increment(this._states.pattern,this.options,t)),this._states.once&&this._states.once.getTime()<=i.getTime()||s===null||this._states.maxRuns<=0||this._states.kill||this.options.stopAt&&s.getTime()>=this.options.stopAt.getTime()?null:s};ce.prototype._calculatePreviousRun=function(i,t){let e=new _e(void 0,this.options.timezone||this.options.utcOffset);if(this.options.startAt.getTime()<=e.getTime()){i=this.options.startAt;let s=i.getTime()+this.options.interval*1e3;for(;s<=e.getTime();)i=new _e(i,this.options.timezone||this.options.utcOffset).increment(this._states.pattern,this.options,!0),s=i.getTime()+this.options.interval*1e3;t=!0}return[i,t]};ce.Cron=ce;ce.scheduledJobs=us;var or=require("obsidian");var Qi=require("crypto");var Ve=require("fs"),aa=require("path");function vl(i){return`mcp__${i.replace(/[\s.]+/g,"_")}`}function Qs(i,t,e={}){let s=t.permissionRules.allow.length>0||t.permissionRules.deny.length>0,n=t.permissionMode?.trim(),a=!!n&&n!=="default",r=e.mcpAllowServers??[],o=r.length>0;if(!(s||a||o))return null;let l=(0,aa.join)(i,".claude"),d=(0,aa.join)(l,"settings.local.json");(0,Ve.existsSync)(l)||(0,Ve.mkdirSync)(l,{recursive:!0});let h=null;if((0,Ve.existsSync)(d))try{h=(0,Ve.readFileSync)(d,"utf-8")}catch{h=null}let u={};if(a&&(u.defaultMode=n),s||o){let p=[...t.permissionRules.allow];for(let f of r)p.push(vl(f));u.permissions={allow:p,deny:t.permissionRules.deny}}return(0,Ve.writeFileSync)(d,JSON.stringify(u,null,2)+`
11833
- `,"utf-8"),{path:d,backupContent:h}}function Et(i){if(i)try{i.backupContent!==null?(0,Ve.writeFileSync)(i.path,i.backupContent,"utf-8"):(0,Ve.existsSync)(i.path)&&(0,Ve.unlinkSync)(i.path)}catch{}}function Li(i){if(typeof i=="string")return i;if(Array.isArray(i))return i.map(e=>typeof e=="string"?e:e&&typeof e=="object"&&"text"in e&&typeof e.text=="string"?e.text:"").filter(Boolean).join(`
11834
- `);if(i&&typeof i=="object"){for(let t of["output","result","text","message"])if(t in i)return Li(i[t])}}function ia(i,t=[]){if(Array.isArray(i)){for(let r of i)ia(r,t);return t}if(!i||typeof i!="object")return t;let e=i,s=typeof e.tool_name=="string"&&e.tool_name||typeof e.tool=="string"&&e.tool||typeof e.name=="string"&&e.name,n=typeof e.command=="string"?e.command:typeof e.input=="string"?e.input:typeof e.cmd=="string"?e.cmd:void 0,a=typeof e.reason=="string"?e.reason:void 0;s&&["tool_use","tool","name","tool_name"].some(r=>r in e)&&t.push({tool:s,command:n,reason:a});for(let r of Object.values(e))ia(r,t);return t}function Fi(i){if(!i||typeof i!="object")return;let t=i,e=t.usage;if(e&&typeof e=="object"){let n=typeof e.input_tokens=="number"?e.input_tokens:0,a=typeof e.output_tokens=="number"?e.output_tokens:0,r=typeof e.cache_creation_input_tokens=="number"?e.cache_creation_input_tokens:0,o=typeof e.cache_read_input_tokens=="number"?e.cache_read_input_tokens:0,c=n+a+r+o;if(c>0)return c}let s=t.modelUsage;if(s&&typeof s=="object"){let n=0;for(let a of Object.values(s)){if(!a||typeof a!="object")continue;let r=a;n+=typeof r.inputTokens=="number"?r.inputTokens:0,n+=typeof r.outputTokens=="number"?r.outputTokens:0,n+=typeof r.cacheReadInputTokens=="number"?r.cacheReadInputTokens:0,n+=typeof r.cacheCreationInputTokens=="number"?r.cacheCreationInputTokens:0}if(n>0)return n}for(let n of["tokens_used","total_tokens","totalTokens"])if(typeof t[n]=="number")return t[n];for(let n of Object.values(t)){let a=Fi(n);if(typeof a=="number")return a}}function Oi(i){if(!i||typeof i!="object")return;let t=i;if(typeof t.total_cost_usd=="number")return t.total_cost_usd;for(let e of Object.values(t)){let s=Oi(e);if(typeof s=="number")return s}}function ra(i){if(!i||typeof i!="object")return;let t=i;if(t.type==="result"&&typeof t.result=="string"&&t.result.trim())return t.result}function Zs(i){if(!i||typeof i!="object")return;let t=i;if(t.modelUsage&&typeof t.modelUsage=="object"){let s=Object.keys(t.modelUsage);if(s.length>0&&s[0])return s[0]}let e=t.message;if(e&&typeof e.model=="string"&&e.model)return e.model;if(typeof t.model=="string"&&t.model)return t.model;for(let s of Object.values(t)){let n=Zs(s);if(n)return n}}function bl(i){return/^gpt-|codex/i.test(i.trim())}var Ni={id:"claude-code",label:"Claude Code",cliPath(i){return i.claudeCliPath},buildExec(i){let t=["-p",i.prompt,"--output-format",i.streaming?"stream-json":"json"];i.streaming&&t.push("--verbose");let e=i.modelSource==="settings"&&bl(i.model);i.model&&!e&&t.push("--model",i.model),i.effort&&t.push("--effort",i.effort);let s=i.agent.permissionMode?.trim();return s&&s!=="default"?t.push("--permission-mode",s):t.push("--permission-mode","bypassPermissions"),Promise.resolve({cliPath:i.settings.claudeCliPath,args:t})},parseExecOutput(i,t,e){let s=i.trim(),n;if(e){let c=pe(s);for(let l=c.length-1;l>=0;l--){let d=c[l]?.trim();if(d)try{let h=JSON.parse(d);if(h&&typeof h=="object"){n=h;break}}catch{}}}else if(s.startsWith("{")||s.startsWith("["))try{n=JSON.parse(s)}catch{n=void 0}let a=Li(n)??"";if(!a&&e){let c=[];for(let l of pe(s)){let d=l.trim();if(d)try{let h=JSON.parse(d);if(h.type==="assistant"&&h.message?.content)for(let u of h.message.content)u.type==="text"&&u.text&&c.push(u.text);else h.type==="result"&&typeof h.result=="string"&&c.push(h.result)}catch{}}a=c.join(`
11835
- `).trim()}a||(a=t.trim()||"(no output)");let r=Zs(n),o=ra(n);if((!r||!o)&&e)for(let c of pe(s)){let l=c.trim();if(l)try{let d=JSON.parse(l);if(!r){let h=Zs(d);h&&(r=h)}if(!o){let h=ra(d);h&&(o=h)}if(r&&o)break}catch{}}return{outputText:a,finalResult:o,tokensUsed:Fi(n),costUsd:Oi(n),toolsUsed:ia(n),concreteModel:r,rawJson:n}},extractStreamChunk(i){let t=i.trim();if(!t)return null;let e;try{e=JSON.parse(t)}catch{return null}let s=e.type;if(s==="assistant"){let n=e.message;if(n?.content&&Array.isArray(n.content)){let a=[];for(let r of n.content)if(r.type==="text"&&typeof r.text=="string")a.push(r.text);else if(r.type==="tool_use"){let o=String(r.name??"tool"),c=r.input,l=c?.command??c?.content??"";a.push(`
11832
+ Your scope's inbox, topics, index, and log are NOT deleted.`))try{await Di(this.plugin.app,this.plugin.settings.fleetFolder,o.name),await this.plugin.refreshFromVault(),new N.Notice(`Wiki Keeper "${o.name}" deleted.`),this.scheduleRerender()}catch(f){let g=f instanceof Error?f.message:String(f);new N.Notice(`Failed to delete: ${g}`)}}}new N.Setting(e).setName("Add Wiki Keeper").setDesc("Create a new scoped wiki agent. All fields optional.").addButton(o=>o.setButtonText("+ Add").onClick(()=>{new ea(this.plugin,()=>{this.scheduleRerender()}).open()}))}scheduleRerender(){window.setTimeout(async()=>{try{await this.plugin.refreshFromVault()}catch{}this.display()},600)}},ea=class extends N.Modal{constructor(e,s){super(e.app);this.plugin=e;this.onCreated=s;this.input=Xn()}input;onOpen(){let{contentEl:e}=this;e.empty(),e.addClass("af-wk-modal"),e.createEl("h2",{text:"Add Wiki Keeper"});let s=e.createDiv({cls:"af-wk-banner"});s.createEl("strong",{text:"All fields are optional. "}),s.createSpan({text:"Click Create with everything blank and you'll get a whole-vault keeper with sensible defaults (inbox at _sources/inbox, topics at topics/, nightly ingest at 3am, Sunday lint)."}),e.createEl("h3",{text:"Scope",cls:"af-wk-section-h"}),new N.Setting(e).setName("Scope folder").setDesc("Optional. Vault-relative path. Empty = whole vault.").addText(h=>h.setPlaceholder("(empty = whole vault)").setValue(this.input.scopeRoot).onChange(d=>{this.input.scopeRoot=d.trim(),this.renderPreview()})),new N.Setting(e).setName("Slug").setDesc("Optional. Agent name suffix. Default: derived from scope folder name, or 'wiki-keeper' for whole-vault.").addText(h=>h.setPlaceholder("(auto)").setValue(this.input.scopeSlug).onChange(d=>{this.input.scopeSlug=d.trim(),this.renderPreview()})),this.renderPreview(),e.createEl("h3",{text:"Sources",cls:"af-wk-section-h"}),new N.Setting(e).setName("Watched folders").setDesc("Optional. Comma- or newline-separated vault-relative paths. Read-only \u2014 claims are extracted but files are never moved. Leave empty for inbox-only mode (you drop files into _sources/inbox/ and they get archived after processing).").addTextArea(h=>h.setPlaceholder("(empty = inbox-only)").setValue(this.input.watchedFolders.join(", ")).onChange(d=>{this.input.watchedFolders=d.split(/[,\n]/).map(u=>u.trim()).filter(Boolean)})),new N.Setting(e).setName("Exclude patterns").setDesc("Optional. Glob patterns to skip. Leave empty to process everything under watched + inbox.").addTextArea(h=>h.setPlaceholder("(empty = no excludes)").setValue(this.input.excludePatterns.join(", ")).onChange(d=>{this.input.excludePatterns=d.split(/[,\n]/).map(u=>u.trim()).filter(Boolean)})),new N.Setting(e).setName("Watch files modified since").setDesc("Watched mode only \u2014 files whose last modification date is before this are skipped. Defaults to today so an established vault doesn't flood the keeper on first run. Clear the field to process everything.").addText(h=>{h.inputEl.type="date",h.setValue(this.input.watchedSince).onChange(d=>{this.input.watchedSince=d.trim()})});let n=this.plugin.runtime.getSnapshot().channels.map(h=>h.name);new N.Setting(e).setName("Heartbeat channel").setDesc("Optional. Slack/Telegram channel for ingest + lint summaries. Leave as (none) to disable.").addDropdown(h=>{h.addOption("","(none)");for(let d of n)h.addOption(d,d);h.setValue(this.input.heartbeatChannel).onChange(d=>{this.input.heartbeatChannel=d})}),e.createEl("h3",{text:"Advanced",cls:"af-wk-section-h"}),new N.Setting(e).setName("Max tokens per ingest").setDesc("Hard cap on token spend per run. Unprocessed files resume next cycle.").addText(h=>h.setValue(String(this.input.maxTokensPerIngest)).onChange(d=>{let u=parseInt(d,10);!isNaN(u)&&u>0&&(this.input.maxTokensPerIngest=u)})),new N.Setting(e).setName("File substantive answers").setDesc("If on, wiki-query files long answers under _topics/syntheses/. Off = answers live only in chat.").addToggle(h=>h.setValue(this.input.fileSubstantiveAnswers).onChange(d=>{this.input.fileSubstantiveAnswers=d})),new N.Setting(e).setName("Obsidian URL scheme for citations").setDesc("If on, external-channel (Slack/Telegram) replies rewrite [[wikilinks]] as obsidian:// URLs.").addToggle(h=>h.setValue(this.input.obsidianUrlScheme).onChange(d=>{this.input.obsidianUrlScheme=d}));let a=e.createEl("h3",{text:"Paths (expert)",cls:"af-wk-section-h"});a.title="Paths are relative to scope_root. Defaults work for almost everyone. Override only if your vault layout demands it \u2014 these cannot be changed after creation.";let r=(h,d,u)=>{new N.Setting(e).setName(h).setDesc(d).addText(p=>p.setPlaceholder(String(this.input[u]??"")).setValue(String(this.input[u]??"")).onChange(m=>{this.input[u]=m.trim()||_i[u]}))};r("Inbox path","Where one-off source drops land.","inboxPath"),r("Archive path","Where processed inbox files are moved after summarization.","archivePath"),r("Topics root","Folder under scope_root that holds the generated topic pages.","topicsRoot"),r("Index path","Relative file path for the curated index.","indexPath"),r("Log path","Relative file path for the keeper's activity log.","logPath"),r("State file","Hidden JSON file that tracks watched-source mtimes.","stateFile");let o=e.createDiv({cls:"af-wk-modal-footer"}),c=o.createEl("button",{text:"Cancel"});c.onclick=()=>this.close();let l=o.createEl("button",{text:"Create",cls:"mod-cta"});l.onclick=async()=>{l.setText("Creating\u2026"),l.disabled=!0;try{let{name:h}=await Pi(this.app.vault,this.plugin.settings.fleetFolder,this.input);await this.plugin.refreshFromVault(),this.close(),new N.Notice(`Wiki Keeper "${h}" created.`),this.onCreated()}catch(h){let d=h instanceof Error?h.message:String(h);new N.Notice(`Failed to create Wiki Keeper: ${d}`),l.setText("Create"),l.disabled=!1}}}renderPreview(){let e=this.contentEl.querySelector(".af-wk-name-preview");e||(e=this.contentEl.createDiv({cls:"af-wk-name-preview"}));let s=this.input.scopeSlug||this.input.scopeRoot;e.setText(`\u2192 Will create agent: ${Qn(s)}`)}onClose(){this.contentEl.empty()}},ta=class extends N.Modal{constructor(e,s,n){super(e.app);this.plugin=e;this.agent=s;this.onSaved=n;let a=s.wikiKeeper;this.edit={watchedFolders:[...a.watchedFolders],excludePatterns:[...a.excludePatterns],watchedSince:a.watchedSince,heartbeatChannel:s.heartbeatChannel??"",fileSubstantiveAnswers:a.fileSubstantiveAnswers,obsidianUrlScheme:a.obsidianUrlScheme,maxTokensPerIngest:a.maxTokensPerIngest,maxTokensPerRefresh:a.maxTokensPerRefresh,indexSplitThreshold:a.indexSplitThreshold,dedupSimilarityThreshold:a.dedupSimilarityThreshold,summaryStaleDays:a.summaryStaleDays}}edit;onOpen(){let{contentEl:e}=this;e.empty(),e.addClass("af-wk-modal"),e.createEl("h2",{text:`Edit ${this.agent.name}`});let s=e.createDiv({cls:"af-wk-banner"}),n=this.agent.wikiKeeper.scopeRoot||"(whole vault)";s.createEl("strong",{text:"Scope: "}),s.createSpan({text:n}),s.createEl("br"),s.createSpan({text:"Scope and paths are fixed after creation \u2014 changing them would orphan existing topic pages. To move a Wiki Keeper, delete this one and create a new one at the new scope."}),e.createEl("h3",{text:"Sources",cls:"af-wk-section-h"}),new N.Setting(e).setName("Watched folders").setDesc("Comma- or newline-separated vault-relative paths.").addTextArea(l=>l.setValue(this.edit.watchedFolders.join(", ")).onChange(h=>{this.edit.watchedFolders=h.split(/[,\n]/).map(d=>d.trim()).filter(Boolean)})),new N.Setting(e).setName("Exclude patterns").setDesc("Glob patterns to skip.").addTextArea(l=>l.setValue(this.edit.excludePatterns.join(", ")).onChange(h=>{this.edit.excludePatterns=h.split(/[,\n]/).map(d=>d.trim()).filter(Boolean)})),new N.Setting(e).setName("Watch files modified since").setDesc("Watched mode skips files older than this date. Clear to process everything.").addText(l=>{l.inputEl.type="date",l.setValue(this.edit.watchedSince).onChange(h=>{this.edit.watchedSince=h.trim()})});let a=this.plugin.runtime.getSnapshot().channels.map(l=>l.name);new N.Setting(e).setName("Heartbeat channel").addDropdown(l=>{l.addOption("","(none)");for(let h of a)l.addOption(h,h);l.setValue(this.edit.heartbeatChannel).onChange(h=>{this.edit.heartbeatChannel=h})}),e.createEl("h3",{text:"Advanced",cls:"af-wk-section-h"}),new N.Setting(e).setName("Max tokens per ingest").addText(l=>l.setValue(String(this.edit.maxTokensPerIngest)).onChange(h=>{let d=parseInt(h,10);!isNaN(d)&&d>0&&(this.edit.maxTokensPerIngest=d)})),new N.Setting(e).setName("Max tokens per refresh").setDesc("Separate budget for the synthesis-refresh phase that regenerates topic-page summaries.").addText(l=>l.setValue(String(this.edit.maxTokensPerRefresh)).onChange(h=>{let d=parseInt(h,10);!isNaN(d)&&d>0&&(this.edit.maxTokensPerRefresh=d)})),new N.Setting(e).setName("Index split threshold").setDesc("Topic-page count above which index.md splits into per-type sub-MOCs.").addText(l=>l.setValue(String(this.edit.indexSplitThreshold)).onChange(h=>{let d=parseInt(h,10);!isNaN(d)&&d>0&&(this.edit.indexSplitThreshold=d)})),new N.Setting(e).setName("Summary stale (days)").setDesc("Lint flags topic-page summaries older than this and chains wiki-refresh.").addText(l=>l.setValue(String(this.edit.summaryStaleDays)).onChange(h=>{let d=parseInt(h,10);!isNaN(d)&&d>0&&(this.edit.summaryStaleDays=d)})),new N.Setting(e).setName("Dedup similarity threshold").setDesc("Levenshtein-ratio above which lint proposes merging two same-type pages (0.0\u20131.0).").addText(l=>l.setValue(String(this.edit.dedupSimilarityThreshold)).onChange(h=>{let d=parseFloat(h);!isNaN(d)&&d>0&&d<=1&&(this.edit.dedupSimilarityThreshold=d)})),new N.Setting(e).setName("File substantive answers").setDesc("Compounding: wiki-query files long answers under _topics/syntheses/ and bullets each cited topic page. Default ON.").addToggle(l=>l.setValue(this.edit.fileSubstantiveAnswers).onChange(h=>{this.edit.fileSubstantiveAnswers=h})),new N.Setting(e).setName("Obsidian URL scheme for citations").setDesc("Rewrite [[wikilinks]] as obsidian:// URLs when replying via Slack/Telegram.").addToggle(l=>l.setValue(this.edit.obsidianUrlScheme).onChange(h=>{this.edit.obsidianUrlScheme=h}));let r=e.createDiv({cls:"af-wk-modal-footer"}),o=r.createEl("button",{text:"Cancel"});o.onclick=()=>this.close();let c=r.createEl("button",{text:"Save",cls:"mod-cta"});c.onclick=async()=>{c.setText("Saving\u2026"),c.disabled=!0;try{await Ri(this.app.vault,this.plugin.settings.fleetFolder,this.agent.name,this.edit),await this.plugin.refreshFromVault(),this.close(),new N.Notice("Saved."),this.onSaved()}catch(l){let h=l instanceof Error?l.message:String(l);new N.Notice(`Failed to save: ${h}`),c.setText("Save"),c.disabled=!1}}}onClose(){this.contentEl.empty()}};function ml(i){return i.type==="slack",i.botToken}function fl(i){return i.length<=10?"***":`${i.slice(0,6)}\u2026${i.slice(-4)}`}var or=require("crypto");function je(i,t,e,s,n,a,r,o){return je.fromTZ(je.tp(i,t,e,s,n,a,r),o)}je.fromTZISO=(i,t,e)=>je.fromTZ(gl(i,t),e);je.fromTZ=function(i,t){let e=new Date(Date.UTC(i.y,i.m-1,i.d,i.h,i.i,i.s)),s=sa(i.tz,e),n=new Date(e.getTime()-s),a=sa(i.tz,n);if(a-s===0)return n;{let r=new Date(e.getTime()-a),o=sa(i.tz,r);if(o-a===0)return r;if(!t&&o-a>0)return r;if(t)throw new Error("Invalid date passed to fromTZ()");return n}};je.toTZ=function(i,t){let e=i.toLocaleString("en-US",{timeZone:t}).replace(/[\u202f]/," "),s=new Date(e);return{y:s.getFullYear(),m:s.getMonth()+1,d:s.getDate(),h:s.getHours(),i:s.getMinutes(),s:s.getSeconds(),tz:t}};je.tp=(i,t,e,s,n,a,r)=>({y:i,m:t,d:e,h:s,i:n,s:a,tz:r});function sa(i,t=new Date){let e=t.toLocaleString("en-US",{timeZone:i,timeZoneName:"shortOffset"}).split(" ").slice(-1)[0],s=t.toLocaleString("en-US").replace(/[\u202f]/," ");return Date.parse(`${s} GMT`)-Date.parse(`${s} ${e}`)}function gl(i,t){let e=new Date(Date.parse(i));if(isNaN(e))throw new Error("minitz: Invalid ISO8601 passed to parser.");let s=i.substring(9);return i.includes("Z")||s.includes("-")||s.includes("+")?je.tp(e.getUTCFullYear(),e.getUTCMonth()+1,e.getUTCDate(),e.getUTCHours(),e.getUTCMinutes(),e.getUTCSeconds(),"Etc/UTC"):je.tp(e.getFullYear(),e.getMonth()+1,e.getDate(),e.getHours(),e.getMinutes(),e.getSeconds(),t)}je.minitz=je;function yl(i){if(i===void 0&&(i={}),delete i.name,i.legacyMode=i.legacyMode===void 0?!0:i.legacyMode,i.paused=i.paused===void 0?!1:i.paused,i.maxRuns=i.maxRuns===void 0?1/0:i.maxRuns,i.catch=i.catch===void 0?!1:i.catch,i.interval=i.interval===void 0?0:parseInt(i.interval,10),i.utcOffset=i.utcOffset===void 0?void 0:parseInt(i.utcOffset,10),i.unref=i.unref===void 0?!1:i.unref,i.startAt&&(i.startAt=new Ae(i.startAt,i.timezone)),i.stopAt&&(i.stopAt=new Ae(i.stopAt,i.timezone)),i.interval!==null){if(isNaN(i.interval))throw new Error("CronOptions: Supplied value for interval is not a number");if(i.interval<0)throw new Error("CronOptions: Supplied value for interval can not be negative")}if(i.utcOffset!==void 0){if(isNaN(i.utcOffset))throw new Error("CronOptions: Invalid value passed for utcOffset, should be number representing minutes offset from UTC.");if(i.utcOffset<-870||i.utcOffset>870)throw new Error("CronOptions: utcOffset out of bounds.");if(i.utcOffset!==void 0&&i.timezone)throw new Error("CronOptions: Combining 'utcOffset' with 'timezone' is not allowed.")}if(i.unref!==!0&&i.unref!==!1)throw new Error("CronOptions: Unref should be either true, false or undefined(false).");return i}var na=32,hs=31|na,Mi=[1,2,4,8,16];function He(i,t){this.pattern=i,this.timezone=t,this.second=Array(60).fill(0),this.minute=Array(60).fill(0),this.hour=Array(24).fill(0),this.day=Array(31).fill(0),this.month=Array(12).fill(0),this.dayOfWeek=Array(7).fill(0),this.lastDayOfMonth=!1,this.starDOM=!1,this.starDOW=!1,this.parse()}He.prototype.parse=function(){if(!(typeof this.pattern=="string"||this.pattern.constructor===String))throw new TypeError("CronPattern: Pattern has to be of type string.");this.pattern.indexOf("@")>=0&&(this.pattern=this.handleNicknames(this.pattern).trim());let i=this.pattern.replace(/\s+/g," ").split(" ");if(i.length<5||i.length>6)throw new TypeError("CronPattern: invalid configuration format ('"+this.pattern+"'), exactly five or six space separated parts are required.");if(i.length===5&&i.unshift("0"),i[3].indexOf("L")>=0&&(i[3]=i[3].replace("L",""),this.lastDayOfMonth=!0),i[3]=="*"&&(this.starDOM=!0),i[4].length>=3&&(i[4]=this.replaceAlphaMonths(i[4])),i[5].length>=3&&(i[5]=this.replaceAlphaDays(i[5])),i[5]=="*"&&(this.starDOW=!0),this.pattern.indexOf("?")>=0){let t=new Ae(new Date,this.timezone).getDate(!0);i[0]=i[0].replace("?",t.getSeconds()),i[1]=i[1].replace("?",t.getMinutes()),i[2]=i[2].replace("?",t.getHours()),this.starDOM||(i[3]=i[3].replace("?",t.getDate())),i[4]=i[4].replace("?",t.getMonth()+1),this.starDOW||(i[5]=i[5].replace("?",t.getDay()))}this.throwAtIllegalCharacters(i),this.partToArray("second",i[0],0,1),this.partToArray("minute",i[1],0,1),this.partToArray("hour",i[2],0,1),this.partToArray("day",i[3],-1,1),this.partToArray("month",i[4],-1,1),this.partToArray("dayOfWeek",i[5],0,hs),this.dayOfWeek[7]&&(this.dayOfWeek[0]=this.dayOfWeek[7])};He.prototype.partToArray=function(i,t,e,s){let n=this[i],a=i==="day"&&this.lastDayOfMonth;if(t===""&&!a)throw new TypeError("CronPattern: configuration entry "+i+" ("+t+") is empty, check for trailing spaces.");if(t==="*")return n.fill(s);let r=t.split(",");if(r.length>1)for(let o=0;o<r.length;o++)this.partToArray(i,r[o],e,s);else t.indexOf("-")!==-1&&t.indexOf("/")!==-1?this.handleRangeWithStepping(t,i,e,s):t.indexOf("-")!==-1?this.handleRange(t,i,e,s):t.indexOf("/")!==-1?this.handleStepping(t,i,e,s):t!==""&&this.handleNumber(t,i,e,s)};He.prototype.throwAtIllegalCharacters=function(i){for(let t=0;t<i.length;t++)if((t===5?/[^/*0-9,\-#L]+/:/[^/*0-9,-]+/).test(i[t]))throw new TypeError("CronPattern: configuration entry "+t+" ("+i[t]+") contains illegal characters.")};He.prototype.handleNumber=function(i,t,e,s){let n=this.extractNth(i,t),a=parseInt(n[0],10)+e;if(isNaN(a))throw new TypeError("CronPattern: "+t+" is not a number: '"+i+"'");this.setPart(t,a,n[1]||s)};He.prototype.setPart=function(i,t,e){if(!Object.prototype.hasOwnProperty.call(this,i))throw new TypeError("CronPattern: Invalid part specified: "+i);if(i==="dayOfWeek"){if(t===7&&(t=0),(t<0||t>6)&&t!=="L")throw new RangeError("CronPattern: Invalid value for dayOfWeek: "+t);this.setNthWeekdayOfMonth(t,e);return}if(i==="second"||i==="minute"){if(t<0||t>=60)throw new RangeError("CronPattern: Invalid value for "+i+": "+t)}else if(i==="hour"){if(t<0||t>=24)throw new RangeError("CronPattern: Invalid value for "+i+": "+t)}else if(i==="day"){if(t<0||t>=31)throw new RangeError("CronPattern: Invalid value for "+i+": "+t)}else if(i==="month"&&(t<0||t>=12))throw new RangeError("CronPattern: Invalid value for "+i+": "+t);this[i][t]=e};He.prototype.handleRangeWithStepping=function(i,t,e,s){let n=this.extractNth(i,t),a=n[0].match(/^(\d+)-(\d+)\/(\d+)$/);if(a===null)throw new TypeError("CronPattern: Syntax error, illegal range with stepping: '"+i+"'");let[,r,o,c]=a;if(r=parseInt(r,10)+e,o=parseInt(o,10)+e,c=parseInt(c,10),isNaN(r))throw new TypeError("CronPattern: Syntax error, illegal lower range (NaN)");if(isNaN(o))throw new TypeError("CronPattern: Syntax error, illegal upper range (NaN)");if(isNaN(c))throw new TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(c===0)throw new TypeError("CronPattern: Syntax error, illegal stepping: 0");if(c>this[t].length)throw new TypeError("CronPattern: Syntax error, steps cannot be greater than maximum value of part ("+this[t].length+")");if(r>o)throw new TypeError("CronPattern: From value is larger than to value: '"+i+"'");for(let l=r;l<=o;l+=c)this.setPart(t,l,n[1]||s)};He.prototype.extractNth=function(i,t){let e=i,s;if(e.includes("#")){if(t!=="dayOfWeek")throw new Error("CronPattern: nth (#) only allowed in day-of-week field");s=e.split("#")[1],e=e.split("#")[0]}return[e,s]};He.prototype.handleRange=function(i,t,e,s){let n=this.extractNth(i,t),a=n[0].split("-");if(a.length!==2)throw new TypeError("CronPattern: Syntax error, illegal range: '"+i+"'");let r=parseInt(a[0],10)+e,o=parseInt(a[1],10)+e;if(isNaN(r))throw new TypeError("CronPattern: Syntax error, illegal lower range (NaN)");if(isNaN(o))throw new TypeError("CronPattern: Syntax error, illegal upper range (NaN)");if(r>o)throw new TypeError("CronPattern: From value is larger than to value: '"+i+"'");for(let c=r;c<=o;c++)this.setPart(t,c,n[1]||s)};He.prototype.handleStepping=function(i,t,e,s){let n=this.extractNth(i,t),a=n[0].split("/");if(a.length!==2)throw new TypeError("CronPattern: Syntax error, illegal stepping: '"+i+"'");let r=0;a[0]!=="*"&&(r=parseInt(a[0],10)+e);let o=parseInt(a[1],10);if(isNaN(o))throw new TypeError("CronPattern: Syntax error, illegal stepping: (NaN)");if(o===0)throw new TypeError("CronPattern: Syntax error, illegal stepping: 0");if(o>this[t].length)throw new TypeError("CronPattern: Syntax error, max steps for part is ("+this[t].length+")");for(let c=r;c<this[t].length;c+=o)this.setPart(t,c,n[1]||s)};He.prototype.replaceAlphaDays=function(i){return i.replace(/-sun/gi,"-7").replace(/sun/gi,"0").replace(/mon/gi,"1").replace(/tue/gi,"2").replace(/wed/gi,"3").replace(/thu/gi,"4").replace(/fri/gi,"5").replace(/sat/gi,"6")};He.prototype.replaceAlphaMonths=function(i){return i.replace(/jan/gi,"1").replace(/feb/gi,"2").replace(/mar/gi,"3").replace(/apr/gi,"4").replace(/may/gi,"5").replace(/jun/gi,"6").replace(/jul/gi,"7").replace(/aug/gi,"8").replace(/sep/gi,"9").replace(/oct/gi,"10").replace(/nov/gi,"11").replace(/dec/gi,"12")};He.prototype.handleNicknames=function(i){let t=i.trim().toLowerCase();return t==="@yearly"||t==="@annually"?"0 0 1 1 *":t==="@monthly"?"0 0 1 * *":t==="@weekly"?"0 0 * * 0":t==="@daily"?"0 0 * * *":t==="@hourly"?"0 * * * *":i};He.prototype.setNthWeekdayOfMonth=function(i,t){if(t==="L")this.dayOfWeek[i]=this.dayOfWeek[i]|na;else if(t<6&&t>0)this.dayOfWeek[i]=this.dayOfWeek[i]|Mi[t-1];else if(t===hs)this.dayOfWeek[i]=hs;else throw new TypeError(`CronPattern: nth weekday of of range, should be 1-5 or L. Value: ${t}`)};var Li=[31,28,31,30,31,30,31,31,30,31,30,31],pt=[["month","year",0],["day","month",-1],["hour","day",0],["minute","hour",0],["second","minute",0]];function Ae(i,t){if(this.tz=t,i&&i instanceof Date)if(!isNaN(i))this.fromDate(i);else throw new TypeError("CronDate: Invalid date passed to CronDate constructor");else if(i===void 0)this.fromDate(new Date);else if(i&&typeof i=="string")this.fromString(i);else if(i instanceof Ae)this.fromCronDate(i);else throw new TypeError("CronDate: Invalid type ("+typeof i+") passed to CronDate constructor")}Ae.prototype.isNthWeekdayOfMonth=function(i,t,e,s){let a=new Date(Date.UTC(i,t,e)).getUTCDay(),r=0;for(let o=1;o<=e;o++)new Date(Date.UTC(i,t,o)).getUTCDay()===a&&r++;if(s&hs&&Mi[r-1]&s)return!0;if(s&na){let o=new Date(Date.UTC(i,t+1,0)).getUTCDate();for(let c=e+1;c<=o;c++)if(new Date(Date.UTC(i,t,c)).getUTCDay()===a)return!1;return!0}return!1};Ae.prototype.fromDate=function(i){if(this.tz!==void 0)if(typeof this.tz=="number")this.ms=i.getUTCMilliseconds(),this.second=i.getUTCSeconds(),this.minute=i.getUTCMinutes()+this.tz,this.hour=i.getUTCHours(),this.day=i.getUTCDate(),this.month=i.getUTCMonth(),this.year=i.getUTCFullYear(),this.apply();else{let t=je.toTZ(i,this.tz);this.ms=i.getMilliseconds(),this.second=t.s,this.minute=t.i,this.hour=t.h,this.day=t.d,this.month=t.m-1,this.year=t.y}else this.ms=i.getMilliseconds(),this.second=i.getSeconds(),this.minute=i.getMinutes(),this.hour=i.getHours(),this.day=i.getDate(),this.month=i.getMonth(),this.year=i.getFullYear()};Ae.prototype.fromCronDate=function(i){this.tz=i.tz,this.year=i.year,this.month=i.month,this.day=i.day,this.hour=i.hour,this.minute=i.minute,this.second=i.second,this.ms=i.ms};Ae.prototype.apply=function(){if(this.month>11||this.day>Li[this.month]||this.hour>59||this.minute>59||this.second>59||this.hour<0||this.minute<0||this.second<0){let i=new Date(Date.UTC(this.year,this.month,this.day,this.hour,this.minute,this.second,this.ms));return this.ms=i.getUTCMilliseconds(),this.second=i.getUTCSeconds(),this.minute=i.getUTCMinutes(),this.hour=i.getUTCHours(),this.day=i.getUTCDate(),this.month=i.getUTCMonth(),this.year=i.getUTCFullYear(),!0}else return!1};Ae.prototype.fromString=function(i){if(typeof this.tz=="number"){let t=je.fromTZISO(i);this.ms=t.getUTCMilliseconds(),this.second=t.getUTCSeconds(),this.minute=t.getUTCMinutes(),this.hour=t.getUTCHours(),this.day=t.getUTCDate(),this.month=t.getUTCMonth(),this.year=t.getUTCFullYear(),this.apply()}else return this.fromDate(je.fromTZISO(i,this.tz))};Ae.prototype.findNext=function(i,t,e,s){let n=this[t],a;e.lastDayOfMonth&&(this.month!==1?a=Li[this.month]:a=new Date(Date.UTC(this.year,this.month+1,0,0,0,0,0)).getUTCDate());let r=!e.starDOW&&t=="day"?new Date(Date.UTC(this.year,this.month,1,0,0,0,0)).getUTCDay():void 0;for(let o=this[t]+s;o<e[t].length;o++){let c=e[t][o];if(t==="day"&&e.lastDayOfMonth&&o-s==a&&(c=!0),t==="day"&&!e.starDOW){let l=e.dayOfWeek[(r+(o-s-1))%7];if(l&&l&hs)l=this.isNthWeekdayOfMonth(this.year,this.month,o-s,l);else if(l)throw new Error(`CronDate: Invalid value for dayOfWeek encountered. ${l}`);i.legacyMode&&!e.starDOM?c=c||l:c=c&&l}if(c)return this[t]=o-s,n!==this[t]?2:1}return 3};Ae.prototype.recurse=function(i,t,e){let s=this.findNext(t,pt[e][0],i,pt[e][2]);if(s>1){let n=e+1;for(;n<pt.length;)this[pt[n][0]]=-pt[n][2],n++;if(s===3)return this[pt[e][1]]++,this[pt[e][0]]=-pt[e][2],this.apply(),this.recurse(i,t,0);if(this.apply())return this.recurse(i,t,e-1)}return e+=1,e>=pt.length?this:this.year>=3e3?null:this.recurse(i,t,e)};Ae.prototype.increment=function(i,t,e){return this.second+=t.interval>1&&e?t.interval:1,this.ms=0,this.apply(),this.recurse(i,t,0)};Ae.prototype.getDate=function(i){return i||this.tz===void 0?new Date(this.year,this.month,this.day,this.hour,this.minute,this.second,this.ms):typeof this.tz=="number"?new Date(Date.UTC(this.year,this.month,this.day,this.hour,this.minute-this.tz,this.second,this.ms)):je(this.year,this.month+1,this.day,this.hour,this.minute,this.second,this.tz)};Ae.prototype.getTime=function(){return this.getDate().getTime()};function Xs(i){return Object.prototype.toString.call(i)==="[object Function]"||typeof i=="function"||i instanceof Function}function vl(i){typeof Deno<"u"&&typeof Deno.unrefTimer<"u"?Deno.unrefTimer(i):i&&typeof i.unref<"u"&&i.unref()}var Ii=30*1e3,us=[];function pe(i,t,e){if(!(this instanceof pe))return new pe(i,t,e);let s,n;if(Xs(t))n=t;else if(typeof t=="object")s=t;else if(t!==void 0)throw new Error("Cron: Invalid argument passed for optionsIn. Should be one of function, or object (options).");if(Xs(e))n=e;else if(typeof e=="object")s=e;else if(e!==void 0)throw new Error("Cron: Invalid argument passed for funcIn. Should be one of function, or object (options).");if(this.name=s?s.name:void 0,this.options=yl(s),this._states={kill:!1,blocking:!1,previousRun:void 0,currentRun:void 0,once:void 0,currentTimeout:void 0,maxRuns:s?s.maxRuns:void 0,paused:s?s.paused:!1,pattern:void 0},i&&(i instanceof Date||typeof i=="string"&&i.indexOf(":")>0)?this._states.once=new Ae(i,this.options.timezone||this.options.utcOffset):this._states.pattern=new He(i,this.options.timezone),this.name){if(us.find(r=>r.name===this.name))throw new Error("Cron: Tried to initialize new named job '"+this.name+"', but name already taken.");us.push(this)}return n!==void 0&&(this.fn=n,this.schedule()),this}pe.prototype.nextRun=function(i){let t=this._next(i);return t?t.getDate():null};pe.prototype.nextRuns=function(i,t){i>this._states.maxRuns&&(i=this._states.maxRuns);let e=[],s=t||this._states.currentRun;for(;i--&&(s=this.nextRun(s));)e.push(s);return e};pe.prototype.getPattern=function(){return this._states.pattern?this._states.pattern.pattern:void 0};pe.prototype.isRunning=function(){let i=this.nextRun(this._states.currentRun),t=!this._states.paused,e=this.fn!==void 0,s=!this._states.kill;return t&&e&&s&&i!==null};pe.prototype.isStopped=function(){return this._states.kill};pe.prototype.isBusy=function(){return this._states.blocking};pe.prototype.currentRun=function(){return this._states.currentRun?this._states.currentRun.getDate():null};pe.prototype.previousRun=function(){return this._states.previousRun?this._states.previousRun.getDate():null};pe.prototype.msToNext=function(i){i=i||new Date;let t=this._next(i);return t?t.getTime()-i.getTime():null};pe.prototype.stop=function(){this._states.kill=!0,this._states.currentTimeout&&clearTimeout(this._states.currentTimeout);let i=us.indexOf(this);i>=0&&us.splice(i,1)};pe.prototype.pause=function(){return this._states.paused=!0,!this._states.kill};pe.prototype.resume=function(){return this._states.paused=!1,!this._states.kill};pe.prototype.schedule=function(i){if(i&&this.fn)throw new Error("Cron: It is not allowed to schedule two functions using the same Croner instance.");i&&(this.fn=i);let t=this.msToNext(),e=this.nextRun(this._states.currentRun);return t==null||isNaN(t)||e===null?this:(t>Ii&&(t=Ii),this._states.currentTimeout=setTimeout(()=>this._checkTrigger(e),t),this._states.currentTimeout&&this.options.unref&&vl(this._states.currentTimeout),this)};pe.prototype._trigger=async function(i){if(this._states.blocking=!0,this._states.currentRun=new Ae(void 0,this.options.timezone||this.options.utcOffset),this.options.catch)try{await this.fn(this,this.options.context)}catch(t){Xs(this.options.catch)&&this.options.catch(t,this)}else await this.fn(this,this.options.context);this._states.previousRun=new Ae(i,this.options.timezone||this.options.utcOffset),this._states.blocking=!1};pe.prototype.trigger=async function(){await this._trigger()};pe.prototype._checkTrigger=function(i){let t=new Date,e=!this._states.paused&&t.getTime()>=i,s=this._states.blocking&&this.options.protect;e&&!s?(this._states.maxRuns--,this._trigger()):e&&s&&Xs(this.options.protect)&&setTimeout(()=>this.options.protect(this),0),this.schedule()};pe.prototype._next=function(i){let t=!!(i||this._states.currentRun),e=!1;!i&&this.options.startAt&&this.options.interval&&([i,t]=this._calculatePreviousRun(i,t),e=!i),i=new Ae(i,this.options.timezone||this.options.utcOffset),this.options.startAt&&i&&i.getTime()<this.options.startAt.getTime()&&(i=this.options.startAt);let s=this._states.once||new Ae(i,this.options.timezone||this.options.utcOffset);return!e&&s!==this._states.once&&(s=s.increment(this._states.pattern,this.options,t)),this._states.once&&this._states.once.getTime()<=i.getTime()||s===null||this._states.maxRuns<=0||this._states.kill||this.options.stopAt&&s.getTime()>=this.options.stopAt.getTime()?null:s};pe.prototype._calculatePreviousRun=function(i,t){let e=new Ae(void 0,this.options.timezone||this.options.utcOffset);if(this.options.startAt.getTime()<=e.getTime()){i=this.options.startAt;let s=i.getTime()+this.options.interval*1e3;for(;s<=e.getTime();)i=new Ae(i,this.options.timezone||this.options.utcOffset).increment(this._states.pattern,this.options,!0),s=i.getTime()+this.options.interval*1e3;t=!0}return[i,t]};pe.Cron=pe;pe.scheduledJobs=us;var lr=require("obsidian");var Zi=require("crypto");var Ve=require("fs"),aa=require("path");function wl(i){return`mcp__${i.replace(/[\s.]+/g,"_")}`}function Qs(i,t,e={}){let s=t.permissionRules.allow.length>0||t.permissionRules.deny.length>0,n=t.permissionMode?.trim(),a=!!n&&n!=="default",r=e.mcpAllowServers??[],o=r.length>0;if(!(s||a||o))return null;let l=(0,aa.join)(i,".claude"),h=(0,aa.join)(l,"settings.local.json");(0,Ve.existsSync)(l)||(0,Ve.mkdirSync)(l,{recursive:!0});let d=null;if((0,Ve.existsSync)(h))try{d=(0,Ve.readFileSync)(h,"utf-8")}catch{d=null}let u={};if(a&&(u.defaultMode=n),s||o){let p=[...t.permissionRules.allow];for(let m of r)p.push(wl(m));u.permissions={allow:p,deny:t.permissionRules.deny}}return(0,Ve.writeFileSync)(h,JSON.stringify(u,null,2)+`
11833
+ `,"utf-8"),{path:h,backupContent:d}}function Et(i){if(i)try{i.backupContent!==null?(0,Ve.writeFileSync)(i.path,i.backupContent,"utf-8"):(0,Ve.existsSync)(i.path)&&(0,Ve.unlinkSync)(i.path)}catch{}}function Fi(i){if(typeof i=="string")return i;if(Array.isArray(i))return i.map(e=>typeof e=="string"?e:e&&typeof e=="object"&&"text"in e&&typeof e.text=="string"?e.text:"").filter(Boolean).join(`
11834
+ `);if(i&&typeof i=="object"){for(let t of["output","result","text","message"])if(t in i)return Fi(i[t])}}function ia(i,t=[]){if(Array.isArray(i)){for(let r of i)ia(r,t);return t}if(!i||typeof i!="object")return t;let e=i,s=typeof e.tool_name=="string"&&e.tool_name||typeof e.tool=="string"&&e.tool||typeof e.name=="string"&&e.name,n=typeof e.command=="string"?e.command:typeof e.input=="string"?e.input:typeof e.cmd=="string"?e.cmd:void 0,a=typeof e.reason=="string"?e.reason:void 0;s&&["tool_use","tool","name","tool_name"].some(r=>r in e)&&t.push({tool:s,command:n,reason:a});for(let r of Object.values(e))ia(r,t);return t}function Oi(i){if(!i||typeof i!="object")return;let t=i,e=t.usage;if(e&&typeof e=="object"){let n=typeof e.input_tokens=="number"?e.input_tokens:0,a=typeof e.output_tokens=="number"?e.output_tokens:0,r=typeof e.cache_creation_input_tokens=="number"?e.cache_creation_input_tokens:0,o=typeof e.cache_read_input_tokens=="number"?e.cache_read_input_tokens:0,c=n+a+r+o;if(c>0)return c}let s=t.modelUsage;if(s&&typeof s=="object"){let n=0;for(let a of Object.values(s)){if(!a||typeof a!="object")continue;let r=a;n+=typeof r.inputTokens=="number"?r.inputTokens:0,n+=typeof r.outputTokens=="number"?r.outputTokens:0,n+=typeof r.cacheReadInputTokens=="number"?r.cacheReadInputTokens:0,n+=typeof r.cacheCreationInputTokens=="number"?r.cacheCreationInputTokens:0}if(n>0)return n}for(let n of["tokens_used","total_tokens","totalTokens"])if(typeof t[n]=="number")return t[n];for(let n of Object.values(t)){let a=Oi(n);if(typeof a=="number")return a}}function Ni(i){if(!i||typeof i!="object")return;let t=i;if(typeof t.total_cost_usd=="number")return t.total_cost_usd;for(let e of Object.values(t)){let s=Ni(e);if(typeof s=="number")return s}}function ra(i){if(!i||typeof i!="object")return;let t=i;if(t.type==="result"&&typeof t.result=="string"&&t.result.trim())return t.result}function Zs(i){if(!i||typeof i!="object")return;let t=i;if(t.modelUsage&&typeof t.modelUsage=="object"){let s=Object.keys(t.modelUsage);if(s.length>0&&s[0])return s[0]}let e=t.message;if(e&&typeof e.model=="string"&&e.model)return e.model;if(typeof t.model=="string"&&t.model)return t.model;for(let s of Object.values(t)){let n=Zs(s);if(n)return n}}function bl(i){return/^gpt-|codex/i.test(i.trim())}var Bi={id:"claude-code",label:"Claude Code",cliPath(i){return i.claudeCliPath},buildExec(i){let t=["-p",i.prompt,"--output-format",i.streaming?"stream-json":"json"];i.streaming&&t.push("--verbose");let e=i.modelSource==="settings"&&bl(i.model);i.model&&!e&&t.push("--model",i.model),i.effort&&t.push("--effort",i.effort);let s=i.agent.permissionMode?.trim();return s&&s!=="default"?t.push("--permission-mode",s):t.push("--permission-mode","bypassPermissions"),Promise.resolve({cliPath:i.settings.claudeCliPath,args:t})},parseExecOutput(i,t,e){let s=i.trim(),n;if(e){let c=ge(s);for(let l=c.length-1;l>=0;l--){let h=c[l]?.trim();if(h)try{let d=JSON.parse(h);if(d&&typeof d=="object"){n=d;break}}catch{}}}else if(s.startsWith("{")||s.startsWith("["))try{n=JSON.parse(s)}catch{n=void 0}let a=Fi(n)??"";if(!a&&e){let c=[];for(let l of ge(s)){let h=l.trim();if(h)try{let d=JSON.parse(h);if(d.type==="assistant"&&d.message?.content)for(let u of d.message.content)u.type==="text"&&u.text&&c.push(u.text);else d.type==="result"&&typeof d.result=="string"&&c.push(d.result)}catch{}}a=c.join(`
11835
+ `).trim()}a||(a=t.trim()||"(no output)");let r=Zs(n),o=ra(n);if((!r||!o)&&e)for(let c of ge(s)){let l=c.trim();if(l)try{let h=JSON.parse(l);if(!r){let d=Zs(h);d&&(r=d)}if(!o){let d=ra(h);d&&(o=d)}if(r&&o)break}catch{}}return{outputText:a,finalResult:o,tokensUsed:Oi(n),costUsd:Ni(n),toolsUsed:ia(n),concreteModel:r,rawJson:n}},extractStreamChunk(i){let t=i.trim();if(!t)return null;let e;try{e=JSON.parse(t)}catch{return null}let s=e.type;if(s==="assistant"){let n=e.message;if(n?.content&&Array.isArray(n.content)){let a=[];for(let r of n.content)if(r.type==="text"&&typeof r.text=="string")a.push(r.text);else if(r.type==="tool_use"){let o=String(r.name??"tool"),c=r.input,l=c?.command??c?.content??"";a.push(`
11836
11836
  \u25B8 ${o}${l?`: ${String(l).slice(0,200)}`:""}
11837
11837
  `)}if(a.length>0)return a.join("")}}if(s==="result"){let n=typeof e.result=="string"?e.result:null;if(n)return`
11838
- ${n}`}return null},setupPermissions(i,t,e,s){let n=Qs(i,t,{mcpAllowServers:s?.mcpAllowServers});return n?Promise.resolve({restore:()=>Et(n)}):Promise.resolve(null)}};var re=require("fs"),ca=require("crypto"),ms=require("os"),Ye=require("path");var wl=/^[A-Z][A-Za-z]*$/;function kl(i){let t=i.trim();if(!t)return{error:"empty Bash() matches every command \u2014 use the read-only sandbox instead"};let e=t.split(/\s+/).filter(Boolean),s=[];for(let n=0;n<e.length;n++){let a=e[n],r=n===e.length-1;if(a==="*"){if(r)continue;return{error:"a wildcard in the middle of a command can't be expressed as a prefix rule"}}if(a.includes("*"))return{error:"embedded wildcards aren't supported (execpolicy matches argv prefixes only)"};s.push(a)}return s.length===0?{error:"a bare wildcard matches every command \u2014 use the read-only sandbox instead"}:{tokens:s}}function xl(i,t){return`prefix_rule(pattern=[${i.map(s=>JSON.stringify(s)).join(", ")}], decision="${t}", justification="agent-fleet")`}function Sl(i){let t=[],e=[],s=(a,r)=>{let o=a.trim();if(!o||o.startsWith("mcp__"))return;let c=o.match(/^Bash\((.*)\)$/s);if(!c){e.push({rule:o,reason:wl.test(o)?"tool-name rules are governed by the sandbox, not execpolicy":"not a Bash(...) command pattern"});return}let l=kl(c[1]);if("error"in l){e.push({rule:o,reason:l.error});return}t.push(xl(l.tokens,r))};for(let a of i.permissionRules.deny)s(a,"forbidden");for(let a of i.permissionRules.allow)s(a,"allow");return t.length===0?{rulesText:null,dropped:e,emitted:0}:{rulesText:`${`# Generated by Agent Fleet for agent "${i.name}". Do not edit \u2014 regenerated each run.
11838
+ ${n}`}return null},setupPermissions(i,t,e,s){let n=Qs(i,t,{mcpAllowServers:s?.mcpAllowServers});return n?Promise.resolve({restore:()=>Et(n)}):Promise.resolve(null)}};var le=require("fs"),ca=require("crypto"),ms=require("os"),Ye=require("path");var kl=/^[A-Z][A-Za-z]*$/;function xl(i){let t=i.trim();if(!t)return{error:"empty Bash() matches every command \u2014 use the read-only sandbox instead"};let e=t.split(/\s+/).filter(Boolean),s=[];for(let n=0;n<e.length;n++){let a=e[n],r=n===e.length-1;if(a==="*"){if(r)continue;return{error:"a wildcard in the middle of a command can't be expressed as a prefix rule"}}if(a.includes("*"))return{error:"embedded wildcards aren't supported (execpolicy matches argv prefixes only)"};s.push(a)}return s.length===0?{error:"a bare wildcard matches every command \u2014 use the read-only sandbox instead"}:{tokens:s}}function Sl(i,t){return`prefix_rule(pattern=[${i.map(s=>JSON.stringify(s)).join(", ")}], decision="${t}", justification="agent-fleet")`}function Cl(i){let t=[],e=[],s=(a,r)=>{let o=a.trim();if(!o||o.startsWith("mcp__"))return;let c=o.match(/^Bash\((.*)\)$/s);if(!c){e.push({rule:o,reason:kl.test(o)?"tool-name rules are governed by the sandbox, not execpolicy":"not a Bash(...) command pattern"});return}let l=xl(c[1]);if("error"in l){e.push({rule:o,reason:l.error});return}t.push(Sl(l.tokens,r))};for(let a of i.permissionRules.deny)s(a,"forbidden");for(let a of i.permissionRules.allow)s(a,"allow");return t.length===0?{rulesText:null,dropped:e,emitted:0}:{rulesText:`${`# Generated by Agent Fleet for agent "${i.name}". Do not edit \u2014 regenerated each run.
11839
11839
  # Source: this agent's permissionRules (allow/deny), translated to Codex execpolicy.
11840
11840
  `}${t.join(`
11841
11841
  `)}
11842
- `,dropped:e,emitted:t.length}}function Cl(){let i=process.env.CODEX_HOME?.trim();return i||(0,Ye.join)((0,ms.homedir)(),".codex")}var Ui=(0,Ye.join)((0,ms.tmpdir)(),"agent-fleet-codex");function Tl(i){let t=i.name.replace(/[^A-Za-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")||"agent",e=(0,ca.createHash)("sha1").update(i.filePath).digest("hex").slice(0,8);return(0,Ye.join)(Ui,`${t}-${e}`)}function _l(i,t){let e=`${i}.${process.pid}.${Date.now()}.tmp`;(0,re.writeFileSync)(e,t,"utf-8"),(0,re.renameSync)(e,i)}function Al(i,t){try{let e=(0,re.lstatSync)(t);if(e.isSymbolicLink()){try{if((0,re.readlinkSync)(t)===i)return}catch{}(0,re.unlinkSync)(t)}else e.isDirectory()?(0,re.rmSync)(t,{recursive:!0,force:!0}):(0,re.unlinkSync)(t)}catch{}(0,re.symlinkSync)(i,t)}function El(i,t,e=Cl()){if(!(0,re.existsSync)(e))return null;let s=Tl(i);(0,re.mkdirSync)(s,{recursive:!0});for(let o of(0,re.readdirSync)(e))o!=="rules"&&Al((0,Ye.join)(e,o),(0,Ye.join)(s,o));let n=(0,Ye.join)(s,"rules");(0,re.mkdirSync)(n,{recursive:!0});let a=(0,Ye.join)(e,"rules");if((0,re.existsSync)(a)){for(let o of(0,re.readdirSync)(a))if(o.endsWith(".rules"))try{(0,re.copyFileSync)((0,Ye.join)(a,o),(0,Ye.join)(n,`user-${o}`))}catch{}}let r=(0,Ye.join)(n,"agent-fleet.rules");return _l(r,t),{codexHome:s,rulesPath:r}}function $i(){try{(0,re.rmSync)(Ui,{recursive:!0,force:!0})}catch{}}var oa=new Map,la=new Map;function ji(){oa.clear(),la.clear()}function Wi(i,t,e){return new Promise(s=>{let n=!1,a=r=>{n||(n=!0,s(r))};try{let r=ot(i,["execpolicy","check","--rules",t,...e]),o=setTimeout(()=>{try{r.kill()}catch{}a(null)},8e3);r.on("error",()=>{clearTimeout(o),a(null)}),r.on("close",c=>{clearTimeout(o),a(c)})}catch{a(null)}})}function Pl(i){let t=oa.get(i);if(t)return t;let e=(async()=>{let s=null;try{s=(0,re.mkdtempSync)((0,Ye.join)((0,ms.tmpdir)(),"af-codex-probe-"));let n=(0,Ye.join)(s,"probe.rules");return(0,re.writeFileSync)(n,`prefix_rule(pattern=["ls"], decision="allow")
11843
- `,"utf-8"),await Wi(i,n,["ls"])===0}catch{return!1}finally{if(s)try{(0,re.rmSync)(s,{recursive:!0,force:!0})}catch{}}})();return oa.set(i,e),e}async function Rl(i,t,e){let s=`${i}:${(0,ca.createHash)("sha1").update(e).digest("hex")}`,n=la.get(s);if(n!==void 0)return n;let r=await Wi(i,t,["true"])===0;return la.set(s,r),r}var Bi=new Set;function ps(i,t){Bi.has(i)||(Bi.add(i),console.warn(`Agent Fleet: ${t}`))}async function Hi(i,t){if(!(i.permissionRules.allow.length>0||i.permissionRules.deny.length>0))return null;let{rulesText:s,dropped:n}=Sl(i);if(n.length>0&&ps(`dropped:${i.name}:${n.map(l=>l.rule).join("|")}`,`agent "${i.name}": ${n.length} permission rule(s) can't be enforced by Codex and were ignored \u2014 ${n.map(l=>`"${l.rule}" (${l.reason})`).join("; ")}. File/network access is governed by the sandbox (Permission Mode).`),!s)return null;let a=t.codexCliPath;if(!await Pl(a))return ps(`unsupported:${a}`,`this Codex build doesn't support execpolicy rules; agent "${i.name}" runs with sandbox-only enforcement. Update Codex to enforce command allow/deny rules.`),null;let o;try{o=El(i,s)}catch(l){return ps(`overlay-fail:${i.name}`,`couldn't build the Codex permission overlay for agent "${i.name}" (${l instanceof Error?l.message:String(l)}); falling back to sandbox-only (symlinks may be unavailable on this platform).`),null}return o?await Rl(a,o.rulesPath,s)?{restore:()=>{},env:{CODEX_HOME:o.codexHome}}:(ps(`invalid-rules:${i.name}`,`generated Codex rules for agent "${i.name}" failed validation; falling back to sandbox-only.`),null):(ps("no-codex-home",`Codex home (~/.codex) not found; agent "${i.name}" runs with sandbox-only enforcement. Run \`codex login\` first.`),null)}function Dl(i){let t=i.trim();return/^(opus|sonnet|haiku|opusplan)$/i.test(t)||/claude|anthropic/i.test(t)}function Il(i){let t=i.trim().toLowerCase();return t?t==="max"?"xhigh":["low","medium","high","xhigh"].includes(t)?t:"":""}function Ml(i){switch((i??"").trim()){case"plan":case"read-only":return["--sandbox","read-only"];case"acceptEdits":case"default":case"workspace-write":return["--sandbox","workspace-write"];case"danger-full-access":return["--sandbox","danger-full-access"];default:return["--dangerously-bypass-approvals-and-sandbox"]}}function Ll(i){let t=["exec","--json","--skip-git-repo-check"],e=i.modelSource==="settings"&&Dl(i.model);i.model&&!e&&t.push("-m",i.model);let s=Il(i.effort);return s&&t.push("-c",`model_reasoning_effort="${s}"`),t.push(...Ml(i.agent.permissionMode)),i.resumeSessionId&&t.push("resume",i.resumeSessionId),t.push("-"),{args:t,stdinPayload:i.prompt}}function qi(i){let t=i.trim();if(!t)return null;try{let e=JSON.parse(t);return e&&typeof e=="object"&&!Array.isArray(e)?e:null}catch{return null}}function en(i){let t=i.item;return t&&typeof t=="object"?t:null}function da(i){let t=typeof i.type=="string"?i.type:"";if(t==="command_execution")return{tool:"shell",command:typeof i.command=="string"?i.command:void 0};if(t==="mcp_tool_call"){let e=typeof i.server=="string"?i.server:"mcp",s=typeof i.tool=="string"?i.tool:"tool";return{tool:`mcp__${e}__${s}`}}return t==="web_search"?{tool:"web_search",command:typeof i.query=="string"?i.query:void 0}:t==="file_change"?{tool:"file_change",command:(Array.isArray(i.changes)?i.changes:[]).map(n=>`${typeof n.kind=="string"?n.kind:"update"} ${typeof n.path=="string"?n.path:""}`.trim()).filter(Boolean).join(", ")||void 0}:null}function zi(i){let t=i.usage;if(!t||typeof t!="object")return 0;let e=typeof t.input_tokens=="number"?t.input_tokens:0,s=typeof t.output_tokens=="number"?t.output_tokens:0;return e+s}function Fl(i){let t=i.usage;return!t||typeof t!="object"?0:typeof t.input_tokens=="number"?t.input_tokens:0}function ha(){return{emittedTextLengths:new Map}}function Gi(i,t){let e=typeof i.type=="string"?i.type:"",s=[];if(e==="thread.started"&&typeof i.thread_id=="string"&&i.thread_id)return s.push({kind:"session",sessionId:i.thread_id}),s;if(e==="turn.completed")return s.push({kind:"usage",contextTokens:Fl(i),totalTokens:zi(i)}),s;if(e==="turn.failed"){let n=i.error,a=n&&typeof n.message=="string"?n.message:"turn failed";return s.push({kind:"turn-failed",message:a}),s}if(e==="error"){let n=typeof i.message=="string"?i.message:"stream error";return s.push({kind:"error",message:n}),s}if(e==="item.started"||e==="item.updated"||e==="item.completed"){let n=en(i);if(!n)return s;let a=typeof n.type=="string"?n.type:"";if(a==="agent_message"){let r=typeof n.text=="string"?n.text:"",o=typeof n.id=="string"?n.id:"__single__",c=t.emittedTextLengths.get(o)??0;return r.length>c&&(s.push({kind:"text",text:r.slice(c)}),t.emittedTextLengths.set(o,r.length)),s}if(a==="error"){let r=typeof n.message=="string"?n.message:"item error";return s.push({kind:"error",message:r}),s}if(e==="item.started"){let r=da(n);r&&s.push({kind:"tool",toolName:r.tool,command:r.command})}return s}return s}var fs={id:"codex",label:"Codex",cliPath(i){return i.codexCliPath},buildExec(i){let{args:t,stdinPayload:e}=Ll(i);return Promise.resolve({cliPath:i.settings.codexCliPath,args:t,stdinPayload:e})},parseExecOutput(i,t,e){let s=[],n=[],a=[],r=0,o,c;for(let h of pe(i)){let u=qi(h);if(!u)continue;let p=typeof u.type=="string"?u.type:"";if(p==="thread.started"&&typeof u.thread_id=="string")o=u.thread_id;else if(p==="turn.completed")r+=zi(u),c=u;else if(p==="turn.failed"){let f=u.error;a.push(f&&typeof f.message=="string"?f.message:"turn failed")}else if(p==="error")a.push(typeof u.message=="string"?u.message:"stream error");else if(p==="item.completed"){let f=en(u);if(!f)continue;let m=typeof f.type=="string"?f.type:"";if(m==="agent_message"&&typeof f.text=="string"&&f.text.trim())s.push(f.text);else if(m==="error"&&typeof f.message=="string")a.push(f.message);else{let g=da(f);g&&n.push(g)}}}let l=s.join(`
11842
+ `,dropped:e,emitted:t.length}}function Tl(){let i=process.env.CODEX_HOME?.trim();return i||(0,Ye.join)((0,ms.homedir)(),".codex")}var $i=(0,Ye.join)((0,ms.tmpdir)(),"agent-fleet-codex");function _l(i){let t=i.name.replace(/[^A-Za-z0-9_-]+/g,"-").replace(/^-+|-+$/g,"")||"agent",e=(0,ca.createHash)("sha1").update(i.filePath).digest("hex").slice(0,8);return(0,Ye.join)($i,`${t}-${e}`)}function Al(i,t){let e=`${i}.${process.pid}.${Date.now()}.tmp`;(0,le.writeFileSync)(e,t,"utf-8"),(0,le.renameSync)(e,i)}function El(i,t){try{let e=(0,le.lstatSync)(t);if(e.isSymbolicLink()){try{if((0,le.readlinkSync)(t)===i)return}catch{}(0,le.unlinkSync)(t)}else e.isDirectory()?(0,le.rmSync)(t,{recursive:!0,force:!0}):(0,le.unlinkSync)(t)}catch{}(0,le.symlinkSync)(i,t)}function Pl(i,t,e=Tl()){if(!(0,le.existsSync)(e))return null;let s=_l(i);(0,le.mkdirSync)(s,{recursive:!0});for(let o of(0,le.readdirSync)(e))o!=="rules"&&El((0,Ye.join)(e,o),(0,Ye.join)(s,o));let n=(0,Ye.join)(s,"rules");(0,le.mkdirSync)(n,{recursive:!0});let a=(0,Ye.join)(e,"rules");if((0,le.existsSync)(a)){for(let o of(0,le.readdirSync)(a))if(o.endsWith(".rules"))try{(0,le.copyFileSync)((0,Ye.join)(a,o),(0,Ye.join)(n,`user-${o}`))}catch{}}let r=(0,Ye.join)(n,"agent-fleet.rules");return Al(r,t),{codexHome:s,rulesPath:r}}function ji(){try{(0,le.rmSync)($i,{recursive:!0,force:!0})}catch{}}var oa=new Map,la=new Map;function Wi(){oa.clear(),la.clear()}function Hi(i,t,e){return new Promise(s=>{let n=!1,a=r=>{n||(n=!0,s(r))};try{let r=lt(i,["execpolicy","check","--rules",t,...e]),o=window.setTimeout(()=>{try{r.kill()}catch{}a(null)},8e3);r.on("error",()=>{window.clearTimeout(o),a(null)}),r.on("close",c=>{window.clearTimeout(o),a(c)})}catch{a(null)}})}function Rl(i){let t=oa.get(i);if(t)return t;let e=(async()=>{let s=null;try{s=(0,le.mkdtempSync)((0,Ye.join)((0,ms.tmpdir)(),"af-codex-probe-"));let n=(0,Ye.join)(s,"probe.rules");return(0,le.writeFileSync)(n,`prefix_rule(pattern=["ls"], decision="allow")
11843
+ `,"utf-8"),await Hi(i,n,["ls"])===0}catch{return!1}finally{if(s)try{(0,le.rmSync)(s,{recursive:!0,force:!0})}catch{}}})();return oa.set(i,e),e}async function Dl(i,t,e){let s=`${i}:${(0,ca.createHash)("sha1").update(e).digest("hex")}`,n=la.get(s);if(n!==void 0)return n;let r=await Hi(i,t,["true"])===0;return la.set(s,r),r}var Ui=new Set;function ps(i,t){Ui.has(i)||(Ui.add(i),console.warn(`Agent Fleet: ${t}`))}async function qi(i,t){if(!(i.permissionRules.allow.length>0||i.permissionRules.deny.length>0))return null;let{rulesText:s,dropped:n}=Cl(i);if(n.length>0&&ps(`dropped:${i.name}:${n.map(l=>l.rule).join("|")}`,`agent "${i.name}": ${n.length} permission rule(s) can't be enforced by Codex and were ignored \u2014 ${n.map(l=>`"${l.rule}" (${l.reason})`).join("; ")}. File/network access is governed by the sandbox (Permission Mode).`),!s)return null;let a=t.codexCliPath;if(!await Rl(a))return ps(`unsupported:${a}`,`this Codex build doesn't support execpolicy rules; agent "${i.name}" runs with sandbox-only enforcement. Update Codex to enforce command allow/deny rules.`),null;let o;try{o=Pl(i,s)}catch(l){return ps(`overlay-fail:${i.name}`,`couldn't build the Codex permission overlay for agent "${i.name}" (${l instanceof Error?l.message:String(l)}); falling back to sandbox-only (symlinks may be unavailable on this platform).`),null}return o?await Dl(a,o.rulesPath,s)?{restore:()=>{},env:{CODEX_HOME:o.codexHome}}:(ps(`invalid-rules:${i.name}`,`generated Codex rules for agent "${i.name}" failed validation; falling back to sandbox-only.`),null):(ps("no-codex-home",`Codex home (~/.codex) not found; agent "${i.name}" runs with sandbox-only enforcement. Run \`codex login\` first.`),null)}function Il(i){let t=i.trim();return/^(opus|sonnet|haiku|opusplan)$/i.test(t)||/claude|anthropic/i.test(t)}function Ml(i){let t=i.trim().toLowerCase();return t?t==="max"?"xhigh":["low","medium","high","xhigh"].includes(t)?t:"":""}function Ll(i){switch((i??"").trim()){case"plan":case"read-only":return["--sandbox","read-only"];case"acceptEdits":case"default":case"workspace-write":return["--sandbox","workspace-write"];case"danger-full-access":return["--sandbox","danger-full-access"];default:return["--dangerously-bypass-approvals-and-sandbox"]}}function Fl(i){let t=["exec","--json","--skip-git-repo-check"],e=i.modelSource==="settings"&&Il(i.model);i.model&&!e&&t.push("-m",i.model);let s=Ml(i.effort);return s&&t.push("-c",`model_reasoning_effort="${s}"`),t.push(...Ll(i.agent.permissionMode)),i.resumeSessionId&&t.push("resume",i.resumeSessionId),t.push("-"),{args:t,stdinPayload:i.prompt}}function zi(i){let t=i.trim();if(!t)return null;try{let e=JSON.parse(t);return e&&typeof e=="object"&&!Array.isArray(e)?e:null}catch{return null}}function en(i){let t=i.item;return t&&typeof t=="object"?t:null}function da(i){let t=typeof i.type=="string"?i.type:"";if(t==="command_execution")return{tool:"shell",command:typeof i.command=="string"?i.command:void 0};if(t==="mcp_tool_call"){let e=typeof i.server=="string"?i.server:"mcp",s=typeof i.tool=="string"?i.tool:"tool";return{tool:`mcp__${e}__${s}`}}return t==="web_search"?{tool:"web_search",command:typeof i.query=="string"?i.query:void 0}:t==="file_change"?{tool:"file_change",command:(Array.isArray(i.changes)?i.changes:[]).map(n=>`${typeof n.kind=="string"?n.kind:"update"} ${typeof n.path=="string"?n.path:""}`.trim()).filter(Boolean).join(", ")||void 0}:null}function Gi(i){let t=i.usage;if(!t||typeof t!="object")return 0;let e=typeof t.input_tokens=="number"?t.input_tokens:0,s=typeof t.output_tokens=="number"?t.output_tokens:0;return e+s}function Ol(i){let t=i.usage;return!t||typeof t!="object"?0:typeof t.input_tokens=="number"?t.input_tokens:0}function ha(){return{emittedTextLengths:new Map}}function Vi(i,t){let e=typeof i.type=="string"?i.type:"",s=[];if(e==="thread.started"&&typeof i.thread_id=="string"&&i.thread_id)return s.push({kind:"session",sessionId:i.thread_id}),s;if(e==="turn.completed")return s.push({kind:"usage",contextTokens:Ol(i),totalTokens:Gi(i)}),s;if(e==="turn.failed"){let n=i.error,a=n&&typeof n.message=="string"?n.message:"turn failed";return s.push({kind:"turn-failed",message:a}),s}if(e==="error"){let n=typeof i.message=="string"?i.message:"stream error";return s.push({kind:"error",message:n}),s}if(e==="item.started"||e==="item.updated"||e==="item.completed"){let n=en(i);if(!n)return s;let a=typeof n.type=="string"?n.type:"";if(a==="agent_message"){let r=typeof n.text=="string"?n.text:"",o=typeof n.id=="string"?n.id:"__single__",c=t.emittedTextLengths.get(o)??0;return r.length>c&&(s.push({kind:"text",text:r.slice(c)}),t.emittedTextLengths.set(o,r.length)),s}if(a==="error"){let r=typeof n.message=="string"?n.message:"item error";return s.push({kind:"error",message:r}),s}if(e==="item.started"){let r=da(n);r&&s.push({kind:"tool",toolName:r.tool,command:r.command})}return s}return s}var fs={id:"codex",label:"Codex",cliPath(i){return i.codexCliPath},buildExec(i){let{args:t,stdinPayload:e}=Fl(i);return Promise.resolve({cliPath:i.settings.codexCliPath,args:t,stdinPayload:e})},parseExecOutput(i,t,e){let s=[],n=[],a=[],r=0,o,c;for(let d of ge(i)){let u=zi(d);if(!u)continue;let p=typeof u.type=="string"?u.type:"";if(p==="thread.started"&&typeof u.thread_id=="string")o=u.thread_id;else if(p==="turn.completed")r+=Gi(u),c=u;else if(p==="turn.failed"){let m=u.error;a.push(m&&typeof m.message=="string"?m.message:"turn failed")}else if(p==="error")a.push(typeof u.message=="string"?u.message:"stream error");else if(p==="item.completed"){let m=en(u);if(!m)continue;let f=typeof m.type=="string"?m.type:"";if(f==="agent_message"&&typeof m.text=="string"&&m.text.trim())s.push(m.text);else if(f==="error"&&typeof m.message=="string")a.push(m.message);else{let g=da(m);g&&n.push(g)}}}let l=s.join(`
11844
11844
 
11845
11845
  `).trim();l||(l=a.join(`
11846
- `).trim()),l||(l=t.trim()||"(no output)");let d=s[s.length-1];return{outputText:l,finalResult:d?.trim()?d:void 0,tokensUsed:r>0?r:void 0,costUsd:void 0,toolsUsed:n,concreteModel:void 0,rawJson:c,sessionId:o}},extractStreamChunk(i){let t=qi(i);if(!t)return null;let e=typeof t.type=="string"?t.type:"";if(e==="item.completed"){let s=en(t);return s&&s.type==="agent_message"&&typeof s.text=="string"&&s.text.trim()?s.text:null}if(e==="item.started"){let s=en(t);if(!s)return null;let n=da(s);if(n){let a=n.command?`: ${n.command.slice(0,200)}`:"";return`
11846
+ `).trim()),l||(l=t.trim()||"(no output)");let h=s[s.length-1];return{outputText:l,finalResult:h?.trim()?h:void 0,tokensUsed:r>0?r:void 0,costUsd:void 0,toolsUsed:n,concreteModel:void 0,rawJson:c,sessionId:o}},extractStreamChunk(i){let t=zi(i);if(!t)return null;let e=typeof t.type=="string"?t.type:"";if(e==="item.completed"){let s=en(t);return s&&s.type==="agent_message"&&typeof s.text=="string"&&s.text.trim()?s.text:null}if(e==="item.started"){let s=en(t);if(!s)return null;let n=da(s);if(n){let a=n.command?`: ${n.command.slice(0,200)}`:"";return`
11847
11847
  \u25B8 ${n.tool}${a}
11848
11848
  `}return null}if(e==="turn.failed"){let s=t.error;return`
11849
11849
  \u2716 ${s&&typeof s.message=="string"?s.message:"turn failed"}
11850
- `}return null},setupPermissions(i,t,e,s){return Hi(t,e)}};function bt(i){let t=(i??"").trim().toLowerCase();return t==="codex"||t==="openai-codex"?"codex":"claude-code"}function Vi(i){return bt(i)==="codex"?fs:Ni}var Yi=new Set(["","default","subscription"]);function Pt(i,t,e){let s=ua(i?.model);if(s)return{value:pa(s),source:"task"};let n=ua(t.model);if(n)return{value:pa(n),source:"agent"};let a=ua(e.defaultModel);return a?{value:pa(a),source:"settings"}:{value:"",source:"cli-default"}}function gs(i){return!Yi.has(i.trim())}function ua(i){if(!i)return"";let t=i.trim();return t||""}function pa(i){return Yi.has(i)?"":i}function tn(i,t){let e=i.wikiReferences;if(!e||e.length===0)return null;let s=[];for(let a of e){let r=t.getAgentByName(a.agent);if(!r||!r.wikiKeeper)continue;let o=r.wikiKeeper,c=o.scopeRoot?`${o.scopeRoot.replace(/\/+$/,"")}/`:"";s.push({agentName:r.name,scopeRoot:o.scopeRoot||"(whole vault)",topicsPath:`${c}${o.topicsRoot}`,inboxPath:`${c}${o.inboxPath}`,indexPath:`${c}${o.indexPath}`})}if(s.length===0)return null;let n=["## Wiki Access"];n.push("You have read access to the following wikis maintained by other agents. Use the `wiki-query` skill in consumer mode when the user asks something a wiki may already cover."),n.push("");for(let a of s)n.push(`### Wiki: \`${a.agentName}\``),n.push(`- scope root: \`${a.scopeRoot}\``),n.push(`- topics: \`${a.topicsPath}/\``),n.push(`- index: \`${a.indexPath}\``),n.push(`- inbox: \`${a.inboxPath}/\``),n.push("");return n.push("### Rules"),n.push("- **Cite every factual claim** from a wiki using `[[<topics-path>/<page>]]`. If a claim has no page, say the wiki doesn't cover it \u2014 do not fabricate."),n.push("- **When the user shares something durable** that isn't yet in a wiki (a decision, a new entity mention, a competitor change, a meeting outcome), write a short markdown file to the relevant wiki's inbox at `<inbox>/YYYY-MM-DD-<slug>.md` with a one-line note + the source. The wiki keeper files it canonically on its next ingest."),n.push("- **Do NOT write to `<topics-path>/` directly.** The wiki keeper is the canonical curator of topic pages. Use the inbox as your deposit point."),n.push("- **When the question spans multiple wikis**, be explicit about which scope each cited page belongs to."),n.join(`
11851
- `)}var lt=require("fs"),nn=require("path");var sn=require("fs"),Ol=require("path");var ma="remember",Eh=`mcp__${ma}`,Ki=String.raw`
11850
+ `}return null},setupPermissions(i,t,e,s){return qi(t,e)}};function wt(i){let t=(i??"").trim().toLowerCase();return t==="codex"||t==="openai-codex"?"codex":"claude-code"}function Yi(i){return wt(i)==="codex"?fs:Bi}var Ki=new Set(["","default","subscription"]);function Pt(i,t,e){let s=ua(i?.model);if(s)return{value:pa(s),source:"task"};let n=ua(t.model);if(n)return{value:pa(n),source:"agent"};let a=ua(e.defaultModel);return a?{value:pa(a),source:"settings"}:{value:"",source:"cli-default"}}function gs(i){return!Ki.has(i.trim())}function ua(i){if(!i)return"";let t=i.trim();return t||""}function pa(i){return Ki.has(i)?"":i}function tn(i,t){let e=i.wikiReferences;if(!e||e.length===0)return null;let s=[];for(let a of e){let r=t.getAgentByName(a.agent);if(!r||!r.wikiKeeper)continue;let o=r.wikiKeeper,c=o.scopeRoot?`${o.scopeRoot.replace(/\/+$/,"")}/`:"";s.push({agentName:r.name,scopeRoot:o.scopeRoot||"(whole vault)",topicsPath:`${c}${o.topicsRoot}`,inboxPath:`${c}${o.inboxPath}`,indexPath:`${c}${o.indexPath}`})}if(s.length===0)return null;let n=["## Wiki Access"];n.push("You have read access to the following wikis maintained by other agents. Use the `wiki-query` skill in consumer mode when the user asks something a wiki may already cover."),n.push("");for(let a of s)n.push(`### Wiki: \`${a.agentName}\``),n.push(`- scope root: \`${a.scopeRoot}\``),n.push(`- topics: \`${a.topicsPath}/\``),n.push(`- index: \`${a.indexPath}\``),n.push(`- inbox: \`${a.inboxPath}/\``),n.push("");return n.push("### Rules"),n.push("- **Cite every factual claim** from a wiki using `[[<topics-path>/<page>]]`. If a claim has no page, say the wiki doesn't cover it \u2014 do not fabricate."),n.push("- **When the user shares something durable** that isn't yet in a wiki (a decision, a new entity mention, a competitor change, a meeting outcome), write a short markdown file to the relevant wiki's inbox at `<inbox>/YYYY-MM-DD-<slug>.md` with a one-line note + the source. The wiki keeper files it canonically on its next ingest."),n.push("- **Do NOT write to `<topics-path>/` directly.** The wiki keeper is the canonical curator of topic pages. Use the inbox as your deposit point."),n.push("- **When the question spans multiple wikis**, be explicit about which scope each cited page belongs to."),n.join(`
11851
+ `)}var ct=require("fs"),nn=require("path");var sn=require("fs"),Nl=require("path");var ma="remember",Ph=`mcp__${ma}`,Ji=String.raw`
11852
11852
  const fs = require("fs");
11853
11853
  const path = require("path");
11854
11854
  const PENDING_DIR = process.env.AF_PENDING_DIR;
@@ -11940,7 +11940,7 @@ function handle(req) {
11940
11940
  send({ jsonrpc: "2.0", id, error: { code: -32601, message: "method not found: " + method } });
11941
11941
  }
11942
11942
  }
11943
- `;function Ji(i){let t=[];for(let e of i){let s=e.trim();if(s)try{let n=JSON.parse(s),a=typeof n.text=="string"?n.text.trim():"";if(!a)continue;let r=n.section==="Preferences"||n.section==="Procedures"||n.section==="Observations"?n.section:void 0;t.push({text:a,pinned:n.pinned===!0,section:r,source:typeof n.source=="string"?n.source:"mcp"})}catch{}}return t}var Nl=0;function Bl(i,t){return{def:{name:ma,type:"stdio",enabled:!0,command:"node",env:{AF_PENDING_DIR:i,AF_SOURCE:t},status:"connected",scope:"user",tools:[],toolDetails:[]},inlineScript:Ki}}function an(i){let t=i.agentGrants.map(n=>n.trim().toLowerCase()).filter(Boolean),e=t.length>0?new Set(t):null,s=[];for(let n of i.registry){if(!n.enabled||e&&!e.has(n.name.trim().toLowerCase())||n.type==="unknown")continue;let a={};if(n.type==="stdio"){if(n.envSecretKeys&&n.envSecretKeys.length>0){let r={};for(let o of n.envSecretKeys){let c=process.env[o];c&&(r[o]=c)}Object.keys(r).length>0&&(a.env=r)}}else if(n.auth!=="none"){let r=i.getBearerToken(n.name);r&&(a.bearerToken=r)}s.push({def:n,secrets:a})}return i.remember&&s.push(Bl(i.remember.pendingDir,i.remember.source)),s}function Ul(i){return`AF_MCP_${i.toUpperCase().replace(/[^A-Z0-9]+/g,"_").replace(/^_+|_+$/g,"")||"SERVER"}_TOKEN`}function Xi(i){return/^[A-Za-z0-9_-]+$/.test(i)?i:`"${i.replace(/"/g,'\\"')}"`}function $l(i,t){let{def:e,secrets:s}=i;if(e.type==="unknown")throw new Error(`server ${e.name} has unknown transport`);let n=e.type;if(n==="stdio"){let a=e.command??"node",r=t?[t]:e.args??[],o={...e.env??{},...s?.env??{}};return{name:e.name,type:n,command:a,args:r,env:o}}if(!e.url)throw new Error(`server ${e.name} (${n}) has no url`);return{name:e.name,type:n,url:e.url,headers:e.headers,bearerToken:s?.bearerToken,oauthResource:e.oauth?.resource,oauthClientId:e.oauth?.clientId}}function jl(i){if(i.type==="stdio"){let s={command:i.command,args:i.args??[]};return i.env&&Object.keys(i.env).length>0&&(s.env=i.env),s}let t={...i.headers??{}};i.bearerToken&&(t.Authorization=`Bearer ${i.bearerToken}`);let e={type:i.type,url:i.url};return Object.keys(t).length>0&&(e.headers=t),e}function Wl(i){let t=Xi(i.name),e=[],s={};if(i.type==="stdio"){e.push("-c",`mcp_servers.${t}.command=${JSON.stringify(i.command??"node")}`),i.args&&i.args.length>0&&e.push("-c",`mcp_servers.${t}.args=${JSON.stringify(i.args)}`);for(let[n,a]of Object.entries(i.env??{}))e.push("-c",`mcp_servers.${t}.env.${Xi(n)}=${JSON.stringify(a)}`)}else{if(e.push("-c",`mcp_servers.${t}.url=${JSON.stringify(i.url)}`),i.bearerToken){let n=Ul(i.name);s[n]=i.bearerToken,e.push("-c",`mcp_servers.${t}.bearer_token_env_var=${JSON.stringify(n)}`)}i.oauthResource&&e.push("-c",`mcp_servers.${t}.oauth_resource=${JSON.stringify(i.oauthResource)}`),i.oauthClientId&&e.push("-c",`mcp_servers.${t}.oauth.client_id=${JSON.stringify(i.oauthClientId)}`)}return e.push("-c",`mcp_servers.${t}.enabled=true`),{args:e,env:s}}function rn(i,t,e){if(e.length===0)return null;let s=bt(t)==="codex",n=[],a=(0,nn.join)(i,".claude");try{(0,lt.existsSync)(a)||(0,lt.mkdirSync)(a,{recursive:!0});let r=`${process.pid}-${Date.now()}-${Nl++}`,o=[],c=0;for(let h of e){try{let u=null;h.inlineScript&&(u=(0,nn.join)(a,`af-mcp-${Hl(h.def.name)}.${r}-${c}.cjs`),(0,lt.writeFileSync)(u,h.inlineScript,"utf-8"),n.push(u)),o.push($l(h,u))}catch(u){console.warn(`Agent Fleet: skipping MCP server "${h.def.name}" in projection:`,u)}c++}if(o.length===0)return fa(n),null;if(s){let h=[],u={};for(let p of o){let f=Wl(p);h.push(...f.args),Object.assign(u,f.env)}return{args:h,env:u,tempFiles:n}}let l={};for(let h of o)l[h.name]=jl(h);let d=(0,nn.join)(a,`af-mcp.${r}.json`);return(0,lt.writeFileSync)(d,JSON.stringify({mcpServers:l},null,2),"utf-8"),n.push(d),{args:["--mcp-config",d],env:{},tempFiles:n}}catch(r){return console.warn("Agent Fleet: couldn't install MCP projection; run proceeds without fleet MCP.",r),fa(n),null}}function wt(i){i&&fa(i.tempFiles)}function fa(i){for(let t of i)try{(0,lt.existsSync)(t)&&(0,lt.unlinkSync)(t)}catch{}}function Hl(i){return i.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"server"}var on=class{constructor(t,e,s){this.settings=t;this.repository=e;this.mcpAuth=s}runningProcesses=new Map;abortAgent(t){let e=this.runningProcesses.get(t);return e?(e.kill(),this.runningProcesses.delete(t),!0):!1}async buildPrompt(t,e,s,n=t.memory){let a=[t.body.trim()];for(let o of t.skills){let c=this.repository.getSkillByName(o);if(c){let l=[c.body.trim()];c.toolsBody.trim()&&l.push(`### Tools
11943
+ `;function Xi(i){let t=[];for(let e of i){let s=e.trim();if(s)try{let n=JSON.parse(s),a=typeof n.text=="string"?n.text.trim():"";if(!a)continue;let r=n.section==="Preferences"||n.section==="Procedures"||n.section==="Observations"?n.section:void 0;t.push({text:a,pinned:n.pinned===!0,section:r,source:typeof n.source=="string"?n.source:"mcp"})}catch{}}return t}var Bl=0;function Ul(i,t){return{def:{name:ma,type:"stdio",enabled:!0,command:"node",env:{AF_PENDING_DIR:i,AF_SOURCE:t},status:"connected",scope:"user",tools:[],toolDetails:[]},inlineScript:Ji}}function an(i){let t=i.agentGrants.map(n=>n.trim().toLowerCase()).filter(Boolean),e=t.length>0?new Set(t):null,s=[];for(let n of i.registry){if(!n.enabled||e&&!e.has(n.name.trim().toLowerCase())||n.type==="unknown")continue;let a={};if(n.type==="stdio"){if(n.envSecretKeys&&n.envSecretKeys.length>0){let r={};for(let o of n.envSecretKeys){let c=process.env[o];c&&(r[o]=c)}Object.keys(r).length>0&&(a.env=r)}}else if(n.auth!=="none"){let r=i.getBearerToken(n.name);r&&(a.bearerToken=r)}s.push({def:n,secrets:a})}return i.remember&&s.push(Ul(i.remember.pendingDir,i.remember.source)),s}function $l(i){return`AF_MCP_${i.toUpperCase().replace(/[^A-Z0-9]+/g,"_").replace(/^_+|_+$/g,"")||"SERVER"}_TOKEN`}function Qi(i){return/^[A-Za-z0-9_-]+$/.test(i)?i:`"${i.replace(/"/g,'\\"')}"`}function jl(i,t){let{def:e,secrets:s}=i;if(e.type==="unknown")throw new Error(`server ${e.name} has unknown transport`);let n=e.type;if(n==="stdio"){let a=e.command??"node",r=t?[t]:e.args??[],o={...e.env??{},...s?.env??{}};return{name:e.name,type:n,command:a,args:r,env:o}}if(!e.url)throw new Error(`server ${e.name} (${n}) has no url`);return{name:e.name,type:n,url:e.url,headers:e.headers,bearerToken:s?.bearerToken,oauthResource:e.oauth?.resource,oauthClientId:e.oauth?.clientId}}function Wl(i){if(i.type==="stdio"){let s={command:i.command,args:i.args??[]};return i.env&&Object.keys(i.env).length>0&&(s.env=i.env),s}let t={...i.headers??{}};i.bearerToken&&(t.Authorization=`Bearer ${i.bearerToken}`);let e={type:i.type,url:i.url};return Object.keys(t).length>0&&(e.headers=t),e}function Hl(i){let t=Qi(i.name),e=[],s={};if(i.type==="stdio"){e.push("-c",`mcp_servers.${t}.command=${JSON.stringify(i.command??"node")}`),i.args&&i.args.length>0&&e.push("-c",`mcp_servers.${t}.args=${JSON.stringify(i.args)}`);for(let[n,a]of Object.entries(i.env??{}))e.push("-c",`mcp_servers.${t}.env.${Qi(n)}=${JSON.stringify(a)}`)}else{if(e.push("-c",`mcp_servers.${t}.url=${JSON.stringify(i.url)}`),i.bearerToken){let n=$l(i.name);s[n]=i.bearerToken,e.push("-c",`mcp_servers.${t}.bearer_token_env_var=${JSON.stringify(n)}`)}i.oauthResource&&e.push("-c",`mcp_servers.${t}.oauth_resource=${JSON.stringify(i.oauthResource)}`),i.oauthClientId&&e.push("-c",`mcp_servers.${t}.oauth.client_id=${JSON.stringify(i.oauthClientId)}`)}return e.push("-c",`mcp_servers.${t}.enabled=true`),{args:e,env:s}}function rn(i,t,e){if(e.length===0)return null;let s=wt(t)==="codex",n=[],a=(0,nn.join)(i,".claude");try{(0,ct.existsSync)(a)||(0,ct.mkdirSync)(a,{recursive:!0});let r=`${process.pid}-${Date.now()}-${Bl++}`,o=[],c=0;for(let d of e){try{let u=null;d.inlineScript&&(u=(0,nn.join)(a,`af-mcp-${ql(d.def.name)}.${r}-${c}.cjs`),(0,ct.writeFileSync)(u,d.inlineScript,"utf-8"),n.push(u)),o.push(jl(d,u))}catch(u){console.warn(`Agent Fleet: skipping MCP server "${d.def.name}" in projection:`,u)}c++}if(o.length===0)return fa(n),null;if(s){let d=[],u={};for(let p of o){let m=Hl(p);d.push(...m.args),Object.assign(u,m.env)}return{args:d,env:u,tempFiles:n}}let l={};for(let d of o)l[d.name]=Wl(d);let h=(0,nn.join)(a,`af-mcp.${r}.json`);return(0,ct.writeFileSync)(h,JSON.stringify({mcpServers:l},null,2),"utf-8"),n.push(h),{args:["--mcp-config",h],env:{},tempFiles:n}}catch(r){return console.warn("Agent Fleet: couldn't install MCP projection; run proceeds without fleet MCP.",r),fa(n),null}}function bt(i){i&&fa(i.tempFiles)}function fa(i){for(let t of i)try{(0,ct.existsSync)(t)&&(0,ct.unlinkSync)(t)}catch{}}function ql(i){return i.toLowerCase().replace(/[^a-z0-9]+/g,"-").replace(/^-+|-+$/g,"")||"server"}var on=class{constructor(t,e,s){this.settings=t;this.repository=e;this.mcpAuth=s}runningProcesses=new Map;abortAgent(t){let e=this.runningProcesses.get(t);return e?(e.kill(),this.runningProcesses.delete(t),!0):!1}async buildPrompt(t,e,s,n=t.memory){let a=[t.body.trim()];for(let o of t.skills){let c=this.repository.getSkillByName(o);if(c){let l=[c.body.trim()];c.toolsBody.trim()&&l.push(`### Tools
11944
11944
  ${c.toolsBody.trim()}`),c.referencesBody.trim()&&l.push(`### References
11945
11945
  ${c.referencesBody.trim()}`),c.examplesBody.trim()&&l.push(`### Examples
11946
11946
  ${c.examplesBody.trim()}`),a.push(`## Skill: ${c.name}
@@ -11951,22 +11951,22 @@ ${t.skillsBody.trim()}`),t.contextBody.trim()&&a.push(`## Agent Context
11951
11951
  ${t.contextBody.trim()}`),n){let o=await this.repository.readWorkingMemory(t.name),c=Hs(t,o);c&&a.push(c)}let r=tn(t,this.repository);return r&&a.push(r),a.push(`## Task
11952
11952
  ${(s??e.body).trim()}`),a.filter(Boolean).join(`
11953
11953
 
11954
- `)}async execute(t,e,s,n,a){let r=t.memory&&!a?.suppressMemoryCapture,o=await this.buildPrompt(t,e,s,r),c=(0,Qi.randomUUID)(),l=Pt(e,t,this.settings),d=n!=null,h=Vi(t.adapter),u=await h.buildExec({prompt:o,model:gs(l.value)?l.value:"",modelSource:l.source,effort:e.effort||t.effort||"",agent:t,settings:this.settings,streaming:d}),p=t.cwd?.trim()?t.cwd:this.repository.getVaultBasePath()??".",f=r?this.repository.getPendingDirAbsolutePath(t.name):null,m=an({registry:this.repository.getMcpServers(),agentGrants:t.mcpServers??[],getBearerToken:w=>this.mcpAuth?.getToken(w),remember:f?{pendingDir:f,source:"mcp"}:null}),g=rn(p,t.adapter,m);g&&u.args.push(...g.args);let v=await h.setupPermissions(p,t,this.settings,{mcpAllowServers:m.map(w=>w.def.name)}),k=Date.now();try{return await new Promise((w,y)=>{let C=ot(u.cliPath,u.args,{cwd:p,env:{...process.env,AWS_REGION:this.settings.awsRegion,...g?.env??{},...v?.env??{}}});if(u.stdinPayload!==void 0)try{C.stdin?.write(u.stdinPayload),C.stdin?.end()}catch(S){C.kill(),y(S instanceof Error?S:new Error(String(S)));return}this.runningProcesses.set(t.name,C);let T="",_="",O=!1,E=setTimeout(()=>{O=!0,C.kill()},t.timeout*1e3);C.stdout.on("data",S=>{let P=S.toString();if(T+=P,d&&n)for(let R of pe(P)){let N=h.extractStreamChunk(R);N&&n(N)}}),C.stderr.on("data",S=>{_+=S.toString()}),C.on("error",S=>{clearTimeout(E),y(S)}),C.on("close",S=>{clearTimeout(E),this.runningProcesses.delete(t.name);let P=h.parseExecOutput(T,_,d);w({runId:c,prompt:o,exitCode:S,durationSeconds:Math.max(1,Math.round((Date.now()-k)/1e3)),stdout:T,stderr:_,outputText:P.outputText,rawJson:P.rawJson,tokensUsed:P.tokensUsed,costUsd:P.costUsd,toolsUsed:P.toolsUsed,timedOut:O,resolvedModel:l.value,modelSource:l.source,concreteModel:P.concreteModel,finalResult:P.finalResult})})})}finally{v?.restore(),wt(g)}}};function Zi(i){return ae(i).slice(0,60)||"candidate"}function tr(i){let t=Math.max(400,i.tokenBudget*4);return[`You are running a nightly memory **reflection** for the agent "${i.agentName}".`,"Review the raw memory log and your current working memory below, then produce an","updated, consolidated working memory.","","Rules:","- Remove duplicates; resolve contradictions in favor of the NEWEST fact.","- File each fact under exactly one of: Preferences, Procedures, Observations.","- Keep durable user/process preferences, marking them `[pin]` \u2014 never drop or"," summarize pinned Preferences.","- Summarize the Observations section FROM THE RAW LOG (not from prior summaries)",` if needed so the whole memory fits within roughly ${i.tokenBudget} tokens`,` (~${t} characters).`,"- Note any friction that recurred across multiple runs as a skill candidate.","","Reply with EXACTLY these two fenced blocks and nothing else:","","```memory","## Preferences","- [pin] <durable preference> <!-- src:reflection -->","## Procedures","- <how-to learning>","## Observations","- <current fact>","```","","```candidates",'[{"key":"short-stable-key","pattern":"what recurred","evidence":["runs/..."],"suggestedSkill":"optional-name"}]',"```","","If there is nothing worth remembering, still emit a `memory` block preserving the","existing pinned Preferences. Use an empty array `[]` for candidates when none.","","\u2500\u2500 CURRENT WORKING MEMORY \u2500\u2500",i.workingMemoryBody.trim()||"(empty)","","\u2500\u2500 RAW MEMORY LOG (ground truth) \u2500\u2500",i.recentRaw.trim()||"(empty)",i.recentRunsSummary?`
11954
+ `)}async execute(t,e,s,n,a){let r=t.memory&&!a?.suppressMemoryCapture,o=await this.buildPrompt(t,e,s,r),c=(0,Zi.randomUUID)(),l=Pt(e,t,this.settings),h=n!=null,d=Yi(t.adapter),u=await d.buildExec({prompt:o,model:gs(l.value)?l.value:"",modelSource:l.source,effort:e.effort||t.effort||"",agent:t,settings:this.settings,streaming:h}),p=t.cwd?.trim()?t.cwd:this.repository.getVaultBasePath()??".",m=r?this.repository.getPendingDirAbsolutePath(t.name):null,f=an({registry:this.repository.getMcpServers(),agentGrants:t.mcpServers??[],getBearerToken:k=>this.mcpAuth?.getToken(k),remember:m?{pendingDir:m,source:"mcp"}:null}),g=rn(p,t.adapter,f);g&&u.args.push(...g.args);let v=await d.setupPermissions(p,t,this.settings,{mcpAllowServers:f.map(k=>k.def.name)}),b=Date.now();try{return await new Promise((k,y)=>{let S=lt(u.cliPath,u.args,{cwd:p,env:{...process.env,AWS_REGION:this.settings.awsRegion,...g?.env??{},...v?.env??{}}});if(u.stdinPayload!==void 0)try{S.stdin?.write(u.stdinPayload),S.stdin?.end()}catch(C){S.kill(),y(C instanceof Error?C:new Error(String(C)));return}this.runningProcesses.set(t.name,S);let T="",_="",D=!1,M=window.setTimeout(()=>{D=!0,S.kill()},t.timeout*1e3);S.stdout.on("data",C=>{let I=C.toString();if(T+=I,h&&n)for(let P of ge(I)){let L=d.extractStreamChunk(P);L&&n(L)}}),S.stderr.on("data",C=>{_+=C.toString()}),S.on("error",C=>{window.clearTimeout(M),y(C)}),S.on("close",C=>{window.clearTimeout(M),this.runningProcesses.delete(t.name);let I=d.parseExecOutput(T,_,h);k({runId:c,prompt:o,exitCode:C,durationSeconds:Math.max(1,Math.round((Date.now()-b)/1e3)),stdout:T,stderr:_,outputText:I.outputText,rawJson:I.rawJson,tokensUsed:I.tokensUsed,costUsd:I.costUsd,toolsUsed:I.toolsUsed,timedOut:D,resolvedModel:l.value,modelSource:l.source,concreteModel:I.concreteModel,finalResult:I.finalResult})})})}finally{v?.restore(),bt(g)}}};function er(i){return oe(i).slice(0,60)||"candidate"}function sr(i){let t=Math.max(400,i.tokenBudget*4);return[`You are running a nightly memory **reflection** for the agent "${i.agentName}".`,"Review the raw memory log and your current working memory below, then produce an","updated, consolidated working memory.","","Rules:","- Remove duplicates; resolve contradictions in favor of the NEWEST fact.","- File each fact under exactly one of: Preferences, Procedures, Observations.","- Keep durable user/process preferences, marking them `[pin]` \u2014 never drop or"," summarize pinned Preferences.","- Summarize the Observations section FROM THE RAW LOG (not from prior summaries)",` if needed so the whole memory fits within roughly ${i.tokenBudget} tokens`,` (~${t} characters).`,"- Note any friction that recurred across multiple runs as a skill candidate.","","Reply with EXACTLY these two fenced blocks and nothing else:","","```memory","## Preferences","- [pin] <durable preference> <!-- src:reflection -->","## Procedures","- <how-to learning>","## Observations","- <current fact>","```","","```candidates",'[{"key":"short-stable-key","pattern":"what recurred","evidence":["runs/..."],"suggestedSkill":"optional-name"}]',"```","","If there is nothing worth remembering, still emit a `memory` block preserving the","existing pinned Preferences. Use an empty array `[]` for candidates when none.","","\u2500\u2500 CURRENT WORKING MEMORY \u2500\u2500",i.workingMemoryBody.trim()||"(empty)","","\u2500\u2500 RAW MEMORY LOG (ground truth) \u2500\u2500",i.recentRaw.trim()||"(empty)",i.recentRunsSummary?`
11955
11955
  \u2500\u2500 RECENT ACTIVITY \u2500\u2500
11956
11956
  ${i.recentRunsSummary.trim()}`:""].join(`
11957
- `)}function er(i,t){let e=new RegExp("```"+t+"(?![A-Za-z0-9-])[^\\n]*\\n([\\s\\S]*?)```","i"),s=i.match(e);return s?s[1]??"":null}function sr(i){let t=er(i,"memory"),e=t!==null?Ws(t):null,s=[],n=er(i,"candidates");if(n!==null&&n.trim())try{let a=JSON.parse(n.trim());Array.isArray(a)&&(s=a.map(r=>ql(r)).filter(r=>r!==null))}catch{}return{sections:e,candidates:s}}function ql(i){if(typeof i!="object"||i===null)return null;let t=i,e=typeof t.pattern=="string"?t.pattern.trim():"";return e?{key:typeof t.key=="string"&&t.key.trim()?Zi(t.key):Zi(e),pattern:e,evidence:Array.isArray(t.evidence)?t.evidence.filter(n=>typeof n=="string"):[],suggestedSkill:typeof t.suggestedSkill=="string"?t.suggestedSkill:void 0}:null}function nr(i,t,e){let s=new Map;for(let a of i)s.set(a.key,{...a,evidence:[...a.evidence]});let n=new Map;for(let a of t){let r=n.get(a.key);r?(r.evidence=Array.from(new Set([...r.evidence??[],...a.evidence??[]])),a.suggestedSkill&&(r.suggestedSkill=a.suggestedSkill)):n.set(a.key,{...a,evidence:[...a.evidence??[]]})}for(let a of n.values()){let r=s.get(a.key);r?(r.occurrences+=1,r.lastSeen=e,r.evidence=Array.from(new Set([...r.evidence,...a.evidence??[]])),a.suggestedSkill&&(r.suggestedSkill=a.suggestedSkill)):s.set(a.key,{key:a.key,pattern:a.pattern,occurrences:1,firstSeen:e,lastSeen:e,evidence:[...a.evidence??[]],proposed:!1,suggestedSkill:a.suggestedSkill})}return[...s.values()]}var zl=1.5,Wt=class i{constructor(t){this.store=t}static locks=new Map;static __resetLocksForTest(){i.locks.clear()}async capture(t,e,s,n){!t.memory||e.length===0||await this.withLock(t.name,()=>this.applyCaptures(t,e,s,n))}async drainPending(t,e){t.memory&&await this.withLock(t.name,async()=>{let s=await this.store.readAndClearPending(t.name),n=Ji(s);if(n.length===0)return;let a=[];for(let r of n){let o=a[a.length-1],c={text:r.text,pinned:r.pinned,section:r.section};o&&o.source===r.source?o.entries.push(c):a.push({source:r.source,entries:[c]})}for(let r of a)await this.applyCaptures(t,r.entries,r.source,e)})}async reflect(t,e,s){return!t.memory||e===null||!e.some(n=>n.entries.length>0)?!1:(await this.withLock(t.name,async()=>{let n=this.store.getWorkingMemoryPath(t.name),a=await this.store.readWorkingMemory(t.name),r=li(a,e),o={filePath:a?.filePath??n,agent:t.name,schema:a?.schema??2,lastUpdated:s,lastReflection:s,tokenEstimate:0,sections:r};await this.store.writeWorkingMemory(t.name,o)}),!0)}async applyCaptures(t,e,s,n){let a=e.map(p=>({...p,text:ti(p.text)})).filter(p=>p.text);if(a.length===0)return;await this.store.migrateLegacyMemory?.(t.name);let r=this.store.getWorkingMemoryPath(t.name),o=await this.store.readWorkingMemory(t.name)??si(r,t.name),c=n.slice(0,10),l=a.map(p=>`- ${n} [${s}]${p.pinned?" [pin]":""} ${p.text}`);await this.store.appendRawMemory(t.name,l,n);let d=new Set(o.sections.flatMap(p=>p.entries).map(p=>p.text.trim().toLowerCase())),h=o;for(let p of a){let f=p.text.trim().toLowerCase();if(d.has(f))continue;d.add(f);let m={text:p.text,source:s,date:c,pinned:p.pinned??!1},g=p.section??(p.pinned?"Preferences":Za);h=ri(h,[m],g,n)}let u=Math.ceil((t.memoryTokenBudget||0)*zl);if(u>0){let{wm:p,spilled:f}=oi(h,u);f.length>0&&console.info(`Agent Fleet: working memory for "${t.name}" exceeded hard cap; spilled ${f.length} entr${f.length===1?"y":"ies"} to raw-only (still in the archive). A reflection pass will consolidate.`),h=p}await this.store.writeWorkingMemory(t.name,h)}withLock(t,e){let n=(i.locks.get(t)??Promise.resolve()).then(e,e);return i.locks.set(t,n.then(()=>{},()=>{})),n}};var ys=ze(require("crypto")),ar=ze(require("https")),ln=ze(require("http")),ir=ze(require("fs")),ga=ze(require("path"));var cn=class{constructor(t){this.settings=t;this.settings}authManager;setAuthManager(t){this.authManager=t}async probeServer(t){try{if(t.type==="stdio"&&t.command)return(await this.probeStdioServer(t.command,t.args)).tools;if((t.type==="http"||t.type==="sse")&&t.url)return await this.probeHttpServer(t)}catch(e){console.warn(`McpManager: probe failed for ${t.name}:`,e)}return[]}async authenticateServer(t,e,s="http"){let n=await this.discoverOAuthMetadata(e);if(!n)throw new Error("Server does not support OAuth \u2014 no authorization metadata found.");let{metadata:a,resourceScopes:r,resource:o}=n;if(!a.registration_endpoint)throw new Error("Server does not support Dynamic Client Registration.");let c=await this.startOAuthCallbackServer(),l=`http://localhost:${c.port}/callback`;try{let d=await this.registerOAuthClient(a.registration_endpoint,l),h=ys.randomBytes(32).toString("base64url"),u=ys.createHash("sha256").update(h).digest("base64url"),p=ys.randomBytes(16).toString("hex"),f=new URLSearchParams({response_type:"code",client_id:d,code_challenge:u,code_challenge_method:"S256",redirect_uri:l,state:p,resource:o}),m=r??a.scopes_supported;m?.length&&f.set("scope",m.join(" "));let g=new URL(a.authorization_endpoint);for(let[y,C]of f)g.searchParams.set(y,C);let v=g.toString();console.log("McpManager: OAuth DCR client_id:",d),ui(v);let k=await c.waitForCode(p,18e4),w=await this.exchangeOAuthCode(a.token_endpoint,k,l,d,h);this.authManager?.storeOAuthToken(t,{accessToken:w.access_token,refreshToken:w.refresh_token,expiresAt:w.expires_in?Date.now()+w.expires_in*1e3:void 0,tokenEndpoint:a.token_endpoint,clientId:d,resource:o})}finally{c.close()}}async refreshProbeTokens(){if(!this.authManager)return;let t=this.authManager.getExpiringTokens();for(let[e,s]of t)if(s.refreshToken)try{let n=new URLSearchParams({grant_type:"refresh_token",refresh_token:s.refreshToken,client_id:s.clientId}).toString(),a=await this.oauthFetch(s.tokenEndpoint,"POST",n,"application/x-www-form-urlencoded");if(a.status===200){let r=JSON.parse(a.body),o=r.access_token;o&&this.authManager.storeOAuthToken(e,{accessToken:o,refreshToken:r.refresh_token??s.refreshToken,expiresAt:typeof r.expires_in=="number"?Date.now()+r.expires_in*1e3:void 0,tokenEndpoint:s.tokenEndpoint,clientId:s.clientId,resource:s.resource})}}catch(n){console.warn(`McpManager: failed to refresh token for ${e}:`,n)}}async discoverOAuthMetadata(t){let e=t.endsWith("/sse")?t.replace(/\/sse$/,"/mcp"):t,s=new URL(e),n;try{let h=await this.oauthFetch(e,"POST","{}","application/json");h.status===401&&(n=h.headers?.["www-authenticate"]?.match(/resource_metadata="([^"]+)"/)?.[1])}catch{}n||(n=`${s.origin}/.well-known/oauth-protected-resource${s.pathname}`);let a=s.origin,r,o=e;try{let h=await this.oauthFetch(n,"GET");if(h.status===200){let u=JSON.parse(h.body),p=u.authorization_servers;p?.[0]&&(a=p[0]),Array.isArray(u.scopes_supported)&&(r=u.scopes_supported),typeof u.resource=="string"&&(o=u.resource)}}catch{}let c=new URL(a),l=c.pathname==="/"?"":c.pathname,d=`${c.origin}/.well-known/oauth-authorization-server${l}`;try{let h=await this.oauthFetch(d,"GET");if(h.status===200)return{metadata:JSON.parse(h.body),resourceScopes:r,resource:o}}catch{}if(l){let h=`${c.origin}/.well-known/oauth-authorization-server`;try{let u=await this.oauthFetch(h,"GET");if(u.status===200)return{metadata:JSON.parse(u.body),resourceScopes:r,resource:o}}catch{}}return null}async registerOAuthClient(t,e){let s=JSON.stringify({client_name:"Agent Fleet Obsidian Plugin",redirect_uris:[e],grant_types:["authorization_code","refresh_token"],response_types:["code"],token_endpoint_auth_method:"none"}),n=await this.oauthFetch(t,"POST",s,"application/json");if(n.status!==200&&n.status!==201)throw new Error(`Client registration failed (HTTP ${n.status})`);let a=JSON.parse(n.body);if(!a.client_id)throw new Error("Client registration response missing client_id");return a.client_id}async startOAuthCallbackServer(){let t=null,e=null,s=ln.createServer((a,r)=>{let o=new URL(a.url??"/","http://localhost");if(o.pathname!=="/callback"){r.writeHead(404),r.end();return}let c=o.searchParams.get("error");if(c){let h=o.searchParams.get("error_description")??c;r.writeHead(200,{"Content-Type":"text/html"}),r.end("<html><body style='font-family:system-ui;text-align:center;padding:60px'><h2>Authorization Failed</h2><p>"+h+"</p><p style='color:#888'>You can close this tab.</p></body></html>"),e?.(new Error(`OAuth denied: ${h}`));return}let l=o.searchParams.get("code"),d=o.searchParams.get("state");if(!l||!d){r.writeHead(400),r.end("Missing code or state");return}r.writeHead(200,{"Content-Type":"text/html"}),r.end("<html><body style='font-family:system-ui;text-align:center;padding:60px'><h2 style='color:#22c55e'>Authenticated!</h2><p>You can close this tab and return to Obsidian.</p><script>setTimeout(()=>window.close(),2000)</script></body></html>"),t?.(l,d)});return{port:await new Promise((a,r)=>{s.listen(0,"127.0.0.1",()=>{let o=s.address();if(!o||typeof o=="string"){r(new Error("Failed to bind callback server"));return}a(o.port)}),s.on("error",r)}),waitForCode:(a,r)=>new Promise((o,c)=>{let l=setTimeout(()=>{c(new Error("Authentication timed out \u2014 complete authorization in your browser and try again."))},r);t=(d,h)=>{clearTimeout(l),h!==a?c(new Error("OAuth state mismatch \u2014 possible CSRF attack")):o(d)},e=d=>{clearTimeout(l),c(d)}}),close:()=>{try{s.close()}catch{}}}}async exchangeOAuthCode(t,e,s,n,a){let r=new URLSearchParams({grant_type:"authorization_code",code:e,redirect_uri:s,client_id:n,code_verifier:a}).toString(),o=await this.oauthFetch(t,"POST",r,"application/x-www-form-urlencoded");if(o.status!==200)throw new Error(`Token exchange failed (HTTP ${o.status}): ${o.body}`);let c=JSON.parse(o.body);if(!c.access_token)throw new Error("Token response missing access_token");return c}oauthFetch(t,e,s,n){return new Promise((a,r)=>{let o=new URL(t),c=o.protocol==="https:",l={Accept:"application/json"};s&&(l["Content-Type"]=n??"application/json",l["Content-Length"]=String(Buffer.byteLength(s)));let d={hostname:o.hostname,port:o.port||(c?443:80),path:o.pathname+o.search,method:e,headers:l},u=(c?ar:ln).request(d,f=>{let m="";f.on("data",g=>{m+=g.toString()}),f.on("end",()=>{let g={};for(let[v,k]of Object.entries(f.headers))typeof k=="string"?g[v]=k:Array.isArray(k)&&(g[v]=k.join(", "));a({status:f.statusCode??0,body:m,headers:g})})});u.on("error",r);let p=setTimeout(()=>{u.destroy(),r(new Error("OAuth request timed out"))},15e3);u.on("close",()=>clearTimeout(p)),s&&u.write(s),u.end()})}probeStdioServer(t,e){return new Promise(s=>{let n=e&&e.length>0?`${t} ${e.join(" ")}`:t,a=hi(n,{env:{...process.env}}),r="",o,c=[],l=!1,d=!1,h=!1,u=()=>{l||(l=!0,a.kill(),s({description:o,tools:c}))},p=setTimeout(u,1e4);a.stdout.on("data",f=>{r+=f.toString();let m=pe(r);r=m.pop()??"";for(let g of m){let v=g.trim();if(v){try{let k=JSON.parse(v);if(k.id===1&&k.result){o=k.result.instructions??k.result.serverInfo?.description,d=!0;try{a.stdin.write(JSON.stringify({jsonrpc:"2.0",method:"notifications/initialized"})+`
11957
+ `)}function tr(i,t){let e=new RegExp("```"+t+"(?![A-Za-z0-9-])[^\\n]*\\n([\\s\\S]*?)```","i"),s=i.match(e);return s?s[1]??"":null}function nr(i){let t=tr(i,"memory"),e=t!==null?Ws(t):null,s=[],n=tr(i,"candidates");if(n!==null&&n.trim())try{let a=JSON.parse(n.trim());Array.isArray(a)&&(s=a.map(r=>zl(r)).filter(r=>r!==null))}catch{}return{sections:e,candidates:s}}function zl(i){if(typeof i!="object"||i===null)return null;let t=i,e=typeof t.pattern=="string"?t.pattern.trim():"";return e?{key:typeof t.key=="string"&&t.key.trim()?er(t.key):er(e),pattern:e,evidence:Array.isArray(t.evidence)?t.evidence.filter(n=>typeof n=="string"):[],suggestedSkill:typeof t.suggestedSkill=="string"?t.suggestedSkill:void 0}:null}function ar(i,t,e){let s=new Map;for(let a of i)s.set(a.key,{...a,evidence:[...a.evidence]});let n=new Map;for(let a of t){let r=n.get(a.key);r?(r.evidence=Array.from(new Set([...r.evidence??[],...a.evidence??[]])),a.suggestedSkill&&(r.suggestedSkill=a.suggestedSkill)):n.set(a.key,{...a,evidence:[...a.evidence??[]]})}for(let a of n.values()){let r=s.get(a.key);r?(r.occurrences+=1,r.lastSeen=e,r.evidence=Array.from(new Set([...r.evidence,...a.evidence??[]])),a.suggestedSkill&&(r.suggestedSkill=a.suggestedSkill)):s.set(a.key,{key:a.key,pattern:a.pattern,occurrences:1,firstSeen:e,lastSeen:e,evidence:[...a.evidence??[]],proposed:!1,suggestedSkill:a.suggestedSkill})}return[...s.values()]}var Gl=1.5,Ht=class i{constructor(t){this.store=t}static locks=new Map;static __resetLocksForTest(){i.locks.clear()}async capture(t,e,s,n){!t.memory||e.length===0||await this.withLock(t.name,()=>this.applyCaptures(t,e,s,n))}async drainPending(t,e){t.memory&&await this.withLock(t.name,async()=>{let s=await this.store.readAndClearPending(t.name),n=Xi(s);if(n.length===0)return;let a=[];for(let r of n){let o=a[a.length-1],c={text:r.text,pinned:r.pinned,section:r.section};o&&o.source===r.source?o.entries.push(c):a.push({source:r.source,entries:[c]})}for(let r of a)await this.applyCaptures(t,r.entries,r.source,e)})}async reflect(t,e,s){return!t.memory||e===null||!e.some(n=>n.entries.length>0)?!1:(await this.withLock(t.name,async()=>{let n=this.store.getWorkingMemoryPath(t.name),a=await this.store.readWorkingMemory(t.name),r=ci(a,e),o={filePath:a?.filePath??n,agent:t.name,schema:a?.schema??2,lastUpdated:s,lastReflection:s,tokenEstimate:0,sections:r};await this.store.writeWorkingMemory(t.name,o)}),!0)}async applyCaptures(t,e,s,n){let a=e.map(p=>({...p,text:si(p.text)})).filter(p=>p.text);if(a.length===0)return;await this.store.migrateLegacyMemory?.(t.name);let r=this.store.getWorkingMemoryPath(t.name),o=await this.store.readWorkingMemory(t.name)??ni(r,t.name),c=n.slice(0,10),l=a.map(p=>`- ${n} [${s}]${p.pinned?" [pin]":""} ${p.text}`);await this.store.appendRawMemory(t.name,l,n);let h=new Set(o.sections.flatMap(p=>p.entries).map(p=>p.text.trim().toLowerCase())),d=o;for(let p of a){let m=p.text.trim().toLowerCase();if(h.has(m))continue;h.add(m);let f={text:p.text,source:s,date:c,pinned:p.pinned??!1},g=p.section??(p.pinned?"Preferences":ei);d=oi(d,[f],g,n)}let u=Math.ceil((t.memoryTokenBudget||0)*Gl);if(u>0){let{wm:p,spilled:m}=li(d,u);m.length>0&&console.info(`Agent Fleet: working memory for "${t.name}" exceeded hard cap; spilled ${m.length} entr${m.length===1?"y":"ies"} to raw-only (still in the archive). A reflection pass will consolidate.`),d=p}await this.store.writeWorkingMemory(t.name,d)}withLock(t,e){let n=(i.locks.get(t)??Promise.resolve()).then(e,e);return i.locks.set(t,n.then(()=>{},()=>{})),n}};var ys=ze(require("crypto")),ir=ze(require("https")),ln=ze(require("http")),rr=ze(require("fs")),ga=ze(require("path"));var cn=class{constructor(t){this.settings=t;this.settings}authManager;setAuthManager(t){this.authManager=t}async probeServer(t){try{if(t.type==="stdio"&&t.command)return(await this.probeStdioServer(t.command,t.args)).tools;if((t.type==="http"||t.type==="sse")&&t.url)return await this.probeHttpServer(t)}catch(e){console.warn(`McpManager: probe failed for ${t.name}:`,e)}return[]}async authenticateServer(t,e,s="http"){let n=await this.discoverOAuthMetadata(e);if(!n)throw new Error("Server does not support OAuth \u2014 no authorization metadata found.");let{metadata:a,resourceScopes:r,resource:o}=n;if(!a.registration_endpoint)throw new Error("Server does not support Dynamic Client Registration.");let c=await this.startOAuthCallbackServer(),l=`http://localhost:${c.port}/callback`;try{let h=await this.registerOAuthClient(a.registration_endpoint,l),d=ys.randomBytes(32).toString("base64url"),u=ys.createHash("sha256").update(d).digest("base64url"),p=ys.randomBytes(16).toString("hex"),m=new URLSearchParams({response_type:"code",client_id:h,code_challenge:u,code_challenge_method:"S256",redirect_uri:l,state:p,resource:o}),f=r??a.scopes_supported;f?.length&&m.set("scope",f.join(" "));let g=new URL(a.authorization_endpoint);for(let[y,S]of m)g.searchParams.set(y,S);let v=g.toString();pi(v);let b=await c.waitForCode(p,18e4),k=await this.exchangeOAuthCode(a.token_endpoint,b,l,h,d);this.authManager?.storeOAuthToken(t,{accessToken:k.access_token,refreshToken:k.refresh_token,expiresAt:k.expires_in?Date.now()+k.expires_in*1e3:void 0,tokenEndpoint:a.token_endpoint,clientId:h,resource:o})}finally{c.close()}}async refreshProbeTokens(){if(!this.authManager)return;let t=this.authManager.getExpiringTokens();for(let[e,s]of t)if(s.refreshToken)try{let n=new URLSearchParams({grant_type:"refresh_token",refresh_token:s.refreshToken,client_id:s.clientId}).toString(),a=await this.oauthFetch(s.tokenEndpoint,"POST",n,"application/x-www-form-urlencoded");if(a.status===200){let r=JSON.parse(a.body),o=r.access_token;o&&this.authManager.storeOAuthToken(e,{accessToken:o,refreshToken:r.refresh_token??s.refreshToken,expiresAt:typeof r.expires_in=="number"?Date.now()+r.expires_in*1e3:void 0,tokenEndpoint:s.tokenEndpoint,clientId:s.clientId,resource:s.resource})}}catch(n){console.warn(`McpManager: failed to refresh token for ${e}:`,n)}}async discoverOAuthMetadata(t){let e=t.endsWith("/sse")?t.replace(/\/sse$/,"/mcp"):t,s=new URL(e),n;try{let d=await this.oauthFetch(e,"POST","{}","application/json");d.status===401&&(n=d.headers?.["www-authenticate"]?.match(/resource_metadata="([^"]+)"/)?.[1])}catch{}n||(n=`${s.origin}/.well-known/oauth-protected-resource${s.pathname}`);let a=s.origin,r,o=e;try{let d=await this.oauthFetch(n,"GET");if(d.status===200){let u=JSON.parse(d.body),p=u.authorization_servers;p?.[0]&&(a=p[0]),Array.isArray(u.scopes_supported)&&(r=u.scopes_supported),typeof u.resource=="string"&&(o=u.resource)}}catch{}let c=new URL(a),l=c.pathname==="/"?"":c.pathname,h=`${c.origin}/.well-known/oauth-authorization-server${l}`;try{let d=await this.oauthFetch(h,"GET");if(d.status===200)return{metadata:JSON.parse(d.body),resourceScopes:r,resource:o}}catch{}if(l){let d=`${c.origin}/.well-known/oauth-authorization-server`;try{let u=await this.oauthFetch(d,"GET");if(u.status===200)return{metadata:JSON.parse(u.body),resourceScopes:r,resource:o}}catch{}}return null}async registerOAuthClient(t,e){let s=JSON.stringify({client_name:"Agent Fleet Obsidian Plugin",redirect_uris:[e],grant_types:["authorization_code","refresh_token"],response_types:["code"],token_endpoint_auth_method:"none"}),n=await this.oauthFetch(t,"POST",s,"application/json");if(n.status!==200&&n.status!==201)throw new Error(`Client registration failed (HTTP ${n.status})`);let a=JSON.parse(n.body);if(!a.client_id)throw new Error("Client registration response missing client_id");return a.client_id}async startOAuthCallbackServer(){let t=null,e=null,s=ln.createServer((a,r)=>{let o=new URL(a.url??"/","http://localhost");if(o.pathname!=="/callback"){r.writeHead(404),r.end();return}let c=o.searchParams.get("error");if(c){let d=o.searchParams.get("error_description")??c;r.writeHead(200,{"Content-Type":"text/html"}),r.end("<html><body style='font-family:system-ui;text-align:center;padding:60px'><h2>Authorization Failed</h2><p>"+d+"</p><p style='color:#888'>You can close this tab.</p></body></html>"),e?.(new Error(`OAuth denied: ${d}`));return}let l=o.searchParams.get("code"),h=o.searchParams.get("state");if(!l||!h){r.writeHead(400),r.end("Missing code or state");return}r.writeHead(200,{"Content-Type":"text/html"}),r.end("<html><body style='font-family:system-ui;text-align:center;padding:60px'><h2 style='color:#22c55e'>Authenticated!</h2><p>You can close this tab and return to Obsidian.</p><script>window.setTimeout(()=>window.close(),2000)</script></body></html>"),t?.(l,h)});return{port:await new Promise((a,r)=>{s.listen(0,"127.0.0.1",()=>{let o=s.address();if(!o||typeof o=="string"){r(new Error("Failed to bind callback server"));return}a(o.port)}),s.on("error",r)}),waitForCode:(a,r)=>new Promise((o,c)=>{let l=window.setTimeout(()=>{c(new Error("Authentication timed out \u2014 complete authorization in your browser and try again."))},r);t=(h,d)=>{window.clearTimeout(l),d!==a?c(new Error("OAuth state mismatch \u2014 possible CSRF attack")):o(h)},e=h=>{window.clearTimeout(l),c(h)}}),close:()=>{try{s.close()}catch{}}}}async exchangeOAuthCode(t,e,s,n,a){let r=new URLSearchParams({grant_type:"authorization_code",code:e,redirect_uri:s,client_id:n,code_verifier:a}).toString(),o=await this.oauthFetch(t,"POST",r,"application/x-www-form-urlencoded");if(o.status!==200)throw new Error(`Token exchange failed (HTTP ${o.status}): ${o.body}`);let c=JSON.parse(o.body);if(!c.access_token)throw new Error("Token response missing access_token");return c}oauthFetch(t,e,s,n){return new Promise((a,r)=>{let o=new URL(t),c=o.protocol==="https:",l={Accept:"application/json"};s&&(l["Content-Type"]=n??"application/json",l["Content-Length"]=String(Buffer.byteLength(s)));let h={hostname:o.hostname,port:o.port||(c?443:80),path:o.pathname+o.search,method:e,headers:l},u=(c?ir:ln).request(h,m=>{let f="";m.on("data",g=>{f+=g.toString()}),m.on("end",()=>{let g={};for(let[v,b]of Object.entries(m.headers))typeof b=="string"?g[v]=b:Array.isArray(b)&&(g[v]=b.join(", "));a({status:m.statusCode??0,body:f,headers:g})})});u.on("error",r);let p=window.setTimeout(()=>{u.destroy(),r(new Error("OAuth request timed out"))},15e3);u.on("close",()=>window.clearTimeout(p)),s&&u.write(s),u.end()})}probeStdioServer(t,e){return new Promise(s=>{let n=e&&e.length>0?`${t} ${e.join(" ")}`:t,a=ui(n,{env:{...process.env}}),r="",o,c=[],l=!1,h=!1,d=!1,u=()=>{l||(l=!0,a.kill(),s({description:o,tools:c}))},p=window.setTimeout(u,1e4);a.stdout.on("data",m=>{r+=m.toString();let f=ge(r);r=f.pop()??"";for(let g of f){let v=g.trim();if(v){try{let b=JSON.parse(v);if(b.id===1&&b.result){o=b.result.instructions??b.result.serverInfo?.description,h=!0;try{a.stdin.write(JSON.stringify({jsonrpc:"2.0",method:"notifications/initialized"})+`
11958
11958
  `),a.stdin.write(JSON.stringify({jsonrpc:"2.0",id:2,method:"tools/list"})+`
11959
- `)}catch{clearTimeout(p),u();return}}else if(k.id===2&&k.result){for(let w of k.result.tools??[])c.push({name:w.name,description:w.description,inputSchema:w.inputSchema});h=!0}}catch{}d&&h&&(clearTimeout(p),u())}}}),a.on("error",()=>{clearTimeout(p),u()}),a.on("close",()=>{clearTimeout(p),u()});try{a.stdin.write(JSON.stringify({jsonrpc:"2.0",id:1,method:"initialize",params:{protocolVersion:"2024-11-05",capabilities:{},clientInfo:{name:"agent-fleet",version:"1.0.0"}}})+`
11960
- `)}catch{clearTimeout(p),u()}})}async probeHttpServer(t){let e=await this.findServerToken(t);if(!e)return console.log(`McpManager: no auth token for ${t.name}, skipping tool probe`),[];let s=t.url.endsWith("/sse")?t.url.replace(/\/sse$/,"/mcp"):t.url;try{let a=(await this.httpRequest(s,e,{jsonrpc:"2.0",id:1,method:"initialize",params:{protocolVersion:"2025-03-26",capabilities:{},clientInfo:{name:"agent-fleet",version:"1.0.0"}}}))?._sessionId;await this.httpRequest(s,e,{jsonrpc:"2.0",method:"notifications/initialized"},a);let r=await this.httpRequest(s,e,{jsonrpc:"2.0",id:2,method:"tools/list"},a),o=[],d=r?.result?.tools??[];for(let h of d)o.push({name:h.name,description:h.description,inputSchema:h.inputSchema});return o}catch(n){return console.warn(`McpManager: HTTP probe failed for ${t.name}:`,n),[]}}async findServerToken(t){if(this.authManager){let a=this.authManager.getToken(t.name);if(a)return a}let e=t.name.replace(/^claude\.ai\s+/i,"").replace(/\s+/g,"_").toUpperCase(),s=[`${e}_API_KEY`,`${e}_API_KEY_MILO`,`${e}_TOKEN`];for(let a of s){let r=process.env[a];if(r)return r}let n=[ga.join(Yn(),".openclaw","workspace",".env"),ga.join(Yn(),".env")];for(let a of n)try{let r=ir.readFileSync(a,"utf8");for(let o of pe(r)){let c=o.trim().match(/^(?:export\s+)?([A-Za-z_]\w*)=(.*)$/);if(c){let l=c[1],d=c[2].replace(/^["']|["']$/g,"");if(s.includes(l))return d}}}catch{}}httpRequest(t,e,s,n){return new Promise((a,r)=>{let o=JSON.stringify(s),c=new URL(t),l=c.protocol==="https:",d={"Content-Type":"application/json",Accept:"application/json, text/event-stream",Authorization:`Bearer ${e}`,"Content-Length":String(Buffer.byteLength(o))};n&&(d["mcp-session-id"]=n);let h={hostname:c.hostname,port:c.port||(l?443:80),path:c.pathname+c.search,method:"POST",headers:d},p=(l?ar:ln).request(h,m=>{let g="";m.on("data",v=>{g+=v.toString()}),m.on("end",()=>{let v=m.headers["mcp-session-id"];if((m.headers["content-type"]??"").includes("text/event-stream")){for(let w of pe(g))if(w.startsWith("data: "))try{let y=JSON.parse(w.slice(6));v&&(y._sessionId=v),a(y);return}catch{}a(null)}else try{let w=JSON.parse(g);v&&(w._sessionId=v),a(w)}catch{a(null)}})});p.on("error",r);let f=setTimeout(()=>{p.destroy(),a(null)},15e3);p.on("close",()=>clearTimeout(f)),p.write(o),p.end()})}};var Gl={"every 5m":"*/5 * * * *","every 10m":"*/10 * * * *","every 15m":"*/15 * * * *","every 30m":"*/30 * * * *","every 1h":"0 * * * *","every 2h":"0 */2 * * *",hourly:"0 * * * *","daily at 9am":"0 9 * * *","daily at 6pm":"0 18 * * *","weekdays at 9am":"0 9 * * 1-5","weekly on monday":"0 9 * * 1","monthly on 1st":"0 9 1 * *"},dn=class{constructor(t,e){this.maxConcurrentRuns=t;this.callbacks=e}jobs=new Map;activeRuns=0;queue=[];paused=!1;setMaxConcurrentRuns(t){this.maxConcurrentRuns=t}parseSchedule(t){return Gl[t.toLowerCase()]??t}toLocalISOString(t){let e=s=>String(s).padStart(2,"0");return`${t.getFullYear()}-${e(t.getMonth()+1)}-${e(t.getDate())}T${e(t.getHours())}:${e(t.getMinutes())}:${e(t.getSeconds())}`}async registerTask(t){if(this.unregisterTask(t.taskId),!(!t.enabled||t.type==="immediate"))try{if(t.type==="once"&&t.runAt){let e=new ce(new Date(t.runAt),{name:t.taskId,catch:!0},()=>{this.enqueue({task:t,reason:"scheduled"})});this.jobs.set(t.taskId,e),await this.callbacks.onTaskScheduled(t,t.runAt);return}if(t.type==="recurring"&&t.schedule){let e=this.parseSchedule(t.schedule),s=new ce(e,{name:t.taskId,catch:!0,protect:!0,timezone:Intl.DateTimeFormat().resolvedOptions().timeZone},()=>{this.enqueue({task:t,reason:"scheduled"})});this.jobs.set(t.taskId,s);let n=s.nextRun();await this.callbacks.onTaskScheduled(t,n?this.toLocalISOString(n):void 0)}}catch(e){console.error(`Agent Fleet: Failed to register task "${t.taskId}":`,e)}}unregisterTask(t){let e=this.jobs.get(t);e&&(e.stop(),this.jobs.delete(t))}async loadTasks(t){for(let e of t)await this.registerTask(e)}async handleStartupCatchUp(t){let e=Date.now();for(let s of t)!s.enabled||!s.catchUp||!s.nextRun||new Date(s.nextRun).getTime()<e&&await this.enqueue({task:s,reason:"catch-up"})}async enqueue(t){this.queue.push(t),await this.processQueue()}pauseAll(){this.paused=!0,this.jobs.forEach(t=>t.pause())}resumeAll(){this.paused=!1,this.jobs.forEach(t=>t.resume()),this.processQueue()}shutdown(){this.paused=!0,this.jobs.forEach(t=>t.stop()),this.jobs.clear(),this.queue.length=0}getQueueSize(){return this.queue.length}async processQueue(){if(!this.paused)for(;this.activeRuns<this.maxConcurrentRuns&&this.queue.length>0;){let t=this.queue.shift();if(!t)return;this.activeRuns+=1,this.callbacks.onTaskTriggered(t).finally(async()=>{this.activeRuns-=1,await this.processQueue()})}}};var vs=class i{constructor(t,e,s){this.repository=t;this.settings=e;this.executor=new on(e,t,s),this.mcpManager=new cn(e),s&&this.mcpManager.setAuthManager(s),this.memoryWriter=new Wt(t),this.scheduler=new dn(e.maxConcurrentRuns,{onTaskTriggered:n=>this.runPendingTask(n),onTaskScheduled:(n,a)=>this.repository.updateTaskRunMetadata(n,{nextRun:a})})}scheduler;executor;mcpManager;snapshot={agents:[],skills:[],tasks:[],channels:[],mcpServers:[],validationIssues:[]};runtimeState=new Map;recentRuns=[];chartRuns=[];static CHART_WINDOW_DAYS=14;statusChangeListeners=new Set;runOutputListeners=new Map;runOutputBuffers=new Map;heartbeatJobs=new Map;reflectionJobs=new Map;reflectionsInFlight=new Set;reflectionRunning=0;reflectionWaiters=[];heartbeatRegisteredAt=0;heartbeatsInFlight=new Set;heartbeatResultHandler;memoryWriter;async initialize(){this.snapshot=await this.repository.loadAll(),await this.repository.migrateAllLegacyMemory(),await this.refreshRunCaches();let t=this.snapshot.tasks.filter(e=>this.repository.getAgentByName(e.agent)?.enabled!==!1);await this.scheduler.loadTasks(t),await this.scheduler.handleStartupCatchUp(t),this.registerHeartbeats(),this.registerReflections(),this.emitStatusChange()}onHeartbeatResult(t){this.heartbeatResultHandler=t}async refreshFromVault(){this.snapshot=await this.repository.loadAll(),await this.rebuildSchedules(),await this.refreshRunCaches(),this.emitStatusChange()}getSnapshot(){return this.snapshot}getRecentRuns(){return this.recentRuns}getChartRuns(){return this.chartRuns}async refreshRunCaches(){this.recentRuns=await this.repository.listRecentRuns();let t=new Date;t.setDate(t.getDate()-(i.CHART_WINDOW_DAYS-1)),this.chartRuns=await this.repository.listRunsSince(t)}getAgentState(t){let e=this.runtimeState.get(t),s=this.snapshot.agents.find(n=>n.name===t);return s&&!s.enabled?{status:"disabled",lastRun:e?.lastRun,currentRunId:e?.currentRunId}:e??{status:"idle"}}getFleetStatus(){let t=new Date,e=o=>String(o).padStart(2,"0"),s=`${t.getFullYear()}-${e(t.getMonth()+1)}-${e(t.getDate())}`,n=this.recentRuns.filter(o=>{let c=new Date(o.started);return`${c.getFullYear()}-${e(c.getMonth()+1)}-${e(c.getDate())}`===s}).length,a=Array.from(this.runtimeState.values()).filter(o=>o.status==="running").length,r=this.recentRuns.flatMap(o=>o.approvals??[]).filter(o=>o.status==="pending").length;return{running:a,pending:r,completedToday:n}}subscribe(t){return this.statusChangeListeners.add(t),()=>this.statusChangeListeners.delete(t)}onRunOutput(t,e){let s=this.runOutputListeners.get(t);s||(s=new Set,this.runOutputListeners.set(t,s)),s.add(e);let n=this.runOutputBuffers.get(t);return n&&e(n),()=>{this.runOutputListeners.get(t)?.delete(e)}}getRunOutputBuffer(t){return this.runOutputBuffers.get(t)??""}async handleVaultChange(t){await this.repository.loadFile(t),this.snapshot=this.repository.getSnapshot(),await this.rebuildSchedules(),await this.refreshRunCaches(),this.emitStatusChange()}async handleVaultDelete(t){this.repository.removeFile(t),this.snapshot=this.repository.getSnapshot(),await this.rebuildSchedules(),await this.refreshRunCaches(),this.emitStatusChange()}abortedAgents=new Set;abortAgentRun(t){let e=this.executor.abortAgent(t);return e&&(this.abortedAgents.add(t),this.runtimeState.set(t,{status:"idle"}),this.emitStatusChange()),e}wasAborted(t){return this.abortedAgents.has(t)}consumeAborted(t){let e=this.abortedAgents.has(t);return this.abortedAgents.delete(t),e}async runTaskNow(t,e){await this.scheduler.enqueue({task:{...t,type:"immediate"},reason:"manual",promptOverride:e})}async runAgentNow(t,e){let s=t.heartbeatBody.trim()&&e==="Run now and summarize the current state."?t.heartbeatBody.trim():e,n=s===t.heartbeatBody.trim()&&t.heartbeatBody.trim().length>0,a={filePath:"",taskId:n?`heartbeat-${Date.now()}`:`manual-${Date.now()}`,agent:t.name,type:"immediate",priority:"medium",enabled:!0,created:new Date().toISOString(),runCount:0,catchUp:!1,tags:n?[...t.tags,"heartbeat"]:t.tags,body:s};await this.scheduler.enqueue({task:a,reason:n?"heartbeat":"manual",promptOverride:s})}async resolveApproval(t,e,s){t.filePath&&(await this.repository.setApprovalDecision(t.filePath,e,s),await this.refreshRunCaches(),this.emitStatusChange())}async pruneOldRuns(){let t=Date.now()-this.settings.runLogRetentionDays*24*60*60*1e3,e=await this.repository.listRecentRuns(500);for(let s of e)s.filePath&&new Date(s.started).getTime()<t&&await this.repository.trashFile(s.filePath)}async rebuildSchedules(){this.scheduler.pauseAll();for(let t of this.snapshot.tasks)this.scheduler.unregisterTask(t.taskId);this.scheduler.setMaxConcurrentRuns(this.settings.maxConcurrentRuns),await this.scheduler.loadTasks(this.snapshot.tasks.filter(t=>this.repository.getAgentByName(t.agent)?.enabled!==!1)),this.scheduler.resumeAll(),this.registerHeartbeats(),this.registerReflections()}shutdown(){for(let[,t]of this.heartbeatJobs)t.stop();this.heartbeatJobs.clear(),this.heartbeatsInFlight.clear();for(let[,t]of this.reflectionJobs)t.stop();this.reflectionJobs.clear(),this.reflectionsInFlight.clear(),this.scheduler.shutdown()}registerHeartbeats(){for(let[,t]of this.heartbeatJobs)t.stop();this.heartbeatJobs.clear(),this.heartbeatRegisteredAt=Date.now();for(let t of this.snapshot.agents)if(!(!t.enabled||!t.heartbeatEnabled||!t.heartbeatSchedule.trim()||!t.heartbeatBody.trim()))try{let e=new ce(t.heartbeatSchedule,{name:`heartbeat:${t.name}`,catch:!0,protect:!0,timezone:Intl.DateTimeFormat().resolvedOptions().timeZone},()=>{this.runHeartbeat(t.name)});this.heartbeatJobs.set(t.name,e)}catch(e){console.error(`Agent Fleet: failed to register heartbeat for "${t.name}":`,e)}}async runHeartbeat(t){if(!(Date.now()-this.heartbeatRegisteredAt<1e4)&&!this.heartbeatsInFlight.has(t)){this.heartbeatsInFlight.add(t);try{let e=this.repository.getAgentByName(t);if(!e||!e.enabled||!e.heartbeatBody.trim())return;let s={filePath:"",taskId:`heartbeat-${Date.now()}`,agent:e.name,type:"immediate",priority:"medium",enabled:!0,created:new Date().toISOString(),runCount:0,catchUp:!1,tags:[...e.tags,"heartbeat"],body:e.heartbeatBody.trim()};await this.scheduler.enqueue({task:s,reason:"heartbeat",promptOverride:e.heartbeatBody.trim()})}finally{this.heartbeatsInFlight.delete(t)}}}getNextHeartbeat(t){let e=this.heartbeatJobs.get(t);return e?e.nextRun()??null:null}registerReflections(){for(let[,t]of this.reflectionJobs)t.stop();this.reflectionJobs.clear();for(let t of this.snapshot.agents){if(!t.enabled||!t.memory||!t.reflection.enabled)continue;let e=t.reflection.schedule.trim();if(e)try{let s=new ce(e,{name:`reflection:${t.name}`,catch:!0,protect:!0,timezone:Intl.DateTimeFormat().resolvedOptions().timeZone},()=>{this.runReflection(t.name)});this.reflectionJobs.set(t.name,s)}catch(s){console.error(`Agent Fleet: failed to register reflection for "${t.name}":`,s)}}}getNextReflection(t){return this.reflectionJobs.get(t)?.nextRun()??null}async runReflectionNow(t){return this.runReflection(t)}async listPendingProposals(){return(await this.repository.listProposals()).filter(e=>e.status==="pending")}async acceptProposal(t){let e=await this.repository.readProposal(t);if(!e)return{ok:!1,message:"Proposal not found."};try{let s=await this.repository.applyProposal(e);return s?(await this.repository.setProposalStatus(t,"accepted"),await this.refreshFromVault(),{ok:!0,message:`Applied \u2192 ${s}`}):{ok:!1,message:"Couldn't apply \u2014 target skill not found; proposal left pending."}}catch(s){return{ok:!1,message:`Failed to apply: ${s instanceof Error?s.message:String(s)}`}}}async rejectProposal(t){await this.repository.setProposalStatus(t,"rejected"),this.emitStatusChange()}async withReflectionSlot(t){let e=Math.max(1,this.settings.maxConcurrentRuns);this.reflectionRunning>=e?await new Promise(s=>this.reflectionWaiters.push(s)):this.reflectionRunning++;try{return await t()}finally{let s=this.reflectionWaiters.shift();s?s():this.reflectionRunning--}}async runReflection(t){let e=this.repository.getAgentByName(t);if(!e||!e.enabled||!e.memory)return{ok:!1,message:"Agent not found, disabled, or memory off."};if(this.reflectionsInFlight.has(t))return{ok:!1,message:"A reflection is already in progress."};this.reflectionsInFlight.add(t);let s=new Date().toISOString();try{await this.repository.migrateLegacyMemory(t);let n=await this.repository.readWorkingMemory(t),a=n?Ge(n.sections):"",r=await this.repository.readRecentRaw(t,2),o=tr({agentName:t,workingMemoryBody:a,recentRaw:r,tokenBudget:e.memoryTokenBudget}),c={filePath:"",taskId:`reflection-${Date.now()}`,agent:e.name,type:"immediate",priority:"low",enabled:!0,created:s,runCount:0,catchUp:!1,tags:[...e.tags,"reflection"],body:o,model:e.reflection.model||void 0},l=await this.withReflectionSlot(()=>this.executor.execute(e,c,o,void 0,{suppressMemoryCapture:!0})),d=sr(l.outputText),h=await this.memoryWriter.reflect(e,d.sections,s);if(d.candidates.length>0){let u=await this.repository.readCandidates(t),p=nr(u,d.candidates,s);await this.repository.writeCandidates(t,p),await this.generateProposals(e,p,s)}return await this.refreshRunCaches(),this.emitStatusChange(),h?{ok:!0,message:"Reflection complete \u2014 working memory consolidated."}:{ok:!1,message:"Reflection produced no memory block; working memory left unchanged."}}catch(n){let a=n instanceof Error?n.message:String(n);return console.warn(`Agent Fleet: reflection failed for "${t}":`,n),{ok:!1,message:`Reflection failed: ${a}`}}finally{this.reflectionsInFlight.delete(t)}}async generateProposals(t,e,s){if(!t.reflection.proposeSkills)return;let n=t.reflection.recurrenceThreshold||3;for(let a of e){if(a.proposed||a.occurrences<n)continue;let o={id:`prop-${s.slice(0,10)}-${a.key}`.slice(0,80),type:"skill_create",agent:t.name,status:"pending",created:s,targetSkill:a.suggestedSkill||a.key,candidate:a.key,evidence:a.evidence,rationale:a.pattern,body:`This skill was proposed by reflection because the following friction recurred ${a.occurrences} times:
11959
+ `)}catch{window.clearTimeout(p),u();return}}else if(b.id===2&&b.result){for(let k of b.result.tools??[])c.push({name:k.name,description:k.description,inputSchema:k.inputSchema});d=!0}}catch{}h&&d&&(window.clearTimeout(p),u())}}}),a.on("error",()=>{window.clearTimeout(p),u()}),a.on("close",()=>{window.clearTimeout(p),u()});try{a.stdin.write(JSON.stringify({jsonrpc:"2.0",id:1,method:"initialize",params:{protocolVersion:"2024-11-05",capabilities:{},clientInfo:{name:"agent-fleet",version:"1.0.0"}}})+`
11960
+ `)}catch{window.clearTimeout(p),u()}})}async probeHttpServer(t){let e=await this.findServerToken(t);if(!e)return[];let s=t.url.endsWith("/sse")?t.url.replace(/\/sse$/,"/mcp"):t.url;try{let a=(await this.httpRequest(s,e,{jsonrpc:"2.0",id:1,method:"initialize",params:{protocolVersion:"2025-03-26",capabilities:{},clientInfo:{name:"agent-fleet",version:"1.0.0"}}}))?._sessionId;await this.httpRequest(s,e,{jsonrpc:"2.0",method:"notifications/initialized"},a);let r=await this.httpRequest(s,e,{jsonrpc:"2.0",id:2,method:"tools/list"},a),o=[],h=r?.result?.tools??[];for(let d of h)o.push({name:d.name,description:d.description,inputSchema:d.inputSchema});return o}catch(n){return console.warn(`McpManager: HTTP probe failed for ${t.name}:`,n),[]}}async findServerToken(t){if(this.authManager){let a=this.authManager.getToken(t.name);if(a)return a}let e=t.name.replace(/^claude\.ai\s+/i,"").replace(/\s+/g,"_").toUpperCase(),s=[`${e}_API_KEY`,`${e}_API_KEY_MILO`,`${e}_TOKEN`];for(let a of s){let r=process.env[a];if(r)return r}let n=[ga.join(Yn(),".openclaw","workspace",".env"),ga.join(Yn(),".env")];for(let a of n)try{let r=rr.readFileSync(a,"utf8");for(let o of ge(r)){let c=o.trim().match(/^(?:export\s+)?([A-Za-z_]\w*)=(.*)$/);if(c){let l=c[1],h=c[2].replace(/^["']|["']$/g,"");if(s.includes(l))return h}}}catch{}}httpRequest(t,e,s,n){return new Promise((a,r)=>{let o=JSON.stringify(s),c=new URL(t),l=c.protocol==="https:",h={"Content-Type":"application/json",Accept:"application/json, text/event-stream",Authorization:`Bearer ${e}`,"Content-Length":String(Buffer.byteLength(o))};n&&(h["mcp-session-id"]=n);let d={hostname:c.hostname,port:c.port||(l?443:80),path:c.pathname+c.search,method:"POST",headers:h},p=(l?ir:ln).request(d,f=>{let g="";f.on("data",v=>{g+=v.toString()}),f.on("end",()=>{let v=f.headers["mcp-session-id"];if((f.headers["content-type"]??"").includes("text/event-stream")){for(let k of ge(g))if(k.startsWith("data: "))try{let y=JSON.parse(k.slice(6));v&&(y._sessionId=v),a(y);return}catch{}a(null)}else try{let k=JSON.parse(g);v&&(k._sessionId=v),a(k)}catch{a(null)}})});p.on("error",r);let m=window.setTimeout(()=>{p.destroy(),a(null)},15e3);p.on("close",()=>window.clearTimeout(m)),p.write(o),p.end()})}};var Vl={"every 5m":"*/5 * * * *","every 10m":"*/10 * * * *","every 15m":"*/15 * * * *","every 30m":"*/30 * * * *","every 1h":"0 * * * *","every 2h":"0 */2 * * *",hourly:"0 * * * *","daily at 9am":"0 9 * * *","daily at 6pm":"0 18 * * *","weekdays at 9am":"0 9 * * 1-5","weekly on monday":"0 9 * * 1","monthly on 1st":"0 9 1 * *"},dn=class{constructor(t,e){this.maxConcurrentRuns=t;this.callbacks=e}jobs=new Map;activeRuns=0;queue=[];paused=!1;setMaxConcurrentRuns(t){this.maxConcurrentRuns=t}parseSchedule(t){return Vl[t.toLowerCase()]??t}toLocalISOString(t){let e=s=>String(s).padStart(2,"0");return`${t.getFullYear()}-${e(t.getMonth()+1)}-${e(t.getDate())}T${e(t.getHours())}:${e(t.getMinutes())}:${e(t.getSeconds())}`}async registerTask(t){if(this.unregisterTask(t.taskId),!(!t.enabled||t.type==="immediate"))try{if(t.type==="once"&&t.runAt){let e=new pe(new Date(t.runAt),{name:t.taskId,catch:!0},()=>{this.enqueue({task:t,reason:"scheduled"})});this.jobs.set(t.taskId,e),await this.callbacks.onTaskScheduled(t,t.runAt);return}if(t.type==="recurring"&&t.schedule){let e=this.parseSchedule(t.schedule),s=new pe(e,{name:t.taskId,catch:!0,protect:!0,timezone:Intl.DateTimeFormat().resolvedOptions().timeZone},()=>{this.enqueue({task:t,reason:"scheduled"})});this.jobs.set(t.taskId,s);let n=s.nextRun();await this.callbacks.onTaskScheduled(t,n?this.toLocalISOString(n):void 0)}}catch(e){console.error(`Agent Fleet: Failed to register task "${t.taskId}":`,e)}}unregisterTask(t){let e=this.jobs.get(t);e&&(e.stop(),this.jobs.delete(t))}async loadTasks(t){for(let e of t)await this.registerTask(e)}async handleStartupCatchUp(t){let e=Date.now();for(let s of t)!s.enabled||!s.catchUp||!s.nextRun||new Date(s.nextRun).getTime()<e&&await this.enqueue({task:s,reason:"catch-up"})}async enqueue(t){this.queue.push(t),await this.processQueue()}pauseAll(){this.paused=!0,this.jobs.forEach(t=>t.pause())}resumeAll(){this.paused=!1,this.jobs.forEach(t=>t.resume()),this.processQueue()}shutdown(){this.paused=!0,this.jobs.forEach(t=>t.stop()),this.jobs.clear(),this.queue.length=0}getQueueSize(){return this.queue.length}async processQueue(){if(!this.paused)for(;this.activeRuns<this.maxConcurrentRuns&&this.queue.length>0;){let t=this.queue.shift();if(!t)return;this.activeRuns+=1,this.callbacks.onTaskTriggered(t).finally(async()=>{this.activeRuns-=1,await this.processQueue()})}}};var vs=class i{constructor(t,e,s){this.repository=t;this.settings=e;this.executor=new on(e,t,s),this.mcpManager=new cn(e),s&&this.mcpManager.setAuthManager(s),this.memoryWriter=new Ht(t),this.scheduler=new dn(e.maxConcurrentRuns,{onTaskTriggered:n=>this.runPendingTask(n),onTaskScheduled:(n,a)=>this.repository.updateTaskRunMetadata(n,{nextRun:a})})}scheduler;executor;mcpManager;snapshot={agents:[],skills:[],tasks:[],channels:[],mcpServers:[],validationIssues:[]};runtimeState=new Map;recentRuns=[];chartRuns=[];static CHART_WINDOW_DAYS=14;statusChangeListeners=new Set;runOutputListeners=new Map;runOutputBuffers=new Map;heartbeatJobs=new Map;reflectionJobs=new Map;reflectionsInFlight=new Set;reflectionRunning=0;reflectionWaiters=[];heartbeatRegisteredAt=0;heartbeatsInFlight=new Set;heartbeatResultHandler;memoryWriter;async initialize(){this.snapshot=await this.repository.loadAll(),await this.repository.migrateAllLegacyMemory(),await this.refreshRunCaches();let t=this.snapshot.tasks.filter(e=>this.repository.getAgentByName(e.agent)?.enabled!==!1);await this.scheduler.loadTasks(t),await this.scheduler.handleStartupCatchUp(t),this.registerHeartbeats(),this.registerReflections(),this.emitStatusChange()}onHeartbeatResult(t){this.heartbeatResultHandler=t}async refreshFromVault(){this.snapshot=await this.repository.loadAll(),await this.rebuildSchedules(),await this.refreshRunCaches(),this.emitStatusChange()}getSnapshot(){return this.snapshot}getRecentRuns(){return this.recentRuns}getChartRuns(){return this.chartRuns}async refreshRunCaches(){this.recentRuns=await this.repository.listRecentRuns();let t=new Date;t.setDate(t.getDate()-(i.CHART_WINDOW_DAYS-1)),this.chartRuns=await this.repository.listRunsSince(t)}getAgentState(t){let e=this.runtimeState.get(t),s=this.snapshot.agents.find(n=>n.name===t);return s&&!s.enabled?{status:"disabled",lastRun:e?.lastRun,currentRunId:e?.currentRunId}:e??{status:"idle"}}getFleetStatus(){let t=new Date,e=o=>String(o).padStart(2,"0"),s=`${t.getFullYear()}-${e(t.getMonth()+1)}-${e(t.getDate())}`,n=this.recentRuns.filter(o=>{let c=new Date(o.started);return`${c.getFullYear()}-${e(c.getMonth()+1)}-${e(c.getDate())}`===s}).length,a=Array.from(this.runtimeState.values()).filter(o=>o.status==="running").length,r=this.recentRuns.flatMap(o=>o.approvals??[]).filter(o=>o.status==="pending").length;return{running:a,pending:r,completedToday:n}}subscribe(t){return this.statusChangeListeners.add(t),()=>this.statusChangeListeners.delete(t)}onRunOutput(t,e){let s=this.runOutputListeners.get(t);s||(s=new Set,this.runOutputListeners.set(t,s)),s.add(e);let n=this.runOutputBuffers.get(t);return n&&e(n),()=>{this.runOutputListeners.get(t)?.delete(e)}}getRunOutputBuffer(t){return this.runOutputBuffers.get(t)??""}async handleVaultChange(t){await this.repository.loadFile(t),this.snapshot=this.repository.getSnapshot(),await this.rebuildSchedules(),await this.refreshRunCaches(),this.emitStatusChange()}async handleVaultDelete(t){this.repository.removeFile(t),this.snapshot=this.repository.getSnapshot(),await this.rebuildSchedules(),await this.refreshRunCaches(),this.emitStatusChange()}abortedAgents=new Set;abortAgentRun(t){let e=this.executor.abortAgent(t);return e&&(this.abortedAgents.add(t),this.runtimeState.set(t,{status:"idle"}),this.emitStatusChange()),e}wasAborted(t){return this.abortedAgents.has(t)}consumeAborted(t){let e=this.abortedAgents.has(t);return this.abortedAgents.delete(t),e}async runTaskNow(t,e){await this.scheduler.enqueue({task:{...t,type:"immediate"},reason:"manual",promptOverride:e})}async runAgentNow(t,e){let s=t.heartbeatBody.trim()&&e==="Run now and summarize the current state."?t.heartbeatBody.trim():e,n=s===t.heartbeatBody.trim()&&t.heartbeatBody.trim().length>0,a={filePath:"",taskId:n?`heartbeat-${Date.now()}`:`manual-${Date.now()}`,agent:t.name,type:"immediate",priority:"medium",enabled:!0,created:new Date().toISOString(),runCount:0,catchUp:!1,tags:n?[...t.tags,"heartbeat"]:t.tags,body:s};await this.scheduler.enqueue({task:a,reason:n?"heartbeat":"manual",promptOverride:s})}async resolveApproval(t,e,s){t.filePath&&(await this.repository.setApprovalDecision(t.filePath,e,s),await this.refreshRunCaches(),this.emitStatusChange())}async pruneOldRuns(){let t=Date.now()-this.settings.runLogRetentionDays*24*60*60*1e3,e=await this.repository.listRecentRuns(500);for(let s of e)s.filePath&&new Date(s.started).getTime()<t&&await this.repository.trashFile(s.filePath)}async rebuildSchedules(){this.scheduler.pauseAll();for(let t of this.snapshot.tasks)this.scheduler.unregisterTask(t.taskId);this.scheduler.setMaxConcurrentRuns(this.settings.maxConcurrentRuns),await this.scheduler.loadTasks(this.snapshot.tasks.filter(t=>this.repository.getAgentByName(t.agent)?.enabled!==!1)),this.scheduler.resumeAll(),this.registerHeartbeats(),this.registerReflections()}shutdown(){for(let[,t]of this.heartbeatJobs)t.stop();this.heartbeatJobs.clear(),this.heartbeatsInFlight.clear();for(let[,t]of this.reflectionJobs)t.stop();this.reflectionJobs.clear(),this.reflectionsInFlight.clear(),this.scheduler.shutdown()}registerHeartbeats(){for(let[,t]of this.heartbeatJobs)t.stop();this.heartbeatJobs.clear(),this.heartbeatRegisteredAt=Date.now();for(let t of this.snapshot.agents)if(!(!t.enabled||!t.heartbeatEnabled||!t.heartbeatSchedule.trim()||!t.heartbeatBody.trim()))try{let e=new pe(t.heartbeatSchedule,{name:`heartbeat:${t.name}`,catch:!0,protect:!0,timezone:Intl.DateTimeFormat().resolvedOptions().timeZone},()=>{this.runHeartbeat(t.name)});this.heartbeatJobs.set(t.name,e)}catch(e){console.error(`Agent Fleet: failed to register heartbeat for "${t.name}":`,e)}}async runHeartbeat(t){if(!(Date.now()-this.heartbeatRegisteredAt<1e4)&&!this.heartbeatsInFlight.has(t)){this.heartbeatsInFlight.add(t);try{let e=this.repository.getAgentByName(t);if(!e||!e.enabled||!e.heartbeatBody.trim())return;let s={filePath:"",taskId:`heartbeat-${Date.now()}`,agent:e.name,type:"immediate",priority:"medium",enabled:!0,created:new Date().toISOString(),runCount:0,catchUp:!1,tags:[...e.tags,"heartbeat"],body:e.heartbeatBody.trim()};await this.scheduler.enqueue({task:s,reason:"heartbeat",promptOverride:e.heartbeatBody.trim()})}finally{this.heartbeatsInFlight.delete(t)}}}getNextHeartbeat(t){let e=this.heartbeatJobs.get(t);return e?e.nextRun()??null:null}registerReflections(){for(let[,t]of this.reflectionJobs)t.stop();this.reflectionJobs.clear();for(let t of this.snapshot.agents){if(!t.enabled||!t.memory||!t.reflection.enabled)continue;let e=t.reflection.schedule.trim();if(e)try{let s=new pe(e,{name:`reflection:${t.name}`,catch:!0,protect:!0,timezone:Intl.DateTimeFormat().resolvedOptions().timeZone},()=>{this.runReflection(t.name)});this.reflectionJobs.set(t.name,s)}catch(s){console.error(`Agent Fleet: failed to register reflection for "${t.name}":`,s)}}}getNextReflection(t){return this.reflectionJobs.get(t)?.nextRun()??null}async runReflectionNow(t){return this.runReflection(t)}async listPendingProposals(){return(await this.repository.listProposals()).filter(e=>e.status==="pending")}async acceptProposal(t){let e=await this.repository.readProposal(t);if(!e)return{ok:!1,message:"Proposal not found."};try{let s=await this.repository.applyProposal(e);return s?(await this.repository.setProposalStatus(t,"accepted"),await this.refreshFromVault(),{ok:!0,message:`Applied \u2192 ${s}`}):{ok:!1,message:"Couldn't apply \u2014 target skill not found; proposal left pending."}}catch(s){return{ok:!1,message:`Failed to apply: ${s instanceof Error?s.message:String(s)}`}}}async rejectProposal(t){await this.repository.setProposalStatus(t,"rejected"),this.emitStatusChange()}async withReflectionSlot(t){let e=Math.max(1,this.settings.maxConcurrentRuns);this.reflectionRunning>=e?await new Promise(s=>this.reflectionWaiters.push(s)):this.reflectionRunning++;try{return await t()}finally{let s=this.reflectionWaiters.shift();s?s():this.reflectionRunning--}}async runReflection(t){let e=this.repository.getAgentByName(t);if(!e||!e.enabled||!e.memory)return{ok:!1,message:"Agent not found, disabled, or memory off."};if(this.reflectionsInFlight.has(t))return{ok:!1,message:"A reflection is already in progress."};this.reflectionsInFlight.add(t);let s=new Date().toISOString();try{await this.repository.migrateLegacyMemory(t);let n=await this.repository.readWorkingMemory(t),a=n?Ge(n.sections):"",r=await this.repository.readRecentRaw(t,2),o=sr({agentName:t,workingMemoryBody:a,recentRaw:r,tokenBudget:e.memoryTokenBudget}),c={filePath:"",taskId:`reflection-${Date.now()}`,agent:e.name,type:"immediate",priority:"low",enabled:!0,created:s,runCount:0,catchUp:!1,tags:[...e.tags,"reflection"],body:o,model:e.reflection.model||void 0},l=await this.withReflectionSlot(()=>this.executor.execute(e,c,o,void 0,{suppressMemoryCapture:!0})),h=nr(l.outputText),d=await this.memoryWriter.reflect(e,h.sections,s);if(h.candidates.length>0){let u=await this.repository.readCandidates(t),p=ar(u,h.candidates,s);await this.repository.writeCandidates(t,p),await this.generateProposals(e,p,s)}return await this.refreshRunCaches(),this.emitStatusChange(),d?{ok:!0,message:"Reflection complete \u2014 working memory consolidated."}:{ok:!1,message:"Reflection produced no memory block; working memory left unchanged."}}catch(n){let a=n instanceof Error?n.message:String(n);return console.warn(`Agent Fleet: reflection failed for "${t}":`,n),{ok:!1,message:`Reflection failed: ${a}`}}finally{this.reflectionsInFlight.delete(t)}}async generateProposals(t,e,s){if(!t.reflection.proposeSkills)return;let n=t.reflection.recurrenceThreshold||3;for(let a of e){if(a.proposed||a.occurrences<n)continue;let o={id:`prop-${s.slice(0,10)}-${a.key}`.slice(0,80),type:"skill_create",agent:t.name,status:"pending",created:s,targetSkill:a.suggestedSkill||a.key,candidate:a.key,evidence:a.evidence,rationale:a.pattern,body:`This skill was proposed by reflection because the following friction recurred ${a.occurrences} times:
11961
11961
 
11962
11962
  > ${a.pattern}
11963
11963
 
11964
- Document the reliable steps to handle this so future runs don't rediscover them.`};try{await this.repository.writeProposal(o),a.proposed=!0,await this.repository.writeCandidates(t.name,e)}catch(c){console.warn(`Agent Fleet: failed to write proposal for "${t.name}"`,c)}}}async runPendingTask({task:t,promptOverride:e}){let s=this.repository.getAgentByName(t.agent);if(!s||!s.enabled)return;let n=new Date().toISOString();this.runtimeState.set(s.name,{status:"running",currentTaskId:t.taskId,runStarted:n}),this.runOutputBuffers.set(s.name,""),this.emitStatusChange();try{let a=await this.executor.execute(s,t,e,u=>{let p=this.runOutputBuffers.get(s.name)??"";this.runOutputBuffers.set(s.name,p+u);let f=this.runOutputListeners.get(s.name);if(f)for(let m of f)m(u)}),r=this.consumeAborted(s.name),o=r?[]:this.buildApprovals(s,a.toolsUsed),c=r?"cancelled":this.resolveRunStatus(a,o),l={runId:a.runId,agent:s.name,task:t.taskId,status:c,started:n,completed:new Date().toISOString(),durationSeconds:a.durationSeconds,tokensUsed:a.tokensUsed,costUsd:a.costUsd,model:a.resolvedModel||s.model,modelSource:a.modelSource,concreteModel:a.concreteModel,exitCode:a.exitCode,tags:Array.from(new Set([...s.tags,...t.tags])),prompt:a.prompt,output:a.outputText,toolsUsed:a.toolsUsed.map(u=>`${u.tool}${u.command?`: ${u.command}`:""}`),finalResult:a.finalResult,stderr:a.stderr,approvals:o},d=await this.repository.writeRunLog(l);if(await this.repository.updateTaskRunMetadata(t,{lastRun:n,runCount:t.runCount+1}),s.memory){let p=t.tags.includes("heartbeat")?"heartbeat":`task:${t.taskId}`,f=js(a.outputText);try{await this.memoryWriter.capture(s,f,p,new Date().toISOString())}catch(m){console.warn(`Agent Fleet: failed to append memory for "${s.name}"`,m)}}if(t.tags.includes("heartbeat")&&!r&&s.heartbeatChannel&&l.output.trim())try{this.heartbeatResultHandler?.(s.name,s.heartbeatChannel,l.output)}catch(u){console.warn(`Agent Fleet: heartbeat channel delivery failed for ${s.name}`,u)}r&&(l.output="Task was manually stopped."),await this.refreshRunCaches(),this.runtimeState.set(s.name,{status:r||c==="success"?"idle":c==="pending_approval"?"pending":"error",currentRunId:a.runId,lastRun:{...l,filePath:d}}),r||this.notify(l)}catch(a){let r=this.consumeAborted(s.name),o=r?"cancelled":"failure",c=Pt(t,s,this.settings),l={runId:(0,rr.randomUUID)(),agent:s.name,task:t.taskId,status:o,started:n,completed:new Date().toISOString(),durationSeconds:Math.round((Date.now()-new Date(n).getTime())/1e3),model:c.value||s.model,modelSource:c.source,exitCode:r?-1:1,tags:Array.from(new Set([...s.tags,...t.tags])),prompt:e??t.body,output:r?"Task was manually stopped.":a instanceof Error?a.message:String(a),toolsUsed:[]},d=await this.repository.writeRunLog(l);await this.refreshRunCaches(),this.runtimeState.set(s.name,{status:r?"idle":"error",lastRun:{...l,filePath:d}}),r||this.notify(l)}finally{if(s.memory)try{await this.memoryWriter.drainPending(s,new Date().toISOString())}catch(a){console.warn(`Agent Fleet: failed to drain pending memory for "${s.name}"`,a)}this.runOutputBuffers.delete(s.name),this.runOutputListeners.delete(s.name),this.emitStatusChange()}}buildApprovals(t,e){let s=e.filter(n=>t.approvalRequired.includes(n.tool)).map(n=>({tool:n.tool,command:n.command,reason:n.reason,status:"pending"}));return s.length>0?s:void 0}resolveRunStatus(t,e){return e?.length?"pending_approval":t.timedOut?"timeout":t.exitCode===0?"success":"failure"}notify(t){if(this.settings.notificationLevel==="none"||this.settings.notificationLevel==="failures-only"&&t.status==="success")return;let s=(pe(t.output).map(a=>a.trim()).find(a=>a&&!a.startsWith("{")&&!a.startsWith("["))??"").slice(0,120)||t.status,n=t.status==="success"?`\u2705 ${t.agent}: ${s}`:t.status==="pending_approval"?`\u{1F535} ${t.agent} needs approval: ${(t.approvals??[])[0]?.tool??"tool action"}`:`\u274C ${t.agent}: ${s}`;new or.Notice(n,t.status==="success"?5e3:0)}emitStatusChange(){for(let t of this.statusChangeListeners)t()}};function Vl(i){return i.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-{2,}/g,"-").replace(/^-|-$/g,"")}function bs(i,t){return`${i}-${Vl(t)}`}var Ht="af-channel-cred",ws="af-mcp-secret",hn=class{constructor(t){this.storage=t;t||console.warn("Agent Fleet: SecretStorage unavailable (Obsidian < 1.11.4). Secrets will use plaintext fallback.")}get available(){return!!this.storage}setJson(t,e,s){if(!this.storage)return;let n=bs(t,e);this.storage.setSecret(n,JSON.stringify(s))}getJson(t,e){if(!this.storage)return null;let s=bs(t,e),n=this.storage.getSecret(s);if(!n)return null;try{return JSON.parse(n)}catch{return null}}setString(t,e,s){if(!this.storage)return;let n=bs(t,e);this.storage.setSecret(n,s)}getString(t,e){if(!this.storage)return null;let s=bs(t,e);return this.storage.getSecret(s)||null}delete(t,e){if(!this.storage)return;let s=bs(t,e);this.storage.setSecret(s,"")}listByPrefix(t){return this.storage?this.storage.listSecrets().filter(e=>e.startsWith(t+"-")):[]}};var un=class{tokens=new Map;oauthTokens=new Map;secretStore;setSecretStore(t){this.secretStore=t}storeProbeToken(t,e){this.tokens.set(t,e)}storeStaticToken(t,e){this.tokens.set(t,e),this.secretStore?.setJson(ws,t,{accessToken:e})}storeOAuthToken(t,e){this.oauthTokens.set(t,e),this.tokens.set(t,e.accessToken),this.secretStore?.setJson(ws,t,{accessToken:e.accessToken,refreshToken:e.refreshToken,expiresAt:e.expiresAt,tokenEndpoint:e.tokenEndpoint,clientId:e.clientId,resource:e.resource})}hydrate(t){if(!this.secretStore)return null;let e=this.secretStore.getJson(ws,t);return e?.accessToken?(this.tokens.set(t,e.accessToken),e.tokenEndpoint&&e.clientId&&e.resource&&this.oauthTokens.set(t,{accessToken:e.accessToken,refreshToken:e.refreshToken,expiresAt:e.expiresAt,tokenEndpoint:e.tokenEndpoint,clientId:e.clientId,resource:e.resource}),e):null}getToken(t){return this.tokens.get(t)??this.hydrate(t)?.accessToken??void 0}getOAuthToken(t){return this.oauthTokens.has(t)?this.oauthTokens.get(t):(this.hydrate(t),this.oauthTokens.get(t))}hasToken(t){return this.tokens.has(t)||!!this.hydrate(t)}removeToken(t){this.tokens.delete(t),this.oauthTokens.delete(t),this.secretStore?.delete(ws,t)}getExpiringTokens(t=5*6e4){let e=new Map,s=Date.now();for(let[n,a]of this.oauthTokens)a.refreshToken&&a.expiresAt&&a.expiresAt-s<t&&e.set(n,a);return e}};var ct=require("obsidian");var pn=require("crypto"),Qe=require("obsidian");function ks(){return(0,pn.randomUUID)()}function lr(i){let t=`${i.timestamp}|${i.content.slice(0,80)}`;return(0,pn.createHash)("sha1").update(t).digest("hex").slice(0,16)}var qt=class i{constructor(t,e,s,n,a){this.agent=t;this.settings=e;this.repository=s;this.vault=n,this.channelName=a?.channelName,this.conversationId=a?.conversationId,this.channelContext=a?.channelContext,this.inAppConversationId=a?.inAppConversationId,this.threadAnchorId=a?.threadAnchorId,this.parentSession=a?.parentSession,this.mcpAuth=a?.mcpAuth,this.memoryWriter=new Wt(s)}messages=[];isStreaming=!1;isProcessAlive=!1;settingsState=null;mcpProjection=null;get pendingTurnCount(){return this.pendingTurns}lastActiveAt=Date.now();process=null;claudeSessionId=null;claudeResumeAttempted=!1;vault;stdoutBuffer="";processListeners=null;basePromptSent=!1;codexTurnState=null;codexQueue=[];codexResumeAttempted=!1;codexTurnErrors=[];codexStderr="";codexPermState=null;get isCodex(){return bt(this.agent.adapter)==="codex"}channelName;conversationId;channelContext;inAppConversationId;conversationName="";threadAnchorId;parentSession;threadAnchorIndex;threads=new Map;threadIndex={};activeOnEvent=null;turnResponseText="";displayedLen=0;turnToolCalls=[];pendingTurns=0;turnResolve=null;turnReject=null;needsCompactBeforeNextTurn=!1;lastCompactTriggerAt=0;static WATCHDOG_FALLBACK_MINUTES=10;watchdogTimer=null;getWatchdogMs(){let t=this.settings.chatWatchdogMinutes;return(typeof t=="number"&&t>0?t:i.WATCHDOG_FALLBACK_MINUTES)*60*1e3}armWatchdog(){this.clearWatchdog();let t=this.getWatchdogMs();this.watchdogTimer=setTimeout(()=>{if(this.watchdogTimer=null,!this.isStreaming)return;this.activeOnEvent?.({type:"error",content:"",errorMessage:`no response from the CLI for ${Math.round(t/6e4)} minutes \u2014 giving up`});let e=new Error("Watchdog timeout");this.handleProcessError(e);try{this.process?.kill()}catch{}},t)}clearWatchdog(){this.watchdogTimer&&(clearTimeout(this.watchdogTimer),this.watchdogTimer=null)}currentToolName;activityListeners=new Set;onActivityChange(t){return this.activityListeners.add(t),t(),()=>{this.activityListeners.delete(t)}}emitActivity(){for(let t of this.activityListeners)t()}setStreaming(t){this.isStreaming!==t&&(this.isStreaming=t,t||(this.currentToolName=void 0),this.emitActivity())}setCurrentTool(t){this.currentToolName!==t&&(this.currentToolName=t,this.emitActivity())}stats={costTotalUsd:0,turnCount:0};statsListeners=new Set;onStatsChange(t){return this.statsListeners.add(t),t({...this.stats}),()=>{this.statsListeners.delete(t)}}getStats(){return{...this.stats}}emitStats(){let t={...this.stats};for(let e of this.statsListeners)e(t)}mcpAuth;buildMcpProjection(t){let e=this.agent.memory?this.repository.getPendingDirAbsolutePath(this.agent.name):null,s=an({registry:this.repository.getMcpServers(),agentGrants:this.agent.mcpServers??[],getBearerToken:n=>this.mcpAuth?.getToken(n),remember:e?{pendingDir:e,source:`mcp:${this.captureSource()}`}:null});return this.mcpProjection=rn(t,this.agent.adapter,s),{args:this.mcpProjection?.args??[],env:this.mcpProjection?.env??{},allowServers:s.map(n=>n.def.name)}}memoryWriter;captureSource(){return`chat:${this.inAppConversationId||this.conversationId||"default"}`}getConversationName(){return this.conversationName}async setConversationName(t){this.conversationName=t,await this.persist()}refreshAgent(){let t=this.repository.getAgentByName(this.agent.name);t&&(this.agent=t)}get isThread(){return!!this.threadAnchorId}async loadPersistedState(){let t=this.getChatFilePath(),e=this.vault.getAbstractFileByPath(t);if(!(e instanceof Qe.TFile))return!1;try{let s=await this.vault.cachedRead(e);if(this.isThread){let a=JSON.parse(s);return a.messages?.length>0||a.sessionId?(this.messages=(a.messages??[]).map(r=>r.id?r:{...r,id:lr(r)}),this.claudeSessionId=a.sessionId??null,this.threadAnchorIndex=a.anchorIndex,this.claudeSessionId&&(this.basePromptSent=!0),!0):!1}let n=JSON.parse(s);if(n.name&&(this.conversationName=n.name),n.messages?.length>0)return this.messages=n.messages.map(a=>a.id?a:{...a,id:lr(a)}),this.claudeSessionId=n.sessionId??null,this.threadIndex=n.threads??{},this.claudeSessionId&&(this.basePromptSent=!0),!0}catch{}return!1}getThreadIndex(){return{...this.threadIndex}}async persist(){let t=new Date().toISOString(),e=this.getChatFilePath(),s;if(this.isThread){let a={anchorMessageId:this.threadAnchorId,anchorIndex:this.threadAnchorIndex??0,sessionId:this.claudeSessionId,messages:this.messages,createdAt:this.parentSession?.threadIndex[this.threadAnchorId]?.createdAt??t,lastActive:t};s=JSON.stringify(a,null,2)}else{let a={sessionId:this.claudeSessionId,messages:this.messages,lastActive:t,name:this.conversationName||void 0,threads:Object.keys(this.threadIndex).length>0?this.threadIndex:void 0};s=JSON.stringify(a,null,2)}let n=this.vault.getAbstractFileByPath(e);n instanceof Qe.TFile?await this.vault.modify(n,s):(await this.ensureParentFolders(e),await this.vault.create(e,s)),this.isThread&&this.parentSession&&this.threadAnchorId&&await this.parentSession.upsertThreadIndex(this.threadAnchorId,{path:e,createdAt:this.parentSession.threadIndex[this.threadAnchorId]?.createdAt??t,messageCount:this.messages.length,lastActive:t})}async upsertThreadIndex(t,e){this.threadIndex[t]=e,await this.persist()}async ensureParentFolders(t){let e=t.lastIndexOf("/");if(e<=0)return;let n=t.slice(0,e).split("/"),a="";for(let r of n)if(a=a?`${a}/${r}`:r,!this.vault.getAbstractFileByPath(a))try{await this.vault.createFolder(a)}catch(o){if(!(o instanceof Error?o.message:String(o)).includes("already exists"))throw o}}async clearPersistedState(){let t=this.getChatFilePath(),e=this.vault.getAbstractFileByPath(t);e instanceof Qe.TFile&&await this.vault.delete(e),this.messages=[],this.claudeSessionId=null,this.basePromptSent=!1}getChatFilePath(){if(this.threadAnchorId&&this.parentSession)return this.parentSession.getThreadFilePath(this.threadAnchorId);if(this.channelName&&this.conversationId){let s=this.settings.fleetFolder,n=ae(this.conversationId)||"conversation";return(0,Qe.normalizePath)(`${s}/channels/${this.channelName}/sessions/${n}.json`)}if(!this.inAppConversationId)throw new Error("ChatSession requires inAppConversationId (or channel options) to resolve a file path");let t=ae(this.inAppConversationId)||"conversation";if(this.agent.isFolder){let s=this.agent.filePath.replace(/\/agent\.md$/,"");return(0,Qe.normalizePath)(`${s}/conversations/${t}.json`)}let e=this.repository.getMemoryPath(this.agent.name).replace(/\/[^/]+$/,"");return(0,Qe.normalizePath)(`${e}/${this.agent.name}-conversations/${t}.json`)}getThreadFilePath(t){let e=this.getParentChatFilePath(),s=e.replace(/\/[^/]+$/,""),n=e.slice(s.length+1).replace(/\.json$/,"");return(0,Qe.normalizePath)(`${s}/${n}.threads/${t}.json`)}getParentChatFilePath(){if(this.channelName&&this.conversationId){let t=this.settings.fleetFolder,e=ae(this.conversationId)||"conversation";return(0,Qe.normalizePath)(`${t}/channels/${this.channelName}/sessions/${e}.json`)}if(this.inAppConversationId){let t=ae(this.inAppConversationId)||"conversation";if(this.agent.isFolder){let s=this.agent.filePath.replace(/\/agent\.md$/,"");return(0,Qe.normalizePath)(`${s}/conversations/${t}.json`)}let e=this.repository.getMemoryPath(this.agent.name).replace(/\/[^/]+$/,"");return(0,Qe.normalizePath)(`${e}/${this.agent.name}-conversations/${t}.json`)}throw new Error("ChatSession requires inAppConversationId (or channel options) to resolve a parent file path")}async ensureProcess(){if(this.process&&this.isProcessAlive)return;this.refreshAgent();let t=["--input-format","stream-json","--output-format","stream-json","--verbose"];this.claudeSessionId?(t.push("--resume",this.claudeSessionId),this.basePromptSent=!0,this.claudeResumeAttempted=!0):this.claudeResumeAttempted=!1;let e=Pt(null,this.agent,this.settings);gs(e.value)&&t.push("--model",e.value);let s=this.agent.permissionMode?.trim();s&&s!=="default"?t.push("--permission-mode",s):t.push("--permission-mode","bypassPermissions"),this.agent.effort&&t.push("--effort",this.agent.effort);let n=this.agent.cwd?.trim()?this.agent.cwd:this.repository.getVaultBasePath()??".",a=this.buildMcpProjection(n);t.push(...a.args),this.settingsState=Qs(n,this.agent,{mcpAllowServers:a.allowServers});let r=ot(this.settings.claudeCliPath,t,{cwd:n,env:{...process.env,AWS_REGION:this.settings.awsRegion,...a.env}});this.process=r,this.isProcessAlive=!0,this.stdoutBuffer="",this.processListeners={onStdout:o=>this.handleStdout(o),onStderr:()=>{},onError:o=>this.handleProcessError(o),onClose:()=>this.handleProcessClose()},r.stdout.on("data",this.processListeners.onStdout),r.stderr.on("data",this.processListeners.onStderr),r.on("error",this.processListeners.onError),r.on("close",this.processListeners.onClose)}detachProcessListeners(){this.process&&this.processListeners&&(this.process.stdout?.removeListener("data",this.processListeners.onStdout),this.process.stderr?.removeListener("data",this.processListeners.onStderr),this.process.removeListener("error",this.processListeners.onError),this.process.removeListener("close",this.processListeners.onClose)),this.processListeners=null}handleStdout(t){this.isStreaming&&this.armWatchdog(),this.stdoutBuffer+=t.toString();let e=pe(this.stdoutBuffer);this.stdoutBuffer=e.pop()??"";for(let s of e){let n=s.trim();if(n)try{let a=JSON.parse(n);this.handleEvent(a)}catch{}}}handleEvent(t){if(this.isCodex){this.handleCodexEvent(t);return}if(typeof t.session_id=="string"&&(this.claudeSessionId=t.session_id),this.updateStatsFromEvent(t),t.type==="system"&&t.subtype==="compact_boundary"){let s=t.compact_metadata,n=s&&typeof s.pre_tokens=="number"?s.pre_tokens:0,a=s&&typeof s.post_tokens=="number"?s.post_tokens:0;a>0&&(this.stats.contextTokensUsed=a),this.stats.lastCompact={preTokens:n,postTokens:a},this.emitStats(),this.needsCompactBeforeNextTurn=!1,this.activeOnEvent?.({type:"compacted",content:"",compact:{preTokens:n,postTokens:a}});return}if(t.type==="result"){let s=typeof t.api_error_status=="string"&&!!t.api_error_status;if(t.is_error===!0||s){let n=this.describeResultError(t);this.activeOnEvent?.({type:"error",content:"",errorMessage:n}),this.claudeResumeAttempted&&t.is_error===!0&&!s&&this.clearSessionId()}this.handleTurnEnd();return}let e=this.parseStreamEvent(t);e&&this.dispatchStreamEvent(e)}dispatchStreamEvent(t){let e=t;if(t.type==="text"){let s=this.turnResponseText.length===0;if(s&&(this.displayedLen=0),this.turnResponseText+=t.content,this.setCurrentTool(void 0),s&&this.turnResponseText.length>0&&this.emitActivity(),this.agent.memory){let n=ei(this.turnResponseText),a=n.length>this.displayedLen?n.slice(this.displayedLen):"";this.displayedLen=n.length,e={...t,content:a}}}else t.type==="tool_use"&&t.toolName&&(this.turnToolCalls.push({name:t.toolName,command:t.content||void 0}),this.setCurrentTool(t.toolName));this.activeOnEvent?.(e)}handleCodexEvent(t){this.codexTurnState||(this.codexTurnState=ha());let e=Gi(t,this.codexTurnState);for(let s of e)switch(s.kind){case"session":this.claudeSessionId=s.sessionId;break;case"text":this.dispatchStreamEvent({type:"text",content:s.text});break;case"tool":this.dispatchStreamEvent({type:"tool_use",content:s.command?s.command.slice(0,150):"",toolName:s.toolName});break;case"usage":{s.contextTokens>0&&s.contextTokens!==this.stats.contextTokensUsed&&(this.stats.contextTokensUsed=s.contextTokens),this.stats.turnCount+=1,this.emitStats();break}case"turn-failed":case"error":this.codexTurnErrors.push(s.message),this.activeOnEvent?.({type:"error",content:"",errorMessage:s.message});break}}get hasCurrentTurnText(){return this.turnResponseText.length>0}describeResultError(t){let e=[],s=typeof t.api_error_status=="string"?t.api_error_status:"",n=typeof t.subtype=="string"?t.subtype:"",a=typeof t.result=="string"?t.result:"";return s?e.push(`API ${s}`):n?e.push(n.replace(/_/g," ")):e.push("unknown error"),a&&e.push(`\u2014 ${a}`),e.join(" ")}updateStatsFromEvent(t){let e=!1,s=typeof t.model=="string"?t.model:void 0,n=t.message,a=n&&typeof n.model=="string"?n.model:void 0,r=s||a;if(r&&r!==this.stats.concreteModel&&(this.stats.concreteModel=r,e=!0),t.type==="rate_limit_event"){let o=t.rate_limit_info;o&&(this.stats.rateLimit={type:typeof o.rateLimitType=="string"?o.rateLimitType:"unknown",resetsAt:typeof o.resetsAt=="number"?o.resetsAt:void 0,status:typeof o.status=="string"?o.status:void 0,isUsingOverage:typeof o.isUsingOverage=="boolean"?o.isUsingOverage:void 0},e=!0)}if(t.type==="assistant"&&n){let o=n.usage;if(o){let c=typeof o.input_tokens=="number"?o.input_tokens:0,l=typeof o.cache_read_input_tokens=="number"?o.cache_read_input_tokens:0,d=typeof o.cache_creation_input_tokens=="number"?o.cache_creation_input_tokens:0,h=c+l+d;h>0&&h!==this.stats.contextTokensUsed&&(this.stats.contextTokensUsed=h,e=!0)}}if(t.type==="result"){let o=typeof t.total_cost_usd=="number"?t.total_cost_usd:0;o>0&&(this.stats.costTotalUsd+=o,e=!0);let c=t.modelUsage;if(c)for(let l of Object.values(c)){let d=l;typeof d.contextWindow=="number"&&d.contextWindow!==this.stats.contextWindow&&(this.stats.contextWindow=d.contextWindow,e=!0)}this.stats.turnCount+=1,e=!0}t.type==="result"&&this.evaluateAutoCompact(),e&&this.emitStats()}evaluateAutoCompact(){if(this.isCodex)return;let t=this.agent.autoCompactThreshold??0;if(t<=0||t>=100)return;let e=this.stats.contextWindow,s=this.stats.contextTokensUsed;!e||!s||s/e*100<t||Date.now()-this.lastCompactTriggerAt<3e4||(this.needsCompactBeforeNextTurn=!0)}handleTurnEnd(){this.lastActiveAt=Date.now();let t=this.turnResponseText,e=t;if(this.agent.memory){let n=js(t);e=ls(t),n.length>0&&this.memoryWriter.capture(this.agent,n,this.captureSource(),new Date().toISOString()).catch(a=>console.warn(`Agent Fleet: chat memory capture failed for "${this.agent.name}"`,a)),this.memoryWriter.drainPending(this.agent,new Date().toISOString()).catch(a=>console.warn(`Agent Fleet: chat pending drain failed for "${this.agent.name}"`,a))}e.trim()&&this.messages.push({id:ks(),role:"assistant",content:e,timestamp:new Date().toISOString(),toolCalls:this.turnToolCalls.length>0?[...this.turnToolCalls]:void 0});let s={text:this.turnResponseText,toolCalls:[...this.turnToolCalls]};if(this.activeOnEvent?.({type:"result",content:"",toolCalls:[...this.turnToolCalls]}),this.turnResponseText="",this.turnToolCalls=[],this.pendingTurns--,this.isCodex){let n=this.codexQueue.shift();if(n!==void 0){this.armWatchdog(),this.startCodexTurn(n).catch(a=>{this.handleProcessError(a instanceof Error?a:new Error(String(a)))});return}this.pendingTurns=0}if(this.pendingTurns<=0){this.pendingTurns=0,this.clearWatchdog(),this.setStreaming(!1),this.persist();let n=this.turnResolve;this.turnResolve=null,this.turnReject=null,n?.(s)}}handleProcessError(t){this.isProcessAlive=!1,this.process=null,this.pendingTurns=0,this.turnResponseText="",this.turnToolCalls=[],this.codexQueue=[],this.clearWatchdog(),this.setStreaming(!1),Et(this.settingsState),this.settingsState=null,this.codexPermState?.restore(),this.codexPermState=null,wt(this.mcpProjection),this.mcpProjection=null;let e=this.turnReject;this.turnResolve=null,this.turnReject=null,e?.(t)}handleProcessClose(){if(this.isProcessAlive=!1,this.process=null,Et(this.settingsState),this.settingsState=null,wt(this.mcpProjection),this.mcpProjection=null,this.turnResolve){this.claudeResumeAttempted&&!this.turnResponseText.trim()&&this.clearSessionId();let t={text:this.turnResponseText,toolCalls:[...this.turnToolCalls]};this.turnResponseText.trim()&&this.messages.push({id:ks(),role:"assistant",content:this.turnResponseText,timestamp:new Date().toISOString(),toolCalls:this.turnToolCalls.length>0?[...this.turnToolCalls]:void 0}),this.pendingTurns=0,this.turnResponseText="",this.turnToolCalls=[],this.clearWatchdog(),this.setStreaming(!1),this.persist();let e=this.turnResolve;this.turnResolve=null,this.turnReject=null,e?.(t)}}async sendMessage(t,e,s,n){this.lastActiveAt=Date.now(),this.messages.push({id:ks(),role:"user",content:t,timestamp:new Date().toISOString(),attachments:n&&n.length>0?n:void 0});let a=s??t;if(this.basePromptSent||(a=`${await this.buildBasePrompt()}
11964
+ Document the reliable steps to handle this so future runs don't rediscover them.`};try{await this.repository.writeProposal(o),a.proposed=!0,await this.repository.writeCandidates(t.name,e)}catch(c){console.warn(`Agent Fleet: failed to write proposal for "${t.name}"`,c)}}}async runPendingTask({task:t,promptOverride:e}){let s=this.repository.getAgentByName(t.agent);if(!s||!s.enabled)return;let n=new Date().toISOString();this.runtimeState.set(s.name,{status:"running",currentTaskId:t.taskId,runStarted:n}),this.runOutputBuffers.set(s.name,""),this.emitStatusChange();try{let a=await this.executor.execute(s,t,e,u=>{let p=this.runOutputBuffers.get(s.name)??"";this.runOutputBuffers.set(s.name,p+u);let m=this.runOutputListeners.get(s.name);if(m)for(let f of m)f(u)}),r=this.consumeAborted(s.name),o=r?[]:this.buildApprovals(s,a.toolsUsed),c=r?"cancelled":this.resolveRunStatus(a,o),l={runId:a.runId,agent:s.name,task:t.taskId,status:c,started:n,completed:new Date().toISOString(),durationSeconds:a.durationSeconds,tokensUsed:a.tokensUsed,costUsd:a.costUsd,model:a.resolvedModel||s.model,modelSource:a.modelSource,concreteModel:a.concreteModel,exitCode:a.exitCode,tags:Array.from(new Set([...s.tags,...t.tags])),prompt:a.prompt,output:a.outputText,toolsUsed:a.toolsUsed.map(u=>`${u.tool}${u.command?`: ${u.command}`:""}`),finalResult:a.finalResult,stderr:a.stderr,approvals:o},h=await this.repository.writeRunLog(l);if(await this.repository.updateTaskRunMetadata(t,{lastRun:n,runCount:t.runCount+1}),s.memory){let p=t.tags.includes("heartbeat")?"heartbeat":`task:${t.taskId}`,m=js(a.outputText);try{await this.memoryWriter.capture(s,m,p,new Date().toISOString())}catch(f){console.warn(`Agent Fleet: failed to append memory for "${s.name}"`,f)}}if(t.tags.includes("heartbeat")&&!r&&s.heartbeatChannel&&l.output.trim())try{this.heartbeatResultHandler?.(s.name,s.heartbeatChannel,l.output)}catch(u){console.warn(`Agent Fleet: heartbeat channel delivery failed for ${s.name}`,u)}r&&(l.output="Task was manually stopped."),await this.refreshRunCaches(),this.runtimeState.set(s.name,{status:r||c==="success"?"idle":c==="pending_approval"?"pending":"error",currentRunId:a.runId,lastRun:{...l,filePath:h}}),r||this.notify(l)}catch(a){let r=this.consumeAborted(s.name),o=r?"cancelled":"failure",c=Pt(t,s,this.settings),l={runId:(0,or.randomUUID)(),agent:s.name,task:t.taskId,status:o,started:n,completed:new Date().toISOString(),durationSeconds:Math.round((Date.now()-new Date(n).getTime())/1e3),model:c.value||s.model,modelSource:c.source,exitCode:r?-1:1,tags:Array.from(new Set([...s.tags,...t.tags])),prompt:e??t.body,output:r?"Task was manually stopped.":a instanceof Error?a.message:String(a),toolsUsed:[]},h=await this.repository.writeRunLog(l);await this.refreshRunCaches(),this.runtimeState.set(s.name,{status:r?"idle":"error",lastRun:{...l,filePath:h}}),r||this.notify(l)}finally{if(s.memory)try{await this.memoryWriter.drainPending(s,new Date().toISOString())}catch(a){console.warn(`Agent Fleet: failed to drain pending memory for "${s.name}"`,a)}this.runOutputBuffers.delete(s.name),this.runOutputListeners.delete(s.name),this.emitStatusChange()}}buildApprovals(t,e){let s=e.filter(n=>t.approvalRequired.includes(n.tool)).map(n=>({tool:n.tool,command:n.command,reason:n.reason,status:"pending"}));return s.length>0?s:void 0}resolveRunStatus(t,e){return e?.length?"pending_approval":t.timedOut?"timeout":t.exitCode===0?"success":"failure"}notify(t){if(this.settings.notificationLevel==="none"||this.settings.notificationLevel==="failures-only"&&t.status==="success")return;let s=(ge(t.output).map(a=>a.trim()).find(a=>a&&!a.startsWith("{")&&!a.startsWith("["))??"").slice(0,120)||t.status,n=t.status==="success"?`\u2705 ${t.agent}: ${s}`:t.status==="pending_approval"?`\u{1F535} ${t.agent} needs approval: ${(t.approvals??[])[0]?.tool??"tool action"}`:`\u274C ${t.agent}: ${s}`;new lr.Notice(n,t.status==="success"?5e3:0)}emitStatusChange(){for(let t of this.statusChangeListeners)t()}};function Yl(i){return i.toLowerCase().replace(/[^a-z0-9-]/g,"-").replace(/-{2,}/g,"-").replace(/^-|-$/g,"")}function ws(i,t){return`${i}-${Yl(t)}`}var qt="af-channel-cred",bs="af-mcp-secret",hn=class{constructor(t){this.storage=t;t||console.warn("Agent Fleet: SecretStorage unavailable (Obsidian < 1.11.4). Secrets will use plaintext fallback.")}get available(){return!!this.storage}setJson(t,e,s){if(!this.storage)return;let n=ws(t,e);this.storage.setSecret(n,JSON.stringify(s))}getJson(t,e){if(!this.storage)return null;let s=ws(t,e),n=this.storage.getSecret(s);if(!n)return null;try{return JSON.parse(n)}catch{return null}}setString(t,e,s){if(!this.storage)return;let n=ws(t,e);this.storage.setSecret(n,s)}getString(t,e){if(!this.storage)return null;let s=ws(t,e);return this.storage.getSecret(s)||null}delete(t,e){if(!this.storage)return;let s=ws(t,e);this.storage.setSecret(s,"")}listByPrefix(t){return this.storage?this.storage.listSecrets().filter(e=>e.startsWith(t+"-")):[]}};var un=class{tokens=new Map;oauthTokens=new Map;secretStore;setSecretStore(t){this.secretStore=t}storeProbeToken(t,e){this.tokens.set(t,e)}storeStaticToken(t,e){this.tokens.set(t,e),this.secretStore?.setJson(bs,t,{accessToken:e})}storeOAuthToken(t,e){this.oauthTokens.set(t,e),this.tokens.set(t,e.accessToken),this.secretStore?.setJson(bs,t,{accessToken:e.accessToken,refreshToken:e.refreshToken,expiresAt:e.expiresAt,tokenEndpoint:e.tokenEndpoint,clientId:e.clientId,resource:e.resource})}hydrate(t){if(!this.secretStore)return null;let e=this.secretStore.getJson(bs,t);return e?.accessToken?(this.tokens.set(t,e.accessToken),e.tokenEndpoint&&e.clientId&&e.resource&&this.oauthTokens.set(t,{accessToken:e.accessToken,refreshToken:e.refreshToken,expiresAt:e.expiresAt,tokenEndpoint:e.tokenEndpoint,clientId:e.clientId,resource:e.resource}),e):null}getToken(t){return this.tokens.get(t)??this.hydrate(t)?.accessToken??void 0}getOAuthToken(t){return this.oauthTokens.has(t)?this.oauthTokens.get(t):(this.hydrate(t),this.oauthTokens.get(t))}hasToken(t){return this.tokens.has(t)||!!this.hydrate(t)}removeToken(t){this.tokens.delete(t),this.oauthTokens.delete(t),this.secretStore?.delete(bs,t)}getExpiringTokens(t=5*6e4){let e=new Map,s=Date.now();for(let[n,a]of this.oauthTokens)a.refreshToken&&a.expiresAt&&a.expiresAt-s<t&&e.set(n,a);return e}};var dt=require("obsidian");var pn=require("crypto"),it=require("obsidian");function ks(){return(0,pn.randomUUID)()}function cr(i){let t=`${i.timestamp}|${i.content.slice(0,80)}`;return(0,pn.createHash)("sha1").update(t).digest("hex").slice(0,16)}var zt=class i{constructor(t,e,s,n,a){this.agent=t;this.settings=e;this.repository=s;this.vault=n,this.channelName=a?.channelName,this.conversationId=a?.conversationId,this.channelContext=a?.channelContext,this.inAppConversationId=a?.inAppConversationId,this.threadAnchorId=a?.threadAnchorId,this.parentSession=a?.parentSession,this.mcpAuth=a?.mcpAuth,this.memoryWriter=new Ht(s)}messages=[];isStreaming=!1;isProcessAlive=!1;settingsState=null;mcpProjection=null;get pendingTurnCount(){return this.pendingTurns}lastActiveAt=Date.now();process=null;claudeSessionId=null;claudeResumeAttempted=!1;vault;stdoutBuffer="";processListeners=null;basePromptSent=!1;codexTurnState=null;codexQueue=[];codexResumeAttempted=!1;codexTurnErrors=[];codexStderr="";codexPermState=null;get isCodex(){return wt(this.agent.adapter)==="codex"}channelName;conversationId;channelContext;inAppConversationId;conversationName="";threadAnchorId;parentSession;threadAnchorIndex;threads=new Map;threadIndex={};activeOnEvent=null;turnResponseText="";displayedLen=0;turnToolCalls=[];pendingTurns=0;turnResolve=null;turnReject=null;needsCompactBeforeNextTurn=!1;lastCompactTriggerAt=0;static WATCHDOG_FALLBACK_MINUTES=10;watchdogTimer=null;getWatchdogMs(){let t=this.settings.chatWatchdogMinutes;return(typeof t=="number"&&t>0?t:i.WATCHDOG_FALLBACK_MINUTES)*60*1e3}armWatchdog(){this.clearWatchdog();let t=this.getWatchdogMs();this.watchdogTimer=window.setTimeout(()=>{if(this.watchdogTimer=null,!this.isStreaming)return;this.activeOnEvent?.({type:"error",content:"",errorMessage:`no response from the CLI for ${Math.round(t/6e4)} minutes \u2014 giving up`});let e=new Error("Watchdog timeout");this.handleProcessError(e);try{this.process?.kill()}catch{}},t)}clearWatchdog(){this.watchdogTimer&&(window.clearTimeout(this.watchdogTimer),this.watchdogTimer=null)}currentToolName;activityListeners=new Set;onActivityChange(t){return this.activityListeners.add(t),t(),()=>{this.activityListeners.delete(t)}}emitActivity(){for(let t of this.activityListeners)t()}setStreaming(t){this.isStreaming!==t&&(this.isStreaming=t,t||(this.currentToolName=void 0),this.emitActivity())}setCurrentTool(t){this.currentToolName!==t&&(this.currentToolName=t,this.emitActivity())}stats={costTotalUsd:0,turnCount:0};statsListeners=new Set;onStatsChange(t){return this.statsListeners.add(t),t({...this.stats}),()=>{this.statsListeners.delete(t)}}getStats(){return{...this.stats}}emitStats(){let t={...this.stats};for(let e of this.statsListeners)e(t)}mcpAuth;buildMcpProjection(t){let e=this.agent.memory?this.repository.getPendingDirAbsolutePath(this.agent.name):null,s=an({registry:this.repository.getMcpServers(),agentGrants:this.agent.mcpServers??[],getBearerToken:n=>this.mcpAuth?.getToken(n),remember:e?{pendingDir:e,source:`mcp:${this.captureSource()}`}:null});return this.mcpProjection=rn(t,this.agent.adapter,s),{args:this.mcpProjection?.args??[],env:this.mcpProjection?.env??{},allowServers:s.map(n=>n.def.name)}}memoryWriter;captureSource(){return`chat:${this.inAppConversationId||this.conversationId||"default"}`}getConversationName(){return this.conversationName}async setConversationName(t){this.conversationName=t,await this.persist()}refreshAgent(){let t=this.repository.getAgentByName(this.agent.name);t&&(this.agent=t)}get isThread(){return!!this.threadAnchorId}async loadPersistedState(){let t=this.getChatFilePath(),e=this.vault.getAbstractFileByPath(t);if(!(e instanceof it.TFile))return!1;try{let s=await this.vault.cachedRead(e);if(this.isThread){let a=JSON.parse(s);return a.messages?.length>0||a.sessionId?(this.messages=(a.messages??[]).map(r=>r.id?r:{...r,id:cr(r)}),this.claudeSessionId=a.sessionId??null,this.threadAnchorIndex=a.anchorIndex,this.claudeSessionId&&(this.basePromptSent=!0),!0):!1}let n=JSON.parse(s);if(n.name&&(this.conversationName=n.name),n.messages?.length>0)return this.messages=n.messages.map(a=>a.id?a:{...a,id:cr(a)}),this.claudeSessionId=n.sessionId??null,this.threadIndex=n.threads??{},this.claudeSessionId&&(this.basePromptSent=!0),!0}catch{}return!1}getThreadIndex(){return{...this.threadIndex}}async persist(){let t=new Date().toISOString(),e=this.getChatFilePath(),s;if(this.isThread){let a={anchorMessageId:this.threadAnchorId,anchorIndex:this.threadAnchorIndex??0,sessionId:this.claudeSessionId,messages:this.messages,createdAt:this.parentSession?.threadIndex[this.threadAnchorId]?.createdAt??t,lastActive:t};s=JSON.stringify(a,null,2)}else{let a={sessionId:this.claudeSessionId,messages:this.messages,lastActive:t,name:this.conversationName||void 0,threads:Object.keys(this.threadIndex).length>0?this.threadIndex:void 0};s=JSON.stringify(a,null,2)}let n=this.vault.getAbstractFileByPath(e);n instanceof it.TFile?await this.vault.modify(n,s):(await this.ensureParentFolders(e),await this.vault.create(e,s)),this.isThread&&this.parentSession&&this.threadAnchorId&&await this.parentSession.upsertThreadIndex(this.threadAnchorId,{path:e,createdAt:this.parentSession.threadIndex[this.threadAnchorId]?.createdAt??t,messageCount:this.messages.length,lastActive:t})}async upsertThreadIndex(t,e){this.threadIndex[t]=e,await this.persist()}async ensureParentFolders(t){let e=t.lastIndexOf("/");if(e<=0)return;let n=t.slice(0,e).split("/"),a="";for(let r of n)if(a=a?`${a}/${r}`:r,!this.vault.getAbstractFileByPath(a))try{await this.vault.createFolder(a)}catch(o){if(!(o instanceof Error?o.message:String(o)).includes("already exists"))throw o}}async clearPersistedState(){let t=this.getChatFilePath();await this.repository.trashFile(t),this.messages=[],this.claudeSessionId=null,this.basePromptSent=!1}getChatFilePath(){if(this.threadAnchorId&&this.parentSession)return this.parentSession.getThreadFilePath(this.threadAnchorId);if(this.channelName&&this.conversationId){let s=this.settings.fleetFolder,n=oe(this.conversationId)||"conversation";return(0,it.normalizePath)(`${s}/channels/${this.channelName}/sessions/${n}.json`)}if(!this.inAppConversationId)throw new Error("ChatSession requires inAppConversationId (or channel options) to resolve a file path");let t=oe(this.inAppConversationId)||"conversation";if(this.agent.isFolder){let s=this.agent.filePath.replace(/\/agent\.md$/,"");return(0,it.normalizePath)(`${s}/conversations/${t}.json`)}let e=this.repository.getMemoryPath(this.agent.name).replace(/\/[^/]+$/,"");return(0,it.normalizePath)(`${e}/${this.agent.name}-conversations/${t}.json`)}getThreadFilePath(t){let e=this.getParentChatFilePath(),s=e.replace(/\/[^/]+$/,""),n=e.slice(s.length+1).replace(/\.json$/,"");return(0,it.normalizePath)(`${s}/${n}.threads/${t}.json`)}getParentChatFilePath(){if(this.channelName&&this.conversationId){let t=this.settings.fleetFolder,e=oe(this.conversationId)||"conversation";return(0,it.normalizePath)(`${t}/channels/${this.channelName}/sessions/${e}.json`)}if(this.inAppConversationId){let t=oe(this.inAppConversationId)||"conversation";if(this.agent.isFolder){let s=this.agent.filePath.replace(/\/agent\.md$/,"");return(0,it.normalizePath)(`${s}/conversations/${t}.json`)}let e=this.repository.getMemoryPath(this.agent.name).replace(/\/[^/]+$/,"");return(0,it.normalizePath)(`${e}/${this.agent.name}-conversations/${t}.json`)}throw new Error("ChatSession requires inAppConversationId (or channel options) to resolve a parent file path")}async ensureProcess(){if(this.process&&this.isProcessAlive)return;this.refreshAgent();let t=["--input-format","stream-json","--output-format","stream-json","--verbose"];this.claudeSessionId?(t.push("--resume",this.claudeSessionId),this.basePromptSent=!0,this.claudeResumeAttempted=!0):this.claudeResumeAttempted=!1;let e=Pt(null,this.agent,this.settings);gs(e.value)&&t.push("--model",e.value);let s=this.agent.permissionMode?.trim();s&&s!=="default"?t.push("--permission-mode",s):t.push("--permission-mode","bypassPermissions"),this.agent.effort&&t.push("--effort",this.agent.effort);let n=this.agent.cwd?.trim()?this.agent.cwd:this.repository.getVaultBasePath()??".",a=this.buildMcpProjection(n);t.push(...a.args),this.settingsState=Qs(n,this.agent,{mcpAllowServers:a.allowServers});let r=lt(this.settings.claudeCliPath,t,{cwd:n,env:{...process.env,AWS_REGION:this.settings.awsRegion,...a.env}});this.process=r,this.isProcessAlive=!0,this.stdoutBuffer="",this.processListeners={onStdout:o=>this.handleStdout(o),onStderr:()=>{},onError:o=>this.handleProcessError(o),onClose:()=>this.handleProcessClose()},r.stdout.on("data",this.processListeners.onStdout),r.stderr.on("data",this.processListeners.onStderr),r.on("error",this.processListeners.onError),r.on("close",this.processListeners.onClose)}detachProcessListeners(){this.process&&this.processListeners&&(this.process.stdout?.removeListener("data",this.processListeners.onStdout),this.process.stderr?.removeListener("data",this.processListeners.onStderr),this.process.removeListener("error",this.processListeners.onError),this.process.removeListener("close",this.processListeners.onClose)),this.processListeners=null}handleStdout(t){this.isStreaming&&this.armWatchdog(),this.stdoutBuffer+=t.toString();let e=ge(this.stdoutBuffer);this.stdoutBuffer=e.pop()??"";for(let s of e){let n=s.trim();if(n)try{let a=JSON.parse(n);this.handleEvent(a)}catch{}}}handleEvent(t){if(this.isCodex){this.handleCodexEvent(t);return}if(typeof t.session_id=="string"&&(this.claudeSessionId=t.session_id),this.updateStatsFromEvent(t),t.type==="system"&&t.subtype==="compact_boundary"){let s=t.compact_metadata,n=s&&typeof s.pre_tokens=="number"?s.pre_tokens:0,a=s&&typeof s.post_tokens=="number"?s.post_tokens:0;a>0&&(this.stats.contextTokensUsed=a),this.stats.lastCompact={preTokens:n,postTokens:a},this.emitStats(),this.needsCompactBeforeNextTurn=!1,this.activeOnEvent?.({type:"compacted",content:"",compact:{preTokens:n,postTokens:a}});return}if(t.type==="result"){let s=typeof t.api_error_status=="string"&&!!t.api_error_status;if(t.is_error===!0||s){let n=this.describeResultError(t);this.activeOnEvent?.({type:"error",content:"",errorMessage:n}),this.claudeResumeAttempted&&t.is_error===!0&&!s&&this.clearSessionId()}this.handleTurnEnd();return}let e=this.parseStreamEvent(t);e&&this.dispatchStreamEvent(e)}dispatchStreamEvent(t){let e=t;if(t.type==="text"){let s=this.turnResponseText.length===0;if(s&&(this.displayedLen=0),this.turnResponseText+=t.content,this.setCurrentTool(void 0),s&&this.turnResponseText.length>0&&this.emitActivity(),this.agent.memory){let n=ti(this.turnResponseText),a=n.length>this.displayedLen?n.slice(this.displayedLen):"";this.displayedLen=n.length,e={...t,content:a}}}else t.type==="tool_use"&&t.toolName&&(this.turnToolCalls.push({name:t.toolName,command:t.content||void 0}),this.setCurrentTool(t.toolName));this.activeOnEvent?.(e)}handleCodexEvent(t){this.codexTurnState||(this.codexTurnState=ha());let e=Vi(t,this.codexTurnState);for(let s of e)switch(s.kind){case"session":this.claudeSessionId=s.sessionId;break;case"text":this.dispatchStreamEvent({type:"text",content:s.text});break;case"tool":this.dispatchStreamEvent({type:"tool_use",content:s.command?s.command.slice(0,150):"",toolName:s.toolName});break;case"usage":{s.contextTokens>0&&s.contextTokens!==this.stats.contextTokensUsed&&(this.stats.contextTokensUsed=s.contextTokens),this.stats.turnCount+=1,this.emitStats();break}case"turn-failed":case"error":this.codexTurnErrors.push(s.message),this.activeOnEvent?.({type:"error",content:"",errorMessage:s.message});break}}get hasCurrentTurnText(){return this.turnResponseText.length>0}describeResultError(t){let e=[],s=typeof t.api_error_status=="string"?t.api_error_status:"",n=typeof t.subtype=="string"?t.subtype:"",a=typeof t.result=="string"?t.result:"";return s?e.push(`API ${s}`):n?e.push(n.replace(/_/g," ")):e.push("unknown error"),a&&e.push(`\u2014 ${a}`),e.join(" ")}updateStatsFromEvent(t){let e=!1,s=typeof t.model=="string"?t.model:void 0,n=t.message,a=n&&typeof n.model=="string"?n.model:void 0,r=s||a;if(r&&r!==this.stats.concreteModel&&(this.stats.concreteModel=r,e=!0),t.type==="rate_limit_event"){let o=t.rate_limit_info;o&&(this.stats.rateLimit={type:typeof o.rateLimitType=="string"?o.rateLimitType:"unknown",resetsAt:typeof o.resetsAt=="number"?o.resetsAt:void 0,status:typeof o.status=="string"?o.status:void 0,isUsingOverage:typeof o.isUsingOverage=="boolean"?o.isUsingOverage:void 0},e=!0)}if(t.type==="assistant"&&n){let o=n.usage;if(o){let c=typeof o.input_tokens=="number"?o.input_tokens:0,l=typeof o.cache_read_input_tokens=="number"?o.cache_read_input_tokens:0,h=typeof o.cache_creation_input_tokens=="number"?o.cache_creation_input_tokens:0,d=c+l+h;d>0&&d!==this.stats.contextTokensUsed&&(this.stats.contextTokensUsed=d,e=!0)}}if(t.type==="result"){let o=typeof t.total_cost_usd=="number"?t.total_cost_usd:0;o>0&&(this.stats.costTotalUsd+=o,e=!0);let c=t.modelUsage;if(c)for(let l of Object.values(c)){let h=l;typeof h.contextWindow=="number"&&h.contextWindow!==this.stats.contextWindow&&(this.stats.contextWindow=h.contextWindow,e=!0)}this.stats.turnCount+=1,e=!0}t.type==="result"&&this.evaluateAutoCompact(),e&&this.emitStats()}evaluateAutoCompact(){if(this.isCodex)return;let t=this.agent.autoCompactThreshold??0;if(t<=0||t>=100)return;let e=this.stats.contextWindow,s=this.stats.contextTokensUsed;!e||!s||s/e*100<t||Date.now()-this.lastCompactTriggerAt<3e4||(this.needsCompactBeforeNextTurn=!0)}handleTurnEnd(){this.lastActiveAt=Date.now();let t=this.turnResponseText,e=t;if(this.agent.memory){let n=js(t);e=ls(t),n.length>0&&this.memoryWriter.capture(this.agent,n,this.captureSource(),new Date().toISOString()).catch(a=>console.warn(`Agent Fleet: chat memory capture failed for "${this.agent.name}"`,a)),this.memoryWriter.drainPending(this.agent,new Date().toISOString()).catch(a=>console.warn(`Agent Fleet: chat pending drain failed for "${this.agent.name}"`,a))}e.trim()&&this.messages.push({id:ks(),role:"assistant",content:e,timestamp:new Date().toISOString(),toolCalls:this.turnToolCalls.length>0?[...this.turnToolCalls]:void 0});let s={text:this.turnResponseText,toolCalls:[...this.turnToolCalls]};if(this.activeOnEvent?.({type:"result",content:"",toolCalls:[...this.turnToolCalls]}),this.turnResponseText="",this.turnToolCalls=[],this.pendingTurns--,this.isCodex){let n=this.codexQueue.shift();if(n!==void 0){this.armWatchdog(),this.startCodexTurn(n).catch(a=>{this.handleProcessError(a instanceof Error?a:new Error(String(a)))});return}this.pendingTurns=0}if(this.pendingTurns<=0){this.pendingTurns=0,this.clearWatchdog(),this.setStreaming(!1),this.persist();let n=this.turnResolve;this.turnResolve=null,this.turnReject=null,n?.(s)}}handleProcessError(t){this.isProcessAlive=!1,this.process=null,this.pendingTurns=0,this.turnResponseText="",this.turnToolCalls=[],this.codexQueue=[],this.clearWatchdog(),this.setStreaming(!1),Et(this.settingsState),this.settingsState=null,this.codexPermState?.restore(),this.codexPermState=null,bt(this.mcpProjection),this.mcpProjection=null;let e=this.turnReject;this.turnResolve=null,this.turnReject=null,e?.(t)}handleProcessClose(){if(this.isProcessAlive=!1,this.process=null,Et(this.settingsState),this.settingsState=null,bt(this.mcpProjection),this.mcpProjection=null,this.turnResolve){this.claudeResumeAttempted&&!this.turnResponseText.trim()&&this.clearSessionId();let t={text:this.turnResponseText,toolCalls:[...this.turnToolCalls]};this.turnResponseText.trim()&&this.messages.push({id:ks(),role:"assistant",content:this.turnResponseText,timestamp:new Date().toISOString(),toolCalls:this.turnToolCalls.length>0?[...this.turnToolCalls]:void 0}),this.pendingTurns=0,this.turnResponseText="",this.turnToolCalls=[],this.clearWatchdog(),this.setStreaming(!1),this.persist();let e=this.turnResolve;this.turnResolve=null,this.turnReject=null,e?.(t)}}async sendMessage(t,e,s,n){this.lastActiveAt=Date.now(),this.messages.push({id:ks(),role:"user",content:t,timestamp:new Date().toISOString(),attachments:n&&n.length>0?n:void 0});let a=s??t;if(this.basePromptSent||(a=`${await this.buildBasePrompt()}
11965
11965
 
11966
11966
  ## Task
11967
11967
  ${a}`,this.basePromptSent=!0),this.isCodex){this.stats.lastCompact&&(this.stats.lastCompact=void 0,this.emitStats()),this.activeOnEvent=e,this.turnResponseText="",this.turnToolCalls=[],this.pendingTurns=1,this.setStreaming(!0),this.armWatchdog();try{await this.startCodexTurn(a)}catch(c){throw this.pendingTurns=0,this.clearWatchdog(),this.setStreaming(!1),new Error(`Failed to start Codex process: ${c instanceof Error?c.message:String(c)}`)}return new Promise((c,l)=>{this.turnResolve=c,this.turnReject=l})}await this.ensureProcess();let r=this.needsCompactBeforeNextTurn;r&&(this.needsCompactBeforeNextTurn=!1,this.lastCompactTriggerAt=Date.now()),this.stats.lastCompact&&(this.stats.lastCompact=void 0,this.emitStats()),this.activeOnEvent=e,this.turnResponseText="",this.turnToolCalls=[],this.pendingTurns=r?2:1,this.setStreaming(!0),this.armWatchdog();let o=c=>{let l=JSON.stringify({type:"user",message:{role:"user",content:c}});this.process.stdin.write(l+`
11968
- `)};try{r&&o("/compact"),o(a)}catch(c){throw this.pendingTurns=0,this.setStreaming(!1),new Error(`Failed to write to Claude process stdin: ${c instanceof Error?c.message:String(c)}`)}return new Promise((c,l)=>{this.turnResolve=c,this.turnReject=l})}scheduleCompact(){this.isCodex||(this.needsCompactBeforeNextTurn=!0)}async startCodexTurn(t){this.refreshAgent();let e=Pt(null,this.agent,this.settings),s=await fs.buildExec({prompt:t,model:gs(e.value)?e.value:"",modelSource:e.source,effort:this.agent.effort??"",agent:this.agent,settings:this.settings,streaming:!0,resumeSessionId:this.claudeSessionId});e.value&&this.stats.concreteModel!==e.value&&(this.stats.concreteModel=e.value,this.emitStats()),this.codexTurnState=ha(),this.codexResumeAttempted=!!this.claudeSessionId,this.codexTurnErrors=[],this.codexStderr="";let n=this.agent.cwd?.trim()?this.agent.cwd:this.repository.getVaultBasePath()??".",a=this.buildMcpProjection(n);s.args.push(...a.args),this.codexPermState=await fs.setupPermissions(n,this.agent,this.settings);let r=ot(s.cliPath,s.args,{cwd:n,env:{...process.env,AWS_REGION:this.settings.awsRegion,...a.env,...this.codexPermState?.env??{}}});this.process=r,this.isProcessAlive=!0,this.stdoutBuffer="",this.processListeners={onStdout:o=>this.handleStdout(o),onStderr:o=>{this.codexStderr+=o.toString()},onError:o=>this.handleProcessError(o),onClose:o=>this.handleCodexProcessClose(o)},r.stdout.on("data",this.processListeners.onStdout),r.stderr.on("data",this.processListeners.onStderr),r.on("error",this.processListeners.onError),r.on("close",this.processListeners.onClose);try{r.stdin.write(s.stdinPayload??t),r.stdin.end()}catch(o){try{r.kill()}catch{}throw o instanceof Error?o:new Error(String(o))}}handleCodexProcessClose(t){if(this.detachProcessListeners(),this.isProcessAlive=!1,this.process=null,this.stdoutBuffer="",this.codexPermState?.restore(),this.codexPermState=null,wt(this.mcpProjection),this.mcpProjection=null,t!==0&&!this.turnResponseText.trim()){let s=this.codexTurnErrors.join("; ")||this.codexStderr.trim().slice(-500)||`Codex CLI exited with code ${t??"unknown"}`;this.codexResumeAttempted&&this.clearSessionId(),this.codexQueue=[],this.activeOnEvent?.({type:"error",content:"",errorMessage:s})}this.handleTurnEnd()}injectMessage(t,e,s){if(this.isCodex){if(!this.isStreaming&&this.pendingTurns===0)return;this.messages.push({id:ks(),role:"user",content:t,timestamp:new Date().toISOString(),attachments:s&&s.length>0?s:void 0}),this.codexQueue.push(e??t),this.pendingTurns++;return}if(!this.process||!this.isProcessAlive)return;this.messages.push({id:ks(),role:"user",content:t,timestamp:new Date().toISOString(),attachments:s&&s.length>0?s:void 0});let a=JSON.stringify({type:"user",message:{role:"user",content:e??t}});try{this.process.stdin.write(a+`
11969
- `)}catch(r){console.warn("Agent Fleet: injectMessage stdin write failed",r);return}this.pendingTurns++}abort(){this.detachProcessListeners(),this.process&&(this.process.kill(),this.process=null),this.isProcessAlive=!1,this.stdoutBuffer="",this.turnResponseText="",this.turnToolCalls=[],this.pendingTurns=0,this.codexQueue=[],this.clearWatchdog(),this.setStreaming(!1),Et(this.settingsState),this.settingsState=null,this.codexPermState?.restore(),this.codexPermState=null,wt(this.mcpProjection),this.mcpProjection=null;let t=this.turnReject;this.turnResolve=null,this.turnReject=null,t?.(new Error("Aborted"))}dispose(){for(let t of this.threads.values())t.abort();this.threads.clear(),this.threadIndex={},this.abort()}hibernate(){this.isStreaming||this.pendingTurns>0||(this.detachProcessListeners(),this.process&&(this.process.kill(),this.process=null),this.isProcessAlive=!1,this.stdoutBuffer="",Et(this.settingsState),this.settingsState=null,wt(this.mcpProjection),this.mcpProjection=null)}clearSessionId(){this.claudeSessionId=null,this.basePromptSent=!1,this.claudeResumeAttempted=!1}async buildBasePrompt(){let t=[this.agent.body.trim()];for(let s of this.agent.skills){let n=this.repository.getSkillByName(s);if(n){let a=[n.body.trim()];n.toolsBody.trim()&&a.push(`### Tools
11968
+ `)};try{r&&o("/compact"),o(a)}catch(c){throw this.pendingTurns=0,this.setStreaming(!1),new Error(`Failed to write to Claude process stdin: ${c instanceof Error?c.message:String(c)}`)}return new Promise((c,l)=>{this.turnResolve=c,this.turnReject=l})}scheduleCompact(){this.isCodex||(this.needsCompactBeforeNextTurn=!0)}async startCodexTurn(t){this.refreshAgent();let e=Pt(null,this.agent,this.settings),s=await fs.buildExec({prompt:t,model:gs(e.value)?e.value:"",modelSource:e.source,effort:this.agent.effort??"",agent:this.agent,settings:this.settings,streaming:!0,resumeSessionId:this.claudeSessionId});e.value&&this.stats.concreteModel!==e.value&&(this.stats.concreteModel=e.value,this.emitStats()),this.codexTurnState=ha(),this.codexResumeAttempted=!!this.claudeSessionId,this.codexTurnErrors=[],this.codexStderr="";let n=this.agent.cwd?.trim()?this.agent.cwd:this.repository.getVaultBasePath()??".",a=this.buildMcpProjection(n);s.args.push(...a.args),this.codexPermState=await fs.setupPermissions(n,this.agent,this.settings);let r=lt(s.cliPath,s.args,{cwd:n,env:{...process.env,AWS_REGION:this.settings.awsRegion,...a.env,...this.codexPermState?.env??{}}});this.process=r,this.isProcessAlive=!0,this.stdoutBuffer="",this.processListeners={onStdout:o=>this.handleStdout(o),onStderr:o=>{this.codexStderr+=o.toString()},onError:o=>this.handleProcessError(o),onClose:o=>this.handleCodexProcessClose(o)},r.stdout.on("data",this.processListeners.onStdout),r.stderr.on("data",this.processListeners.onStderr),r.on("error",this.processListeners.onError),r.on("close",this.processListeners.onClose);try{r.stdin.write(s.stdinPayload??t),r.stdin.end()}catch(o){try{r.kill()}catch{}throw o instanceof Error?o:new Error(String(o))}}handleCodexProcessClose(t){if(this.detachProcessListeners(),this.isProcessAlive=!1,this.process=null,this.stdoutBuffer="",this.codexPermState?.restore(),this.codexPermState=null,bt(this.mcpProjection),this.mcpProjection=null,t!==0&&!this.turnResponseText.trim()){let s=this.codexTurnErrors.join("; ")||this.codexStderr.trim().slice(-500)||`Codex CLI exited with code ${t??"unknown"}`;this.codexResumeAttempted&&this.clearSessionId(),this.codexQueue=[],this.activeOnEvent?.({type:"error",content:"",errorMessage:s})}this.handleTurnEnd()}injectMessage(t,e,s){if(this.isCodex){if(!this.isStreaming&&this.pendingTurns===0)return;this.messages.push({id:ks(),role:"user",content:t,timestamp:new Date().toISOString(),attachments:s&&s.length>0?s:void 0}),this.codexQueue.push(e??t),this.pendingTurns++;return}if(!this.process||!this.isProcessAlive)return;this.messages.push({id:ks(),role:"user",content:t,timestamp:new Date().toISOString(),attachments:s&&s.length>0?s:void 0});let a=JSON.stringify({type:"user",message:{role:"user",content:e??t}});try{this.process.stdin.write(a+`
11969
+ `)}catch(r){console.warn("Agent Fleet: injectMessage stdin write failed",r);return}this.pendingTurns++}abort(){this.detachProcessListeners(),this.process&&(this.process.kill(),this.process=null),this.isProcessAlive=!1,this.stdoutBuffer="",this.turnResponseText="",this.turnToolCalls=[],this.pendingTurns=0,this.codexQueue=[],this.clearWatchdog(),this.setStreaming(!1),Et(this.settingsState),this.settingsState=null,this.codexPermState?.restore(),this.codexPermState=null,bt(this.mcpProjection),this.mcpProjection=null;let t=this.turnReject;this.turnResolve=null,this.turnReject=null,t?.(new Error("Aborted"))}dispose(){for(let t of this.threads.values())t.abort();this.threads.clear(),this.threadIndex={},this.abort()}hibernate(){this.isStreaming||this.pendingTurns>0||(this.detachProcessListeners(),this.process&&(this.process.kill(),this.process=null),this.isProcessAlive=!1,this.stdoutBuffer="",Et(this.settingsState),this.settingsState=null,bt(this.mcpProjection),this.mcpProjection=null)}clearSessionId(){this.claudeSessionId=null,this.basePromptSent=!1,this.claudeResumeAttempted=!1}async buildBasePrompt(){let t=[this.agent.body.trim()];for(let s of this.agent.skills){let n=this.repository.getSkillByName(s);if(n){let a=[n.body.trim()];n.toolsBody.trim()&&a.push(`### Tools
11970
11970
  ${n.toolsBody.trim()}`),n.referencesBody.trim()&&a.push(`### References
11971
11971
  ${n.referencesBody.trim()}`),n.examplesBody.trim()&&a.push(`### Examples
11972
11972
  ${n.examplesBody.trim()}`),t.push(`## Skill: ${n.name}
@@ -11981,15 +11981,15 @@ ${s}
11981
11981
  ${a.join(`
11982
11982
  `)}`)}return t.filter(Boolean).join(`
11983
11983
 
11984
- `)}async openOrCreateThread(t){if(this.isThread)throw new Error("Nested threads are not supported.");let e=this.threads.get(t);if(e)return e;let s=this.messages.findIndex(r=>r.id===t);if(s<0)throw new Error(`Thread anchor message "${t}" not found in parent.`);let n=new i(this.agent,this.settings,this.repository,this.vault,{threadAnchorId:t,parentSession:this,mcpAuth:this.mcpAuth});return n.threadAnchorIndex=s,await n.loadPersistedState()||(n.threadAnchorIndex=s),this.threads.set(t,n),n}closeThread(t){let e=this.threads.get(t);e&&(e.abort(),this.threads.delete(t))}hibernateIdleThreads(t){let e=Date.now();for(let s of this.threads.values())s.isProcessAlive&&e-s.lastActiveAt>t&&s.hibernate()}parseStreamEvent(t){let e=t.type;if(e==="assistant"){let s=t.message;if(s?.content&&Array.isArray(s.content))for(let n of s.content){if(n.type==="text"&&typeof n.text=="string")return{type:"text",content:n.text};if(n.type==="tool_use"){let a=String(n.name??"tool"),r=n.input,o=r?.command??r?.content??r?.file_path??r?.path??"";return{type:"tool_use",content:o?String(o).slice(0,150):"",toolName:a}}}}if(e==="content_block_delta"){let s=t.delta;if(s?.type==="text_delta"&&typeof s.text=="string")return{type:"text",content:s.text}}return null}};var mn=class{constructor(t){this.config=t;this.now=t.now??Date.now}buckets=new Map;now;tryConsume(t){let e=this.now(),s=e-this.config.windowMs,a=(this.buckets.get(t)??[]).filter(r=>r>s);return a.length>=this.config.maxPerWindow?(this.buckets.set(t,a),!1):(a.push(e),this.buckets.set(t,a),!0)}currentCount(t){let s=this.now()-this.config.windowMs;return(this.buckets.get(t)??[]).filter(a=>a>s).length}reset(t){this.buckets.delete(t)}resetAll(){this.buckets.clear()}};function fn(i){let t=Yl(i),e=[];for(let s of t)if(s.kind==="code"){let n=s.text.replace(/^```[^\n]*\n/,"```\n");e.push(n)}else e.push(Kl(s.text));return e.join("")}function Yl(i){let t=[],e=0,s=!1,n=0;for(;e<i.length;)i.startsWith("```",e)?s?(e+=3,i[e]===`
11985
- `&&(e+=1),t.push({kind:"code",text:i.slice(n,e)}),n=e,s=!1):(e>n&&t.push({kind:"prose",text:i.slice(n,e)}),n=e,s=!0,e+=3):e+=1;return n<i.length&&t.push({kind:s?"code":"prose",text:i.slice(n)}),t}function Kl(i){return Jl(i).map(s=>{if(s.isCode)return s.text;let n=s.text;return n=n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"),n=n.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(a,r,o)=>`<${o}|${r}>`),n=n.replace(/\*\*([^*]+)\*\*/g,"*$1*"),n=n.replace(/^#{1,6}\s+(.+)$/gm,"*$1*"),n}).join("")}function Jl(i){let t=[],e=/`([^`\n]+)`/g,s=0,n;for(;n=e.exec(i);)n.index>s&&t.push({text:i.slice(s,n.index),isCode:!1}),t.push({text:n[0],isCode:!0}),s=n.index+n[0].length;return s<i.length&&t.push({text:i.slice(s),isCode:!1}),t}function cr(i,t=3e3){if(i.length<=t)return[i];let e=[],s=i;for(;s.length>t;){let n=s.slice(0,t),a=Xl(n)%2===1,r;if(a){let o=Ql(n);if(o>0)r=o;else{e.push(n+"\n```"),s="```\n"+s.slice(t);continue}}else{if(r=n.lastIndexOf(`
11984
+ `)}async openOrCreateThread(t){if(this.isThread)throw new Error("Nested threads are not supported.");let e=this.threads.get(t);if(e)return e;let s=this.messages.findIndex(r=>r.id===t);if(s<0)throw new Error(`Thread anchor message "${t}" not found in parent.`);let n=new i(this.agent,this.settings,this.repository,this.vault,{threadAnchorId:t,parentSession:this,mcpAuth:this.mcpAuth});return n.threadAnchorIndex=s,await n.loadPersistedState()||(n.threadAnchorIndex=s),this.threads.set(t,n),n}closeThread(t){let e=this.threads.get(t);e&&(e.abort(),this.threads.delete(t))}hibernateIdleThreads(t){let e=Date.now();for(let s of this.threads.values())s.isProcessAlive&&e-s.lastActiveAt>t&&s.hibernate()}parseStreamEvent(t){let e=t.type;if(e==="assistant"){let s=t.message;if(s?.content&&Array.isArray(s.content))for(let n of s.content){if(n.type==="text"&&typeof n.text=="string")return{type:"text",content:n.text};if(n.type==="tool_use"){let a=String(n.name??"tool"),r=n.input,o=r?.command??r?.content??r?.file_path??r?.path??"";return{type:"tool_use",content:o?String(o).slice(0,150):"",toolName:a}}}}if(e==="content_block_delta"){let s=t.delta;if(s?.type==="text_delta"&&typeof s.text=="string")return{type:"text",content:s.text}}return null}};var mn=class{constructor(t){this.config=t;this.now=t.now??Date.now}buckets=new Map;now;tryConsume(t){let e=this.now(),s=e-this.config.windowMs,a=(this.buckets.get(t)??[]).filter(r=>r>s);return a.length>=this.config.maxPerWindow?(this.buckets.set(t,a),!1):(a.push(e),this.buckets.set(t,a),!0)}currentCount(t){let s=this.now()-this.config.windowMs;return(this.buckets.get(t)??[]).filter(a=>a>s).length}reset(t){this.buckets.delete(t)}resetAll(){this.buckets.clear()}};function fn(i){let t=Kl(i),e=[];for(let s of t)if(s.kind==="code"){let n=s.text.replace(/^```[^\n]*\n/,"```\n");e.push(n)}else e.push(Jl(s.text));return e.join("")}function Kl(i){let t=[],e=0,s=!1,n=0;for(;e<i.length;)i.startsWith("```",e)?s?(e+=3,i[e]===`
11985
+ `&&(e+=1),t.push({kind:"code",text:i.slice(n,e)}),n=e,s=!1):(e>n&&t.push({kind:"prose",text:i.slice(n,e)}),n=e,s=!0,e+=3):e+=1;return n<i.length&&t.push({kind:s?"code":"prose",text:i.slice(n)}),t}function Jl(i){return Xl(i).map(s=>{if(s.isCode)return s.text;let n=s.text;return n=n.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;"),n=n.replace(/\[([^\]]+)\]\(([^)]+)\)/g,(a,r,o)=>`<${o}|${r}>`),n=n.replace(/\*\*([^*]+)\*\*/g,"*$1*"),n=n.replace(/^#{1,6}\s+(.+)$/gm,"*$1*"),n}).join("")}function Xl(i){let t=[],e=/`([^`\n]+)`/g,s=0,n;for(;n=e.exec(i);)n.index>s&&t.push({text:i.slice(s,n.index),isCode:!1}),t.push({text:n[0],isCode:!0}),s=n.index+n[0].length;return s<i.length&&t.push({text:i.slice(s),isCode:!1}),t}function dr(i,t=3e3){if(i.length<=t)return[i];let e=[],s=i;for(;s.length>t;){let n=s.slice(0,t),a=Ql(n)%2===1,r;if(a){let o=Zl(n);if(o>0)r=o;else{e.push(n+"\n```"),s="```\n"+s.slice(t);continue}}else{if(r=n.lastIndexOf(`
11986
11986
 
11987
11987
  `),r<t/2){let o=n.lastIndexOf(`
11988
- `);o>t/2?r=o:r=t}r<=0&&(r=t)}e.push(s.slice(0,r)),s=s.slice(r).replace(/^\n+/,"")}return s.length>0&&e.push(s),e}function Xl(i){let t=0,e=0;for(;(e=i.indexOf("```",e))!==-1;)t+=1,e+=3;return t}function Ql(i){let t=0,e=0,s=0;for(;s<i.length;){let n=i.indexOf("```",s);if(n===-1)break;t+=1,s=n+3,t%2===0&&(e=s)}return e}function Zl(i,t){let e=i.trim(),s=e.toLowerCase();for(let n of t){let a=n.toLowerCase(),r=[`use ${a}:`,`use ${a}`,`@${a}:`,`@${a}`,`${a}:`];for(let o of r)if(s.startsWith(o)){let c=e.slice(o.length).trim();return{agent:n,rest:c}}}return null}var gn=class{constructor(t){this.deps=t;this.now=t.now??(()=>Date.now());let e=t.getSettings();this.rateLimiter=new mn({maxPerWindow:Math.max(1,e.channelRateLimitPerConversation),windowMs:Math.max(1e3,e.channelRateLimitWindowMinutes*6e4),now:this.now})}adapters=new Map;adapterConfigs=new Map;sessions=new Map;conversationLocks=new Map;rateLimiter;metrics=new Map;statusListeners=new Set;adapterUnsubscribes=new Map;now;threadBindings=new Map;hibernationInterval=null;started=!1;async start(t){if(!this.started){this.started=!0;for(let e of t.channels)await this.bringUpChannel(e,t);this.hibernationInterval=setInterval(()=>{this.runHibernationSweep()},6e4)}}async stop(){if(!this.started)return;this.started=!1,this.hibernationInterval&&(clearInterval(this.hibernationInterval),this.hibernationInterval=null);let t=Array.from(this.adapters.values());await Promise.all(t.map(async e=>{try{await e.stop()}catch(s){console.warn(`Agent Fleet: channel adapter ${e.config.name} stop() failed`,s)}})),this.adapters.clear(),this.adapterConfigs.clear();for(let e of this.adapterUnsubscribes.values())for(let s of e)s();this.adapterUnsubscribes.clear(),this.conversationLocks.size>0&&await Promise.allSettled(Array.from(this.conversationLocks.values()));for(let e of this.sessions.values())try{e.session.isStreaming?e.session.abort():e.session.hibernate()}catch{}this.sessions.clear(),this.conversationLocks.clear(),this.conversationLockGen.clear(),this.rateLimiter.resetAll()}async reconcile(t){if(!this.started)return;let e=new Map;for(let s of t.channels)e.set(s.name,s);for(let[s,n]of this.adapters){let a=e.get(s),r=a&&this.isChannelRuntimeValid(a,t);if(!a||!a.enabled||!r){await this.tearDownChannel(s);continue}let o=this.adapterConfigs.get(s);o&&this.requiresRestart(o,a)?(await this.tearDownChannel(s),await this.bringUpChannel(a,t)):(this.adapterConfigs.set(s,a),n.config=a)}for(let[s,n]of e)!this.adapters.has(s)&&n.enabled&&this.isChannelRuntimeValid(n,t)&&await this.bringUpChannel(n,t);this.notifyStatusListeners()}getCredentials(){return this.deps.getChannelCredentials?.()??this.deps.getSettings().channelCredentials??{}}isChannelRuntimeValid(t,e){let s=e.agents.find(a=>a.name===t.defaultAgent);if(!s||s.approvalRequired.length>0)return!1;let n=this.getCredentials()[t.credentialRef];return!(!n||n.type!==t.type)}async bringUpChannel(t,e){if(!t.enabled||!this.isChannelRuntimeValid(t,e))return;let s=this.getCredentials()[t.credentialRef];if(!s)return;let n;try{n=this.deps.adapterFactory(t,s)}catch(r){console.error(`Agent Fleet: failed to build adapter for channel ${t.name}`,r);return}let a=[];a.push(n.onInbound(r=>{this.handleInbound(n,r)})),a.push(n.onStatusChange(()=>this.notifyStatusListeners())),n.onAgentSwitch&&a.push(n.onAgentSwitch((r,o,c)=>{let l=`${t.name}:${r}`;this.threadBindings.set(l,o),this.persistBindings(t.name)})),n.setAllowedAgentsResolver?.(()=>this.resolveAllowedAgents(t)),this.adapters.set(t.name,n),this.adapterConfigs.set(t.name,t),this.adapterUnsubscribes.set(t.name,a),this.ensureMetrics(t.name),await this.loadBindings(t.name);try{await n.start()}catch(r){console.error(`Agent Fleet: channel adapter ${t.name} start() failed`,r)}this.notifyStatusListeners()}async tearDownChannel(t){let e=this.adapters.get(t);if(!e)return;try{await e.stop()}catch(a){console.warn(`Agent Fleet: channel adapter ${t} stop() failed`,a)}let s=this.adapterUnsubscribes.get(t);if(s)for(let a of s)a();this.adapterUnsubscribes.delete(t),this.adapters.delete(t),this.adapterConfigs.delete(t);let n=`${t}:`;for(let[a,r]of this.sessions)if(a.startsWith(n)){try{r.session.isStreaming?r.session.abort():r.session.hibernate()}catch{}this.sessions.delete(a)}}requiresRestart(t,e){return t.type!==e.type||t.credentialRef!==e.credentialRef||JSON.stringify(t.transport)!==JSON.stringify(e.transport)}async handleInbound(t,e){let s=t.config,n=`${s.name}:${e.conversationId}`;if(!(s.allowedUsers.length>0&&(!e.externalUserId||!s.allowedUsers.includes(e.externalUserId)))){if(!this.rateLimiter.tryConsume(n)){console.warn(`Agent Fleet: rate-limited message from ${e.externalUserId} on ${s.name} (conversation ${e.conversationId})`);try{await t.send(e.conversationId,"_Rate limit exceeded. Please slow down and try again in a few minutes._")}catch(a){console.warn(`Agent Fleet: rate-limit reply failed on ${s.name}`,a)}return}await this.withConversationLock(n,async()=>{let a=this.ensureMetrics(s.name);a.messagesReceived+=1,a.lastMessageAt=this.now();let r=this.resolveAllowedAgents(s),o=Zl(e.text,r),c,l;if(o){c=o.agent,l=o.rest;let h=this.threadBindings.get(n);if(this.threadBindings.set(n,c),this.persistBindings(s.name),h!==c)try{await t.setThreadTitle?.(e.conversationId,c)}catch{}if(!l){try{await t.send(e.conversationId,`_Now chatting with *${c}*. Send your next message to start._`)}catch{}return}}else{let h=`${s.name}:${e.conversationId.replace(/:thread:[^:]+$/,`:user:${e.externalUserId}`)}`;c=this.threadBindings.get(n)??this.threadBindings.get(h)??s.defaultAgent,l=e.text}try{await t.setTyping(e.conversationId,!0)}catch{}if(e.images&&e.images.length>0){let h=await this.saveInboundImages(e.images);h&&(l=h+(l||"Please analyze this image."))}let d="";try{let u=await(await this.getOrCreateSession(s,e.conversationId,c)).sendMessage(l,()=>{});if(d=u.text.trim(),u.toolCalls.length>0){let p=ec(u.toolCalls);p&&(d+=`
11988
+ `);o>t/2?r=o:r=t}r<=0&&(r=t)}e.push(s.slice(0,r)),s=s.slice(r).replace(/^\n+/,"")}return s.length>0&&e.push(s),e}function Ql(i){let t=0,e=0;for(;(e=i.indexOf("```",e))!==-1;)t+=1,e+=3;return t}function Zl(i){let t=0,e=0,s=0;for(;s<i.length;){let n=i.indexOf("```",s);if(n===-1)break;t+=1,s=n+3,t%2===0&&(e=s)}return e}function ec(i,t){let e=i.trim(),s=e.toLowerCase();for(let n of t){let a=n.toLowerCase(),r=[`use ${a}:`,`use ${a}`,`@${a}:`,`@${a}`,`${a}:`];for(let o of r)if(s.startsWith(o)){let c=e.slice(o.length).trim();return{agent:n,rest:c}}}return null}var gn=class{constructor(t){this.deps=t;this.now=t.now??(()=>Date.now());let e=t.getSettings();this.rateLimiter=new mn({maxPerWindow:Math.max(1,e.channelRateLimitPerConversation),windowMs:Math.max(1e3,e.channelRateLimitWindowMinutes*6e4),now:this.now})}adapters=new Map;adapterConfigs=new Map;sessions=new Map;conversationLocks=new Map;rateLimiter;metrics=new Map;statusListeners=new Set;adapterUnsubscribes=new Map;now;threadBindings=new Map;hibernationInterval=null;started=!1;async start(t){if(!this.started){this.started=!0;for(let e of t.channels)await this.bringUpChannel(e,t);this.hibernationInterval=window.setInterval(()=>{this.runHibernationSweep()},6e4)}}async stop(){if(!this.started)return;this.started=!1,this.hibernationInterval&&(window.clearInterval(this.hibernationInterval),this.hibernationInterval=null);let t=Array.from(this.adapters.values());await Promise.all(t.map(async e=>{try{await e.stop()}catch(s){console.warn(`Agent Fleet: channel adapter ${e.config.name} stop() failed`,s)}})),this.adapters.clear(),this.adapterConfigs.clear();for(let e of this.adapterUnsubscribes.values())for(let s of e)s();this.adapterUnsubscribes.clear(),this.conversationLocks.size>0&&await Promise.allSettled(Array.from(this.conversationLocks.values()));for(let e of this.sessions.values())try{e.session.isStreaming?e.session.abort():e.session.hibernate()}catch{}this.sessions.clear(),this.conversationLocks.clear(),this.conversationLockGen.clear(),this.rateLimiter.resetAll()}async reconcile(t){if(!this.started)return;let e=new Map;for(let s of t.channels)e.set(s.name,s);for(let[s,n]of this.adapters){let a=e.get(s),r=a&&this.isChannelRuntimeValid(a,t);if(!a||!a.enabled||!r){await this.tearDownChannel(s);continue}let o=this.adapterConfigs.get(s);o&&this.requiresRestart(o,a)?(await this.tearDownChannel(s),await this.bringUpChannel(a,t)):(this.adapterConfigs.set(s,a),n.config=a)}for(let[s,n]of e)!this.adapters.has(s)&&n.enabled&&this.isChannelRuntimeValid(n,t)&&await this.bringUpChannel(n,t);this.notifyStatusListeners()}getCredentials(){return this.deps.getChannelCredentials?.()??this.deps.getSettings().channelCredentials??{}}isChannelRuntimeValid(t,e){let s=e.agents.find(a=>a.name===t.defaultAgent);if(!s||s.approvalRequired.length>0)return!1;let n=this.getCredentials()[t.credentialRef];return!(!n||n.type!==t.type)}async bringUpChannel(t,e){if(!t.enabled||!this.isChannelRuntimeValid(t,e))return;let s=this.getCredentials()[t.credentialRef];if(!s)return;let n;try{n=this.deps.adapterFactory(t,s)}catch(r){console.error(`Agent Fleet: failed to build adapter for channel ${t.name}`,r);return}let a=[];a.push(n.onInbound(r=>{this.handleInbound(n,r)})),a.push(n.onStatusChange(()=>this.notifyStatusListeners())),n.onAgentSwitch&&a.push(n.onAgentSwitch((r,o,c)=>{let l=`${t.name}:${r}`;this.threadBindings.set(l,o),this.persistBindings(t.name)})),n.setAllowedAgentsResolver?.(()=>this.resolveAllowedAgents(t)),this.adapters.set(t.name,n),this.adapterConfigs.set(t.name,t),this.adapterUnsubscribes.set(t.name,a),this.ensureMetrics(t.name),await this.loadBindings(t.name);try{await n.start()}catch(r){console.error(`Agent Fleet: channel adapter ${t.name} start() failed`,r)}this.notifyStatusListeners()}async tearDownChannel(t){let e=this.adapters.get(t);if(!e)return;try{await e.stop()}catch(a){console.warn(`Agent Fleet: channel adapter ${t} stop() failed`,a)}let s=this.adapterUnsubscribes.get(t);if(s)for(let a of s)a();this.adapterUnsubscribes.delete(t),this.adapters.delete(t),this.adapterConfigs.delete(t);let n=`${t}:`;for(let[a,r]of this.sessions)if(a.startsWith(n)){try{r.session.isStreaming?r.session.abort():r.session.hibernate()}catch{}this.sessions.delete(a)}}requiresRestart(t,e){return t.type!==e.type||t.credentialRef!==e.credentialRef||JSON.stringify(t.transport)!==JSON.stringify(e.transport)}async handleInbound(t,e){let s=t.config,n=`${s.name}:${e.conversationId}`;if(!(s.allowedUsers.length>0&&(!e.externalUserId||!s.allowedUsers.includes(e.externalUserId)))){if(!this.rateLimiter.tryConsume(n)){console.warn(`Agent Fleet: rate-limited message from ${e.externalUserId} on ${s.name} (conversation ${e.conversationId})`);try{await t.send(e.conversationId,"_Rate limit exceeded. Please slow down and try again in a few minutes._")}catch(a){console.warn(`Agent Fleet: rate-limit reply failed on ${s.name}`,a)}return}await this.withConversationLock(n,async()=>{let a=this.ensureMetrics(s.name);a.messagesReceived+=1,a.lastMessageAt=this.now();let r=this.resolveAllowedAgents(s),o=ec(e.text,r),c,l;if(o){c=o.agent,l=o.rest;let d=this.threadBindings.get(n);if(this.threadBindings.set(n,c),this.persistBindings(s.name),d!==c)try{await t.setThreadTitle?.(e.conversationId,c)}catch{}if(!l){try{await t.send(e.conversationId,`_Now chatting with *${c}*. Send your next message to start._`)}catch{}return}}else{let d=`${s.name}:${e.conversationId.replace(/:thread:[^:]+$/,`:user:${e.externalUserId}`)}`;c=this.threadBindings.get(n)??this.threadBindings.get(d)??s.defaultAgent,l=e.text}try{await t.setTyping(e.conversationId,!0)}catch{}if(e.images&&e.images.length>0){let d=await this.saveInboundImages(e.images);d&&(l=d+(l||"Please analyze this image."))}let h="";try{let u=await(await this.getOrCreateSession(s,e.conversationId,c)).sendMessage(l,()=>{});if(h=u.text.trim(),u.toolCalls.length>0){let p=tc(u.toolCalls);p&&(h+=`
11989
11989
 
11990
- _${p}_`)}}catch(h){console.error(`Agent Fleet: channel turn failed on ${s.name}/${e.conversationId}`,h),d=`_Sorry \u2014 the agent run failed. ${h instanceof Error?h.message:String(h)}_`}try{d&&((s.allowedAgents.length>1||s.allowedAgents.length===0&&this.resolveAllowedAgents(s).length>1)&&(d=`*[${c}]*
11991
- ${d}`),await this.deliverReply(t,e.conversationId,d),a.messagesSent+=1)}catch(h){console.error(`Agent Fleet: reply delivery failed on ${s.name}`,h)}finally{try{await t.setTyping(e.conversationId,!1)}catch{}}this.enforceHardCap()})}}async deliverReply(t,e,s){let n=cr(s);for(let a of n)await t.send(e,a)}async saveInboundImages(t){let s=`${this.deps.getSettings().fleetFolder}/chat-images`,n=[];for(let a of t)try{this.deps.vault.getAbstractFileByPath((0,ct.normalizePath)(s))||await this.deps.vault.createFolder((0,ct.normalizePath)(s));let r=(0,ct.normalizePath)(`${s}/${a.filename}`),o=r;if(this.deps.vault.getAbstractFileByPath(r)){let h=a.filename.lastIndexOf("."),u=h>0?a.filename.slice(0,h):a.filename,p=h>0?a.filename.slice(h):"";o=(0,ct.normalizePath)(`${s}/${u}_${Date.now()}${p}`)}await this.deps.vault.createBinary(o,a.data);let l=this.deps.vault.adapter.basePath??"",d=l?`${l}/${o}`:o;n.push(`### Image: ${a.filename}
11992
- The image file is located at: ${d}
11990
+ _${p}_`)}}catch(d){console.error(`Agent Fleet: channel turn failed on ${s.name}/${e.conversationId}`,d),h=`_Sorry \u2014 the agent run failed. ${d instanceof Error?d.message:String(d)}_`}try{h&&((s.allowedAgents.length>1||s.allowedAgents.length===0&&this.resolveAllowedAgents(s).length>1)&&(h=`*[${c}]*
11991
+ ${h}`),await this.deliverReply(t,e.conversationId,h),a.messagesSent+=1)}catch(d){console.error(`Agent Fleet: reply delivery failed on ${s.name}`,d)}finally{try{await t.setTyping(e.conversationId,!1)}catch{}}this.enforceHardCap()})}}async deliverReply(t,e,s){let n=dr(s);for(let a of n)await t.send(e,a)}async saveInboundImages(t){let s=`${this.deps.getSettings().fleetFolder}/chat-images`,n=[];for(let a of t)try{this.deps.vault.getAbstractFileByPath((0,dt.normalizePath)(s))||await this.deps.vault.createFolder((0,dt.normalizePath)(s));let r=(0,dt.normalizePath)(`${s}/${a.filename}`),o=r;if(this.deps.vault.getAbstractFileByPath(r)){let d=a.filename.lastIndexOf("."),u=d>0?a.filename.slice(0,d):a.filename,p=d>0?a.filename.slice(d):"";o=(0,dt.normalizePath)(`${s}/${u}_${Date.now()}${p}`)}await this.deps.vault.createBinary(o,a.data);let l=this.deps.vault.adapter.basePath??"",h=l?`${l}/${o}`:o;n.push(`### Image: ${a.filename}
11992
+ The image file is located at: ${h}
11993
11993
  Please read and analyze this image.`)}catch(r){console.warn("Agent Fleet: failed to save inbound image",a.filename,r)}return n.length===0?"":`## Attached Images
11994
11994
 
11995
11995
  ${n.join(`
@@ -11998,24 +11998,24 @@ ${n.join(`
11998
11998
 
11999
11999
  ---
12000
12000
 
12001
- `}async getOrCreateSession(t,e,s){let n=`${t.name}:${e}:${s}`,a=this.sessions.get(n);if(a)return a.session;let r=this.deps.getRepository(),o=r.getAgentByName(s);if(!o)throw new Error(`Channel ${t.name} bound to missing agent ${s}`);let c=new qt(o,this.deps.getSettings(),r,this.deps.vault,{channelName:t.name,conversationId:`${e}:${s}`,channelContext:t.channelContext||void 0,mcpAuth:this.deps.getMcpAuth?.()});try{await c.loadPersistedState()}catch{}return this.sessions.set(n,{session:c,channelName:t.name,conversationId:e,sessionKey:n}),c}resolveAllowedAgents(t){let e=new Set(this.deps.getRepository().getSnapshot().agents.filter(n=>n.enabled).map(n=>n.name));return(t.allowedAgents.length>0?t.allowedAgents:[...e]).filter(n=>e.has(n))}async persistBindings(t){let e=`${t}:`,s={};for(let[o,c]of this.threadBindings)o.startsWith(e)&&(s[o.slice(e.length)]=c);let n=this.deps.getSettings(),a=(0,ct.normalizePath)(`${n.fleetFolder}/channels/${t}/bindings.json`),r=JSON.stringify(s,null,2);try{let o=this.deps.vault.getAbstractFileByPath(a);if(o instanceof ct.TFile)await this.deps.vault.modify(o,r);else{let c=a.slice(0,a.lastIndexOf("/"));if(!this.deps.vault.getAbstractFileByPath(c))try{await this.deps.vault.createFolder(c)}catch{}await this.deps.vault.create(a,r)}}catch(o){console.warn(`Agent Fleet: failed to persist thread bindings for ${t}`,o)}}async loadBindings(t){let e=this.deps.getSettings(),s=(0,ct.normalizePath)(`${e.fleetFolder}/channels/${t}/bindings.json`);try{let n=this.deps.vault.getAbstractFileByPath(s);if(!(n instanceof ct.TFile))return;let a=await this.deps.vault.cachedRead(n),r=JSON.parse(a);for(let[o,c]of Object.entries(r))typeof c=="string"&&this.threadBindings.set(`${t}:${o}`,c)}catch{}}getThreadAgent(t,e){return this.threadBindings.get(`${t}:${e}`)}enforceHardCap(){let t=Math.max(1,this.deps.getSettings().maxConcurrentChannelSessions),e=Array.from(this.sessions.values()).filter(n=>n.session.isProcessAlive&&!n.session.isStreaming);if(e.length<=t)return;e.sort((n,a)=>n.session.lastActiveAt-a.session.lastActiveAt);let s=e.length-t;for(let n=0;n<s;n+=1){let a=e[n];if(!a)break;try{a.session.hibernate()}catch{}}}async runHibernationSweep(){let t=Math.max(6e4,this.deps.getSettings().channelIdleTimeoutMinutes*6e4),e=this.now()-t;for(let s of this.sessions.values())if(s.session.isProcessAlive&&!s.session.isStreaming&&s.session.lastActiveAt<e)try{s.session.hibernate()}catch{}}async broadcastToChannel(t,e){let s=this.adapters.get(t);if(!s){console.warn(`Agent Fleet: broadcastToChannel \u2014 no adapter for channel ${t}`);return}if(!s.broadcast){console.warn(`Agent Fleet: broadcastToChannel \u2014 adapter ${t} does not support broadcast`);return}await s.broadcast(e)}conversationLockGen=new Map;async withConversationLock(t,e){let s=this.conversationLocks.get(t)??Promise.resolve(),n,a=new Promise(o=>{n=o}),r=(this.conversationLockGen.get(t)??0)+1;this.conversationLockGen.set(t,r),this.conversationLocks.set(t,s.then(()=>a));try{await s,await e()}finally{n(),this.conversationLockGen.get(t)===r&&(this.conversationLocks.delete(t),this.conversationLockGen.delete(t))}}ensureMetrics(t){let e=this.metrics.get(t);return e||(e={messagesReceived:0,messagesSent:0,lastMessageAt:null},this.metrics.set(t,e)),e}getMetrics(t){return{...this.ensureMetrics(t)}}getChannelStatus(t){let e=this.adapters.get(t);return e?e.getStatus():"disabled"}getConnectedCount(){let t=0;for(let e of this.adapters.values())e.getStatus()==="connected"&&(t+=1);return t}getSessionCount(t){let e=0,s=`${t}:`;for(let n of this.sessions.keys())n.startsWith(s)&&(e+=1);return e}onStatusChange(t){return this.statusListeners.add(t),()=>this.statusListeners.delete(t)}notifyStatusListeners(){for(let t of this.statusListeners)try{t()}catch{}}};function ec(i){if(i.length===0)return"";let t=new Map;for(let s of i)t.set(s.name,(t.get(s.name)??0)+1);let e=[];for(let[s,n]of t)e.push(n>1?`${s}\xD7${n}`:s);return`Used ${i.length} tool${i.length===1?"":"s"}: ${e.join(", ")}`}var yn=class{credentials=new Map;secretStore;persistCallback;setSecretStore(t){this.secretStore=t}loadCredentials(t){if(this.credentials.clear(),this.secretStore?.available){let e=this.secretStore.listByPrefix(Ht);for(let s of e){let n=Ht+"-",a=s.startsWith(n)?s.slice(n.length):s,r=this.secretStore.getJson(Ht,a);if(r){let o=r._ref??a,c={...r};delete c._ref,this.credentials.set(o,c)}}}if(this.credentials.size===0&&t){for(let[e,s]of Object.entries(t))this.credentials.set(e,s);this.secretStore?.available&&this.credentials.size>0&&this.persistToSecretStore()}}onChanged(t){this.persistCallback=t}get(t){return this.credentials.get(t)}set(t,e){this.credentials.set(t,e),this.persist()}delete(t){this.credentials.delete(t),this.secretStore?.delete(Ht,t),this.persist()}list(){return Array.from(this.credentials.entries()).map(([t,e])=>({ref:t,entry:e}))}toRecord(){let t={};for(let[e,s]of this.credentials.entries())t[e]=s;return t}persist(){this.persistToSecretStore(),this.persistCallback&&this.persistCallback(this.toRecord())}persistToSecretStore(){if(this.secretStore?.available)for(let[t,e]of this.credentials)this.secretStore.setJson(Ht,t,{...e,_ref:t})}};function hr(){return{status:"disconnected",scope:"user",tools:[],toolDetails:[]}}function tc(i,t,e){if(e)return"stdio";let s=(i??"").toLowerCase();return s==="sse"?"sse":s==="http"||s==="streamable-http"||s==="streamable_http"?"http":t?.endsWith("/sse")?"sse":"http"}function ur(i){let t=[],e={},s;try{s=JSON.parse(i)}catch{return{servers:t,tokens:e}}let n=s.mcpServers;if(!n||typeof n!="object")return{servers:t,tokens:e};for(let[a,r]of Object.entries(n)){if(!r||typeof r!="object")continue;let o=r,c=typeof o.command=="string"?o.command:void 0,l=typeof o.url=="string"?o.url:void 0;if(!c&&!l)continue;let d=tc(typeof o.type=="string"?o.type:void 0,l,!!c),h={name:a,type:d,enabled:!0,source:"imported",...hr()};if(d==="stdio")h.command=c,Array.isArray(o.args)&&(h.args=o.args.filter(u=>typeof u=="string")),o.env&&typeof o.env=="object"&&(h.env=dr(o.env));else{h.url=l;let u=o.headers&&typeof o.headers=="object"?dr(o.headers):{},p=u.Authorization??u.authorization;p?.startsWith("Bearer ")?(e[a]=p.slice(7),delete u.Authorization,delete u.authorization,h.auth="oauth"):h.auth="none",Object.keys(u).length>0&&(h.headers=u)}t.push(h)}return{servers:t,tokens:e}}function pr(i){let t=new Map,e=null;for(let n of i.split(/\r?\n/)){let a=n.trim();if(!a||a.startsWith("#"))continue;let r=a.match(/^\[(.+)\]$/);if(r){let u=r[1].trim().match(/^mcp_servers\.(.+)$/);if(!u){e=null;continue}let p=u[1],f=null;p.endsWith(".env")?(f="env",p=p.slice(0,-4)):p.endsWith(".oauth")&&(f="oauth",p=p.slice(0,-6));let m=vn(p);if(!m){e=null;continue}t.has(m)||t.set(m,{name:m,enabled:!0}),e={name:m,sub:f};continue}if(!e)continue;let o=a.match(/^([^=]+?)\s*=\s*(.+)$/);if(!o)continue;let c=vn(o[1].trim()),l=o[2].trim(),d=t.get(e.name);if(e.sub==="env")d.env??={},d.env[c]=zt(l);else if(e.sub==="oauth")c==="client_id"&&(d.oauthClientId=zt(l));else switch(c){case"command":d.command=zt(l);break;case"args":d.args=sc(l);break;case"url":d.url=zt(l);break;case"bearer_token_env_var":d.bearerEnvVar=zt(l);break;case"oauth_resource":d.oauthResource=zt(l);break;case"enabled":d.enabled=l==="true";break;default:break}}let s=[];for(let n of t.values()){if(!n.command&&!n.url)continue;let a=n.command?"stdio":n.url?.endsWith("/sse")?"sse":"http",r={name:n.name,type:a,enabled:n.enabled,source:"imported",...hr()};a==="stdio"?(r.command=n.command,n.args&&n.args.length>0&&(r.args=n.args),n.env&&Object.keys(n.env).length>0&&(r.env=n.env)):(r.url=n.url,n.oauthClientId||n.oauthResource?(r.auth="oauth",r.oauth={clientId:n.oauthClientId,resource:n.oauthResource}):n.bearerEnvVar?(r.auth="bearer",r.envSecretKeys=[n.bearerEnvVar]):r.auth="none"),s.push(r)}return{servers:s,tokens:{}}}function mr(...i){let t=new Map,e={};for(let s of i){for(let n of s.servers){let a=n.name.trim().toLowerCase();t.has(a)||t.set(a,n)}Object.assign(e,s.tokens)}return{servers:[...t.values()],tokens:e}}function vn(i){let t=i.trim();return t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1):t}function zt(i){let t=i.trim();if(t.startsWith('"')||t.startsWith("'")){let e=t[0],s=t.indexOf(e,1);if(s>0)return t.slice(1,s)}return vn(t.replace(/\s+#.*$/,""))}function sc(i){let t=i.trim();try{let s=JSON.parse(t);if(Array.isArray(s))return s.filter(n=>typeof n=="string")}catch{}return t.replace(/^\[/,"").replace(/\]$/,"").split(",").map(s=>vn(s.trim())).filter(Boolean)}function dr(i){let t={};for(let[e,s]of Object.entries(i))typeof s=="string"&&(t[e]=s);return t}var xd=ze(co(),1),Sd=ze(An(),1),Cd=ze(Yt(),1),Td=ze(Aa(),1),_d=ze(Ra(),1),Ad=ze(Oa(),1),bo=ze(Dn(),1),Ed=ze(vo(),1);var Ba=bo.default;var wo=require("obsidian");var Pd="https://slack.com/api";function Rd(i){let t=i.team??"unknown",e=i.channel??"unknown",s=i.thread_ts??i.ts??"unknown";return`slack:${t}:${e}:thread:${s}`}function Dd(i){let t=i.split(":");return t.length>=3&&t[0]==="slack"?t[2]??null:null}function Id(i){let t=i.split(":");if(t[3]==="thread"&&t[4])return t[4]}var Mn=class{type="slack";config;credential;ws=null;status="stopped";stopping=!1;backoffMs=1e3;reconnectTimer=null;inboundHandlers=new Set;statusHandlers=new Set;agentSwitchHandlers=new Set;allowedAgentsResolver;sendQueues=new Map;threadContext=new Map;constructor(t,e){if(e.type!=="slack")throw new Error(`SlackAdapter requires a slack credential, got ${e.type}`);this.config=t,this.credential=e}async start(){this.stopping=!1,await this.connect()}async stop(){if(this.stopping=!0,this.reconnectTimer&&(clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.ws){try{this.ws.close()}catch{}this.ws=null}this.threadContext.clear(),this.sendQueues.clear(),this.setStatus("stopped")}getStatus(){return this.status}async send(t,e){let s=Dd(t);if(!s){console.warn(`Agent Fleet: could not extract channel id from ${t}`);return}let n=Id(t),a=fn(e);await this.enqueueSend(s,async()=>{await this.slackApi("chat.postMessage",{channel:s,text:a,...n?{thread_ts:n}:{}})})}async broadcast(t){let e=this.config.allowedUsers[0];if(!e){console.warn(`Agent Fleet: broadcast on ${this.config.name} skipped \u2014 no allowed users configured`);return}try{let n=(await this.slackApi("conversations.open",{users:e})).channel?.id;if(!n){console.warn(`Agent Fleet: broadcast \u2014 conversations.open returned no channel for user ${e}`);return}let a=fn(t);await this.slackApi("chat.postMessage",{channel:n,text:a})}catch(s){console.error(`Agent Fleet: broadcast failed on ${this.config.name}`,s)}}async setThreadTitle(t,e){let s=this.threadContext.get(t);if(s)try{await this.slackApi("assistant.threads.setTitle",{channel_id:s.channelId,thread_ts:s.threadTs,title:e})}catch(n){console.warn(`Agent Fleet: assistant.threads.setTitle failed on ${this.config.name}`,n)}}async setTyping(t,e){let s=this.threadContext.get(t);if(s)try{await this.slackApi("assistant.threads.setStatus",{channel_id:s.channelId,thread_ts:s.threadTs,status:e?"is thinking...":""})}catch(n){console.warn(`Agent Fleet: assistant.threads.setStatus (${e?"on":"off"}) failed on ${this.config.name}`,n)}}onInbound(t){return this.inboundHandlers.add(t),()=>this.inboundHandlers.delete(t)}onStatusChange(t){return this.statusHandlers.add(t),()=>this.statusHandlers.delete(t)}setAllowedAgentsResolver(t){this.allowedAgentsResolver=t}onAgentSwitch(t){return this.agentSwitchHandlers.add(t),()=>this.agentSwitchHandlers.delete(t)}async connect(){if(this.stopping)return;this.setStatus(this.ws?"reconnecting":"connecting");let t;try{let e=await this.slackApi("apps.connections.open",{},{useAppToken:!0});if(!e.ok||!e.url)throw new Error(e.error??"apps.connections.open returned no URL");t=e.url}catch(e){console.error(`Agent Fleet: Slack apps.connections.open failed for channel ${this.config.name}`,e),this.setStatus("needs-auth"),this.scheduleReconnect();return}try{let e=new Ba(t);e.on("open",()=>{}),e.on("message",a=>{this.handleSocketData(a)}),e.on("error",a=>{console.warn(`Agent Fleet: Slack WebSocket error on ${this.config.name}`,a),this.setStatus("error")}),e.on("close",()=>{this.ws=null,this.stopping||this.scheduleReconnect()}),this.ws=e;let s=setTimeout(()=>{if(this.status==="connecting"||this.status==="reconnecting"){console.warn(`Agent Fleet: Slack WebSocket connect timeout on ${this.config.name}`);try{e.close()}catch{}}},3e4);e.on("close",()=>clearTimeout(s));let n=this.onStatusChange(a=>{a==="connected"&&(clearTimeout(s),n())})}catch(e){console.error("Agent Fleet: Slack WebSocket open failed",e),this.setStatus("error"),this.scheduleReconnect();return}}handleSocketData(t){let e;try{e=JSON.parse(t.toString())}catch{return}if(e.type==="hello"){this.backoffMs=1e3,this.setStatus("connected");return}if(e.type==="disconnect"){try{this.ws?.close()}catch{}return}if(e.type==="events_api"&&e.envelope_id){this.ackEnvelope(e.envelope_id),this.routeEventPayload(e.payload);return}if(e.type==="slash_commands"&&e.envelope_id){this.ackEnvelope(e.envelope_id),this.handleSlashCommand(e.payload);return}if(e.type==="interactive"&&e.envelope_id){this.ackEnvelope(e.envelope_id),this.handleInteraction(e.payload);return}e.envelope_id&&this.ackEnvelope(e.envelope_id)}async handleSlashCommand(t){if(!t)return;let e=t.command,s=t.channel_id,n=t.user_id;if(!(!e||!s||!n)){if(e==="/agents"){let a=this.allowedAgentsResolver?this.allowedAgentsResolver():this.config.allowedAgents;if(a.length===0){await this.slackApi("chat.postEphemeral",{channel:s,user:n,text:"No agents available. Add existing, enabled agents to `allowed_agents` in the channel file."});return}let r=a.map(c=>({type:"button",text:{type:"plain_text",text:c===this.config.defaultAgent?`${c} \u2713`:c,emoji:!0},action_id:`switch_agent_${c}`,value:c})),o=[{type:"section",text:{type:"mrkdwn",text:"*Select an agent to chat with:*"}}];for(let c=0;c<r.length;c+=5)o.push({type:"actions",elements:r.slice(c,c+5)});try{await this.slackApi("chat.postEphemeral",{channel:s,user:n,text:"Select an agent",blocks:o})}catch(c){console.error("Agent Fleet: /agents response failed",c)}return}try{await this.slackApi("chat.postEphemeral",{channel:s,user:n,text:`Unknown command: ${e}`})}catch(a){console.error(`Agent Fleet: slash command response failed for ${e}`,a)}}}async handleInteraction(t){if(!t||t.type!=="block_actions")return;let s=t.actions,n=t.user,a=t.channel,r=t.message;if(!s?.length||!n||!a)return;let o=s[0];if(!o)return;let c=o.action_id,l=o.value;if(!c?.startsWith("switch_agent_")||!l)return;let d=n.id,h=a.id;if(!d||!h)return;let p=`slack:${t.team?.id??"unknown"}:${h}:user:${d}`;for(let f of this.agentSwitchHandlers)try{f(p,l,d)}catch(m){console.error("Agent Fleet: agent switch handler threw",m)}try{await this.slackApi("chat.postEphemeral",{channel:h,user:d,text:`Switched to *${l}*. Send your next message to start.`})}catch(f){console.warn("Agent Fleet: agent switch confirmation failed",f)}try{await this.setThreadTitle(p,l)}catch{}}ackEnvelope(t){if(!(!this.ws||this.ws.readyState!==Ba.OPEN))try{this.ws.send(JSON.stringify({envelope_id:t}))}catch(e){console.warn("Agent Fleet: Slack envelope ACK failed",e)}}routeEventPayload(t){if(!t)return;let e=t.event;if(!e)return;let s=e.type;if(s==="assistant_thread_started"){let d=e.assistant_thread;d?.channel_id&&d.thread_ts&&console.debug(`Agent Fleet: assistant thread started on ${this.config.name} (channel=${d.channel_id}, thread_ts=${d.thread_ts}, user=${d.user_id})`);return}if(s==="assistant_thread_context_changed")return;let n=e,a=s==="message"&&n.subtype===void 0,r=s==="app_mention";if(!a&&!r||n.bot_id||!n.user||!n.text||r&&(n.text=n.text.replace(/^<@[A-Z0-9]+>\s*/,"").trim(),!n.text))return;let o=Rd(n),c=n.thread_ts??n.ts;if(n.channel&&c&&(this.threadContext.set(o,{channelId:n.channel,threadTs:c}),this.threadContext.size>500)){let h=this.threadContext.keys().next();h.done||this.threadContext.delete(h.value)}let l={conversationId:o,externalUserId:n.user,text:n.text,timestamp:new Date().toISOString(),meta:{slack_channel:n.channel,slack_ts:n.ts,thread_ts:n.thread_ts}};for(let d of this.inboundHandlers)try{d(l)}catch(h){console.error("Agent Fleet: Slack inbound handler threw",h)}}scheduleReconnect(){if(this.stopping||this.reconnectTimer)return;let t=this.backoffMs;this.backoffMs=Math.min(3e4,this.backoffMs*2),console.warn(`Agent Fleet: Slack channel ${this.config.name} scheduling reconnect in ${t}ms`),this.reconnectTimer=setTimeout(()=>{this.reconnectTimer=null,!this.stopping&&this.connect()},t)}setStatus(t){if(this.status!==t){this.status=t;for(let e of this.statusHandlers)try{e(t)}catch{}}}async slackApi(t,e,s={}){let n=s.useAppToken?this.credential.appToken:this.credential.botToken,a=`${Pd}/${t}`,r=await(0,wo.requestUrl)({url:a,method:"POST",contentType:"application/json; charset=utf-8",headers:{Authorization:`Bearer ${n}`},body:JSON.stringify(e),throw:!1});if(r.status===429){let c=Number(r.headers["retry-after"]??"1");return await new Promise(l=>setTimeout(l,Math.max(1e3,c*1e3))),this.slackApi(t,e,s)}if(r.status<200||r.status>=300)throw new Error(`Slack ${t} HTTP ${r.status}`);let o=r.json;if(o.ok===!1)throw new Error(`Slack ${t} error: ${o.error??"unknown"}`);return o}async enqueueSend(t,e){let n=(this.sendQueues.get(t)??Promise.resolve()).then(async()=>{try{await e()}finally{await new Promise(r=>setTimeout(r,1e3))}}),a=n.catch(r=>{console.warn(`Agent Fleet: Slack send queue error for ${t}`,r)});this.sendQueues.set(t,a),await n,this.sendQueues.get(t)===a&&this.sendQueues.delete(t)}};var Ua=require("obsidian"),ko="https://api.telegram.org",Ln=class{type="telegram";config;credential;status="stopped";stopping=!1;pollOffset=0;pollTimer=null;backoffMs=1e3;typingIntervals=new Map;pollAbort=null;inboundHandlers=new Set;statusHandlers=new Set;agentSwitchHandlers=new Set;allowedAgentsResolver;constructor(t,e){if(e.type!=="telegram")throw new Error(`TelegramAdapter requires a telegram credential, got ${e.type}`);this.config=t,this.credential=e}async start(){this.stopping=!1;try{let e=(await this.tgApi("getUpdates",{offset:-1,limit:1})).result?.[0];e&&(this.pollOffset=e.update_id+1)}catch{}try{await this.tgApi("setMyCommands",{commands:[{command:"agents",description:"List available agents"}]})}catch{}this.setStatus("connected"),this.poll()}async stop(){this.stopping=!0,this.pollTimer&&(clearTimeout(this.pollTimer),this.pollTimer=null),this.pollAbort?.abort(),this.pollAbort=null;for(let[,t]of this.typingIntervals)clearInterval(t);this.typingIntervals.clear(),this.setStatus("stopped")}getStatus(){return this.status}async send(t,e){let s=xo(t);if(!s)return;let n=So(t),a=Co(e,4096);for(let r of a)await this.tgApi("sendMessage",{chat_id:s,text:r,parse_mode:"Markdown",...n?{message_thread_id:Number(n)}:{}})}async setTyping(t,e){let s=xo(t);if(!s)return;let n=So(t),a={chat_id:s,action:"typing"};if(n&&(a.message_thread_id=Number(n)),e){let r=this.typingIntervals.get(t);r&&clearInterval(r);try{await this.tgApi("sendChatAction",a)}catch(c){console.warn("Agent Fleet: Telegram sendChatAction failed",c)}let o=setInterval(()=>{this.tgApi("sendChatAction",a).catch(()=>{})},4500);this.typingIntervals.set(t,o)}else{let r=this.typingIntervals.get(t);r&&(clearInterval(r),this.typingIntervals.delete(t))}}async setThreadTitle(t,e){}async broadcast(t){let e=this.config.allowedUsers[0];if(e)try{let s=Co(t,4096);for(let n of s)await this.tgApi("sendMessage",{chat_id:e,text:n,parse_mode:"Markdown"})}catch(s){console.error(`Agent Fleet: Telegram broadcast failed on ${this.config.name}`,s)}}onInbound(t){return this.inboundHandlers.add(t),()=>this.inboundHandlers.delete(t)}onStatusChange(t){return this.statusHandlers.add(t),()=>this.statusHandlers.delete(t)}setAllowedAgentsResolver(t){this.allowedAgentsResolver=t}pickerAgents(){return this.allowedAgentsResolver?this.allowedAgentsResolver():this.config.allowedAgents}onAgentSwitch(t){return this.agentSwitchHandlers.add(t),()=>this.agentSwitchHandlers.delete(t)}poll(){this.stopping||(async()=>{try{this.pollAbort=new AbortController;let t=await this.tgApi("getUpdates",{offset:this.pollOffset,timeout:30,allowed_updates:["message","callback_query"]},this.pollAbort.signal);if(t.ok&&t.result)for(let e of t.result){if(this.pollOffset=e.update_id+1,e.callback_query){this.handleCallbackQuery(e.callback_query);continue}e.message&&this.routeMessage(e.message)}this.backoffMs=1e3,this.status!=="connected"&&this.setStatus("connected")}catch(t){if(t instanceof DOMException&&t.name==="AbortError")return;if(console.warn(`Agent Fleet: Telegram poll failed on ${this.config.name}`,t),this.status!=="error"&&this.status!=="needs-auth"){let e=t instanceof Error?t.message:String(t);this.setStatus(e.includes("401")||e.includes("Unauthorized")?"needs-auth":"error")}await new Promise(e=>setTimeout(e,this.backoffMs)),this.backoffMs=Math.min(3e4,this.backoffMs*2)}this.stopping||(this.pollTimer=setTimeout(()=>this.poll(),100))})()}routeMessage(t){let e=t.photo&&t.photo.length>0,s=t.document&&this.isImageMime(t.document.mime_type),n=!!t.text;if(!t.from||!n&&!e&&!s)return;let a=t.text??t.caption??"";if(a==="/agents"||a.startsWith("/agents@")){this.handleAgentsCommand(t);return}if(a.startsWith("/"))return;let r=String(t.from.id),o=String(t.chat.id),c=t.message_thread_id?String(t.message_thread_id):void 0,l=c?`tg:${o}:topic:${c}`:`tg:${o}`;this.buildAndEmitMessage(t,a,l,r,o,c)}async buildAndEmitMessage(t,e,s,n,a,r){let o=[];try{if(t.photo&&t.photo.length>0){let l=t.photo[t.photo.length-1],d=await this.downloadFile(l.file_id,`photo_${t.message_id}.jpg`,"image/jpeg");d&&o.push(d)}if(t.document&&this.isImageMime(t.document.mime_type)){let l=t.document.file_name??`doc_${t.message_id}`,d=t.document.mime_type??"image/jpeg",h=await this.downloadFile(t.document.file_id,l,d);h&&o.push(h)}}catch(l){console.warn("Agent Fleet: Telegram image download failed",l)}let c={conversationId:s,externalUserId:n,text:e,timestamp:new Date(t.date*1e3).toISOString(),meta:{telegram_chat_id:a,telegram_message_id:t.message_id,telegram_thread_id:r,chat_type:t.chat.type},...o.length>0?{images:o}:{}};for(let l of this.inboundHandlers)try{l(c)}catch(d){console.error("Agent Fleet: Telegram inbound handler threw",d)}}async downloadFile(t,e,s){let a=(await this.tgApi("getFile",{file_id:t})).result?.file_path;if(!a)return null;let r=`${ko}/file/bot${this.credential.botToken}/${a}`;return{data:(await(0,Ua.requestUrl)({url:r,method:"GET"})).arrayBuffer,filename:e,mimeType:s}}isImageMime(t){return t?t==="image/jpeg"||t==="image/png"||t==="image/gif"||t==="image/webp"||t==="image/bmp"||t==="image/tiff":!1}async handleAgentsCommand(t){let e=String(t.chat.id),s=t.message_thread_id,n=this.pickerAgents();if(n.length===0){await this.tgApi("sendMessage",{chat_id:e,text:"No agents available. Add existing, enabled agents to `allowed_agents` in the channel file.",...s?{message_thread_id:s}:{}});return}let a=n.map(r=>[{text:r===this.config.defaultAgent?`${r} \u2713`:r,callback_data:`switch:${r}`}]);await this.tgApi("sendMessage",{chat_id:e,text:"*Select an agent to chat with:*",parse_mode:"Markdown",reply_markup:{inline_keyboard:a},...s?{message_thread_id:s}:{}})}async handleCallbackQuery(t){let e=t.data;if(!e?.startsWith("switch:")){await this.tgApi("answerCallbackQuery",{callback_query_id:t.id});return}let s=e.slice(7),n=String(t.from.id),a=String(t.message?.chat?.id??t.from.id),r=t.message?.message_thread_id?String(t.message.message_thread_id):void 0,o=r?`tg:${a}:topic:${r}`:`tg:${a}`;for(let c of this.agentSwitchHandlers)try{c(o,s,n)}catch(l){console.error("Agent Fleet: Telegram agent switch handler threw",l)}if(await this.tgApi("answerCallbackQuery",{callback_query_id:t.id,text:`Switched to ${s}`}),t.message){let l=this.pickerAgents().map(d=>[{text:d===s?`${d} \u2713`:d,callback_data:`switch:${d}`}]);try{await this.tgApi("editMessageText",{chat_id:a,message_id:t.message.message_id,text:`*Active agent: ${s}*`,parse_mode:"Markdown",reply_markup:{inline_keyboard:l}})}catch{}}}async tgApi(t,e,s){if(s?.aborted)throw new DOMException("Aborted","AbortError");let n=`${ko}/bot${this.credential.botToken}/${t}`,a=(0,Ua.requestUrl)({url:n,method:"POST",contentType:"application/json",body:JSON.stringify(e),throw:!1}),r;if(s?r=await Promise.race([a,new Promise((o,c)=>{s.addEventListener("abort",()=>c(new DOMException("Aborted","AbortError")),{once:!0})})]):r=await a,r.status===401||r.status===403)throw new Error(`Telegram ${t} ${r.status} Unauthorized`);if(r.status===429){let c=r.json?.parameters?.retry_after??1;return await new Promise(l=>setTimeout(l,c*1e3)),this.tgApi(t,e)}if(r.status<200||r.status>=300)throw new Error(`Telegram ${t} HTTP ${r.status}: ${r.text}`);return r.json}setStatus(t){if(this.status!==t){this.status=t;for(let e of this.statusHandlers)try{e(t)}catch{}}}};function xo(i){return i.startsWith("tg:")?i.split(":")[1]??null:null}function So(i){let t=i.split(":");if(t[2]==="topic"&&t[3])return t[3]}function Co(i,t){if(i.length<=t)return[i];let e=[],s=i;for(;s.length>t;){let n=s.lastIndexOf(`
12001
+ `}async getOrCreateSession(t,e,s){let n=`${t.name}:${e}:${s}`,a=this.sessions.get(n);if(a)return a.session;let r=this.deps.getRepository(),o=r.getAgentByName(s);if(!o)throw new Error(`Channel ${t.name} bound to missing agent ${s}`);let c=new zt(o,this.deps.getSettings(),r,this.deps.vault,{channelName:t.name,conversationId:`${e}:${s}`,channelContext:t.channelContext||void 0,mcpAuth:this.deps.getMcpAuth?.()});try{await c.loadPersistedState()}catch{}return this.sessions.set(n,{session:c,channelName:t.name,conversationId:e,sessionKey:n}),c}resolveAllowedAgents(t){let e=new Set(this.deps.getRepository().getSnapshot().agents.filter(n=>n.enabled).map(n=>n.name));return(t.allowedAgents.length>0?t.allowedAgents:[...e]).filter(n=>e.has(n))}async persistBindings(t){let e=`${t}:`,s={};for(let[o,c]of this.threadBindings)o.startsWith(e)&&(s[o.slice(e.length)]=c);let n=this.deps.getSettings(),a=(0,dt.normalizePath)(`${n.fleetFolder}/channels/${t}/bindings.json`),r=JSON.stringify(s,null,2);try{let o=this.deps.vault.getAbstractFileByPath(a);if(o instanceof dt.TFile)await this.deps.vault.modify(o,r);else{let c=a.slice(0,a.lastIndexOf("/"));if(!this.deps.vault.getAbstractFileByPath(c))try{await this.deps.vault.createFolder(c)}catch{}await this.deps.vault.create(a,r)}}catch(o){console.warn(`Agent Fleet: failed to persist thread bindings for ${t}`,o)}}async loadBindings(t){let e=this.deps.getSettings(),s=(0,dt.normalizePath)(`${e.fleetFolder}/channels/${t}/bindings.json`);try{let n=this.deps.vault.getAbstractFileByPath(s);if(!(n instanceof dt.TFile))return;let a=await this.deps.vault.cachedRead(n),r=JSON.parse(a);for(let[o,c]of Object.entries(r))typeof c=="string"&&this.threadBindings.set(`${t}:${o}`,c)}catch{}}getThreadAgent(t,e){return this.threadBindings.get(`${t}:${e}`)}enforceHardCap(){let t=Math.max(1,this.deps.getSettings().maxConcurrentChannelSessions),e=Array.from(this.sessions.values()).filter(n=>n.session.isProcessAlive&&!n.session.isStreaming);if(e.length<=t)return;e.sort((n,a)=>n.session.lastActiveAt-a.session.lastActiveAt);let s=e.length-t;for(let n=0;n<s;n+=1){let a=e[n];if(!a)break;try{a.session.hibernate()}catch{}}}async runHibernationSweep(){let t=Math.max(6e4,this.deps.getSettings().channelIdleTimeoutMinutes*6e4),e=this.now()-t;for(let s of this.sessions.values())if(s.session.isProcessAlive&&!s.session.isStreaming&&s.session.lastActiveAt<e)try{s.session.hibernate()}catch{}}async broadcastToChannel(t,e){let s=this.adapters.get(t);if(!s){console.warn(`Agent Fleet: broadcastToChannel \u2014 no adapter for channel ${t}`);return}if(!s.broadcast){console.warn(`Agent Fleet: broadcastToChannel \u2014 adapter ${t} does not support broadcast`);return}await s.broadcast(e)}conversationLockGen=new Map;async withConversationLock(t,e){let s=this.conversationLocks.get(t)??Promise.resolve(),n,a=new Promise(o=>{n=o}),r=(this.conversationLockGen.get(t)??0)+1;this.conversationLockGen.set(t,r),this.conversationLocks.set(t,s.then(()=>a));try{await s,await e()}finally{n(),this.conversationLockGen.get(t)===r&&(this.conversationLocks.delete(t),this.conversationLockGen.delete(t))}}ensureMetrics(t){let e=this.metrics.get(t);return e||(e={messagesReceived:0,messagesSent:0,lastMessageAt:null},this.metrics.set(t,e)),e}getMetrics(t){return{...this.ensureMetrics(t)}}getChannelStatus(t){let e=this.adapters.get(t);return e?e.getStatus():"disabled"}getConnectedCount(){let t=0;for(let e of this.adapters.values())e.getStatus()==="connected"&&(t+=1);return t}getSessionCount(t){let e=0,s=`${t}:`;for(let n of this.sessions.keys())n.startsWith(s)&&(e+=1);return e}onStatusChange(t){return this.statusListeners.add(t),()=>this.statusListeners.delete(t)}notifyStatusListeners(){for(let t of this.statusListeners)try{t()}catch{}}};function tc(i){if(i.length===0)return"";let t=new Map;for(let s of i)t.set(s.name,(t.get(s.name)??0)+1);let e=[];for(let[s,n]of t)e.push(n>1?`${s}\xD7${n}`:s);return`Used ${i.length} tool${i.length===1?"":"s"}: ${e.join(", ")}`}var yn=class{credentials=new Map;secretStore;persistCallback;setSecretStore(t){this.secretStore=t}loadCredentials(t){if(this.credentials.clear(),this.secretStore?.available){let e=this.secretStore.listByPrefix(qt);for(let s of e){let n=qt+"-",a=s.startsWith(n)?s.slice(n.length):s,r=this.secretStore.getJson(qt,a);if(r){let o=r._ref??a,c={...r};delete c._ref,this.credentials.set(o,c)}}}if(this.credentials.size===0&&t){for(let[e,s]of Object.entries(t))this.credentials.set(e,s);this.secretStore?.available&&this.credentials.size>0&&this.persistToSecretStore()}}onChanged(t){this.persistCallback=t}get(t){return this.credentials.get(t)}set(t,e){this.credentials.set(t,e),this.persist()}delete(t){this.credentials.delete(t),this.secretStore?.delete(qt,t),this.persist()}list(){return Array.from(this.credentials.entries()).map(([t,e])=>({ref:t,entry:e}))}toRecord(){let t={};for(let[e,s]of this.credentials.entries())t[e]=s;return t}persist(){this.persistToSecretStore(),this.persistCallback&&this.persistCallback(this.toRecord())}persistToSecretStore(){if(this.secretStore?.available)for(let[t,e]of this.credentials)this.secretStore.setJson(qt,t,{...e,_ref:t})}};function ur(){return{status:"disconnected",scope:"user",tools:[],toolDetails:[]}}function sc(i,t,e){if(e)return"stdio";let s=(i??"").toLowerCase();return s==="sse"?"sse":s==="http"||s==="streamable-http"||s==="streamable_http"?"http":t?.endsWith("/sse")?"sse":"http"}function pr(i){let t=[],e={},s;try{s=JSON.parse(i)}catch{return{servers:t,tokens:e}}let n=s.mcpServers;if(!n||typeof n!="object")return{servers:t,tokens:e};for(let[a,r]of Object.entries(n)){if(!r||typeof r!="object")continue;let o=r,c=typeof o.command=="string"?o.command:void 0,l=typeof o.url=="string"?o.url:void 0;if(!c&&!l)continue;let h=sc(typeof o.type=="string"?o.type:void 0,l,!!c),d={name:a,type:h,enabled:!0,source:"imported",...ur()};if(h==="stdio")d.command=c,Array.isArray(o.args)&&(d.args=o.args.filter(u=>typeof u=="string")),o.env&&typeof o.env=="object"&&(d.env=hr(o.env));else{d.url=l;let u=o.headers&&typeof o.headers=="object"?hr(o.headers):{},p=u.Authorization??u.authorization;p?.startsWith("Bearer ")?(e[a]=p.slice(7),delete u.Authorization,delete u.authorization,d.auth="oauth"):d.auth="none",Object.keys(u).length>0&&(d.headers=u)}t.push(d)}return{servers:t,tokens:e}}function mr(i){let t=new Map,e=null;for(let n of i.split(/\r?\n/)){let a=n.trim();if(!a||a.startsWith("#"))continue;let r=a.match(/^\[(.+)\]$/);if(r){let u=r[1].trim().match(/^mcp_servers\.(.+)$/);if(!u){e=null;continue}let p=u[1],m=null;p.endsWith(".env")?(m="env",p=p.slice(0,-4)):p.endsWith(".oauth")&&(m="oauth",p=p.slice(0,-6));let f=vn(p);if(!f){e=null;continue}t.has(f)||t.set(f,{name:f,enabled:!0}),e={name:f,sub:m};continue}if(!e)continue;let o=a.match(/^([^=]+?)\s*=\s*(.+)$/);if(!o)continue;let c=vn(o[1].trim()),l=o[2].trim(),h=t.get(e.name);if(e.sub==="env")h.env??={},h.env[c]=Gt(l);else if(e.sub==="oauth")c==="client_id"&&(h.oauthClientId=Gt(l));else switch(c){case"command":h.command=Gt(l);break;case"args":h.args=nc(l);break;case"url":h.url=Gt(l);break;case"bearer_token_env_var":h.bearerEnvVar=Gt(l);break;case"oauth_resource":h.oauthResource=Gt(l);break;case"enabled":h.enabled=l==="true";break;default:break}}let s=[];for(let n of t.values()){if(!n.command&&!n.url)continue;let a=n.command?"stdio":n.url?.endsWith("/sse")?"sse":"http",r={name:n.name,type:a,enabled:n.enabled,source:"imported",...ur()};a==="stdio"?(r.command=n.command,n.args&&n.args.length>0&&(r.args=n.args),n.env&&Object.keys(n.env).length>0&&(r.env=n.env)):(r.url=n.url,n.oauthClientId||n.oauthResource?(r.auth="oauth",r.oauth={clientId:n.oauthClientId,resource:n.oauthResource}):n.bearerEnvVar?(r.auth="bearer",r.envSecretKeys=[n.bearerEnvVar]):r.auth="none"),s.push(r)}return{servers:s,tokens:{}}}function fr(...i){let t=new Map,e={};for(let s of i){for(let n of s.servers){let a=n.name.trim().toLowerCase();t.has(a)||t.set(a,n)}Object.assign(e,s.tokens)}return{servers:[...t.values()],tokens:e}}function vn(i){let t=i.trim();return t.startsWith('"')&&t.endsWith('"')||t.startsWith("'")&&t.endsWith("'")?t.slice(1,-1):t}function Gt(i){let t=i.trim();if(t.startsWith('"')||t.startsWith("'")){let e=t[0],s=t.indexOf(e,1);if(s>0)return t.slice(1,s)}return vn(t.replace(/\s+#.*$/,""))}function nc(i){let t=i.trim();try{let s=JSON.parse(t);if(Array.isArray(s))return s.filter(n=>typeof n=="string")}catch{}return t.replace(/^\[/,"").replace(/\]$/,"").split(",").map(s=>vn(s.trim())).filter(Boolean)}function hr(i){let t={};for(let[e,s]of Object.entries(i))typeof s=="string"&&(t[e]=s);return t}var Sd=ze(ho(),1),Cd=ze(An(),1),Td=ze(Kt(),1),_d=ze(Aa(),1),Ad=ze(Ra(),1),Ed=ze(Oa(),1),bo=ze(Dn(),1),Pd=ze(wo(),1);var Ba=bo.default;var ko=require("obsidian");var Rd="https://slack.com/api";function Dd(i){let t=i.team??"unknown",e=i.channel??"unknown",s=i.thread_ts??i.ts??"unknown";return`slack:${t}:${e}:thread:${s}`}function Id(i){let t=i.split(":");return t.length>=3&&t[0]==="slack"?t[2]??null:null}function Md(i){let t=i.split(":");if(t[3]==="thread"&&t[4])return t[4]}var Mn=class{type="slack";config;credential;ws=null;status="stopped";stopping=!1;backoffMs=1e3;reconnectTimer=null;inboundHandlers=new Set;statusHandlers=new Set;agentSwitchHandlers=new Set;allowedAgentsResolver;sendQueues=new Map;threadContext=new Map;constructor(t,e){if(e.type!=="slack")throw new Error(`SlackAdapter requires a slack credential, got ${e.type}`);this.config=t,this.credential=e}async start(){this.stopping=!1,await this.connect()}async stop(){if(this.stopping=!0,this.reconnectTimer&&(window.clearTimeout(this.reconnectTimer),this.reconnectTimer=null),this.ws){try{this.ws.close()}catch{}this.ws=null}this.threadContext.clear(),this.sendQueues.clear(),this.setStatus("stopped")}getStatus(){return this.status}async send(t,e){let s=Id(t);if(!s){console.warn(`Agent Fleet: could not extract channel id from ${t}`);return}let n=Md(t),a=fn(e);await this.enqueueSend(s,async()=>{await this.slackApi("chat.postMessage",{channel:s,text:a,...n?{thread_ts:n}:{}})})}async broadcast(t){let e=this.config.allowedUsers[0];if(!e){console.warn(`Agent Fleet: broadcast on ${this.config.name} skipped \u2014 no allowed users configured`);return}try{let n=(await this.slackApi("conversations.open",{users:e})).channel?.id;if(!n){console.warn(`Agent Fleet: broadcast \u2014 conversations.open returned no channel for user ${e}`);return}let a=fn(t);await this.slackApi("chat.postMessage",{channel:n,text:a})}catch(s){console.error(`Agent Fleet: broadcast failed on ${this.config.name}`,s)}}async setThreadTitle(t,e){let s=this.threadContext.get(t);if(s)try{await this.slackApi("assistant.threads.setTitle",{channel_id:s.channelId,thread_ts:s.threadTs,title:e})}catch(n){console.warn(`Agent Fleet: assistant.threads.setTitle failed on ${this.config.name}`,n)}}async setTyping(t,e){let s=this.threadContext.get(t);if(s)try{await this.slackApi("assistant.threads.setStatus",{channel_id:s.channelId,thread_ts:s.threadTs,status:e?"is thinking...":""})}catch(n){console.warn(`Agent Fleet: assistant.threads.setStatus (${e?"on":"off"}) failed on ${this.config.name}`,n)}}onInbound(t){return this.inboundHandlers.add(t),()=>this.inboundHandlers.delete(t)}onStatusChange(t){return this.statusHandlers.add(t),()=>this.statusHandlers.delete(t)}setAllowedAgentsResolver(t){this.allowedAgentsResolver=t}onAgentSwitch(t){return this.agentSwitchHandlers.add(t),()=>this.agentSwitchHandlers.delete(t)}async connect(){if(this.stopping)return;this.setStatus(this.ws?"reconnecting":"connecting");let t;try{let e=await this.slackApi("apps.connections.open",{},{useAppToken:!0});if(!e.ok||!e.url)throw new Error(e.error??"apps.connections.open returned no URL");t=e.url}catch(e){console.error(`Agent Fleet: Slack apps.connections.open failed for channel ${this.config.name}`,e),this.setStatus("needs-auth"),this.scheduleReconnect();return}try{let e=new Ba(t);e.on("open",()=>{}),e.on("message",a=>{this.handleSocketData(a)}),e.on("error",a=>{console.warn(`Agent Fleet: Slack WebSocket error on ${this.config.name}`,a),this.setStatus("error")}),e.on("close",()=>{this.ws=null,this.stopping||this.scheduleReconnect()}),this.ws=e;let s=window.setTimeout(()=>{if(this.status==="connecting"||this.status==="reconnecting"){console.warn(`Agent Fleet: Slack WebSocket connect timeout on ${this.config.name}`);try{e.close()}catch{}}},3e4);e.on("close",()=>window.clearTimeout(s));let n=this.onStatusChange(a=>{a==="connected"&&(window.clearTimeout(s),n())})}catch(e){console.error("Agent Fleet: Slack WebSocket open failed",e),this.setStatus("error"),this.scheduleReconnect();return}}handleSocketData(t){let e;try{e=JSON.parse(t.toString())}catch{return}if(e.type==="hello"){this.backoffMs=1e3,this.setStatus("connected");return}if(e.type==="disconnect"){try{this.ws?.close()}catch{}return}if(e.type==="events_api"&&e.envelope_id){this.ackEnvelope(e.envelope_id),this.routeEventPayload(e.payload);return}if(e.type==="slash_commands"&&e.envelope_id){this.ackEnvelope(e.envelope_id),this.handleSlashCommand(e.payload);return}if(e.type==="interactive"&&e.envelope_id){this.ackEnvelope(e.envelope_id),this.handleInteraction(e.payload);return}e.envelope_id&&this.ackEnvelope(e.envelope_id)}async handleSlashCommand(t){if(!t)return;let e=t.command,s=t.channel_id,n=t.user_id;if(!(!e||!s||!n)){if(e==="/agents"){let a=this.allowedAgentsResolver?this.allowedAgentsResolver():this.config.allowedAgents;if(a.length===0){await this.slackApi("chat.postEphemeral",{channel:s,user:n,text:"No agents available. Add existing, enabled agents to `allowed_agents` in the channel file."});return}let r=a.map(c=>({type:"button",text:{type:"plain_text",text:c===this.config.defaultAgent?`${c} \u2713`:c,emoji:!0},action_id:`switch_agent_${c}`,value:c})),o=[{type:"section",text:{type:"mrkdwn",text:"*Select an agent to chat with:*"}}];for(let c=0;c<r.length;c+=5)o.push({type:"actions",elements:r.slice(c,c+5)});try{await this.slackApi("chat.postEphemeral",{channel:s,user:n,text:"Select an agent",blocks:o})}catch(c){console.error("Agent Fleet: /agents response failed",c)}return}try{await this.slackApi("chat.postEphemeral",{channel:s,user:n,text:`Unknown command: ${e}`})}catch(a){console.error(`Agent Fleet: slash command response failed for ${e}`,a)}}}async handleInteraction(t){if(!t||t.type!=="block_actions")return;let s=t.actions,n=t.user,a=t.channel;if(!s?.length||!n||!a)return;let r=s[0];if(!r)return;let o=r.action_id,c=r.value;if(!o?.startsWith("switch_agent_")||!c)return;let l=n.id,h=a.id;if(!l||!h)return;let u=`slack:${t.team?.id??"unknown"}:${h}:user:${l}`;for(let p of this.agentSwitchHandlers)try{p(u,c,l)}catch(m){console.error("Agent Fleet: agent switch handler threw",m)}try{await this.slackApi("chat.postEphemeral",{channel:h,user:l,text:`Switched to *${c}*. Send your next message to start.`})}catch(p){console.warn("Agent Fleet: agent switch confirmation failed",p)}try{await this.setThreadTitle(u,c)}catch{}}ackEnvelope(t){if(!(!this.ws||this.ws.readyState!==Ba.OPEN))try{this.ws.send(JSON.stringify({envelope_id:t}))}catch(e){console.warn("Agent Fleet: Slack envelope ACK failed",e)}}routeEventPayload(t){if(!t)return;let e=t.event;if(!e)return;let s=e.type;if(s==="assistant_thread_started"){let h=e.assistant_thread;h?.channel_id&&h.thread_ts&&console.debug(`Agent Fleet: assistant thread started on ${this.config.name} (channel=${h.channel_id}, thread_ts=${h.thread_ts}, user=${h.user_id})`);return}if(s==="assistant_thread_context_changed")return;let n=e,a=s==="message"&&n.subtype===void 0,r=s==="app_mention";if(!a&&!r||n.bot_id||!n.user||!n.text||r&&(n.text=n.text.replace(/^<@[A-Z0-9]+>\s*/,"").trim(),!n.text))return;let o=Dd(n),c=n.thread_ts??n.ts;if(n.channel&&c&&(this.threadContext.set(o,{channelId:n.channel,threadTs:c}),this.threadContext.size>500)){let d=this.threadContext.keys().next();d.done||this.threadContext.delete(d.value)}let l={conversationId:o,externalUserId:n.user,text:n.text,timestamp:new Date().toISOString(),meta:{slack_channel:n.channel,slack_ts:n.ts,thread_ts:n.thread_ts}};for(let h of this.inboundHandlers)try{h(l)}catch(d){console.error("Agent Fleet: Slack inbound handler threw",d)}}scheduleReconnect(){if(this.stopping||this.reconnectTimer)return;let t=this.backoffMs;this.backoffMs=Math.min(3e4,this.backoffMs*2),console.warn(`Agent Fleet: Slack channel ${this.config.name} scheduling reconnect in ${t}ms`),this.reconnectTimer=window.setTimeout(()=>{this.reconnectTimer=null,!this.stopping&&this.connect()},t)}setStatus(t){if(this.status!==t){this.status=t;for(let e of this.statusHandlers)try{e(t)}catch{}}}async slackApi(t,e,s={}){let n=s.useAppToken?this.credential.appToken:this.credential.botToken,a=`${Rd}/${t}`,r=await(0,ko.requestUrl)({url:a,method:"POST",contentType:"application/json; charset=utf-8",headers:{Authorization:`Bearer ${n}`},body:JSON.stringify(e),throw:!1});if(r.status===429){let c=Number(r.headers["retry-after"]??"1");return await new Promise(l=>window.setTimeout(l,Math.max(1e3,c*1e3))),this.slackApi(t,e,s)}if(r.status<200||r.status>=300)throw new Error(`Slack ${t} HTTP ${r.status}`);let o=r.json;if(o.ok===!1)throw new Error(`Slack ${t} error: ${o.error??"unknown"}`);return o}async enqueueSend(t,e){let n=(this.sendQueues.get(t)??Promise.resolve()).then(async()=>{try{await e()}finally{await new Promise(r=>window.setTimeout(r,1e3))}}),a=n.catch(r=>{console.warn(`Agent Fleet: Slack send queue error for ${t}`,r)});this.sendQueues.set(t,a),await n,this.sendQueues.get(t)===a&&this.sendQueues.delete(t)}};var Ua=require("obsidian"),xo="https://api.telegram.org",Ln=class{type="telegram";config;credential;status="stopped";stopping=!1;pollOffset=0;pollTimer=null;backoffMs=1e3;typingIntervals=new Map;pollAbort=null;inboundHandlers=new Set;statusHandlers=new Set;agentSwitchHandlers=new Set;allowedAgentsResolver;constructor(t,e){if(e.type!=="telegram")throw new Error(`TelegramAdapter requires a telegram credential, got ${e.type}`);this.config=t,this.credential=e}async start(){this.stopping=!1;try{let e=(await this.tgApi("getUpdates",{offset:-1,limit:1})).result?.[0];e&&(this.pollOffset=e.update_id+1)}catch{}try{await this.tgApi("setMyCommands",{commands:[{command:"agents",description:"List available agents"}]})}catch{}this.setStatus("connected"),this.poll()}async stop(){this.stopping=!0,this.pollTimer&&(window.clearTimeout(this.pollTimer),this.pollTimer=null),this.pollAbort?.abort(),this.pollAbort=null;for(let[,t]of this.typingIntervals)window.clearInterval(t);this.typingIntervals.clear(),this.setStatus("stopped")}getStatus(){return this.status}async send(t,e){let s=So(t);if(!s)return;let n=Co(t),a=To(e,4096);for(let r of a)await this.tgApi("sendMessage",{chat_id:s,text:r,parse_mode:"Markdown",...n?{message_thread_id:Number(n)}:{}})}async setTyping(t,e){let s=So(t);if(!s)return;let n=Co(t),a={chat_id:s,action:"typing"};if(n&&(a.message_thread_id=Number(n)),e){let r=this.typingIntervals.get(t);r&&window.clearInterval(r);try{await this.tgApi("sendChatAction",a)}catch(c){console.warn("Agent Fleet: Telegram sendChatAction failed",c)}let o=window.setInterval(()=>{this.tgApi("sendChatAction",a).catch(()=>{})},4500);this.typingIntervals.set(t,o)}else{let r=this.typingIntervals.get(t);r&&(window.clearInterval(r),this.typingIntervals.delete(t))}}async setThreadTitle(t,e){}async broadcast(t){let e=this.config.allowedUsers[0];if(e)try{let s=To(t,4096);for(let n of s)await this.tgApi("sendMessage",{chat_id:e,text:n,parse_mode:"Markdown"})}catch(s){console.error(`Agent Fleet: Telegram broadcast failed on ${this.config.name}`,s)}}onInbound(t){return this.inboundHandlers.add(t),()=>this.inboundHandlers.delete(t)}onStatusChange(t){return this.statusHandlers.add(t),()=>this.statusHandlers.delete(t)}setAllowedAgentsResolver(t){this.allowedAgentsResolver=t}pickerAgents(){return this.allowedAgentsResolver?this.allowedAgentsResolver():this.config.allowedAgents}onAgentSwitch(t){return this.agentSwitchHandlers.add(t),()=>this.agentSwitchHandlers.delete(t)}poll(){this.stopping||(async()=>{try{this.pollAbort=new AbortController;let t=await this.tgApi("getUpdates",{offset:this.pollOffset,timeout:30,allowed_updates:["message","callback_query"]},this.pollAbort.signal);if(t.ok&&t.result)for(let e of t.result){if(this.pollOffset=e.update_id+1,e.callback_query){this.handleCallbackQuery(e.callback_query);continue}e.message&&this.routeMessage(e.message)}this.backoffMs=1e3,this.status!=="connected"&&this.setStatus("connected")}catch(t){if(t instanceof DOMException&&t.name==="AbortError")return;if(console.warn(`Agent Fleet: Telegram poll failed on ${this.config.name}`,t),this.status!=="error"&&this.status!=="needs-auth"){let e=t instanceof Error?t.message:String(t);this.setStatus(e.includes("401")||e.includes("Unauthorized")?"needs-auth":"error")}await new Promise(e=>window.setTimeout(e,this.backoffMs)),this.backoffMs=Math.min(3e4,this.backoffMs*2)}this.stopping||(this.pollTimer=window.setTimeout(()=>this.poll(),100))})()}routeMessage(t){let e=t.photo&&t.photo.length>0,s=t.document&&this.isImageMime(t.document.mime_type),n=!!t.text;if(!t.from||!n&&!e&&!s)return;let a=t.text??t.caption??"";if(a==="/agents"||a.startsWith("/agents@")){this.handleAgentsCommand(t);return}if(a.startsWith("/"))return;let r=String(t.from.id),o=String(t.chat.id),c=t.message_thread_id?String(t.message_thread_id):void 0,l=c?`tg:${o}:topic:${c}`:`tg:${o}`;this.buildAndEmitMessage(t,a,l,r,o,c)}async buildAndEmitMessage(t,e,s,n,a,r){let o=[];try{if(t.photo&&t.photo.length>0){let l=t.photo[t.photo.length-1],h=await this.downloadFile(l.file_id,`photo_${t.message_id}.jpg`,"image/jpeg");h&&o.push(h)}if(t.document&&this.isImageMime(t.document.mime_type)){let l=t.document.file_name??`doc_${t.message_id}`,h=t.document.mime_type??"image/jpeg",d=await this.downloadFile(t.document.file_id,l,h);d&&o.push(d)}}catch(l){console.warn("Agent Fleet: Telegram image download failed",l)}let c={conversationId:s,externalUserId:n,text:e,timestamp:new Date(t.date*1e3).toISOString(),meta:{telegram_chat_id:a,telegram_message_id:t.message_id,telegram_thread_id:r,chat_type:t.chat.type},...o.length>0?{images:o}:{}};for(let l of this.inboundHandlers)try{l(c)}catch(h){console.error("Agent Fleet: Telegram inbound handler threw",h)}}async downloadFile(t,e,s){let a=(await this.tgApi("getFile",{file_id:t})).result?.file_path;if(!a)return null;let r=`${xo}/file/bot${this.credential.botToken}/${a}`;return{data:(await(0,Ua.requestUrl)({url:r,method:"GET"})).arrayBuffer,filename:e,mimeType:s}}isImageMime(t){return t?t==="image/jpeg"||t==="image/png"||t==="image/gif"||t==="image/webp"||t==="image/bmp"||t==="image/tiff":!1}async handleAgentsCommand(t){let e=String(t.chat.id),s=t.message_thread_id,n=this.pickerAgents();if(n.length===0){await this.tgApi("sendMessage",{chat_id:e,text:"No agents available. Add existing, enabled agents to `allowed_agents` in the channel file.",...s?{message_thread_id:s}:{}});return}let a=n.map(r=>[{text:r===this.config.defaultAgent?`${r} \u2713`:r,callback_data:`switch:${r}`}]);await this.tgApi("sendMessage",{chat_id:e,text:"*Select an agent to chat with:*",parse_mode:"Markdown",reply_markup:{inline_keyboard:a},...s?{message_thread_id:s}:{}})}async handleCallbackQuery(t){let e=t.data;if(!e?.startsWith("switch:")){await this.tgApi("answerCallbackQuery",{callback_query_id:t.id});return}let s=e.slice(7),n=String(t.from.id),a=String(t.message?.chat?.id??t.from.id),r=t.message?.message_thread_id?String(t.message.message_thread_id):void 0,o=r?`tg:${a}:topic:${r}`:`tg:${a}`;for(let c of this.agentSwitchHandlers)try{c(o,s,n)}catch(l){console.error("Agent Fleet: Telegram agent switch handler threw",l)}if(await this.tgApi("answerCallbackQuery",{callback_query_id:t.id,text:`Switched to ${s}`}),t.message){let l=this.pickerAgents().map(h=>[{text:h===s?`${h} \u2713`:h,callback_data:`switch:${h}`}]);try{await this.tgApi("editMessageText",{chat_id:a,message_id:t.message.message_id,text:`*Active agent: ${s}*`,parse_mode:"Markdown",reply_markup:{inline_keyboard:l}})}catch{}}}async tgApi(t,e,s){if(s?.aborted)throw new DOMException("Aborted","AbortError");let n=`${xo}/bot${this.credential.botToken}/${t}`,a=(0,Ua.requestUrl)({url:n,method:"POST",contentType:"application/json",body:JSON.stringify(e),throw:!1}),r;if(s?r=await Promise.race([a,new Promise((o,c)=>{s.addEventListener("abort",()=>c(new DOMException("Aborted","AbortError")),{once:!0})})]):r=await a,r.status===401||r.status===403)throw new Error(`Telegram ${t} ${r.status} Unauthorized`);if(r.status===429){let c=r.json?.parameters?.retry_after??1;return await new Promise(l=>window.setTimeout(l,c*1e3)),this.tgApi(t,e)}if(r.status<200||r.status>=300)throw new Error(`Telegram ${t} HTTP ${r.status}: ${r.text}`);return r.json}setStatus(t){if(this.status!==t){this.status=t;for(let e of this.statusHandlers)try{e(t)}catch{}}}};function So(i){return i.startsWith("tg:")?i.split(":")[1]??null:null}function Co(i){let t=i.split(":");if(t[2]==="topic"&&t[3])return t[3]}function To(i,t){if(i.length<=t)return[i];let e=[],s=i;for(;s.length>t;){let n=s.lastIndexOf(`
12002
12002
 
12003
12003
  `,t);n<t/2&&(n=s.lastIndexOf(`
12004
- `,t)),n<t/2&&(n=t),e.push(s.slice(0,n)),s=s.slice(n).replace(/^\n+/,"")}return s&&e.push(s),e}var Ps=require("obsidian");var Fn=class extends Ps.ItemView{constructor(e,s){super(e);this.plugin=s}getViewType(){return Ct}getDisplayText(){return"Agent Fleet"}getIcon(){return"bot"}async onOpen(){this.plugin.subscribeView(this),await this.render()}async onClose(){this.plugin.unsubscribeView(this)}async render(){let e=this.contentEl;e.empty(),e.addClass("af-sidebar");let s=this.plugin.runtime.getSnapshot(),n=this.plugin.runtime.getFleetStatus(),a=e.createDiv({cls:"af-sidebar-section"});a.createDiv({cls:"af-sidebar-section-header",text:"AGENT FLEET"});let r=[{icon:"layout-dashboard",label:"Dashboard",page:"dashboard"},{icon:"bot",label:"Agents",page:"agents",badge:()=>s.agents.length},{icon:"columns-3",label:"Tasks Board",page:"kanban"},{icon:"scroll-text",label:"Run History",page:"runs"},{icon:"shield-check",label:"Approvals",page:"approvals",badge:()=>n.pending},{icon:"puzzle",label:"Skills",page:"skills",badge:()=>s.skills.length},{icon:"plug",label:"MCP Servers",page:"mcp",badge:()=>this.plugin.repository.getMcpServers().length},{icon:"radio",label:"Channels",page:"channels",badge:()=>this.plugin.channelManager?.getConnectedCount()??s.channels.length}];for(let l of r){let d=a.createDiv({cls:"af-sidebar-nav-item"}),h=d.createSpan({cls:"af-sidebar-nav-icon"});(0,Ps.setIcon)(h,l.icon),d.createSpan({cls:"af-sidebar-nav-label",text:l.label});let u=l.badge?.();u!==void 0&&u>0&&d.createSpan({cls:"af-sidebar-badge",text:String(u)}),d.setAttribute("role","button"),d.setAttribute("tabindex","0"),d.onclick=()=>void this.plugin.navigateDashboard(l.page),d.onkeydown=p=>{(p.key==="Enter"||p.key===" ")&&(p.preventDefault(),this.plugin.navigateDashboard(l.page))}}let o=e.createDiv({cls:"af-sidebar-section"});o.createDiv({cls:"af-sidebar-section-header",text:"AGENTS"}),s.agents.length===0&&o.createDiv({cls:"af-sidebar-empty",text:"No agents configured"});for(let l of s.agents){let d=this.plugin.runtime.getAgentState(l.name),h=o.createDiv({cls:"af-sidebar-agent-item"});h.createSpan({cls:`af-sidebar-agent-dot ${this.healthToClass(d.status)}`}),h.createSpan({cls:"af-sidebar-agent-name",text:l.name}),h.setAttribute("role","button"),h.setAttribute("tabindex","0"),h.onclick=()=>void this.plugin.navigateDashboard("agent-detail",l.name),h.onkeydown=u=>{(u.key==="Enter"||u.key===" ")&&(u.preventDefault(),this.plugin.navigateDashboard("agent-detail",l.name))}}let c=e.createDiv({cls:"af-sidebar-section"});c.createDiv({cls:"af-sidebar-section-header",text:"QUICK ACTIONS"}),this.renderQuickAction(c,"plus","New Agent",()=>void this.plugin.createAgentTemplate()),this.renderQuickAction(c,"plus","New Task",()=>void this.plugin.openCreateTask()),this.renderQuickAction(c,"plus","New Skill",()=>void this.plugin.createSkillTemplate())}renderQuickAction(e,s,n,a){let r=e.createDiv({cls:"af-sidebar-action-item"}),o=r.createSpan({cls:"af-sidebar-action-icon"});(0,Ps.setIcon)(o,s),r.createSpan({text:n}),r.setAttribute("role","button"),r.setAttribute("tabindex","0"),r.onclick=a,r.onkeydown=c=>{(c.key==="Enter"||c.key===" ")&&(c.preventDefault(),a())}}healthToClass(e){switch(e){case"running":return"running";case"error":return"error";case"pending":return"pending";case"disabled":return"disabled";default:return"idle"}}};var b=require("obsidian");var es=require("obsidian"),Md=["bot","brain","shield-check","search","file-text","rocket","wand","sparkles","zap","target","compass","eye","code","terminal","database","globe","mail","message-circle","book","pen-tool","palette","music","camera","chart-bar","clipboard","cpu","server","cloud","lock","key","bell","calendar","clock","heart","star","flag","bookmark"],On=class extends es.Modal{constructor(e,s,n){super(e);this.onSelect=n;this.selectedIcon=s}searchQuery="";selectedIcon;allIcons=[];gridContainer;onOpen(){this.allIcons=(0,es.getIconIds)().sort();let{contentEl:e}=this;e.empty(),e.addClass("af-icon-picker-modal");let s=e.createEl("input",{cls:"af-icon-picker-search",attr:{type:"text",placeholder:"Search icons...",value:this.searchQuery}});this.gridContainer=e.createDiv({cls:"af-icon-picker-scroll"}),this.renderGrid(),s.addEventListener("input",()=>{this.searchQuery=s.value,this.renderGrid()}),setTimeout(()=>s.focus(),0)}renderGrid(){let e=this.gridContainer;e.empty();let s=this.searchQuery.toLowerCase().trim();if(!s)this.renderSection(e,"Popular",Md),this.renderSection(e,"All Icons",this.allIcons);else{let n=this.allIcons.filter(r=>r.includes(s)),a=n.length===0?"No results":`${n.length} result${n.length!==1?"s":""}`;this.renderSection(e,a,n)}}renderSection(e,s,n){let a=e.createDiv({cls:"af-icon-picker-section"});a.createDiv({cls:"af-icon-picker-section-label",text:s});let r=a.createDiv({cls:"af-icon-picker-grid"});for(let o of n)this.renderIconItem(r,o)}renderIconItem(e,s){let n=e.createDiv({cls:`af-icon-picker-item${this.selectedIcon===s?" selected":""}`});n.setAttribute("title",s),n.setAttribute("aria-label",s),(0,es.setIcon)(n,s),n.addEventListener("click",()=>{this.selectedIcon=s,this.onSelect(s),this.close()})}onClose(){this.contentEl.empty()}};var To=require("obsidian");function D(i,t,e){let s=i.createSpan({cls:e??"af-icon"});return(0,To.setIcon)(s,t),s}function Je(i,t={}){let e=document.createElementNS("http://www.w3.org/2000/svg",i);for(let[s,n]of Object.entries(t))e.setAttribute(s,n);return e}function Ld(i){try{return new Date(i+"T12:00:00").toLocaleDateString(void 0,{month:"short",day:"numeric"})}catch{return i.slice(5)}}function _o(i,t){let e=t.length||1,s=1e3,n=6,a=4,r=4,o=s-a-r-n*(e-1),c=Math.floor(o/e),l=140,d=36,h=18,u=h+l+d,p=Math.max(1,...t.map(m=>m.success+m.failure+m.cancelled)),f=Je("svg",{viewBox:`0 0 ${s} ${u}`,width:"100%",height:String(u),class:"af-chart-bar"});for(let m=0;m<=4;m++){let g=h+l-m/4*l;f.appendChild(Je("line",{x1:String(a),y1:String(g),x2:String(s-r),y2:String(g),stroke:"var(--af-text-faint)","stroke-opacity":"0.15","stroke-width":"1"}))}for(let m=0;m<t.length;m++){let g=t[m],v=a+m*(c+n),k=g.success+g.failure+g.cancelled,w=k/p*l,y=g.success/p*l,C=g.cancelled/p*l,T=g.failure/p*l;if(g.success>0&&f.appendChild(Je("rect",{x:String(v),y:String(h+l-y),width:String(c),height:String(Math.max(y,2)),fill:"var(--af-green)",opacity:"0.85"})),g.cancelled>0&&f.appendChild(Je("rect",{x:String(v),y:String(h+l-y-C),width:String(c),height:String(Math.max(C,2)),fill:"var(--af-yellow)",opacity:"0.85"})),g.failure>0&&f.appendChild(Je("rect",{x:String(v),y:String(h+l-w),width:String(c),height:String(Math.max(T,2)),fill:"var(--af-red)",opacity:"0.85"})),k===0&&f.appendChild(Je("rect",{x:String(v),y:String(h+l-3),width:String(c),height:"3",rx:"1.5",fill:"var(--af-text-faint)",opacity:"0.2"})),k>0){let O=Je("text",{x:String(v+c/2),y:String(h+l-w-5),"text-anchor":"middle","font-size":"10","font-weight":"600",fill:"var(--af-text-secondary)"});O.textContent=String(k),f.appendChild(O)}let _=Je("text",{x:String(v+c/2),y:String(h+l+16),"text-anchor":"middle","font-size":"10",fill:"var(--af-text-muted)"});_.textContent=Ld(g.date),f.appendChild(_)}i.appendChild(f)}function Ao(i,t,e){let c=2*Math.PI*46,l=e>0?t/e:0,d=c*l,h=c-d,u=Je("svg",{viewBox:"0 0 130 130",width:String(130),height:String(130),class:"af-chart-donut"});u.appendChild(Je("circle",{cx:String(65),cy:String(65),r:String(46),fill:"none",stroke:e>0?"var(--af-red)":"var(--af-text-faint)","stroke-width":String(12),opacity:"0.2"})),l>0&&u.appendChild(Je("circle",{cx:String(65),cy:String(65),r:String(46),fill:"none",stroke:"var(--af-green)","stroke-width":String(12),"stroke-dasharray":`${d} ${h}`,"stroke-dashoffset":String(c*.25),"stroke-linecap":"round"}));let p=Je("text",{x:String(65),y:String(61),"text-anchor":"middle","dominant-baseline":"middle","font-size":"24","font-weight":"700",fill:"var(--af-text-primary)"});p.textContent=`${Math.round(l*100)}%`,u.appendChild(p);let f=Je("text",{x:String(65),y:String(83),"text-anchor":"middle","font-size":"10",fill:"var(--af-text-muted)"});f.textContent=`${t}/${e} runs`,u.appendChild(f),i.appendChild(u)}function Eo(i,t){i.draggable=!0,i.addEventListener("dragstart",e=>{e.dataTransfer?.setData("text/plain",t),i.addClass("af-dragging")}),i.addEventListener("dragend",()=>{i.removeClass("af-dragging")})}function Po(i,t){i.addEventListener("dragover",e=>{e.preventDefault(),i.addClass("af-drag-over")}),i.addEventListener("dragleave",e=>{let s=e.relatedTarget;(!s||!i.contains(s))&&i.removeClass("af-drag-over")}),i.addEventListener("drop",e=>{e.preventDefault();let s=e.dataTransfer?.getData("text/plain");i.removeClass("af-drag-over"),s&&t(s)})}function Ro(i){let t=/^##\s+Lint\s+(\d{4}-\d{2}-\d{2})\s*$/gm,e,s=-1,n="";for(;(e=t.exec(i))!==null;)e.index>s&&(s=e.index,n=e[1]??"");if(s<0)return null;let a=i.slice(s),r=a.search(/\n##\s+(?!\s*#)/),o=r<0?a:a.slice(0,r);return{date:n,summary:Nn(o,"Summary"),autoApplied:Nn(o,"Auto-applied"),needsReview:Nn(o,"Needs review"),refreshChained:Nn(o,"Refresh chained")}}function Nn(i,t){let e=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),n=new RegExp(`^###\\s+${e}\\s*$`,"m").exec(i);if(!n)return[];let a=n.index+n[0].length,r=i.slice(a),o=r.search(/\n###\s+/),l=(o<0?r:r.slice(0,o)).split(/\r?\n/).map(h=>h.trimEnd()),d=[];for(let h of l){let u=h.replace(/^\s+/,"");u.startsWith("- ")?d.push(u.slice(2).trim()):d.length>0&&(h.startsWith(" ")||h.startsWith(" "))&&(d[d.length-1]+=" "+u)}return d}var Do={dashboard:"Dashboard",agents:"Agents",kanban:"Tasks Board",runs:"Run History",skills:"Skills Library",approvals:"Approvals",mcp:"MCP Servers",channels:"Channels","wiki-keepers":"Wiki Keepers","agent-detail":"Agent Details","task-detail":"Task Details","create-agent":"Create Agent","create-task":"Create Task","create-skill":"Create Skill","edit-agent":"Edit Agent","edit-task":"Edit Task","edit-skill":"Edit Skill","create-channel":"Create Channel","edit-channel":"Edit Channel","add-mcp-server":"Add MCP Server"},Fd={dashboard:"layout-dashboard",agents:"bot",kanban:"columns-3",runs:"scroll-text",skills:"puzzle",approvals:"shield-check",mcp:"plug",channels:"radio","wiki-keepers":"library","agent-detail":"bot","task-detail":"circle-dot","create-agent":"plus","create-task":"plus","create-skill":"plus","edit-agent":"edit","edit-task":"edit","edit-skill":"edit","create-channel":"plus","edit-channel":"edit","add-mcp-server":"plus"},Od=["dashboard","agents","kanban","runs","approvals","skills","wiki-keepers","mcp","channels"],Io=[["claude-code","Claude Code",!1],["codex","Codex",!1],["process","Process (coming soon)",!0],["http","HTTP (coming soon)",!0]],Lo=[["bypassPermissions","Bypass Permissions","Auto-approve everything except deny list"],["dontAsk","Don\u2019t Ask","Auto-approve all tool calls"],["acceptEdits","Accept Edits","Auto-approve file edits, block bash unless allowed"],["plan","Plan","Read-only mode, no writes or commands"],["default","Default","Ask for each tool call"]],Fo=[["bypassPermissions","Bypass (no sandbox)","No sandbox, auto-approve everything"],["workspace-write","Workspace Write","Sandboxed: writes only inside the working dir"],["read-only","Read Only","Sandboxed: no writes or side-effect commands"]];function Rs(i){let t=i.trim().toLowerCase();return t==="codex"||t==="openai-codex"}function Bn(i){return Rs(i)?Fo:Lo}function Un(i,t){if(Rs(t))switch(i){case"acceptEdits":case"default":return"workspace-write";case"plan":return"read-only";case"dontAsk":return"bypassPermissions";default:return Fo.some(([e])=>e===i)?i:"bypassPermissions"}switch(i){case"workspace-write":return"acceptEdits";case"read-only":return"plan";case"danger-full-access":return"bypassPermissions";default:return Lo.some(([e])=>e===i)?i:"bypassPermissions"}}var Ds=class extends b.ItemView{constructor(e,s){super(e);this.plugin=s}currentPage="dashboard";detailContext;agentDetailTab="overview";streamingUnsubscribes=[];channelStatusUnsubscribe;authenticatingServers=new Set;getViewType(){return vt}getDisplayText(){return"Agent Fleet"}getIcon(){return"bot"}async onOpen(){this.plugin.subscribeView(this),this.channelStatusUnsubscribe=this.plugin.channelManager?.onStatusChange(()=>{this.currentPage==="channels"&&this.render()}),await this.render()}async onClose(){this.cleanupStreaming(),this.channelStatusUnsubscribe?.(),this.channelStatusUnsubscribe=void 0,this.plugin.unsubscribeView(this)}navigateTo(e,s){this.currentPage=e,this.detailContext=s,e!=="agent-detail"&&(this.agentDetailTab="overview"),this.render()}async render(){this.cleanupStreaming();let e=this.contentEl;e.empty(),e.addClass("af-root");let n=e.createDiv({cls:"af-app"}).createDiv({cls:"af-main-content"});this.renderTopBar(n),this.renderTabBar(n);let a=n.createDiv({cls:"af-page"});switch(this.currentPage){case"dashboard":this.renderDashboardPage(a);break;case"agents":this.renderAgentsPage(a);break;case"kanban":this.renderKanbanPage(a);break;case"runs":this.renderRunsPage(a);break;case"skills":this.renderSkillsPage(a);break;case"approvals":this.renderApprovalsPage(a);break;case"mcp":this.renderMcpPage(a);break;case"channels":this.renderChannelsPage(a);break;case"wiki-keepers":this.renderWikiKeepersPage(a);break;case"agent-detail":this.renderAgentDetailPage(a);break;case"task-detail":this.renderTaskDetailPage(a);break;case"create-agent":this.renderCreateAgentPage(a);break;case"create-task":this.renderCreateTaskPage(a);break;case"create-skill":this.renderCreateSkillPage(a);break;case"edit-agent":this.renderEditAgentPage(a);break;case"edit-task":this.renderEditTaskPage(a);break;case"edit-skill":this.renderEditSkillPage(a);break;case"create-channel":this.renderCreateChannelPage(a);break;case"edit-channel":this.renderEditChannelPage(a);break;case"add-mcp-server":this.renderAddMcpServerPage(a);break}}navigate(e,s){this.navigateTo(e,s)}cleanupStreaming(){for(let e of this.streamingUnsubscribes)e();this.streamingUnsubscribes=[]}renderTopBar(e){let s=e.createDiv({cls:"af-top-bar"}),n=s.createDiv({cls:"af-top-bar-title"});D(n,"bot","af-top-bar-icon"),n.createSpan({text:"Agent Fleet"});let a=s.createDiv({cls:"af-breadcrumb"}),r=a.createSpan({cls:"af-breadcrumb-sep"});(0,b.setIcon)(r,"chevron-right");let o=(f,m,g)=>{let v=a.createSpan({cls:m?"af-breadcrumb-link":"",text:f});m&&(v.onclick=()=>this.navigate(m,g))},c=()=>{let f=a.createSpan({cls:"af-breadcrumb-sep"});(0,b.setIcon)(f,"chevron-right")};switch(this.currentPage){case"agent-detail":o("Agents","agents"),c(),o(this.detailContext??"Agent");break;case"task-detail":o("Tasks Board","kanban"),c(),o(this.detailContext??"Task");break;case"edit-agent":o("Agents","agents"),c(),o(this.detailContext??"Agent","agent-detail",this.detailContext),c(),o("Edit");break;case"edit-task":o("Tasks Board","kanban"),c(),o(this.detailContext??"Task","task-detail",this.detailContext),c(),o("Edit");break;case"create-agent":o("Agents","agents"),c(),o("New Agent");break;case"create-task":o("Tasks Board","kanban"),c(),o("New Task");break;case"create-skill":o("Skills Library","skills"),c(),o("New Skill");break;case"edit-skill":o("Skills Library","skills"),c(),o(this.detailContext??"Skill"),c(),o("Edit");break;case"create-channel":o("Channels","channels"),c(),o("New Channel");break;case"edit-channel":o("Channels","channels"),c(),o(this.detailContext??"Channel"),c(),o("Edit");break;case"add-mcp-server":o("MCP Servers","mcp"),c(),o("Add Server");break;default:o(Do[this.currentPage])}s.createDiv({cls:"af-top-bar-spacer"});let l=s.createDiv({cls:"af-search-wrap"});D(l,"search","af-search-icon");let d=l.createEl("input",{cls:"af-search-input",attr:{type:"text",placeholder:"Search agents, tasks, runs..."}});d.addEventListener("input",()=>{this.handleSearch(d.value,l)}),d.addEventListener("blur",()=>{setTimeout(()=>l.querySelector(".af-search-results")?.remove(),200)});let h=this.plugin.runtime.getFleetStatus(),u=s.createDiv({cls:"af-status-pills"});if(h.running>0){let f=u.createSpan({cls:"af-pill yellow"});f.createSpan({cls:"af-dot pulse"}),f.appendText(` ${h.running} Running`)}if(h.pending>0){let f=u.createSpan({cls:"af-pill blue"});f.createSpan({cls:"af-dot"}),f.appendText(` ${h.pending} Pending`)}let p=u.createSpan({cls:"af-pill green"});p.createSpan({cls:"af-dot"}),p.appendText(` ${h.completedToday} Today`)}renderTabBar(e){let s=e.createDiv({cls:"af-tab-bar"}),n=this.plugin.runtime.getSnapshot(),a=this.plugin.runtime.getFleetStatus();for(let r of Od){let o=this.currentPage===r||r==="agents"&&(this.currentPage==="agent-detail"||this.currentPage==="edit-agent"||this.currentPage==="create-agent")||r==="kanban"&&(this.currentPage==="task-detail"||this.currentPage==="edit-task")||r==="skills"&&(this.currentPage==="edit-skill"||this.currentPage==="create-skill")||r==="mcp"&&this.currentPage==="add-mcp-server",c=s.createEl("button",{cls:`af-tab-item${o?" active":""}`}),l=c.createSpan({cls:"af-tab-icon"});if((0,b.setIcon)(l,Fd[r]),c.appendText(r==="dashboard"?"Overview":Do[r]),r==="agents")c.createSpan({cls:"af-badge",text:String(n.agents.length)});else if(r==="skills")c.createSpan({cls:"af-badge",text:String(n.skills.length)});else if(r==="mcp"){let d=this.plugin.repository.getMcpServers().length;c.createSpan({cls:"af-badge",text:String(d)})}else r==="approvals"&&a.pending>0&&c.createSpan({cls:"af-badge af-badge-warn",text:String(a.pending)});c.onclick=()=>this.navigate(r)}}renderDashboardPage(e){let s=e.createDiv({cls:"af-dashboard"}),n=this.plugin.runtime.getSnapshot(),a=this.plugin.runtime.getRecentRuns(),r=this.plugin.runtime.getFleetStatus(),o=a.filter(y=>(y.approvals??[]).some(C=>C.status==="pending"));for(let y of o)for(let C of y.approvals??[])C.status==="pending"&&this.renderApprovalBanner(s,y,C.tool);let c=s.createDiv({cls:"af-dash-grid"}),l=n.agents.filter(y=>y.enabled).length,d=n.agents.length;this.renderStatCard(c,"Active Agents",`${l}`,`/ ${d}`,"bot",`${l} of ${d} enabled`);let h=this.toLocalDateStr(new Date),u=a.filter(y=>this.runToLocalDate(y.started)===h),p=u.filter(y=>y.status==="success").length,f=u.filter(y=>y.status==="failure"||y.status==="timeout").length;this.renderStatCard(c,"Runs Today",String(u.length),"","activity",`${p} passed \xB7 ${f} failed \xB7 ${r.running} running`);let m=u.reduce((y,C)=>y+(C.tokensUsed??0),0),g=u.reduce((y,C)=>y+(C.costUsd??0),0),v=g>0?` \xB7 $${g.toFixed(2)}`:"";this.renderStatCard(c,"Tokens Used",$a(m),"","zap",`today${v}`);let k=n.tasks.filter(y=>y.enabled&&y.schedule);this.renderStatCard(c,"Scheduled Tasks",String(k.length),"","clock",k.length>0?`Next: ${this.getNextTaskLabel(k)}`:"No scheduled tasks"),this.renderChartsRow(s,a,this.plugin.runtime.getChartRuns()),this.renderStreamingCards(s);let w=s.createDiv({cls:"af-dash-split"});this.renderActivityTimeline(w,a),this.renderFleetStatusPanel(w,n)}renderChartsRow(e,s,n){let a=e.createDiv({cls:"af-charts-row"}),r=a.createDiv({cls:"af-section-card af-chart-section"}),c=r.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});D(c,"activity"),c.appendText(" Run Activity (14d)");let l=r.createDiv({cls:"af-chart-body"}),d=this.buildChartData(n,14);d.some(v=>v.success+v.failure+v.cancelled>0)?_o(l,d):this.renderEmptyState(l,"activity","No run data","Run agents to see activity");let h=a.createDiv({cls:"af-section-card af-chart-section"}),p=h.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});D(p,"target"),p.appendText(" Success Rate");let f=h.createDiv({cls:"af-chart-body af-chart-body-center"}),m=s.length,g=s.filter(v=>v.status==="success").length;m>0?Ao(f,g,m):this.renderEmptyState(f,"target","No data","")}toLocalDateStr(e){let s=n=>String(n).padStart(2,"0");return`${e.getFullYear()}-${s(e.getMonth()+1)}-${s(e.getDate())}`}runToLocalDate(e){return this.toLocalDateStr(new Date(e))}buildChartData(e,s){let n=[],a=new Date;for(let r=s-1;r>=0;r--){let o=new Date(a);o.setDate(o.getDate()-r);let c=this.toLocalDateStr(o),l=e.filter(d=>this.runToLocalDate(d.started)===c);n.push({date:c,success:l.filter(d=>d.status==="success").length,failure:l.filter(d=>d.status==="failure"||d.status==="timeout").length,cancelled:l.filter(d=>d.status==="cancelled").length})}return n}renderStreamingCards(e){let n=this.plugin.runtime.getSnapshot().agents.filter(c=>this.plugin.runtime.getAgentState(c.name).status==="running");if(n.length===0)return;let a=e.createDiv({cls:"af-streaming-section"}),o=a.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});D(o,"terminal"),o.appendText(" Active Agents");for(let c of n)this.renderStreamingCard(a,c.name)}renderStreamingCard(e,s){let n=e.createDiv({cls:"af-streaming-card"}),a=this.plugin.runtime.getAgentState(s),r=this.plugin.runtime.getSnapshot(),o=a.currentTaskId?r.tasks.find(f=>f.taskId===a.currentTaskId):void 0,c=o?` \u2192 ${o.taskId}`:a.status==="running"?" \u2192 Heartbeat":"",l=n.createDiv({cls:"af-streaming-card-header"});l.createSpan({cls:"af-dot pulse",attr:{style:"background: var(--af-yellow)"}}),l.createSpan({cls:"af-streaming-card-agent",text:` ${s}`}),c&&l.createSpan({cls:"af-streaming-card-task",text:c});let d=n.createDiv({cls:"af-streaming-output"}),h=this.plugin.runtime.getRunOutputBuffer(s),u=pe(h).slice(-4);d.setText(u.join(`
12005
- `));let p=this.plugin.runtime.onRunOutput(s,()=>{let f=this.plugin.runtime.getRunOutputBuffer(s),m=pe(f).slice(-4);d.setText(m.join(`
12006
- `)),d.scrollTop=d.scrollHeight});this.streamingUnsubscribes.push(p)}renderApprovalBanner(e,s,n){let a=e.createDiv({cls:"af-approval-banner"}),r=a.createDiv({cls:"af-approval-icon"});(0,b.setIcon)(r,"shield-check");let o=a.createDiv({cls:"af-approval-text"});o.createDiv({cls:"af-approval-title",text:`${s.agent} wants to run: ${n}`}),o.createDiv({cls:"af-approval-desc",text:`Approval required for tool: ${n}`});let c=a.createDiv({cls:"af-approval-actions"}),l=c.createEl("button",{cls:"af-btn-approve",text:"Approve"});l.onclick=()=>void this.plugin.runtime.resolveApproval(s,n,"approved").then(()=>this.render());let d=c.createEl("button",{cls:"af-btn-reject",text:"Reject"});d.onclick=()=>void this.plugin.runtime.resolveApproval(s,n,"rejected").then(()=>this.render())}renderStatCard(e,s,n,a,r,o){let c=e.createDiv({cls:"af-stat-card"}),l=c.createDiv({cls:"af-stat-label"});D(l,r,"af-stat-icon"),l.appendText(` ${s}`);let d=c.createDiv({cls:"af-stat-value"});d.appendText(n),a&&d.createSpan({cls:"af-stat-value-suffix",text:a}),c.createDiv({cls:"af-stat-sub",text:o})}renderActivityTimeline(e,s){let n=e.createDiv({cls:"af-section-card"}),r=n.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});D(r,"inbox"),r.appendText(" Recent Activity");let o=n.createDiv({cls:"af-timeline"}),c=s.slice(0,8);if(c.length===0){this.renderEmptyState(o,"inbox","No runs yet","Run an agent to see activity here");return}for(let l of c)this.renderTimelineItem(o,l)}renderTimelineItem(e,s){let n=e.createDiv({cls:"af-timeline-item"}),a=this.statusToTimelineClass(s.status),r=n.createDiv({cls:`af-tl-icon ${a}`});(0,b.setIcon)(r,this.statusToIconName(s.status));let o=n.createDiv({cls:"af-tl-body"}),c=o.createDiv({cls:"af-tl-title"});c.createSpan({cls:"af-agent-tag",text:s.agent}),c.appendText(` ${s.task}`),o.createDiv({cls:"af-tl-desc",text:Ut(s.output,100)});let l=o.createDiv({cls:"af-tl-meta"}),d=l.createSpan();if(D(d,"clock","af-meta-icon"),d.appendText(` ${this.formatStarted(s.started)} \xB7 ${this.formatDuration(s.durationSeconds)}`),s.tokensUsed){let h=l.createSpan();D(h,"zap","af-meta-icon"),h.appendText(` ${s.tokensUsed.toLocaleString()} tokens`)}n.onclick=()=>this.openSlideover(s)}renderFleetStatusPanel(e,s){let n=e.createDiv({cls:"af-section-card"}),a=n.createDiv({cls:"af-section-header"}),r=a.createDiv({cls:"af-section-title"});D(r,"bot"),r.appendText(" Fleet Status");let c=a.createDiv({cls:"af-section-actions"}).createEl("button",{cls:"af-btn-sm primary"});D(c,"plus","af-btn-icon"),c.appendText(" New Agent"),c.onclick=()=>void this.plugin.createAgentTemplate();let l=n.createDiv({cls:"af-agent-mini-list"});if(s.agents.length===0){this.renderEmptyState(l,"bot","No agents yet","Create your first agent to get started");return}for(let h of s.agents)this.renderAgentMini(l,h,s.tasks);let d=s.agents.filter(h=>h.enabled);if(d.length>0){let h=n.createDiv({cls:"af-quick-run"}),u=h.createDiv({cls:"af-quick-run-label"});D(u,"zap","af-meta-icon"),u.appendText(" Quick Run");let p=h.createDiv({cls:"af-quick-run-row"}),f=p.createEl("select",{cls:"af-select"});for(let g of d)f.createEl("option",{text:g.name,attr:{value:g.name}});let m=p.createEl("button",{cls:"af-btn-sm primary"});D(m,"play","af-btn-icon"),m.appendText(" Run"),m.onclick=()=>void this.plugin.runAgentPrompt(f.value)}}renderAgentMini(e,s,n){let a=this.plugin.runtime.getAgentState(s.name),r=n.filter(u=>u.agent===s.name),o=this.healthToClass(a.status),c=e.createDiv({cls:"af-agent-mini"}),l=c.createDiv({cls:`af-agent-avatar ${o}`});s.avatar?.trim()?this.renderAgentAvatar(l,s):l.setText(this.getInitials(s.name));let d=c.createDiv({cls:"af-agent-info"});d.createDiv({cls:"af-agent-name",text:s.name});let h="";if(a.status==="running")h=`Running now \xB7 ${r.length} task${r.length!==1?"s":""}`;else if(!s.enabled)h=`Disabled \xB7 ${r.length} task${r.length!==1?"s":""} paused`;else{let u=r.map(p=>p.nextRun).filter(Boolean).sort()[0];h=u?`Next: ${this.formatNextRun(u)} \xB7 ${r.length} task${r.length!==1?"s":""}`:`${r.length} task${r.length!==1?"s":""}`}d.createDiv({cls:"af-agent-desc",text:h}),c.createDiv({cls:`af-agent-status-dot ${o}`}),c.onclick=()=>this.navigate("agent-detail",s.name)}renderAgentsPage(e){let s=e.createDiv({cls:"af-agents-page"}),n=this.plugin.runtime.getSnapshot(),a=s.createDiv({cls:"af-agents-toolbar"});a.createDiv({cls:"af-page-title",text:"Agents"}),a.createDiv({cls:"af-toolbar-spacer"});let r=a.createEl("button",{cls:"af-btn-sm primary"});D(r,"plus","af-btn-icon"),r.appendText(" New Agent"),r.onclick=()=>void this.plugin.createAgentTemplate();let o=s.createDiv({cls:"af-agents-grid"});if(n.agents.length===0){this.renderEmptyState(o,"bot","No agents configured","Create your first agent to get started");return}for(let c of n.agents)this.renderAgentCard(o,c,n)}renderAgentCard(e,s,n){let a=this.plugin.runtime.getAgentState(s.name),r=this.plugin.runtime.getRecentRuns().filter(E=>E.agent===s.name),o=n.tasks.filter(E=>E.agent===s.name),c=e.createDiv({cls:`af-agent-card${s.enabled?"":" disabled"}`}),l=c.createDiv({cls:"af-agent-card-header"}),d=s.enabled?this.healthToClass(a.status):"disabled",h=l.createDiv({cls:`af-agent-card-avatar ${d}`});this.renderAgentAvatar(h,s);let u=l.createDiv({cls:"af-agent-card-titleblock"}),p=u.createDiv({cls:"af-agent-card-name"});if(p.appendText(s.name),s.heartbeatEnabled&&s.heartbeatSchedule){let E=p.createSpan({cls:"af-heartbeat-indicator"});(0,b.setIcon)(E,"heart-pulse"),E.title=`Heartbeat: ${s.heartbeatSchedule}`}u.createDiv({cls:"af-agent-card-desc",text:s.description??"No description"});let f=l.createDiv({cls:`af-agent-card-toggle${s.enabled?" on":""}`});f.onclick=E=>{E.stopPropagation(),this.plugin.toggleAgent(s.name,!s.enabled)};let m=c.createDiv({cls:"af-agent-card-stats"}),g=r.length,v=r.filter(E=>E.status==="success").length,k=g>0?Math.round(v/g*100):0,w=g>0?Math.round(r.reduce((E,S)=>E+S.durationSeconds,0)/g):0,y=r.reduce((E,S)=>E+(S.tokensUsed??0),0);if(this.renderAgentStat(m,String(g),"Runs"),this.renderAgentStat(m,`${k}%`,"Success"),this.renderAgentStat(m,`${w}s`,"Avg Time"),this.renderAgentStat(m,$a(y),"Tokens"),s.skills.length>0){let E=c.createDiv({cls:"af-agent-card-skills"});for(let S of s.skills)E.createSpan({cls:"af-skill-tag",text:S})}let C=c.createDiv({cls:"af-agent-card-footer"}),T=[`Model: ${s.model}`];s.approvalRequired.length>0&&T.push(`Approval: ${s.approvalRequired.join(", ")}`),s.memory&&T.push("Memory: on"),s.enabled||T.unshift("Disabled"),C.createSpan({cls:"af-agent-card-meta",text:T.join(" \xB7 ")});let _=C.createDiv({cls:"af-agent-card-actions"});if(!s.enabled){let E=_.createEl("button",{cls:"af-btn-sm",text:"Enable"});E.onclick=S=>{S.stopPropagation(),this.plugin.toggleAgent(s.name,!0)}}let O=_.createEl("button",{cls:"af-btn-sm"});if(D(O,"edit","af-btn-icon"),O.appendText(" Edit"),O.onclick=E=>{E.stopPropagation(),this.navigate("edit-agent",s.name)},s.enabled){let E=_.createEl("button",{cls:"af-btn-sm primary"});D(E,"play","af-btn-icon"),E.appendText(" Run"),E.onclick=S=>{S.stopPropagation(),this.plugin.runAgentPrompt(s.name)}}c.onclick=()=>this.navigate("agent-detail",s.name)}renderAgentStat(e,s,n){let a=e.createDiv({cls:"af-agent-stat"});a.createSpan({cls:"af-agent-stat-value",text:s}),a.createSpan({cls:"af-agent-stat-label",text:n})}renderAgentDetailPage(e){let s=e.createDiv({cls:"af-agent-detail-page"}),n=this.detailContext;if(!n){this.renderEmptyState(s,"bot","No agent selected","Select an agent from the list");return}let a=this.plugin.runtime.getSnapshot().agents.find(w=>w.name===n);if(!a){this.renderEmptyState(s,"bot","Agent not found",`Agent "${n}" was not found`);return}let r=this.plugin.runtime.getAgentState(a.name),o=this.plugin.runtime.getRecentRuns().filter(w=>w.agent===a.name),c=s.createDiv({cls:"af-detail-header"}),l=c.createDiv({cls:"af-detail-header-left"}),d=l.createDiv({cls:`af-agent-card-avatar ${this.healthToClass(r.status)}`});this.renderAgentAvatar(d,a);let h=l.createDiv();h.createDiv({cls:"af-detail-header-name",text:a.name}),h.createDiv({cls:"af-detail-header-desc",text:a.description??"No description"});let u=c.createDiv({cls:"af-detail-header-actions"}),p=u.createEl("button",{cls:"af-btn-sm primary"});if(D(p,"message-circle","af-btn-icon"),p.appendText(" Chat"),p.onclick=()=>this.openChatSlideover(a),a.enabled){let w=u.createEl("button",{cls:"af-btn-sm"});D(w,"play","af-btn-icon"),w.appendText(" Run Now"),w.onclick=()=>void this.plugin.runAgentPrompt(a.name);let y=u.createEl("button",{cls:"af-btn-sm"});D(y,"pause","af-btn-icon"),y.appendText(" Disable"),y.onclick=()=>void this.plugin.toggleAgent(a.name,!1)}else{let w=u.createEl("button",{cls:"af-btn-sm"});D(w,"play","af-btn-icon"),w.appendText(" Enable"),w.onclick=()=>void this.plugin.toggleAgent(a.name,!0)}let f=u.createEl("button",{cls:"af-btn-sm"});D(f,"edit","af-btn-icon"),f.appendText(" Edit"),f.onclick=()=>this.navigate("edit-agent",a.name);let m=u.createEl("button",{cls:"af-btn-sm danger"});D(m,"trash-2","af-btn-icon"),m.appendText(" Delete"),m.onclick=()=>void this.plugin.deleteAgent(a.name);let g=s.createDiv({cls:"af-detail-tabs"}),v=[{id:"overview",label:"Overview",icon:"layout-dashboard"},{id:"config",label:"Config",icon:"settings"},{id:"runs",label:"Runs",icon:"scroll-text"},{id:"memory",label:"Memory",icon:"file-text"}];for(let w of v){let y=g.createEl("button",{cls:`af-detail-tab${this.agentDetailTab===w.id?" active":""}`});D(y,w.icon,"af-tab-icon"),y.appendText(` ${w.label}`),y.onclick=()=>{this.agentDetailTab=w.id,this.render()}}let k=s.createDiv({cls:"af-detail-tab-content"});switch(this.agentDetailTab){case"overview":this.renderAgentOverviewTab(k,a,o);break;case"config":this.renderAgentConfigTab(k,a);break;case"runs":this.renderAgentRunsTab(k,o);break;case"memory":this.renderAgentMemoryTab(k,a);break}}renderAgentOverviewTab(e,s,n){let a=e.createDiv({cls:"af-dash-grid"}),r=n.length,o=n.filter(w=>w.status==="success").length,c=r>0?Math.round(o/r*100):0,l=r>0?Math.round(n.reduce((w,y)=>w+y.durationSeconds,0)/r):0,d=n.reduce((w,y)=>w+(y.tokensUsed??0),0),h=n.reduce((w,y)=>w+(y.costUsd??0),0),u=h>0?` \xB7 $${h.toFixed(2)}`:"";if(this.renderStatCard(a,"Total Runs",String(r),"","activity","all time"),this.renderStatCard(a,"Success Rate",`${c}%`,"","check-circle-2",`${o}/${r}`),this.renderStatCard(a,"Avg Time",`${l}s`,"","clock","per run"),this.renderStatCard(a,"Total Tokens",$a(d),"","zap",`all time${u}`),s.isFolder&&(s.heartbeatBody.trim()||s.heartbeatEnabled)){let w=e.createDiv({cls:"af-section-card"}),y=w.createDiv({cls:"af-section-header"}),C=y.createDiv({cls:"af-section-title"});D(C,"heart-pulse"),C.appendText(" Heartbeat");let _=y.createDiv({cls:"af-detail-header-actions"}).createDiv({cls:`af-agent-card-toggle${s.heartbeatEnabled?" on":""}`});_.onclick=async()=>{let S=_.hasClass("on");await this.plugin.repository.updateHeartbeat(s.name,{enabled:!S}),await this.plugin.refreshFromVault(),new b.Notice(`Heartbeat ${S?"paused":"enabled"} for ${s.name}`)};let O=w.createDiv({cls:"af-config-form"});this.renderConfigRow(O,"Schedule",Nd(s.heartbeatSchedule));let E=this.plugin.runtime.getNextHeartbeat(s.name);E&&s.heartbeatEnabled&&this.renderConfigRow(O,"Next run",this.timeUntil(E)),s.heartbeatChannel&&this.renderConfigRow(O,"Channel",s.heartbeatChannel)}if(s.skills.length>0){let w=e.createDiv({cls:"af-section-card"}),C=w.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});D(C,"puzzle"),C.appendText(" Skills");let T=w.createDiv({cls:"af-detail-skills-list"});for(let _ of s.skills)T.createSpan({cls:"af-skill-tag",text:_})}let p=s.mcpServers??[];if(p.length>0){let w=e.createDiv({cls:"af-section-card"}),C=w.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});D(C,"plug"),C.appendText(" MCP Servers");let T=w.createDiv({cls:"af-mcp-overview-list"}),_=this.plugin.repository.getMcpServers();for(let O of p){let E=_.find(N=>N.name===O),S=T.createDiv({cls:"af-mcp-overview-row"}),P=S.createSpan({cls:`af-mcp-status-dot ${E?E.enabled?E.status:"disabled":"disconnected"}`});P.title=E?E.enabled?E.status:"disabled":"unknown",S.createSpan({cls:"af-mcp-overview-name",text:O});let R=E?.toolDetails.length??E?.tools.length??0;R>0?S.createSpan({cls:"af-mcp-overview-tools",text:`${R} tools`}):E&&!E.enabled?S.createSpan({cls:"af-mcp-overview-tools af-muted",text:"disabled"}):E?.status==="needs-auth"&&S.createSpan({cls:"af-mcp-overview-tools af-muted",text:"needs auth"})}}if(s.permissionRules.allow.length>0||s.permissionRules.deny.length>0||s.permissionMode&&s.permissionMode!=="default"){let w=e.createDiv({cls:"af-section-card"}),C=w.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});D(C,"shield-check"),C.appendText(" Permissions");let T=w.createDiv({cls:"af-config-form"});this.renderConfigRow(T,"Mode",s.permissionMode||"default"),s.permissionRules.allow.length>0&&this.renderConfigRow(T,"Allowed",s.permissionRules.allow.join(", ")),s.permissionRules.deny.length>0&&this.renderConfigRow(T,"Denied",s.permissionRules.deny.join(", "))}let m=e.createDiv({cls:"af-section-card"}),v=m.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});D(v,"scroll-text"),v.appendText(" Recent Runs");let k=m.createDiv({cls:"af-timeline"});if(n.length===0)this.renderEmptyState(k,"scroll-text","No runs yet","");else for(let w of n.slice(0,5))this.renderTimelineItem(k,w)}renderAgentConfigTab(e,s){let n=e.createDiv({cls:"af-config-form"});this.renderConfigRow(n,"Name",s.name),this.renderConfigRow(n,"Description",s.description??""),this.renderConfigRow(n,"Model",s.model),this.renderConfigRow(n,"Timeout",`${s.timeout}s`),this.renderConfigRow(n,"Working Directory",s.cwd??"(vault root)"),this.renderConfigRow(n,"Permission Mode",s.permissionMode||"default"),this.renderConfigRow(n,"Approval Required",s.approvalRequired.join(", ")||"none"),s.permissionRules.allow.length>0&&this.renderConfigRow(n,"Allowed Commands",s.permissionRules.allow.join(", ")),s.permissionRules.deny.length>0&&this.renderConfigRow(n,"Blocked Commands",s.permissionRules.deny.join(", ")),this.renderConfigRow(n,"Memory",s.memory?"Enabled":"Disabled"),this.renderConfigRow(n,"Auto-compact",s.autoCompactThreshold&&s.autoCompactThreshold>0?`at ${s.autoCompactThreshold}% context`:"disabled"),s.wikiReferences&&s.wikiReferences.length>0&&this.renderConfigRow(n,"Wiki access",s.wikiReferences.map(c=>c.agent).join(", ")),this.renderConfigRow(n,"Tags",s.tags.join(", ")||"none");let a=n.createDiv({cls:"af-config-prompt-section"});if(a.createDiv({cls:"af-slideover-section-title",text:"SYSTEM PROMPT"}),a.createDiv({cls:"af-output-block",text:s.body||"(empty)"}),s.heartbeatBody.trim()){let c=n.createDiv({cls:"af-config-prompt-section"});c.createDiv({cls:"af-slideover-section-title",text:"HEARTBEAT INSTRUCTION"}),c.createDiv({cls:"af-output-block",text:s.heartbeatBody})}let o=n.createDiv({cls:"af-slideover-actions"}).createEl("button",{cls:"af-btn-sm primary"});D(o,"edit","af-btn-icon"),o.appendText(" Edit Agent"),o.onclick=()=>this.navigate("edit-agent",s.name)}renderConfigRow(e,s,n){let a=e.createDiv({cls:"af-detail-row"});a.createSpan({cls:"af-detail-label",text:s}),a.createSpan({cls:"af-detail-value af-mono",text:n})}renderAgentRunsTab(e,s){if(s.length===0){this.renderEmptyState(e,"scroll-text","No runs yet","Run this agent to see history");return}for(let n of s){let a=e.createDiv({cls:"af-run-list-item"}),r=a.createDiv({cls:`af-tl-icon ${this.statusToTimelineClass(n.status)}`});(0,b.setIcon)(r,this.statusToIconName(n.status));let o=a.createDiv({cls:"af-tl-body"}),c=o.createDiv({cls:"af-tl-title"});c.createSpan({text:n.task}),c.createSpan({cls:`af-status-badge ${this.statusToBadgeClass(n.status)}`,text:this.statusToBadgeText(n.status)});let l=o.createDiv({cls:"af-tl-meta"});l.createSpan({text:`${this.formatStarted(n.started)} \xB7 ${this.formatDuration(n.durationSeconds)}`}),n.tokensUsed&&l.createSpan({text:`${n.tokensUsed.toLocaleString()} tokens`}),o.createDiv({cls:"af-tl-desc",text:Ut(n.output,120)}),a.onclick=()=>this.openSlideover(n)}}async renderAgentMemoryTab(e,s){if(!s.memory){this.renderEmptyState(e,"file-text","Memory disabled","Enable memory in agent config");return}let n=await this.plugin.repository.readWorkingMemory(s.name),a=e.createDiv({cls:"af-form-help"}),r=n?.tokenEstimate??0,o=s.reflection.enabled?`reflection on (${s.reflection.schedule})`:"reflection off";a.setText(`~${r} / ${s.memoryTokenBudget} tokens \xB7 ${o}`),!n||n.sections.length===0?this.renderEmptyState(e,"file-text","No memories yet","Agent will learn from runs"):e.createDiv({cls:"af-output-block"}).setText(Ge(n.sections));let c=e.createDiv({cls:"af-slideover-actions"}),l=c.createEl("button",{cls:"af-btn-sm"});D(l,"moon","af-btn-icon"),l.appendText(" Reflect now"),l.onclick=async()=>{l.disabled=!0,l.setText(" Reflecting\u2026");let h=await this.plugin.runtime.runReflectionNow(s.name);new b.Notice(`Agent Fleet: ${h.message}`),await this.renderAgentMemoryTab((e.empty(),e),s)};let d=c.createEl("button",{cls:"af-btn-sm"});D(d,"external-link","af-btn-icon"),d.appendText(" Open in Editor"),d.onclick=()=>void this.plugin.openPath(this.plugin.repository.getWorkingMemoryPath(s.name))}timeAgo(e){let s=Math.round((Date.now()-e.getTime())/1e3);if(s<60)return"just now";let n=Math.round(s/60);if(n<60)return`${n}m ago`;let a=Math.round(n/60);return a<24?`${a}h ago`:`${Math.round(a/24)}d ago`}timeUntil(e){let s=Math.round((e.getTime()-Date.now())/1e3);if(s<60)return"< 1m";let n=Math.round(s/60);if(n<60)return`in ${n}m`;let a=Math.round(n/60);return a<24?`in ${a}h`:`in ${Math.round(a/24)}d`}renderKanbanPage(e){let s=e.createDiv({cls:"af-kanban-page"}),n=this.plugin.runtime.getSnapshot(),a=this.plugin.runtime.getRecentRuns(),r=s.createDiv({cls:"af-kanban-toolbar"});r.createDiv({cls:"af-page-title",text:"Tasks Board"}),r.createDiv({cls:"af-toolbar-spacer"});let o=r.createEl("button",{cls:"af-btn-sm primary"});D(o,"plus","af-btn-icon"),o.appendText(" New Task"),o.onclick=()=>this.navigate("create-task");let c=s.createDiv({cls:"af-kanban-board"}),l=[],d=[],h=[],u=[],p=[],f=new Set;for(let k of n.agents){let w=this.plugin.runtime.getAgentState(k.name);w.status==="running"&&w.currentTaskId&&f.add(w.currentTaskId)}let m=this.toLocalDateStr(new Date);for(let k of a)k.status==="success"&&this.runToLocalDate(k.started)===m?u.push(k):(k.status==="failure"||k.status==="timeout"||k.status==="cancelled")&&this.runToLocalDate(k.started)===m&&p.push(k);let g=new Set(u.map(k=>k.task)),v=new Set(p.map(k=>k.task));for(let k of n.tasks){let w=g.has(k.taskId)||v.has(k.taskId)||k.lastRun&&this.runToLocalDate(k.lastRun)===m;if(f.has(k.taskId))h.push(k);else{if(w&&!k.schedule)continue;k.schedule&&k.enabled?d.push(k):l.push(k)}}this.renderKanbanColumn(c,"Backlog","inbox",l.length,k=>{for(let w of l)this.renderKanbanTaskCard(k,w,n,!0)},"backlog"),this.renderKanbanColumn(c,"Scheduled","clock",d.length,k=>{for(let w of d)this.renderKanbanTaskCard(k,w,n,!0)},"scheduled"),this.renderKanbanColumn(c,"Running","loader-2",h.length,k=>{for(let w of h)this.renderKanbanRunningCard(k,w)},"running",!1,"running"),this.renderKanbanColumn(c,"Done","check-circle-2",u.length,k=>{for(let w of u.slice(0,10))this.renderKanbanCompletedCard(k,w)},"completed"),this.renderKanbanColumn(c,"Failed","x-circle",p.length,k=>{for(let w of p)this.renderKanbanFailedCard(k,w)},"failed",!1,"failed")}renderKanbanColumn(e,s,n,a,r,o,c=!1,l){let d=e.createDiv({cls:`af-kanban-column${l?` af-kanban-${l}`:""}`});(o==="backlog"||o==="scheduled")&&Po(d,f=>this.handleTaskDrop(f,o));let u=d.createDiv({cls:"af-kanban-col-header"}).createDiv({cls:"af-kanban-col-title"});D(u,n),u.appendText(` ${s} `),u.createSpan({cls:"af-kanban-col-count",text:String(a)});let p=d.createDiv({cls:"af-kanban-col-body"});if(r(p),a===0&&p.createDiv({cls:"af-kanban-empty",text:"No items"}),c){let m=d.createDiv({cls:"af-kanban-col-add"}).createEl("button");D(m,"plus","af-btn-icon"),m.appendText(" Add task"),m.onclick=()=>{this.navigate("create-task")}}}handleTaskDrop(e,s){let n=this.plugin.runtime.getSnapshot().tasks.find(a=>a.taskId===e);if(n){if(s==="backlog")this.setTaskEnabled(n,!1).then(()=>{new b.Notice(`Task "${e}" moved to backlog (disabled)`)});else if(s==="scheduled"){if(!n.schedule&&!n.runAt){new b.Notice(`Task "${e}" needs a schedule. Open task details to set one.`),this.navigate("task-detail",e);return}this.setTaskEnabled(n,!0).then(()=>{new b.Notice(`Task "${e}" moved to scheduled (enabled)`)})}}}async setTaskEnabled(e,s){let n=this.plugin.app.vault.getAbstractFileByPath(e.filePath);if(!n||!(n instanceof b.TFile))return;let a=await this.plugin.app.vault.cachedRead(n),{frontmatter:r,body:o}=Q(a);r.enabled=s,await this.plugin.app.vault.modify(n,H(r,o)),await this.plugin.refreshFromVault()}renderKanbanTaskCard(e,s,n,a){let r=e.createDiv({cls:`af-kanban-card af-priority-${s.priority}`});if(a){Eo(r,s.taskId);let m=r.createDiv({cls:"af-kanban-card-grip"});(0,b.setIcon)(m,"grip-vertical")}let o=r.createDiv({cls:"af-kanban-card-header"});o.createDiv({cls:"af-kanban-card-title",text:s.taskId});let l=(n.agents.find(m=>m.name===s.agent)?.enabled??!1)&&s.enabled,d=o.createSpan({cls:`af-kanban-card-status ${l?"active":"inactive"}`});d.title=l?"Active":"Inactive";let h=r.createDiv({cls:"af-kanban-card-agent"}),u=h.createSpan({cls:"af-kanban-card-agent-icon"});(0,b.setIcon)(u,"bot"),h.createSpan({cls:"af-kanban-card-agent-name",text:s.agent});let f=r.createDiv({cls:"af-kanban-card-footer"}).createSpan({cls:"af-kanban-card-schedule"});l?s.schedule?(D(f,"refresh-cw","af-meta-icon"),f.appendText(` ${this.humanizeCron(s.schedule)}`)):f.appendText(s.runAt??"Manual"):(D(f,"pause","af-meta-icon"),f.appendText(" Paused")),r.onclick=()=>this.navigate("task-detail",s.taskId)}renderKanbanRunningCard(e,s){let n=e.createDiv({cls:"af-kanban-card af-kanban-card-running"});n.createDiv({cls:"af-kanban-card-title",text:s.taskId});let a=n.createDiv({cls:"af-kanban-card-agent"}),r=a.createSpan({cls:"af-kanban-card-agent-icon"});(0,b.setIcon)(r,"bot"),a.createSpan({cls:"af-kanban-card-agent-name",text:s.agent});let c=this.plugin.runtime.getSnapshot().agents.find(C=>C.name===s.agent)?.timeout??300,l=this.plugin.runtime.getAgentState(s.agent),d=l.runStarted?new Date(l.runStarted).getTime():Date.now(),p=n.createDiv({cls:"af-kanban-progress"}).createDiv({cls:"af-kanban-progress-track"}).createDiv({cls:"af-kanban-progress-bar af-kanban-progress-bar-real"}),f=(Date.now()-d)/1e3,m=Math.min(95,f/c*100);p.style.width=`${m}%`;let g=n.createDiv({cls:"af-kanban-card-footer"}),v=g.createSpan({cls:"af-kanban-card-schedule"});D(v,"loader-2","af-meta-icon");let k=Math.round(f);v.appendText(` ${k}s / ${c}s`);let w=g.createEl("button",{cls:"af-kanban-stop-btn"});(0,b.setIcon)(w,"square"),w.title="Stop task",w.onclick=C=>{C.stopPropagation(),this.plugin.runtime.abortAgentRun(s.agent),new b.Notice(`Stopped task "${s.taskId}"`)};let y=setInterval(()=>{let C=(Date.now()-d)/1e3,T=Math.min(95,C/c*100);p.style.width=`${T}%`;let _=Math.round(C);v.textContent="",(0,b.setIcon)(v,"loader-2"),v.appendText(` ${_}s / ${c}s`)},1e3);this.streamingUnsubscribes.push(()=>clearInterval(y))}renderKanbanCompletedCard(e,s){let n=e.createDiv({cls:"af-kanban-card"});n.createDiv({cls:"af-kanban-card-title",text:s.task});let a=n.createDiv({cls:"af-kanban-card-agent"}),r=a.createSpan({cls:"af-kanban-card-agent-icon"});(0,b.setIcon)(r,"bot"),a.createSpan({cls:"af-kanban-card-agent-name",text:s.agent});let c=n.createDiv({cls:"af-kanban-card-footer"}).createSpan({cls:"af-kanban-card-schedule"});D(c,"check-circle-2","af-meta-icon"),c.appendText(` ${this.formatStarted(s.started)} \xB7 ${this.formatDuration(s.durationSeconds)}`),n.onclick=()=>this.openSlideover(s)}renderKanbanFailedCard(e,s){let n=s.status==="cancelled",a=e.createDiv({cls:`af-kanban-card ${n?"af-kanban-card-cancelled":"af-kanban-card-failed"}`});a.createDiv({cls:"af-kanban-card-title",text:s.task});let r=a.createDiv({cls:"af-kanban-card-agent"}),o=r.createSpan({cls:"af-kanban-card-agent-icon"});(0,b.setIcon)(o,"bot"),r.createSpan({cls:"af-kanban-card-agent-name",text:s.agent});let c=n?`Stopped after ${s.durationSeconds}s`:s.status==="timeout"?`Timeout after ${s.durationSeconds}s`:Ut(s.output,60),l=a.createDiv({cls:"af-kanban-card-error"});D(l,n?"square":"alert-triangle","af-meta-icon"),l.appendText(` ${c}`);let d=a.createDiv({cls:"af-kanban-card-footer"}),h=d.createSpan({cls:"af-kanban-card-schedule"});if(D(h,n?"square":"x-circle","af-meta-icon"),h.appendText(` ${this.formatStarted(s.started)}`),!n){let u=d.createEl("button",{cls:"af-btn-sm"});D(u,"refresh-cw","af-btn-icon"),u.appendText(" Retry"),u.onclick=p=>{p.stopPropagation(),this.plugin.runAgentPrompt(s.agent)}}a.onclick=()=>this.openSlideover(s)}renderRunsPage(e){let s=e.createDiv({cls:"af-runs-page"}),n=this.plugin.runtime.getRecentRuns(),a=s.createDiv({cls:"af-runs-toolbar"});a.createDiv({cls:"af-page-title",text:"Run History"}),a.createDiv({cls:"af-toolbar-spacer"});let r=s.createDiv({cls:"af-runs-table"});if(n.length===0){this.renderEmptyState(r,"scroll-text","No runs yet","Run an agent to see history here");return}let o=r.createEl("table"),l=o.createEl("thead").createEl("tr");for(let h of["Status","Agent","Task","Started","Duration","Tokens","Model"])l.createEl("th",{text:h});let d=o.createEl("tbody");for(let h of n.slice(0,50))this.renderRunRow(d,h)}renderRunRow(e,s){let n=e.createEl("tr"),r=n.createEl("td").createSpan({cls:`af-status-badge ${this.statusToBadgeClass(s.status)}`}),o=r.createSpan();(0,b.setIcon)(o,this.statusToIconName(s.status)),r.appendText(` ${this.statusToBadgeText(s.status)}`);let c=n.createEl("td",{cls:"af-agent-link"});c.setText(s.agent),c.onclick=l=>{l.stopPropagation(),this.navigate("agent-detail",s.agent)},n.createEl("td",{text:s.task}),n.createEl("td",{cls:"af-mono",text:this.formatStarted(s.started)}),n.createEl("td",{cls:"af-mono",text:this.formatDuration(s.durationSeconds)}),n.createEl("td",{cls:"af-mono",text:s.tokensUsed?s.tokensUsed.toLocaleString():"\u2014"}),n.createEl("td",{cls:"af-mono",text:s.model}),n.style.cursor="pointer",n.onclick=()=>this.openSlideover(s)}renderSkillsPage(e){let s=e.createDiv({cls:"af-skills-page"}),n=this.plugin.runtime.getSnapshot(),a=s.createDiv({cls:"af-agents-toolbar"});a.createDiv({cls:"af-page-title",text:"Skills Library"}),a.createDiv({cls:"af-toolbar-spacer"});let r=a.createEl("button",{cls:"af-btn-sm primary"});D(r,"plus","af-btn-icon"),r.appendText(" New Skill"),r.onclick=()=>void this.plugin.createSkillTemplate();let o=s.createDiv({cls:"af-skills-grid"});if(n.skills.length===0){this.renderEmptyState(o,"puzzle","No skills yet","Create skills to give agents specialized abilities");return}for(let c of n.skills)this.renderSkillCard(o,c,n.agents)}renderSkillCard(e,s,n){let a=e.createDiv({cls:"af-skill-card"}),r=a.createDiv({cls:"af-skill-card-header"}),o=r.createDiv({cls:"af-skill-card-icon"});(0,b.setIcon)(o,this.getSkillIcon(s.name));let c=r.createEl("button",{cls:"af-btn-sm af-btn-xs"});D(c,"edit","af-btn-icon"),c.onclick=d=>{d.stopPropagation(),this.navigate("edit-skill",s.name)},a.createDiv({cls:"af-skill-card-name",text:s.name}),a.createDiv({cls:"af-skill-card-desc",text:s.description??"No description"});let l=n.filter(d=>d.skills.includes(s.name));if(l.length>0){let d=a.createDiv({cls:"af-skill-card-agents"});for(let h of l)d.createSpan({cls:"af-skill-card-agent-tag",text:h.name})}}renderChannelsPage(e){let s=e.createDiv({cls:"af-agents-page"}),n=this.plugin.runtime.getSnapshot(),a=s.createDiv({cls:"af-agents-toolbar"});a.createDiv({cls:"af-page-title",text:"Channels"}),a.createDiv({cls:"af-toolbar-spacer"});let r=a.createEl("button",{cls:"af-btn-sm primary"});D(r,"plus","af-btn-icon"),r.appendText(" New Channel"),r.onclick=()=>this.navigate("create-channel");let o=s.createDiv({cls:"af-agents-grid"});if(n.channels.length===0){this.renderEmptyState(o,"radio","No channels configured","Connect an agent to Slack or another chat platform");return}for(let c of n.channels)this.renderChannelCard(o,c,n.validationIssues)}async renderWikiKeepersPage(e){let s=e.createDiv({cls:"af-agents-page"}),n=this.plugin.runtime.getSnapshot(),a=s.createDiv({cls:"af-agents-toolbar"});a.createDiv({cls:"af-page-title",text:"Wiki Keepers"}),a.createDiv({cls:"af-toolbar-spacer"});let r=n.agents.filter(c=>c.wikiKeeper!==void 0);if(r.length===0){this.renderEmptyState(s,"library","No Wiki Keepers yet","Open Settings \u2192 Agent Fleet \u2192 Wiki Keepers \u2192 + Add to create one.");return}let o=s.createDiv({cls:"af-wk-list"});o.style.display="flex",o.style.flexDirection="column",o.style.gap="16px";for(let c of r)await this.renderWikiKeeperCard(o,c)}async renderWikiKeeperCard(e,s){let n=s.wikiKeeper,a=e.createDiv({cls:"af-card"});a.style.padding="16px",a.style.border="1px solid var(--background-modifier-border)",a.style.borderRadius="8px";let r=a.createDiv();r.style.display="flex",r.style.alignItems="center",r.style.gap="12px",r.style.marginBottom="12px";let o=r.createDiv();o.style.flex="1",o.createEl("strong",{text:s.name});let c=n.scopeRoot||"(whole vault)";o.createEl("div",{text:`Scope: ${c} \xB7 topics: ${n.topicsRoot}/ \xB7 log: ${n.logPath}`,cls:"af-form-hint"});let l=r.createEl("button",{cls:"af-btn-sm"});l.appendText("Open log"),l.onclick=()=>{let g=n.scopeRoot?`${n.scopeRoot}/${n.logPath}`:n.logPath,v=this.plugin.app.vault.getAbstractFileByPath(g);v instanceof b.TFile?this.plugin.app.workspace.getLeaf().openFile(v):new b.Notice(`Log file not found: ${g}`)};let d=n.scopeRoot?`${n.scopeRoot}/${n.logPath}`:n.logPath,h=this.plugin.app.vault.getAbstractFileByPath(d),u=null;if(h instanceof b.TFile)try{let g=await this.plugin.app.vault.cachedRead(h);u=Ro(g)}catch{u=null}if(!u){a.createDiv({cls:"af-form-hint"}).setText("No lint report yet. Run wiki-lint manually or wait for the weekly task to fire.");return}let p=a.createDiv();if(p.style.display="flex",p.style.alignItems="baseline",p.style.gap="12px",p.style.marginBottom="8px",p.createEl("strong",{text:`Lint ${u.date}`}),p.createSpan({cls:"af-form-hint",text:`${u.summary.length} summary lines \xB7 ${u.autoApplied.length} auto-applied \xB7 ${u.needsReview.length} needs review`}),u.summary.length>0){let g=a.createEl("details");g.createEl("summary",{text:"Summary"});let v=g.createEl("ul");v.style.marginTop="4px";for(let k of u.summary)v.createEl("li",{text:k})}if(u.autoApplied.length>0){let g=a.createEl("details");g.createEl("summary",{text:`Auto-applied (${u.autoApplied.length})`});let v=g.createEl("ul");v.style.marginTop="4px";for(let k of u.autoApplied)v.createEl("li",{text:k})}if(u.refreshChained.length>0){let g=a.createEl("details");g.createEl("summary",{text:`Refresh chained (${u.refreshChained.length})`});let v=g.createEl("ul");v.style.marginTop="4px";for(let k of u.refreshChained)v.createEl("li",{text:k})}let f=a.createDiv();if(f.style.marginTop="12px",f.createEl("strong",{text:`Needs review (${u.needsReview.length})`}),u.needsReview.length===0){f.createDiv({cls:"af-form-hint",text:"All clear. Nothing requires manual review from this lint pass."});return}let m=f.createDiv();m.style.display="flex",m.style.flexDirection="column",m.style.gap="6px",m.style.marginTop="8px";for(let g of u.needsReview){let v=m.createDiv();v.style.display="flex",v.style.alignItems="flex-start",v.style.gap="8px",v.style.padding="8px 10px",v.style.background="var(--background-secondary)",v.style.borderRadius="4px",v.style.fontSize="13px";let k=v.createDiv();k.style.flex="1",k.setText(g);let w=v.createEl("button",{cls:"af-btn-sm",text:"Dismiss"});w.title="Hide this item from the dashboard until the next lint pass (does not modify log.md).",w.onclick=()=>{v.remove()}}}renderChannelCard(e,s,n){let a=this.plugin.channelManager?.getChannelStatus(s.name)??"disabled",r=Mo(a),o=s.enabled&&a!=="disabled"?"af-agent-card":"af-agent-card disabled",c=e.createDiv({cls:o});c.style.cursor="default";let l=c.createDiv({cls:"af-agent-card-header"}),d=l.createDiv({cls:`af-agent-card-avatar ${r}`});(0,b.setIcon)(d,"radio");let h=l.createDiv({cls:"af-agent-card-titleblock"});h.createDiv({cls:"af-agent-card-name",text:s.name}),h.createDiv({cls:"af-agent-card-desc",text:`Default: ${s.defaultAgent}`});let u=l.createSpan({cls:`af-pill ${Bd(a)}`});if(u.createSpan({cls:"af-dot"}),u.appendText(` ${a}`),s.allowedAgents.length>0){let T=c.createDiv({cls:"af-agent-card-skills"});for(let _ of s.allowedAgents){let O=T.createSpan({cls:"af-skill-tag",text:_});_===s.defaultAgent&&(O.style.fontWeight="700")}}let p=c.createDiv({cls:"af-agent-card-stats"}),f=this.plugin.channelManager?.getSessionCount(s.name)??0,m=this.plugin.channelManager?.getMetrics(s.name),g=s.allowedAgents.length>0?String(s.allowedAgents.length):"all";this.renderAgentStat(p,g,"Agents"),this.renderAgentStat(p,String(f),"Sessions"),this.renderAgentStat(p,String(m?.messagesReceived??0),"In"),this.renderAgentStat(p,String(m?.messagesSent??0),"Out");let v=c.createDiv({cls:"af-agent-card-footer"}),k=[s.type];s.enabled||k.push("disabled"),s.allowedUsers.length>0?k.push(`${s.allowedUsers.length} user(s)`):k.push("allowlist empty"),v.createSpan({cls:"af-agent-card-meta",text:k.join(" \xB7 ")});let y=v.createDiv({cls:"af-agent-card-actions"}).createEl("button",{cls:"af-btn-sm"});D(y,"edit","af-btn-icon"),y.appendText(" Edit"),y.onclick=T=>{T.stopPropagation(),this.navigate("edit-channel",s.name)};let C=n.filter(T=>T.path===s.filePath);if(C.length>0){let T=c.createDiv({cls:"af-channel-issues"});for(let _ of C)T.createDiv({cls:"af-channel-issue-row",text:_.message})}}renderCreateChannelPage(e){let s=e.createDiv({cls:"af-create-agent-page"}),n=this.plugin.runtime.getSnapshot(),a=this.plugin.channelCredentials.list(),r=s.createDiv({cls:"af-detail-header"}),o=r.createDiv({cls:"af-detail-header-left"}),c=o.createDiv({cls:"af-agent-card-avatar idle"});(0,b.setIcon)(c,"plus");let l=o.createDiv();l.createDiv({cls:"af-detail-header-name",text:"Create New Channel"}),l.createDiv({cls:"af-detail-header-desc",text:"Connect an external chat transport to an agent"}),r.createDiv({cls:"af-detail-header-actions"});let d={name:"",type:"slack",defaultAgent:n.agents[0]?.name??"",allowedAgents:[],credentialRef:a[0]?.ref??"",allowedUsers:"",perUserSessions:!0,channelContext:"",enabled:!0,tags:"",body:"",transportJson:""},h=s.createDiv({cls:"af-create-form"}),u=h.createDiv({cls:"af-create-section"}),p=u.createDiv({cls:"af-create-section-header"}),f=p.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(f,"radio"),p.createSpan({text:"Channel Details"}),this.createFormField(u,"Name","my-slack","Unique identifier for this channel",$=>{d.name=$});let m=u.createDiv({cls:"af-form-row"});m.createDiv({cls:"af-form-label",text:"Type"});let g=m.createEl("select",{cls:"af-form-select"});g.createEl("option",{text:"slack",attr:{value:"slack"}}),g.createEl("option",{text:"telegram",attr:{value:"telegram"}}),g.addEventListener("change",()=>{d.type=g.value});let v=u.createDiv({cls:"af-form-row"}),k=v.createDiv({cls:"af-form-label"});k.setText("Credential"),this.addTooltip(k,"Configured in Settings \u2192 Agent Fleet \u2192 Channel Credentials");let w=v.createEl("select",{cls:"af-form-select"});a.length===0&&w.createEl("option",{text:"(no credentials configured)",attr:{value:""}});for(let $ of a)w.createEl("option",{text:`${$.ref} (${$.entry.type})`,attr:{value:$.ref}});w.addEventListener("change",()=>{d.credentialRef=w.value});let y=u.createDiv({cls:"af-form-row af-form-row-toggle"});y.createDiv({cls:"af-form-label",text:"Enabled"});let C=y.createDiv({cls:"af-agent-card-toggle on"});C.onclick=()=>{let $=C.hasClass("on");C.toggleClass("on",!$),d.enabled=!$};let T=h.createDiv({cls:"af-create-section"}),_=T.createDiv({cls:"af-create-section-header"}),O=_.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(O,"bot"),_.createSpan({text:"Agent Routing"});let E=T.createDiv({cls:"af-form-row"}),S=E.createDiv({cls:"af-form-label"});S.setText("Default agent"),this.addTooltip(S,"Used when no @agent-name prefix is given in a message");let P=E.createEl("select",{cls:"af-form-select"});for(let $ of n.agents)P.createEl("option",{text:$.name,attr:{value:$.name}});P.addEventListener("change",()=>{d.defaultAgent=P.value});let R=T.createDiv({cls:"af-form-row"}),N=R.createDiv({cls:"af-form-label"});N.setText("Allowed agents"),this.addTooltip(N,"Agents reachable via @prefix. Leave unchecked to allow all agents.");let L=R.createDiv({cls:"af-form-checkboxes"});for(let $ of n.agents){let Ce=L.createEl("label",{cls:"af-form-checkbox-label"}),we=Ce.createEl("input",{attr:{type:"checkbox",value:$.name}});Ce.appendText(` ${$.name}`),we.addEventListener("change",()=>{we.checked?d.allowedAgents.includes($.name)||d.allowedAgents.push($.name):d.allowedAgents=d.allowedAgents.filter(ge=>ge!==$.name)})}let G=T.createDiv({cls:"af-form-row af-form-row-toggle"}),U=G.createDiv({cls:"af-form-label"});U.setText("Per-user sessions"),this.addTooltip(U,"Each external user gets their own isolated Claude session");let X=G.createDiv({cls:"af-agent-card-toggle on"});X.onclick=()=>{let $=X.hasClass("on");X.toggleClass("on",!$),d.perUserSessions=!$};let me=h.createDiv({cls:"af-create-section"}),ye=me.createDiv({cls:"af-create-section-header"}),ee=ye.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(ee,"shield-check"),ye.createSpan({text:"Access Control"});let W=me.createDiv({cls:"af-form-label"});W.setText("Allowed users"),this.addTooltip(W,"Slack user IDs (U...), one per line. Only listed users can reach the bot.");let de=me.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:`U0AQW6P37N1
12007
- U0BXYZ12345`,rows:"4"}});de.addEventListener("input",()=>{d.allowedUsers=de.value});let V=h.createDiv({cls:"af-create-section"}),te=V.createDiv({cls:"af-create-section-header"}),Y=te.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(Y,"message-square");let Z=te.createSpan({text:"Channel Context"});this.addTooltip(Z,"Extra instructions appended to the agent's system prompt when reached through this channel");let j=V.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"You are being contacted via Slack. Keep replies concise...",rows:"6"}});j.addEventListener("input",()=>{d.channelContext=j.value}),this.createFormField(u,"Tags","ops, internal","Comma-separated metadata",$=>{d.tags=$});let fe=h.createDiv({cls:"af-create-section"}),Pe=fe.createDiv({cls:"af-create-section-header"}),Oe=Pe.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(Oe,"settings");let Ue=Pe.createSpan({text:"Advanced"});this.addTooltip(Ue,"Markdown body (shown in the channel detail page) and transport-specific overrides");let Re=fe.createDiv({cls:"af-form-label"});Re.setText("Body (markdown)"),this.addTooltip(Re,"Free-form notes for this channel. Shown in the channel detail page; not sent to the agent.");let Se=fe.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"Notes, runbook snippets, escalation contacts\u2026",rows:"4"}});Se.addEventListener("input",()=>{d.body=Se.value});let De=fe.createDiv({cls:"af-form-label"});De.setText("Transport config (JSON)"),this.addTooltip(De,"Optional JSON object for transport-specific overrides (e.g. Slack socket_mode, telegram webhook settings). Leave blank for defaults.");let Ne=fe.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:`{
12004
+ `,t)),n<t/2&&(n=t),e.push(s.slice(0,n)),s=s.slice(n).replace(/^\n+/,"")}return s&&e.push(s),e}var Ps=require("obsidian");var Fn=class extends Ps.ItemView{constructor(e,s){super(e);this.plugin=s}getViewType(){return Ut}getDisplayText(){return"Agent Fleet"}getIcon(){return"bot"}async onOpen(){this.plugin.subscribeView(this),await this.render()}async onClose(){this.plugin.unsubscribeView(this)}async render(){let e=this.contentEl;e.empty(),e.addClass("af-sidebar");let s=this.plugin.runtime.getSnapshot(),n=this.plugin.runtime.getFleetStatus(),a=e.createDiv({cls:"af-sidebar-section"});a.createDiv({cls:"af-sidebar-section-header",text:"AGENT FLEET"});let r=[{icon:"layout-dashboard",label:"Dashboard",page:"dashboard"},{icon:"bot",label:"Agents",page:"agents",badge:()=>s.agents.length},{icon:"columns-3",label:"Tasks Board",page:"kanban"},{icon:"scroll-text",label:"Run History",page:"runs"},{icon:"shield-check",label:"Approvals",page:"approvals",badge:()=>n.pending},{icon:"puzzle",label:"Skills",page:"skills",badge:()=>s.skills.length},{icon:"plug",label:"MCP Servers",page:"mcp",badge:()=>this.plugin.repository.getMcpServers().length},{icon:"radio",label:"Channels",page:"channels",badge:()=>this.plugin.channelManager?.getConnectedCount()??s.channels.length}];for(let l of r){let h=a.createDiv({cls:"af-sidebar-nav-item"}),d=h.createSpan({cls:"af-sidebar-nav-icon"});(0,Ps.setIcon)(d,l.icon),h.createSpan({cls:"af-sidebar-nav-label",text:l.label});let u=l.badge?.();u!==void 0&&u>0&&h.createSpan({cls:"af-sidebar-badge",text:String(u)}),h.setAttribute("role","button"),h.setAttribute("tabindex","0"),h.onclick=()=>void this.plugin.navigateDashboard(l.page),h.onkeydown=p=>{(p.key==="Enter"||p.key===" ")&&(p.preventDefault(),this.plugin.navigateDashboard(l.page))}}let o=e.createDiv({cls:"af-sidebar-section"});o.createDiv({cls:"af-sidebar-section-header",text:"AGENTS"}),s.agents.length===0&&o.createDiv({cls:"af-sidebar-empty",text:"No agents configured"});for(let l of s.agents){let h=this.plugin.runtime.getAgentState(l.name),d=o.createDiv({cls:"af-sidebar-agent-item"});d.createSpan({cls:`af-sidebar-agent-dot ${this.healthToClass(h.status)}`}),d.createSpan({cls:"af-sidebar-agent-name",text:l.name}),d.setAttribute("role","button"),d.setAttribute("tabindex","0"),d.onclick=()=>void this.plugin.navigateDashboard("agent-detail",l.name),d.onkeydown=u=>{(u.key==="Enter"||u.key===" ")&&(u.preventDefault(),this.plugin.navigateDashboard("agent-detail",l.name))}}let c=e.createDiv({cls:"af-sidebar-section"});c.createDiv({cls:"af-sidebar-section-header",text:"QUICK ACTIONS"}),this.renderQuickAction(c,"plus","New Agent",()=>void this.plugin.createAgentTemplate()),this.renderQuickAction(c,"plus","New Task",()=>void this.plugin.openCreateTask()),this.renderQuickAction(c,"plus","New Skill",()=>void this.plugin.createSkillTemplate())}renderQuickAction(e,s,n,a){let r=e.createDiv({cls:"af-sidebar-action-item"}),o=r.createSpan({cls:"af-sidebar-action-icon"});(0,Ps.setIcon)(o,s),r.createSpan({text:n}),r.setAttribute("role","button"),r.setAttribute("tabindex","0"),r.onclick=a,r.onkeydown=c=>{(c.key==="Enter"||c.key===" ")&&(c.preventDefault(),a())}}healthToClass(e){switch(e){case"running":return"running";case"error":return"error";case"pending":return"pending";case"disabled":return"disabled";default:return"idle"}}};var w=require("obsidian");var ts=require("obsidian"),Ld=["bot","brain","shield-check","search","file-text","rocket","wand","sparkles","zap","target","compass","eye","code","terminal","database","globe","mail","message-circle","book","pen-tool","palette","music","camera","chart-bar","clipboard","cpu","server","cloud","lock","key","bell","calendar","clock","heart","star","flag","bookmark"],On=class extends ts.Modal{constructor(e,s,n){super(e);this.onSelect=n;this.selectedIcon=s}searchQuery="";selectedIcon;allIcons=[];gridContainer;onOpen(){this.allIcons=(0,ts.getIconIds)().sort();let{contentEl:e}=this;e.empty(),e.addClass("af-icon-picker-modal");let s=e.createEl("input",{cls:"af-icon-picker-search",attr:{type:"text",placeholder:"Search icons...",value:this.searchQuery}});this.gridContainer=e.createDiv({cls:"af-icon-picker-scroll"}),this.renderGrid(),s.addEventListener("input",()=>{this.searchQuery=s.value,this.renderGrid()}),window.setTimeout(()=>s.focus(),0)}renderGrid(){let e=this.gridContainer;e.empty();let s=this.searchQuery.toLowerCase().trim();if(!s)this.renderSection(e,"Popular",Ld),this.renderSection(e,"All Icons",this.allIcons);else{let n=this.allIcons.filter(r=>r.includes(s)),a=n.length===0?"No results":`${n.length} result${n.length!==1?"s":""}`;this.renderSection(e,a,n)}}renderSection(e,s,n){let a=e.createDiv({cls:"af-icon-picker-section"});a.createDiv({cls:"af-icon-picker-section-label",text:s});let r=a.createDiv({cls:"af-icon-picker-grid"});for(let o of n)this.renderIconItem(r,o)}renderIconItem(e,s){let n=e.createDiv({cls:`af-icon-picker-item${this.selectedIcon===s?" selected":""}`});n.setAttribute("title",s),n.setAttribute("aria-label",s),(0,ts.setIcon)(n,s),n.addEventListener("click",()=>{this.selectedIcon=s,this.onSelect(s),this.close()})}onClose(){this.contentEl.empty()}};var _o=require("obsidian");function E(i,t,e){let s=i.createSpan({cls:e??"af-icon"});return(0,_o.setIcon)(s,t),s}function Je(i,t={}){let e=activeDocument.createElementNS("http://www.w3.org/2000/svg",i);for(let[s,n]of Object.entries(t))e.setAttribute(s,n);return e}function Fd(i){try{return new Date(i+"T12:00:00").toLocaleDateString(void 0,{month:"short",day:"numeric"})}catch{return i.slice(5)}}function Ao(i,t){let e=t.length||1,s=1e3,n=6,a=4,r=4,o=s-a-r-n*(e-1),c=Math.floor(o/e),l=140,h=36,d=18,u=d+l+h,p=Math.max(1,...t.map(f=>f.success+f.failure+f.cancelled)),m=Je("svg",{viewBox:`0 0 ${s} ${u}`,width:"100%",height:String(u),class:"af-chart-bar"});for(let f=0;f<=4;f++){let g=d+l-f/4*l;m.appendChild(Je("line",{x1:String(a),y1:String(g),x2:String(s-r),y2:String(g),stroke:"var(--af-text-faint)","stroke-opacity":"0.15","stroke-width":"1"}))}for(let f=0;f<t.length;f++){let g=t[f],v=a+f*(c+n),b=g.success+g.failure+g.cancelled,k=b/p*l,y=g.success/p*l,S=g.cancelled/p*l,T=g.failure/p*l;if(g.success>0&&m.appendChild(Je("rect",{x:String(v),y:String(d+l-y),width:String(c),height:String(Math.max(y,2)),fill:"var(--af-green)",opacity:"0.85"})),g.cancelled>0&&m.appendChild(Je("rect",{x:String(v),y:String(d+l-y-S),width:String(c),height:String(Math.max(S,2)),fill:"var(--af-yellow)",opacity:"0.85"})),g.failure>0&&m.appendChild(Je("rect",{x:String(v),y:String(d+l-k),width:String(c),height:String(Math.max(T,2)),fill:"var(--af-red)",opacity:"0.85"})),b===0&&m.appendChild(Je("rect",{x:String(v),y:String(d+l-3),width:String(c),height:"3",rx:"1.5",fill:"var(--af-text-faint)",opacity:"0.2"})),b>0){let D=Je("text",{x:String(v+c/2),y:String(d+l-k-5),"text-anchor":"middle","font-size":"10","font-weight":"600",fill:"var(--af-text-secondary)"});D.textContent=String(b),m.appendChild(D)}let _=Je("text",{x:String(v+c/2),y:String(d+l+16),"text-anchor":"middle","font-size":"10",fill:"var(--af-text-muted)"});_.textContent=Fd(g.date),m.appendChild(_)}i.appendChild(m)}function Eo(i,t,e){let c=2*Math.PI*46,l=e>0?t/e:0,h=c*l,d=c-h,u=Je("svg",{viewBox:"0 0 130 130",width:String(130),height:String(130),class:"af-chart-donut"});u.appendChild(Je("circle",{cx:String(65),cy:String(65),r:String(46),fill:"none",stroke:e>0?"var(--af-red)":"var(--af-text-faint)","stroke-width":String(12),opacity:"0.2"})),l>0&&u.appendChild(Je("circle",{cx:String(65),cy:String(65),r:String(46),fill:"none",stroke:"var(--af-green)","stroke-width":String(12),"stroke-dasharray":`${h} ${d}`,"stroke-dashoffset":String(c*.25),"stroke-linecap":"round"}));let p=Je("text",{x:String(65),y:String(61),"text-anchor":"middle","dominant-baseline":"middle","font-size":"24","font-weight":"700",fill:"var(--af-text-primary)"});p.textContent=`${Math.round(l*100)}%`,u.appendChild(p);let m=Je("text",{x:String(65),y:String(83),"text-anchor":"middle","font-size":"10",fill:"var(--af-text-muted)"});m.textContent=`${t}/${e} runs`,u.appendChild(m),i.appendChild(u)}function Po(i,t){i.draggable=!0,i.addEventListener("dragstart",e=>{e.dataTransfer?.setData("text/plain",t),i.addClass("af-dragging")}),i.addEventListener("dragend",()=>{i.removeClass("af-dragging")})}function Ro(i,t){i.addEventListener("dragover",e=>{e.preventDefault(),i.addClass("af-drag-over")}),i.addEventListener("dragleave",e=>{let s=e.relatedTarget;(!s||!i.contains(s))&&i.removeClass("af-drag-over")}),i.addEventListener("drop",e=>{e.preventDefault();let s=e.dataTransfer?.getData("text/plain");i.removeClass("af-drag-over"),s&&t(s)})}function Do(i){let t=/^##\s+Lint\s+(\d{4}-\d{2}-\d{2})\s*$/gm,e,s=-1,n="";for(;(e=t.exec(i))!==null;)e.index>s&&(s=e.index,n=e[1]??"");if(s<0)return null;let a=i.slice(s),r=a.search(/\n##\s+(?!\s*#)/),o=r<0?a:a.slice(0,r);return{date:n,summary:Nn(o,"Summary"),autoApplied:Nn(o,"Auto-applied"),needsReview:Nn(o,"Needs review"),refreshChained:Nn(o,"Refresh chained")}}function Nn(i,t){let e=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&"),n=new RegExp(`^###\\s+${e}\\s*$`,"m").exec(i);if(!n)return[];let a=n.index+n[0].length,r=i.slice(a),o=r.search(/\n###\s+/),l=(o<0?r:r.slice(0,o)).split(/\r?\n/).map(d=>d.trimEnd()),h=[];for(let d of l){let u=d.replace(/^\s+/,"");u.startsWith("- ")?h.push(u.slice(2).trim()):h.length>0&&(d.startsWith(" ")||d.startsWith(" "))&&(h[h.length-1]+=" "+u)}return h}var Io={dashboard:"Dashboard",agents:"Agents",kanban:"Tasks Board",runs:"Run History",skills:"Skills Library",approvals:"Approvals",mcp:"MCP Servers",channels:"Channels","wiki-keepers":"Wiki Keepers","agent-detail":"Agent Details","task-detail":"Task Details","create-agent":"Create Agent","create-task":"Create Task","create-skill":"Create Skill","edit-agent":"Edit Agent","edit-task":"Edit Task","edit-skill":"Edit Skill","create-channel":"Create Channel","edit-channel":"Edit Channel","add-mcp-server":"Add MCP Server"},Od={dashboard:"layout-dashboard",agents:"bot",kanban:"columns-3",runs:"scroll-text",skills:"puzzle",approvals:"shield-check",mcp:"plug",channels:"radio","wiki-keepers":"library","agent-detail":"bot","task-detail":"circle-dot","create-agent":"plus","create-task":"plus","create-skill":"plus","edit-agent":"edit","edit-task":"edit","edit-skill":"edit","create-channel":"plus","edit-channel":"edit","add-mcp-server":"plus"},Nd=["dashboard","agents","kanban","runs","approvals","skills","wiki-keepers","mcp","channels"],Mo=[["claude-code","Claude Code",!1],["codex","Codex",!1],["process","Process (coming soon)",!0],["http","HTTP (coming soon)",!0]],Fo=[["bypassPermissions","Bypass Permissions","Auto-approve everything except deny list"],["dontAsk","Don\u2019t Ask","Auto-approve all tool calls"],["acceptEdits","Accept Edits","Auto-approve file edits, block bash unless allowed"],["plan","Plan","Read-only mode, no writes or commands"],["default","Default","Ask for each tool call"]],Oo=[["bypassPermissions","Bypass (no sandbox)","No sandbox, auto-approve everything"],["workspace-write","Workspace Write","Sandboxed: writes only inside the working dir"],["read-only","Read Only","Sandboxed: no writes or side-effect commands"]];function Rs(i){let t=i.trim().toLowerCase();return t==="codex"||t==="openai-codex"}function Bn(i){return Rs(i)?Oo:Fo}function Un(i,t){if(Rs(t))switch(i){case"acceptEdits":case"default":return"workspace-write";case"plan":return"read-only";case"dontAsk":return"bypassPermissions";default:return Oo.some(([e])=>e===i)?i:"bypassPermissions"}switch(i){case"workspace-write":return"acceptEdits";case"read-only":return"plan";case"danger-full-access":return"bypassPermissions";default:return Fo.some(([e])=>e===i)?i:"bypassPermissions"}}var Ds=class extends w.ItemView{constructor(e,s){super(e);this.plugin=s}currentPage="dashboard";detailContext;agentDetailTab="overview";streamingUnsubscribes=[];channelStatusUnsubscribe;authenticatingServers=new Set;getViewType(){return Ct}getDisplayText(){return"Agent Fleet"}getIcon(){return"bot"}async onOpen(){this.plugin.subscribeView(this),this.channelStatusUnsubscribe=this.plugin.channelManager?.onStatusChange(()=>{this.currentPage==="channels"&&this.render()}),await this.render()}async onClose(){this.cleanupStreaming(),this.channelStatusUnsubscribe?.(),this.channelStatusUnsubscribe=void 0,this.plugin.unsubscribeView(this)}navigateTo(e,s){this.currentPage=e,this.detailContext=s,e!=="agent-detail"&&(this.agentDetailTab="overview"),this.render()}async render(){this.cleanupStreaming();let e=this.contentEl;e.empty(),e.addClass("af-root");let n=e.createDiv({cls:"af-app"}).createDiv({cls:"af-main-content"});this.renderTopBar(n),this.renderTabBar(n);let a=n.createDiv({cls:"af-page"});switch(this.currentPage){case"dashboard":this.renderDashboardPage(a);break;case"agents":this.renderAgentsPage(a);break;case"kanban":this.renderKanbanPage(a);break;case"runs":this.renderRunsPage(a);break;case"skills":this.renderSkillsPage(a);break;case"approvals":this.renderApprovalsPage(a);break;case"mcp":this.renderMcpPage(a);break;case"channels":this.renderChannelsPage(a);break;case"wiki-keepers":this.renderWikiKeepersPage(a);break;case"agent-detail":this.renderAgentDetailPage(a);break;case"task-detail":this.renderTaskDetailPage(a);break;case"create-agent":this.renderCreateAgentPage(a);break;case"create-task":this.renderCreateTaskPage(a);break;case"create-skill":this.renderCreateSkillPage(a);break;case"edit-agent":this.renderEditAgentPage(a);break;case"edit-task":this.renderEditTaskPage(a);break;case"edit-skill":this.renderEditSkillPage(a);break;case"create-channel":this.renderCreateChannelPage(a);break;case"edit-channel":this.renderEditChannelPage(a);break;case"add-mcp-server":this.renderAddMcpServerPage(a);break}}navigate(e,s){this.navigateTo(e,s)}cleanupStreaming(){for(let e of this.streamingUnsubscribes)e();this.streamingUnsubscribes=[]}renderTopBar(e){let s=e.createDiv({cls:"af-top-bar"}),n=s.createDiv({cls:"af-top-bar-title"});E(n,"bot","af-top-bar-icon"),n.createSpan({text:"Agent Fleet"});let a=s.createDiv({cls:"af-breadcrumb"}),r=a.createSpan({cls:"af-breadcrumb-sep"});(0,w.setIcon)(r,"chevron-right");let o=(m,f,g)=>{let v=a.createSpan({cls:f?"af-breadcrumb-link":"",text:m});f&&(v.onclick=()=>this.navigate(f,g))},c=()=>{let m=a.createSpan({cls:"af-breadcrumb-sep"});(0,w.setIcon)(m,"chevron-right")};switch(this.currentPage){case"agent-detail":o("Agents","agents"),c(),o(this.detailContext??"Agent");break;case"task-detail":o("Tasks Board","kanban"),c(),o(this.detailContext??"Task");break;case"edit-agent":o("Agents","agents"),c(),o(this.detailContext??"Agent","agent-detail",this.detailContext),c(),o("Edit");break;case"edit-task":o("Tasks Board","kanban"),c(),o(this.detailContext??"Task","task-detail",this.detailContext),c(),o("Edit");break;case"create-agent":o("Agents","agents"),c(),o("New Agent");break;case"create-task":o("Tasks Board","kanban"),c(),o("New Task");break;case"create-skill":o("Skills Library","skills"),c(),o("New Skill");break;case"edit-skill":o("Skills Library","skills"),c(),o(this.detailContext??"Skill"),c(),o("Edit");break;case"create-channel":o("Channels","channels"),c(),o("New Channel");break;case"edit-channel":o("Channels","channels"),c(),o(this.detailContext??"Channel"),c(),o("Edit");break;case"add-mcp-server":o("MCP Servers","mcp"),c(),o("Add Server");break;default:o(Io[this.currentPage])}s.createDiv({cls:"af-top-bar-spacer"});let l=s.createDiv({cls:"af-search-wrap"});E(l,"search","af-search-icon");let h=l.createEl("input",{cls:"af-search-input",attr:{type:"text",placeholder:"Search agents, tasks, runs..."}});h.addEventListener("input",()=>{this.handleSearch(h.value,l)}),h.addEventListener("blur",()=>{window.setTimeout(()=>l.querySelector(".af-search-results")?.remove(),200)});let d=this.plugin.runtime.getFleetStatus(),u=s.createDiv({cls:"af-status-pills"});if(d.running>0){let m=u.createSpan({cls:"af-pill yellow"});m.createSpan({cls:"af-dot pulse"}),m.appendText(` ${d.running} Running`)}if(d.pending>0){let m=u.createSpan({cls:"af-pill blue"});m.createSpan({cls:"af-dot"}),m.appendText(` ${d.pending} Pending`)}let p=u.createSpan({cls:"af-pill green"});p.createSpan({cls:"af-dot"}),p.appendText(` ${d.completedToday} Today`)}renderTabBar(e){let s=e.createDiv({cls:"af-tab-bar"}),n=this.plugin.runtime.getSnapshot(),a=this.plugin.runtime.getFleetStatus();for(let r of Nd){let o=this.currentPage===r||r==="agents"&&(this.currentPage==="agent-detail"||this.currentPage==="edit-agent"||this.currentPage==="create-agent")||r==="kanban"&&(this.currentPage==="task-detail"||this.currentPage==="edit-task")||r==="skills"&&(this.currentPage==="edit-skill"||this.currentPage==="create-skill")||r==="mcp"&&this.currentPage==="add-mcp-server",c=s.createEl("button",{cls:`af-tab-item${o?" active":""}`}),l=c.createSpan({cls:"af-tab-icon"});if((0,w.setIcon)(l,Od[r]),c.appendText(r==="dashboard"?"Overview":Io[r]),r==="agents")c.createSpan({cls:"af-badge",text:String(n.agents.length)});else if(r==="skills")c.createSpan({cls:"af-badge",text:String(n.skills.length)});else if(r==="mcp"){let h=this.plugin.repository.getMcpServers().length;c.createSpan({cls:"af-badge",text:String(h)})}else r==="approvals"&&a.pending>0&&c.createSpan({cls:"af-badge af-badge-warn",text:String(a.pending)});c.onclick=()=>this.navigate(r)}}renderDashboardPage(e){let s=e.createDiv({cls:"af-dashboard"}),n=this.plugin.runtime.getSnapshot(),a=this.plugin.runtime.getRecentRuns(),r=this.plugin.runtime.getFleetStatus(),o=a.filter(y=>(y.approvals??[]).some(S=>S.status==="pending"));for(let y of o)for(let S of y.approvals??[])S.status==="pending"&&this.renderApprovalBanner(s,y,S.tool);let c=s.createDiv({cls:"af-dash-grid"}),l=n.agents.filter(y=>y.enabled).length,h=n.agents.length;this.renderStatCard(c,"Active Agents",`${l}`,`/ ${h}`,"bot",`${l} of ${h} enabled`);let d=this.toLocalDateStr(new Date),u=a.filter(y=>this.runToLocalDate(y.started)===d),p=u.filter(y=>y.status==="success").length,m=u.filter(y=>y.status==="failure"||y.status==="timeout").length;this.renderStatCard(c,"Runs Today",String(u.length),"","activity",`${p} passed \xB7 ${m} failed \xB7 ${r.running} running`);let f=u.reduce((y,S)=>y+(S.tokensUsed??0),0),g=u.reduce((y,S)=>y+(S.costUsd??0),0),v=g>0?` \xB7 $${g.toFixed(2)}`:"";this.renderStatCard(c,"Tokens Used",$a(f),"","zap",`today${v}`);let b=n.tasks.filter(y=>y.enabled&&y.schedule);this.renderStatCard(c,"Scheduled Tasks",String(b.length),"","clock",b.length>0?`Next: ${this.getNextTaskLabel(b)}`:"No scheduled tasks"),this.renderChartsRow(s,a,this.plugin.runtime.getChartRuns()),this.renderStreamingCards(s);let k=s.createDiv({cls:"af-dash-split"});this.renderActivityTimeline(k,a),this.renderFleetStatusPanel(k,n)}renderChartsRow(e,s,n){let a=e.createDiv({cls:"af-charts-row"}),r=a.createDiv({cls:"af-section-card af-chart-section"}),c=r.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});E(c,"activity"),c.appendText(" Run Activity (14d)");let l=r.createDiv({cls:"af-chart-body"}),h=this.buildChartData(n,14);h.some(v=>v.success+v.failure+v.cancelled>0)?Ao(l,h):this.renderEmptyState(l,"activity","No run data","Run agents to see activity");let d=a.createDiv({cls:"af-section-card af-chart-section"}),p=d.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});E(p,"target"),p.appendText(" Success Rate");let m=d.createDiv({cls:"af-chart-body af-chart-body-center"}),f=s.length,g=s.filter(v=>v.status==="success").length;f>0?Eo(m,g,f):this.renderEmptyState(m,"target","No data","")}toLocalDateStr(e){let s=n=>String(n).padStart(2,"0");return`${e.getFullYear()}-${s(e.getMonth()+1)}-${s(e.getDate())}`}runToLocalDate(e){return this.toLocalDateStr(new Date(e))}buildChartData(e,s){let n=[],a=new Date;for(let r=s-1;r>=0;r--){let o=new Date(a);o.setDate(o.getDate()-r);let c=this.toLocalDateStr(o),l=e.filter(h=>this.runToLocalDate(h.started)===c);n.push({date:c,success:l.filter(h=>h.status==="success").length,failure:l.filter(h=>h.status==="failure"||h.status==="timeout").length,cancelled:l.filter(h=>h.status==="cancelled").length})}return n}renderStreamingCards(e){let n=this.plugin.runtime.getSnapshot().agents.filter(c=>this.plugin.runtime.getAgentState(c.name).status==="running");if(n.length===0)return;let a=e.createDiv({cls:"af-streaming-section"}),o=a.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});E(o,"terminal"),o.appendText(" Active Agents");for(let c of n)this.renderStreamingCard(a,c.name)}renderStreamingCard(e,s){let n=e.createDiv({cls:"af-streaming-card"}),a=this.plugin.runtime.getAgentState(s),r=this.plugin.runtime.getSnapshot(),o=a.currentTaskId?r.tasks.find(m=>m.taskId===a.currentTaskId):void 0,c=o?` \u2192 ${o.taskId}`:a.status==="running"?" \u2192 Heartbeat":"",l=n.createDiv({cls:"af-streaming-card-header"});l.createSpan({cls:"af-dot pulse",attr:{style:"background: var(--af-yellow)"}}),l.createSpan({cls:"af-streaming-card-agent",text:` ${s}`}),c&&l.createSpan({cls:"af-streaming-card-task",text:c});let h=n.createDiv({cls:"af-streaming-output"}),d=this.plugin.runtime.getRunOutputBuffer(s),u=ge(d).slice(-4);h.setText(u.join(`
12005
+ `));let p=this.plugin.runtime.onRunOutput(s,()=>{let m=this.plugin.runtime.getRunOutputBuffer(s),f=ge(m).slice(-4);h.setText(f.join(`
12006
+ `)),h.scrollTop=h.scrollHeight});this.streamingUnsubscribes.push(p)}renderApprovalBanner(e,s,n){let a=e.createDiv({cls:"af-approval-banner"}),r=a.createDiv({cls:"af-approval-icon"});(0,w.setIcon)(r,"shield-check");let o=a.createDiv({cls:"af-approval-text"});o.createDiv({cls:"af-approval-title",text:`${s.agent} wants to run: ${n}`}),o.createDiv({cls:"af-approval-desc",text:`Approval required for tool: ${n}`});let c=a.createDiv({cls:"af-approval-actions"}),l=c.createEl("button",{cls:"af-btn-approve",text:"Approve"});l.onclick=()=>void this.plugin.runtime.resolveApproval(s,n,"approved").then(()=>this.render());let h=c.createEl("button",{cls:"af-btn-reject",text:"Reject"});h.onclick=()=>void this.plugin.runtime.resolveApproval(s,n,"rejected").then(()=>this.render())}renderStatCard(e,s,n,a,r,o){let c=e.createDiv({cls:"af-stat-card"}),l=c.createDiv({cls:"af-stat-label"});E(l,r,"af-stat-icon"),l.appendText(` ${s}`);let h=c.createDiv({cls:"af-stat-value"});h.appendText(n),a&&h.createSpan({cls:"af-stat-value-suffix",text:a}),c.createDiv({cls:"af-stat-sub",text:o})}renderActivityTimeline(e,s){let n=e.createDiv({cls:"af-section-card"}),r=n.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});E(r,"inbox"),r.appendText(" Recent Activity");let o=n.createDiv({cls:"af-timeline"}),c=s.slice(0,8);if(c.length===0){this.renderEmptyState(o,"inbox","No runs yet","Run an agent to see activity here");return}for(let l of c)this.renderTimelineItem(o,l)}renderTimelineItem(e,s){let n=e.createDiv({cls:"af-timeline-item"}),a=this.statusToTimelineClass(s.status),r=n.createDiv({cls:`af-tl-icon ${a}`});(0,w.setIcon)(r,this.statusToIconName(s.status));let o=n.createDiv({cls:"af-tl-body"}),c=o.createDiv({cls:"af-tl-title"});c.createSpan({cls:"af-agent-tag",text:s.agent}),c.appendText(` ${s.task}`),o.createDiv({cls:"af-tl-desc",text:$t(s.output,100)});let l=o.createDiv({cls:"af-tl-meta"}),h=l.createSpan();if(E(h,"clock","af-meta-icon"),h.appendText(` ${this.formatStarted(s.started)} \xB7 ${this.formatDuration(s.durationSeconds)}`),s.tokensUsed){let d=l.createSpan();E(d,"zap","af-meta-icon"),d.appendText(` ${s.tokensUsed.toLocaleString()} tokens`)}n.onclick=()=>this.openSlideover(s)}renderFleetStatusPanel(e,s){let n=e.createDiv({cls:"af-section-card"}),a=n.createDiv({cls:"af-section-header"}),r=a.createDiv({cls:"af-section-title"});E(r,"bot"),r.appendText(" Fleet Status");let c=a.createDiv({cls:"af-section-actions"}).createEl("button",{cls:"af-btn-sm primary"});E(c,"plus","af-btn-icon"),c.appendText(" New Agent"),c.onclick=()=>void this.plugin.createAgentTemplate();let l=n.createDiv({cls:"af-agent-mini-list"});if(s.agents.length===0){this.renderEmptyState(l,"bot","No agents yet","Create your first agent to get started");return}for(let d of s.agents)this.renderAgentMini(l,d,s.tasks);let h=s.agents.filter(d=>d.enabled);if(h.length>0){let d=n.createDiv({cls:"af-quick-run"}),u=d.createDiv({cls:"af-quick-run-label"});E(u,"zap","af-meta-icon"),u.appendText(" Quick Run");let p=d.createDiv({cls:"af-quick-run-row"}),m=p.createEl("select",{cls:"af-select"});for(let g of h)m.createEl("option",{text:g.name,attr:{value:g.name}});let f=p.createEl("button",{cls:"af-btn-sm primary"});E(f,"play","af-btn-icon"),f.appendText(" Run"),f.onclick=()=>void this.plugin.runAgentPrompt(m.value)}}renderAgentMini(e,s,n){let a=this.plugin.runtime.getAgentState(s.name),r=n.filter(u=>u.agent===s.name),o=this.healthToClass(a.status),c=e.createDiv({cls:"af-agent-mini"}),l=c.createDiv({cls:`af-agent-avatar ${o}`});s.avatar?.trim()?this.renderAgentAvatar(l,s):l.setText(this.getInitials(s.name));let h=c.createDiv({cls:"af-agent-info"});h.createDiv({cls:"af-agent-name",text:s.name});let d="";if(a.status==="running")d=`Running now \xB7 ${r.length} task${r.length!==1?"s":""}`;else if(!s.enabled)d=`Disabled \xB7 ${r.length} task${r.length!==1?"s":""} paused`;else{let u=r.map(p=>p.nextRun).filter(Boolean).sort()[0];d=u?`Next: ${this.formatNextRun(u)} \xB7 ${r.length} task${r.length!==1?"s":""}`:`${r.length} task${r.length!==1?"s":""}`}h.createDiv({cls:"af-agent-desc",text:d}),c.createDiv({cls:`af-agent-status-dot ${o}`}),c.onclick=()=>this.navigate("agent-detail",s.name)}renderAgentsPage(e){let s=e.createDiv({cls:"af-agents-page"}),n=this.plugin.runtime.getSnapshot(),a=s.createDiv({cls:"af-agents-toolbar"});a.createDiv({cls:"af-page-title",text:"Agents"}),a.createDiv({cls:"af-toolbar-spacer"});let r=a.createEl("button",{cls:"af-btn-sm primary"});E(r,"plus","af-btn-icon"),r.appendText(" New Agent"),r.onclick=()=>void this.plugin.createAgentTemplate();let o=s.createDiv({cls:"af-agents-grid"});if(n.agents.length===0){this.renderEmptyState(o,"bot","No agents configured","Create your first agent to get started");return}for(let c of n.agents)this.renderAgentCard(o,c,n)}renderAgentCard(e,s,n){let a=this.plugin.runtime.getAgentState(s.name),r=this.plugin.runtime.getRecentRuns().filter(D=>D.agent===s.name),o=e.createDiv({cls:`af-agent-card${s.enabled?"":" disabled"}`}),c=o.createDiv({cls:"af-agent-card-header"}),l=s.enabled?this.healthToClass(a.status):"disabled",h=c.createDiv({cls:`af-agent-card-avatar ${l}`});this.renderAgentAvatar(h,s);let d=c.createDiv({cls:"af-agent-card-titleblock"}),u=d.createDiv({cls:"af-agent-card-name"});if(u.appendText(s.name),s.heartbeatEnabled&&s.heartbeatSchedule){let D=u.createSpan({cls:"af-heartbeat-indicator"});(0,w.setIcon)(D,"heart-pulse"),D.title=`Heartbeat: ${s.heartbeatSchedule}`}d.createDiv({cls:"af-agent-card-desc",text:s.description??"No description"});let p=c.createDiv({cls:`af-agent-card-toggle${s.enabled?" on":""}`});p.onclick=D=>{D.stopPropagation(),this.plugin.toggleAgent(s.name,!s.enabled)};let m=o.createDiv({cls:"af-agent-card-stats"}),f=r.length,g=r.filter(D=>D.status==="success").length,v=f>0?Math.round(g/f*100):0,b=f>0?Math.round(r.reduce((D,M)=>D+M.durationSeconds,0)/f):0,k=r.reduce((D,M)=>D+(M.tokensUsed??0),0);if(this.renderAgentStat(m,String(f),"Runs"),this.renderAgentStat(m,`${v}%`,"Success"),this.renderAgentStat(m,`${b}s`,"Avg Time"),this.renderAgentStat(m,$a(k),"Tokens"),s.skills.length>0){let D=o.createDiv({cls:"af-agent-card-skills"});for(let M of s.skills)D.createSpan({cls:"af-skill-tag",text:M})}let y=o.createDiv({cls:"af-agent-card-footer"}),S=[`Model: ${s.model}`];s.approvalRequired.length>0&&S.push(`Approval: ${s.approvalRequired.join(", ")}`),s.memory&&S.push("Memory: on"),s.enabled||S.unshift("Disabled"),y.createSpan({cls:"af-agent-card-meta",text:S.join(" \xB7 ")});let T=y.createDiv({cls:"af-agent-card-actions"});if(!s.enabled){let D=T.createEl("button",{cls:"af-btn-sm",text:"Enable"});D.onclick=M=>{M.stopPropagation(),this.plugin.toggleAgent(s.name,!0)}}let _=T.createEl("button",{cls:"af-btn-sm"});if(E(_,"edit","af-btn-icon"),_.appendText(" Edit"),_.onclick=D=>{D.stopPropagation(),this.navigate("edit-agent",s.name)},s.enabled){let D=T.createEl("button",{cls:"af-btn-sm primary"});E(D,"play","af-btn-icon"),D.appendText(" Run"),D.onclick=M=>{M.stopPropagation(),this.plugin.runAgentPrompt(s.name)}}o.onclick=()=>this.navigate("agent-detail",s.name)}renderAgentStat(e,s,n){let a=e.createDiv({cls:"af-agent-stat"});a.createSpan({cls:"af-agent-stat-value",text:s}),a.createSpan({cls:"af-agent-stat-label",text:n})}renderAgentDetailPage(e){let s=e.createDiv({cls:"af-agent-detail-page"}),n=this.detailContext;if(!n){this.renderEmptyState(s,"bot","No agent selected","Select an agent from the list");return}let a=this.plugin.runtime.getSnapshot().agents.find(k=>k.name===n);if(!a){this.renderEmptyState(s,"bot","Agent not found",`Agent "${n}" was not found`);return}let r=this.plugin.runtime.getAgentState(a.name),o=this.plugin.runtime.getRecentRuns().filter(k=>k.agent===a.name),c=s.createDiv({cls:"af-detail-header"}),l=c.createDiv({cls:"af-detail-header-left"}),h=l.createDiv({cls:`af-agent-card-avatar ${this.healthToClass(r.status)}`});this.renderAgentAvatar(h,a);let d=l.createDiv();d.createDiv({cls:"af-detail-header-name",text:a.name}),d.createDiv({cls:"af-detail-header-desc",text:a.description??"No description"});let u=c.createDiv({cls:"af-detail-header-actions"}),p=u.createEl("button",{cls:"af-btn-sm primary"});if(E(p,"message-circle","af-btn-icon"),p.appendText(" Chat"),p.onclick=()=>this.openChatSlideover(a),a.enabled){let k=u.createEl("button",{cls:"af-btn-sm"});E(k,"play","af-btn-icon"),k.appendText(" Run Now"),k.onclick=()=>void this.plugin.runAgentPrompt(a.name);let y=u.createEl("button",{cls:"af-btn-sm"});E(y,"pause","af-btn-icon"),y.appendText(" Disable"),y.onclick=()=>void this.plugin.toggleAgent(a.name,!1)}else{let k=u.createEl("button",{cls:"af-btn-sm"});E(k,"play","af-btn-icon"),k.appendText(" Enable"),k.onclick=()=>void this.plugin.toggleAgent(a.name,!0)}let m=u.createEl("button",{cls:"af-btn-sm"});E(m,"edit","af-btn-icon"),m.appendText(" Edit"),m.onclick=()=>this.navigate("edit-agent",a.name);let f=u.createEl("button",{cls:"af-btn-sm danger"});E(f,"trash-2","af-btn-icon"),f.appendText(" Delete"),f.onclick=()=>void this.plugin.deleteAgent(a.name);let g=s.createDiv({cls:"af-detail-tabs"}),v=[{id:"overview",label:"Overview",icon:"layout-dashboard"},{id:"config",label:"Config",icon:"settings"},{id:"runs",label:"Runs",icon:"scroll-text"},{id:"memory",label:"Memory",icon:"file-text"}];for(let k of v){let y=g.createEl("button",{cls:`af-detail-tab${this.agentDetailTab===k.id?" active":""}`});E(y,k.icon,"af-tab-icon"),y.appendText(` ${k.label}`),y.onclick=()=>{this.agentDetailTab=k.id,this.render()}}let b=s.createDiv({cls:"af-detail-tab-content"});switch(this.agentDetailTab){case"overview":this.renderAgentOverviewTab(b,a,o);break;case"config":this.renderAgentConfigTab(b,a);break;case"runs":this.renderAgentRunsTab(b,o);break;case"memory":this.renderAgentMemoryTab(b,a);break}}renderAgentOverviewTab(e,s,n){let a=e.createDiv({cls:"af-dash-grid"}),r=n.length,o=n.filter(k=>k.status==="success").length,c=r>0?Math.round(o/r*100):0,l=r>0?Math.round(n.reduce((k,y)=>k+y.durationSeconds,0)/r):0,h=n.reduce((k,y)=>k+(y.tokensUsed??0),0),d=n.reduce((k,y)=>k+(y.costUsd??0),0),u=d>0?` \xB7 $${d.toFixed(2)}`:"";if(this.renderStatCard(a,"Total Runs",String(r),"","activity","all time"),this.renderStatCard(a,"Success Rate",`${c}%`,"","check-circle-2",`${o}/${r}`),this.renderStatCard(a,"Avg Time",`${l}s`,"","clock","per run"),this.renderStatCard(a,"Total Tokens",$a(h),"","zap",`all time${u}`),s.isFolder&&(s.heartbeatBody.trim()||s.heartbeatEnabled)){let k=e.createDiv({cls:"af-section-card"}),y=k.createDiv({cls:"af-section-header"}),S=y.createDiv({cls:"af-section-title"});E(S,"heart-pulse"),S.appendText(" Heartbeat");let _=y.createDiv({cls:"af-detail-header-actions"}).createDiv({cls:`af-agent-card-toggle${s.heartbeatEnabled?" on":""}`});_.onclick=async()=>{let C=_.hasClass("on");await this.plugin.repository.updateHeartbeat(s.name,{enabled:!C}),await this.plugin.refreshFromVault(),new w.Notice(`Heartbeat ${C?"paused":"enabled"} for ${s.name}`)};let D=k.createDiv({cls:"af-config-form"});this.renderConfigRow(D,"Schedule",Bd(s.heartbeatSchedule));let M=this.plugin.runtime.getNextHeartbeat(s.name);M&&s.heartbeatEnabled&&this.renderConfigRow(D,"Next run",this.timeUntil(M)),s.heartbeatChannel&&this.renderConfigRow(D,"Channel",s.heartbeatChannel)}if(s.skills.length>0){let k=e.createDiv({cls:"af-section-card"}),S=k.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});E(S,"puzzle"),S.appendText(" Skills");let T=k.createDiv({cls:"af-detail-skills-list"});for(let _ of s.skills)T.createSpan({cls:"af-skill-tag",text:_})}let p=s.mcpServers??[];if(p.length>0){let k=e.createDiv({cls:"af-section-card"}),S=k.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});E(S,"plug"),S.appendText(" MCP Servers");let T=k.createDiv({cls:"af-mcp-overview-list"}),_=this.plugin.repository.getMcpServers();for(let D of p){let M=_.find(L=>L.name===D),C=T.createDiv({cls:"af-mcp-overview-row"}),I=C.createSpan({cls:`af-mcp-status-dot ${M?M.enabled?M.status:"disabled":"disconnected"}`});I.title=M?M.enabled?M.status:"disabled":"unknown",C.createSpan({cls:"af-mcp-overview-name",text:D});let P=M?.toolDetails.length??M?.tools.length??0;P>0?C.createSpan({cls:"af-mcp-overview-tools",text:`${P} tools`}):M&&!M.enabled?C.createSpan({cls:"af-mcp-overview-tools af-muted",text:"disabled"}):M?.status==="needs-auth"&&C.createSpan({cls:"af-mcp-overview-tools af-muted",text:"needs auth"})}}if(s.permissionRules.allow.length>0||s.permissionRules.deny.length>0||s.permissionMode&&s.permissionMode!=="default"){let k=e.createDiv({cls:"af-section-card"}),S=k.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});E(S,"shield-check"),S.appendText(" Permissions");let T=k.createDiv({cls:"af-config-form"});this.renderConfigRow(T,"Mode",s.permissionMode||"default"),s.permissionRules.allow.length>0&&this.renderConfigRow(T,"Allowed",s.permissionRules.allow.join(", ")),s.permissionRules.deny.length>0&&this.renderConfigRow(T,"Denied",s.permissionRules.deny.join(", "))}let f=e.createDiv({cls:"af-section-card"}),v=f.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});E(v,"scroll-text"),v.appendText(" Recent Runs");let b=f.createDiv({cls:"af-timeline"});if(n.length===0)this.renderEmptyState(b,"scroll-text","No runs yet","");else for(let k of n.slice(0,5))this.renderTimelineItem(b,k)}renderAgentConfigTab(e,s){let n=e.createDiv({cls:"af-config-form"});this.renderConfigRow(n,"Name",s.name),this.renderConfigRow(n,"Description",s.description??""),this.renderConfigRow(n,"Model",s.model),this.renderConfigRow(n,"Timeout",`${s.timeout}s`),this.renderConfigRow(n,"Working Directory",s.cwd??"(vault root)"),this.renderConfigRow(n,"Permission Mode",s.permissionMode||"default"),this.renderConfigRow(n,"Approval Required",s.approvalRequired.join(", ")||"none"),s.permissionRules.allow.length>0&&this.renderConfigRow(n,"Allowed Commands",s.permissionRules.allow.join(", ")),s.permissionRules.deny.length>0&&this.renderConfigRow(n,"Blocked Commands",s.permissionRules.deny.join(", ")),this.renderConfigRow(n,"Memory",s.memory?"Enabled":"Disabled"),this.renderConfigRow(n,"Auto-compact",s.autoCompactThreshold&&s.autoCompactThreshold>0?`at ${s.autoCompactThreshold}% context`:"disabled"),s.wikiReferences&&s.wikiReferences.length>0&&this.renderConfigRow(n,"Wiki access",s.wikiReferences.map(c=>c.agent).join(", ")),this.renderConfigRow(n,"Tags",s.tags.join(", ")||"none");let a=n.createDiv({cls:"af-config-prompt-section"});if(a.createDiv({cls:"af-slideover-section-title",text:"SYSTEM PROMPT"}),a.createDiv({cls:"af-output-block",text:s.body||"(empty)"}),s.heartbeatBody.trim()){let c=n.createDiv({cls:"af-config-prompt-section"});c.createDiv({cls:"af-slideover-section-title",text:"HEARTBEAT INSTRUCTION"}),c.createDiv({cls:"af-output-block",text:s.heartbeatBody})}let o=n.createDiv({cls:"af-slideover-actions"}).createEl("button",{cls:"af-btn-sm primary"});E(o,"edit","af-btn-icon"),o.appendText(" Edit Agent"),o.onclick=()=>this.navigate("edit-agent",s.name)}renderConfigRow(e,s,n){let a=e.createDiv({cls:"af-detail-row"});a.createSpan({cls:"af-detail-label",text:s}),a.createSpan({cls:"af-detail-value af-mono",text:n})}renderAgentRunsTab(e,s){if(s.length===0){this.renderEmptyState(e,"scroll-text","No runs yet","Run this agent to see history");return}for(let n of s){let a=e.createDiv({cls:"af-run-list-item"}),r=a.createDiv({cls:`af-tl-icon ${this.statusToTimelineClass(n.status)}`});(0,w.setIcon)(r,this.statusToIconName(n.status));let o=a.createDiv({cls:"af-tl-body"}),c=o.createDiv({cls:"af-tl-title"});c.createSpan({text:n.task}),c.createSpan({cls:`af-status-badge ${this.statusToBadgeClass(n.status)}`,text:this.statusToBadgeText(n.status)});let l=o.createDiv({cls:"af-tl-meta"});l.createSpan({text:`${this.formatStarted(n.started)} \xB7 ${this.formatDuration(n.durationSeconds)}`}),n.tokensUsed&&l.createSpan({text:`${n.tokensUsed.toLocaleString()} tokens`}),o.createDiv({cls:"af-tl-desc",text:$t(n.output,120)}),a.onclick=()=>this.openSlideover(n)}}async renderAgentMemoryTab(e,s){if(!s.memory){this.renderEmptyState(e,"file-text","Memory disabled","Enable memory in agent config");return}let n=await this.plugin.repository.readWorkingMemory(s.name),a=e.createDiv({cls:"af-form-help"}),r=n?.tokenEstimate??0,o=s.reflection.enabled?`reflection on (${s.reflection.schedule})`:"reflection off";a.setText(`~${r} / ${s.memoryTokenBudget} tokens \xB7 ${o}`),!n||n.sections.length===0?this.renderEmptyState(e,"file-text","No memories yet","Agent will learn from runs"):e.createDiv({cls:"af-output-block"}).setText(Ge(n.sections));let c=e.createDiv({cls:"af-slideover-actions"}),l=c.createEl("button",{cls:"af-btn-sm"});E(l,"moon","af-btn-icon"),l.appendText(" Reflect now"),l.onclick=async()=>{l.disabled=!0,l.setText(" Reflecting\u2026");let d=await this.plugin.runtime.runReflectionNow(s.name);new w.Notice(`Agent Fleet: ${d.message}`),await this.renderAgentMemoryTab((e.empty(),e),s)};let h=c.createEl("button",{cls:"af-btn-sm"});E(h,"external-link","af-btn-icon"),h.appendText(" Open in Editor"),h.onclick=()=>void this.plugin.openPath(this.plugin.repository.getWorkingMemoryPath(s.name))}timeAgo(e){let s=Math.round((Date.now()-e.getTime())/1e3);if(s<60)return"just now";let n=Math.round(s/60);if(n<60)return`${n}m ago`;let a=Math.round(n/60);return a<24?`${a}h ago`:`${Math.round(a/24)}d ago`}timeUntil(e){let s=Math.round((e.getTime()-Date.now())/1e3);if(s<60)return"< 1m";let n=Math.round(s/60);if(n<60)return`in ${n}m`;let a=Math.round(n/60);return a<24?`in ${a}h`:`in ${Math.round(a/24)}d`}renderKanbanPage(e){let s=e.createDiv({cls:"af-kanban-page"}),n=this.plugin.runtime.getSnapshot(),a=this.plugin.runtime.getRecentRuns(),r=s.createDiv({cls:"af-kanban-toolbar"});r.createDiv({cls:"af-page-title",text:"Tasks Board"}),r.createDiv({cls:"af-toolbar-spacer"});let o=r.createEl("button",{cls:"af-btn-sm primary"});E(o,"plus","af-btn-icon"),o.appendText(" New Task"),o.onclick=()=>this.navigate("create-task");let c=s.createDiv({cls:"af-kanban-board"}),l=[],h=[],d=[],u=[],p=[],m=new Set;for(let b of n.agents){let k=this.plugin.runtime.getAgentState(b.name);k.status==="running"&&k.currentTaskId&&m.add(k.currentTaskId)}let f=this.toLocalDateStr(new Date);for(let b of a)b.status==="success"&&this.runToLocalDate(b.started)===f?u.push(b):(b.status==="failure"||b.status==="timeout"||b.status==="cancelled")&&this.runToLocalDate(b.started)===f&&p.push(b);let g=new Set(u.map(b=>b.task)),v=new Set(p.map(b=>b.task));for(let b of n.tasks){let k=g.has(b.taskId)||v.has(b.taskId)||b.lastRun&&this.runToLocalDate(b.lastRun)===f;if(m.has(b.taskId))d.push(b);else{if(k&&!b.schedule)continue;b.schedule&&b.enabled?h.push(b):l.push(b)}}this.renderKanbanColumn(c,"Backlog","inbox",l.length,b=>{for(let k of l)this.renderKanbanTaskCard(b,k,n,!0)},"backlog"),this.renderKanbanColumn(c,"Scheduled","clock",h.length,b=>{for(let k of h)this.renderKanbanTaskCard(b,k,n,!0)},"scheduled"),this.renderKanbanColumn(c,"Running","loader-2",d.length,b=>{for(let k of d)this.renderKanbanRunningCard(b,k)},"running",!1,"running"),this.renderKanbanColumn(c,"Done","check-circle-2",u.length,b=>{for(let k of u.slice(0,10))this.renderKanbanCompletedCard(b,k)},"completed"),this.renderKanbanColumn(c,"Failed","x-circle",p.length,b=>{for(let k of p)this.renderKanbanFailedCard(b,k)},"failed",!1,"failed")}renderKanbanColumn(e,s,n,a,r,o,c=!1,l){let h=e.createDiv({cls:`af-kanban-column${l?` af-kanban-${l}`:""}`});(o==="backlog"||o==="scheduled")&&Ro(h,m=>this.handleTaskDrop(m,o));let u=h.createDiv({cls:"af-kanban-col-header"}).createDiv({cls:"af-kanban-col-title"});E(u,n),u.appendText(` ${s} `),u.createSpan({cls:"af-kanban-col-count",text:String(a)});let p=h.createDiv({cls:"af-kanban-col-body"});if(r(p),a===0&&p.createDiv({cls:"af-kanban-empty",text:"No items"}),c){let f=h.createDiv({cls:"af-kanban-col-add"}).createEl("button");E(f,"plus","af-btn-icon"),f.appendText(" Add task"),f.onclick=()=>{this.navigate("create-task")}}}handleTaskDrop(e,s){let n=this.plugin.runtime.getSnapshot().tasks.find(a=>a.taskId===e);if(n){if(s==="backlog")this.setTaskEnabled(n,!1).then(()=>{new w.Notice(`Task "${e}" moved to backlog (disabled)`)});else if(s==="scheduled"){if(!n.schedule&&!n.runAt){new w.Notice(`Task "${e}" needs a schedule. Open task details to set one.`),this.navigate("task-detail",e);return}this.setTaskEnabled(n,!0).then(()=>{new w.Notice(`Task "${e}" moved to scheduled (enabled)`)})}}}async setTaskEnabled(e,s){let n=this.plugin.app.vault.getAbstractFileByPath(e.filePath);if(!n||!(n instanceof w.TFile))return;let a=await this.plugin.app.vault.cachedRead(n),{frontmatter:r,body:o}=J(a);r.enabled=s,await this.plugin.app.vault.modify(n,W(r,o)),await this.plugin.refreshFromVault()}renderKanbanTaskCard(e,s,n,a){let r=e.createDiv({cls:`af-kanban-card af-priority-${s.priority}`});if(a){Po(r,s.taskId);let f=r.createDiv({cls:"af-kanban-card-grip"});(0,w.setIcon)(f,"grip-vertical")}let o=r.createDiv({cls:"af-kanban-card-header"});o.createDiv({cls:"af-kanban-card-title",text:s.taskId});let l=(n.agents.find(f=>f.name===s.agent)?.enabled??!1)&&s.enabled,h=o.createSpan({cls:`af-kanban-card-status ${l?"active":"inactive"}`});h.title=l?"Active":"Inactive";let d=r.createDiv({cls:"af-kanban-card-agent"}),u=d.createSpan({cls:"af-kanban-card-agent-icon"});(0,w.setIcon)(u,"bot"),d.createSpan({cls:"af-kanban-card-agent-name",text:s.agent});let m=r.createDiv({cls:"af-kanban-card-footer"}).createSpan({cls:"af-kanban-card-schedule"});l?s.schedule?(E(m,"refresh-cw","af-meta-icon"),m.appendText(` ${this.humanizeCron(s.schedule)}`)):m.appendText(s.runAt??"Manual"):(E(m,"pause","af-meta-icon"),m.appendText(" Paused")),r.onclick=()=>this.navigate("task-detail",s.taskId)}renderKanbanRunningCard(e,s){let n=e.createDiv({cls:"af-kanban-card af-kanban-card-running"});n.createDiv({cls:"af-kanban-card-title",text:s.taskId});let a=n.createDiv({cls:"af-kanban-card-agent"}),r=a.createSpan({cls:"af-kanban-card-agent-icon"});(0,w.setIcon)(r,"bot"),a.createSpan({cls:"af-kanban-card-agent-name",text:s.agent});let c=this.plugin.runtime.getSnapshot().agents.find(S=>S.name===s.agent)?.timeout??300,l=this.plugin.runtime.getAgentState(s.agent),h=l.runStarted?new Date(l.runStarted).getTime():Date.now(),p=n.createDiv({cls:"af-kanban-progress"}).createDiv({cls:"af-kanban-progress-track"}).createDiv({cls:"af-kanban-progress-bar af-kanban-progress-bar-real"}),m=(Date.now()-h)/1e3,f=Math.min(95,m/c*100);p.setCssStyles({width:`${f}%`});let g=n.createDiv({cls:"af-kanban-card-footer"}),v=g.createSpan({cls:"af-kanban-card-schedule"});E(v,"loader-2","af-meta-icon");let b=Math.round(m);v.appendText(` ${b}s / ${c}s`);let k=g.createEl("button",{cls:"af-kanban-stop-btn"});(0,w.setIcon)(k,"square"),k.title="Stop task",k.onclick=S=>{S.stopPropagation(),this.plugin.runtime.abortAgentRun(s.agent),new w.Notice(`Stopped task "${s.taskId}"`)};let y=window.setInterval(()=>{let S=(Date.now()-h)/1e3,T=Math.min(95,S/c*100);p.setCssStyles({width:`${T}%`});let _=Math.round(S);v.textContent="",(0,w.setIcon)(v,"loader-2"),v.appendText(` ${_}s / ${c}s`)},1e3);this.streamingUnsubscribes.push(()=>window.clearInterval(y))}renderKanbanCompletedCard(e,s){let n=e.createDiv({cls:"af-kanban-card"});n.createDiv({cls:"af-kanban-card-title",text:s.task});let a=n.createDiv({cls:"af-kanban-card-agent"}),r=a.createSpan({cls:"af-kanban-card-agent-icon"});(0,w.setIcon)(r,"bot"),a.createSpan({cls:"af-kanban-card-agent-name",text:s.agent});let c=n.createDiv({cls:"af-kanban-card-footer"}).createSpan({cls:"af-kanban-card-schedule"});E(c,"check-circle-2","af-meta-icon"),c.appendText(` ${this.formatStarted(s.started)} \xB7 ${this.formatDuration(s.durationSeconds)}`),n.onclick=()=>this.openSlideover(s)}renderKanbanFailedCard(e,s){let n=s.status==="cancelled",a=e.createDiv({cls:`af-kanban-card ${n?"af-kanban-card-cancelled":"af-kanban-card-failed"}`});a.createDiv({cls:"af-kanban-card-title",text:s.task});let r=a.createDiv({cls:"af-kanban-card-agent"}),o=r.createSpan({cls:"af-kanban-card-agent-icon"});(0,w.setIcon)(o,"bot"),r.createSpan({cls:"af-kanban-card-agent-name",text:s.agent});let c=n?`Stopped after ${s.durationSeconds}s`:s.status==="timeout"?`Timeout after ${s.durationSeconds}s`:$t(s.output,60),l=a.createDiv({cls:"af-kanban-card-error"});E(l,n?"square":"alert-triangle","af-meta-icon"),l.appendText(` ${c}`);let h=a.createDiv({cls:"af-kanban-card-footer"}),d=h.createSpan({cls:"af-kanban-card-schedule"});if(E(d,n?"square":"x-circle","af-meta-icon"),d.appendText(` ${this.formatStarted(s.started)}`),!n){let u=h.createEl("button",{cls:"af-btn-sm"});E(u,"refresh-cw","af-btn-icon"),u.appendText(" Retry"),u.onclick=p=>{p.stopPropagation(),this.plugin.runAgentPrompt(s.agent)}}a.onclick=()=>this.openSlideover(s)}renderRunsPage(e){let s=e.createDiv({cls:"af-runs-page"}),n=this.plugin.runtime.getRecentRuns(),a=s.createDiv({cls:"af-runs-toolbar"});a.createDiv({cls:"af-page-title",text:"Run History"}),a.createDiv({cls:"af-toolbar-spacer"});let r=s.createDiv({cls:"af-runs-table"});if(n.length===0){this.renderEmptyState(r,"scroll-text","No runs yet","Run an agent to see history here");return}let o=r.createEl("table"),l=o.createEl("thead").createEl("tr");for(let d of["Status","Agent","Task","Started","Duration","Tokens","Model"])l.createEl("th",{text:d});let h=o.createEl("tbody");for(let d of n.slice(0,50))this.renderRunRow(h,d)}renderRunRow(e,s){let n=e.createEl("tr"),r=n.createEl("td").createSpan({cls:`af-status-badge ${this.statusToBadgeClass(s.status)}`}),o=r.createSpan();(0,w.setIcon)(o,this.statusToIconName(s.status)),r.appendText(` ${this.statusToBadgeText(s.status)}`);let c=n.createEl("td",{cls:"af-agent-link"});c.setText(s.agent),c.onclick=l=>{l.stopPropagation(),this.navigate("agent-detail",s.agent)},n.createEl("td",{text:s.task}),n.createEl("td",{cls:"af-mono",text:this.formatStarted(s.started)}),n.createEl("td",{cls:"af-mono",text:this.formatDuration(s.durationSeconds)}),n.createEl("td",{cls:"af-mono",text:s.tokensUsed?s.tokensUsed.toLocaleString():"\u2014"}),n.createEl("td",{cls:"af-mono",text:s.model}),n.setCssStyles({cursor:"pointer"}),n.onclick=()=>this.openSlideover(s)}renderSkillsPage(e){let s=e.createDiv({cls:"af-skills-page"}),n=this.plugin.runtime.getSnapshot(),a=s.createDiv({cls:"af-agents-toolbar"});a.createDiv({cls:"af-page-title",text:"Skills Library"}),a.createDiv({cls:"af-toolbar-spacer"});let r=a.createEl("button",{cls:"af-btn-sm primary"});E(r,"plus","af-btn-icon"),r.appendText(" New Skill"),r.onclick=()=>void this.plugin.createSkillTemplate();let o=s.createDiv({cls:"af-skills-grid"});if(n.skills.length===0){this.renderEmptyState(o,"puzzle","No skills yet","Create skills to give agents specialized abilities");return}for(let c of n.skills)this.renderSkillCard(o,c,n.agents)}renderSkillCard(e,s,n){let a=e.createDiv({cls:"af-skill-card"}),r=a.createDiv({cls:"af-skill-card-header"}),o=r.createDiv({cls:"af-skill-card-icon"});(0,w.setIcon)(o,this.getSkillIcon(s.name));let c=r.createEl("button",{cls:"af-btn-sm af-btn-xs"});E(c,"edit","af-btn-icon"),c.onclick=h=>{h.stopPropagation(),this.navigate("edit-skill",s.name)},a.createDiv({cls:"af-skill-card-name",text:s.name}),a.createDiv({cls:"af-skill-card-desc",text:s.description??"No description"});let l=n.filter(h=>h.skills.includes(s.name));if(l.length>0){let h=a.createDiv({cls:"af-skill-card-agents"});for(let d of l)h.createSpan({cls:"af-skill-card-agent-tag",text:d.name})}}renderChannelsPage(e){let s=e.createDiv({cls:"af-agents-page"}),n=this.plugin.runtime.getSnapshot(),a=s.createDiv({cls:"af-agents-toolbar"});a.createDiv({cls:"af-page-title",text:"Channels"}),a.createDiv({cls:"af-toolbar-spacer"});let r=a.createEl("button",{cls:"af-btn-sm primary"});E(r,"plus","af-btn-icon"),r.appendText(" New Channel"),r.onclick=()=>this.navigate("create-channel");let o=s.createDiv({cls:"af-agents-grid"});if(n.channels.length===0){this.renderEmptyState(o,"radio","No channels configured","Connect an agent to Slack or another chat platform");return}for(let c of n.channels)this.renderChannelCard(o,c,n.validationIssues)}async renderWikiKeepersPage(e){let s=e.createDiv({cls:"af-agents-page"}),n=this.plugin.runtime.getSnapshot(),a=s.createDiv({cls:"af-agents-toolbar"});a.createDiv({cls:"af-page-title",text:"Wiki Keepers"}),a.createDiv({cls:"af-toolbar-spacer"});let r=n.agents.filter(c=>c.wikiKeeper!==void 0);if(r.length===0){this.renderEmptyState(s,"library","No Wiki Keepers yet","Open Settings \u2192 Agent Fleet \u2192 Wiki Keepers \u2192 + Add to create one.");return}let o=s.createDiv({cls:"af-wk-list"});o.setCssStyles({display:"flex"}),o.setCssStyles({flexDirection:"column"}),o.setCssStyles({gap:"16px"});for(let c of r)await this.renderWikiKeeperCard(o,c)}async renderWikiKeeperCard(e,s){let n=s.wikiKeeper,a=e.createDiv({cls:"af-card"});a.setCssStyles({padding:"16px"}),a.setCssStyles({border:"1px solid var(--background-modifier-border)"}),a.setCssStyles({borderRadius:"8px"});let r=a.createDiv();r.setCssStyles({display:"flex"}),r.setCssStyles({alignItems:"center"}),r.setCssStyles({gap:"12px"}),r.setCssStyles({marginBottom:"12px"});let o=r.createDiv();o.setCssStyles({flex:"1"}),o.createEl("strong",{text:s.name});let c=n.scopeRoot||"(whole vault)";o.createEl("div",{text:`Scope: ${c} \xB7 topics: ${n.topicsRoot}/ \xB7 log: ${n.logPath}`,cls:"af-form-hint"});let l=r.createEl("button",{cls:"af-btn-sm"});l.appendText("Open log"),l.onclick=()=>{let g=n.scopeRoot?`${n.scopeRoot}/${n.logPath}`:n.logPath,v=this.plugin.app.vault.getAbstractFileByPath(g);v instanceof w.TFile?this.plugin.app.workspace.getLeaf().openFile(v):new w.Notice(`Log file not found: ${g}`)};let h=n.scopeRoot?`${n.scopeRoot}/${n.logPath}`:n.logPath,d=this.plugin.app.vault.getAbstractFileByPath(h),u=null;if(d instanceof w.TFile)try{let g=await this.plugin.app.vault.cachedRead(d);u=Do(g)}catch{u=null}if(!u){a.createDiv({cls:"af-form-hint"}).setText("No lint report yet. Run wiki-lint manually or wait for the weekly task to fire.");return}let p=a.createDiv();if(p.setCssStyles({display:"flex"}),p.setCssStyles({alignItems:"baseline"}),p.setCssStyles({gap:"12px"}),p.setCssStyles({marginBottom:"8px"}),p.createEl("strong",{text:`Lint ${u.date}`}),p.createSpan({cls:"af-form-hint",text:`${u.summary.length} summary lines \xB7 ${u.autoApplied.length} auto-applied \xB7 ${u.needsReview.length} needs review`}),u.summary.length>0){let g=a.createEl("details");g.createEl("summary",{text:"Summary"});let v=g.createEl("ul");v.setCssStyles({marginTop:"4px"});for(let b of u.summary)v.createEl("li",{text:b})}if(u.autoApplied.length>0){let g=a.createEl("details");g.createEl("summary",{text:`Auto-applied (${u.autoApplied.length})`});let v=g.createEl("ul");v.setCssStyles({marginTop:"4px"});for(let b of u.autoApplied)v.createEl("li",{text:b})}if(u.refreshChained.length>0){let g=a.createEl("details");g.createEl("summary",{text:`Refresh chained (${u.refreshChained.length})`});let v=g.createEl("ul");v.setCssStyles({marginTop:"4px"});for(let b of u.refreshChained)v.createEl("li",{text:b})}let m=a.createDiv();if(m.setCssStyles({marginTop:"12px"}),m.createEl("strong",{text:`Needs review (${u.needsReview.length})`}),u.needsReview.length===0){m.createDiv({cls:"af-form-hint",text:"All clear. Nothing requires manual review from this lint pass."});return}let f=m.createDiv();f.setCssStyles({display:"flex"}),f.setCssStyles({flexDirection:"column"}),f.setCssStyles({gap:"6px"}),f.setCssStyles({marginTop:"8px"});for(let g of u.needsReview){let v=f.createDiv();v.setCssStyles({display:"flex"}),v.setCssStyles({alignItems:"flex-start"}),v.setCssStyles({gap:"8px"}),v.setCssStyles({padding:"8px 10px"}),v.setCssStyles({background:"var(--background-secondary)"}),v.setCssStyles({borderRadius:"4px"}),v.setCssStyles({fontSize:"13px"});let b=v.createDiv();b.setCssStyles({flex:"1"}),b.setText(g);let k=v.createEl("button",{cls:"af-btn-sm",text:"Dismiss"});k.title="Hide this item from the dashboard until the next lint pass (does not modify log.md).",k.onclick=()=>{v.remove()}}}renderChannelCard(e,s,n){let a=this.plugin.channelManager?.getChannelStatus(s.name)??"disabled",r=Lo(a),o=s.enabled&&a!=="disabled"?"af-agent-card":"af-agent-card disabled",c=e.createDiv({cls:o});c.setCssStyles({cursor:"default"});let l=c.createDiv({cls:"af-agent-card-header"}),h=l.createDiv({cls:`af-agent-card-avatar ${r}`});(0,w.setIcon)(h,"radio");let d=l.createDiv({cls:"af-agent-card-titleblock"});d.createDiv({cls:"af-agent-card-name",text:s.name}),d.createDiv({cls:"af-agent-card-desc",text:`Default: ${s.defaultAgent}`});let u=l.createSpan({cls:`af-pill ${Ud(a)}`});if(u.createSpan({cls:"af-dot"}),u.appendText(` ${a}`),s.allowedAgents.length>0){let T=c.createDiv({cls:"af-agent-card-skills"});for(let _ of s.allowedAgents){let D=T.createSpan({cls:"af-skill-tag",text:_});_===s.defaultAgent&&D.setCssStyles({fontWeight:"700"})}}let p=c.createDiv({cls:"af-agent-card-stats"}),m=this.plugin.channelManager?.getSessionCount(s.name)??0,f=this.plugin.channelManager?.getMetrics(s.name),g=s.allowedAgents.length>0?String(s.allowedAgents.length):"all";this.renderAgentStat(p,g,"Agents"),this.renderAgentStat(p,String(m),"Sessions"),this.renderAgentStat(p,String(f?.messagesReceived??0),"In"),this.renderAgentStat(p,String(f?.messagesSent??0),"Out");let v=c.createDiv({cls:"af-agent-card-footer"}),b=[s.type];s.enabled||b.push("disabled"),s.allowedUsers.length>0?b.push(`${s.allowedUsers.length} user(s)`):b.push("allowlist empty"),v.createSpan({cls:"af-agent-card-meta",text:b.join(" \xB7 ")});let y=v.createDiv({cls:"af-agent-card-actions"}).createEl("button",{cls:"af-btn-sm"});E(y,"edit","af-btn-icon"),y.appendText(" Edit"),y.onclick=T=>{T.stopPropagation(),this.navigate("edit-channel",s.name)};let S=n.filter(T=>T.path===s.filePath);if(S.length>0){let T=c.createDiv({cls:"af-channel-issues"});for(let _ of S)T.createDiv({cls:"af-channel-issue-row",text:_.message})}}renderCreateChannelPage(e){let s=e.createDiv({cls:"af-create-agent-page"}),n=this.plugin.runtime.getSnapshot(),a=this.plugin.channelCredentials.list(),r=s.createDiv({cls:"af-detail-header"}),o=r.createDiv({cls:"af-detail-header-left"}),c=o.createDiv({cls:"af-agent-card-avatar idle"});(0,w.setIcon)(c,"plus");let l=o.createDiv();l.createDiv({cls:"af-detail-header-name",text:"Create New Channel"}),l.createDiv({cls:"af-detail-header-desc",text:"Connect an external chat transport to an agent"});let h=r.createDiv({cls:"af-detail-header-actions"}),d={name:"",type:"slack",defaultAgent:n.agents[0]?.name??"",allowedAgents:[],credentialRef:a[0]?.ref??"",allowedUsers:"",perUserSessions:!0,channelContext:"",enabled:!0,tags:"",body:"",transportJson:""},u=s.createDiv({cls:"af-create-form"}),p=u.createDiv({cls:"af-create-section"}),m=p.createDiv({cls:"af-create-section-header"}),f=m.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(f,"radio"),m.createSpan({text:"Channel Details"}),this.createFormField(p,"Name","my-slack","Unique identifier for this channel",$=>{d.name=$});let g=p.createDiv({cls:"af-form-row"});g.createDiv({cls:"af-form-label",text:"Type"});let v=g.createEl("select",{cls:"af-form-select"});v.createEl("option",{text:"slack",attr:{value:"slack"}}),v.createEl("option",{text:"telegram",attr:{value:"telegram"}}),v.addEventListener("change",()=>{d.type=v.value});let b=p.createDiv({cls:"af-form-row"}),k=b.createDiv({cls:"af-form-label"});k.setText("Credential"),this.addTooltip(k,"Configured in Settings \u2192 Agent Fleet \u2192 Channel Credentials");let y=b.createEl("select",{cls:"af-form-select"});a.length===0&&y.createEl("option",{text:"(no credentials configured)",attr:{value:""}});for(let $ of a)y.createEl("option",{text:`${$.ref} (${$.entry.type})`,attr:{value:$.ref}});y.addEventListener("change",()=>{d.credentialRef=y.value});let S=p.createDiv({cls:"af-form-row af-form-row-toggle"});S.createDiv({cls:"af-form-label",text:"Enabled"});let T=S.createDiv({cls:"af-agent-card-toggle on"});T.onclick=()=>{let $=T.hasClass("on");T.toggleClass("on",!$),d.enabled=!$};let _=u.createDiv({cls:"af-create-section"}),D=_.createDiv({cls:"af-create-section-header"}),M=D.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(M,"bot"),D.createSpan({text:"Agent Routing"});let C=_.createDiv({cls:"af-form-row"}),I=C.createDiv({cls:"af-form-label"});I.setText("Default agent"),this.addTooltip(I,"Used when no @agent-name prefix is given in a message");let P=C.createEl("select",{cls:"af-form-select"});for(let $ of n.agents)P.createEl("option",{text:$.name,attr:{value:$.name}});P.addEventListener("change",()=>{d.defaultAgent=P.value});let L=_.createDiv({cls:"af-form-row"}),F=L.createDiv({cls:"af-form-label"});F.setText("Allowed agents"),this.addTooltip(F,"Agents reachable via @prefix. Leave unchecked to allow all agents.");let z=L.createDiv({cls:"af-form-checkboxes"});for(let $ of n.agents){let Te=z.createEl("label",{cls:"af-form-checkbox-label"}),xe=Te.createEl("input",{attr:{type:"checkbox",value:$.name}});Te.appendText(` ${$.name}`),xe.addEventListener("change",()=>{xe.checked?d.allowedAgents.includes($.name)||d.allowedAgents.push($.name):d.allowedAgents=d.allowedAgents.filter(he=>he!==$.name)})}let U=_.createDiv({cls:"af-form-row af-form-row-toggle"}),Z=U.createDiv({cls:"af-form-label"});Z.setText("Per-user sessions"),this.addTooltip(Z,"Each external user gets their own isolated Claude session");let de=U.createDiv({cls:"af-agent-card-toggle on"});de.onclick=()=>{let $=de.hasClass("on");de.toggleClass("on",!$),d.perUserSessions=!$};let me=u.createDiv({cls:"af-create-section"}),ye=me.createDiv({cls:"af-create-section-header"}),X=ye.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(X,"shield-check"),ye.createSpan({text:"Access Control"});let j=me.createDiv({cls:"af-form-label"});j.setText("Allowed users"),this.addTooltip(j,"Slack user IDs (U...), one per line. Only listed users can reach the bot.");let K=me.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:`U0AQW6P37N1
12007
+ U0BXYZ12345`,rows:"4"}});K.addEventListener("input",()=>{d.allowedUsers=K.value});let ne=u.createDiv({cls:"af-create-section"}),G=ne.createDiv({cls:"af-create-section-header"}),ee=G.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(ee,"message-square");let Q=G.createSpan({text:"Channel Context"});this.addTooltip(Q,"Extra instructions appended to the agent's system prompt when reached through this channel");let ae=ne.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"You are being contacted via Slack. Keep replies concise...",rows:"6"}});ae.addEventListener("input",()=>{d.channelContext=ae.value}),this.createFormField(p,"Tags","ops, internal","Comma-separated metadata",$=>{d.tags=$});let ve=u.createDiv({cls:"af-create-section"}),Re=ve.createDiv({cls:"af-create-section-header"}),Le=Re.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(Le,"settings");let Me=Re.createSpan({text:"Advanced"});this.addTooltip(Me,"Markdown body (shown in the channel detail page) and transport-specific overrides");let Fe=ve.createDiv({cls:"af-form-label"});Fe.setText("Body (markdown)"),this.addTooltip(Fe,"Free-form notes for this channel. Shown in the channel detail page; not sent to the agent.");let ke=ve.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"Notes, runbook snippets, escalation contacts\u2026",rows:"4"}});ke.addEventListener("input",()=>{d.body=ke.value});let Oe=ve.createDiv({cls:"af-form-label"});Oe.setText("Transport config (JSON)"),this.addTooltip(Oe,"Optional JSON object for transport-specific overrides (e.g. Slack socket_mode, telegram webhook settings). Leave blank for defaults.");let Ue=ve.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:`{
12008
12008
  "socket_mode": true
12009
- }`,rows:"4"}});Ne.addEventListener("input",()=>{d.transportJson=Ne.value});let $e=s.createDiv({cls:"af-create-footer"}),q=$e.createEl("button",{cls:"af-btn-sm",text:"Cancel"});q.onclick=()=>this.navigate("channels");let ie=$e.createEl("button",{cls:"af-btn-sm primary af-create-submit"});D(ie,"plus","af-btn-icon"),ie.appendText(" Create Channel"),ie.onclick=async()=>{let $=d.name.trim();if(!$){new b.Notice("Channel name is required.");return}if(!d.credentialRef){new b.Notice("Select a credential.");return}let Ce;if(d.transportJson.trim())try{let se=JSON.parse(d.transportJson);if(se&&typeof se=="object"&&!Array.isArray(se))Ce=se;else{new b.Notice("Transport config must be a JSON object.");return}}catch(se){new b.Notice(`Transport JSON is invalid: ${se instanceof Error?se.message:String(se)}`);return}let we=se=>se.split(/[\n,]+/).map(I=>I.trim()).filter(Boolean),ge=se=>se.split(",").map(I=>I.trim()).filter(Boolean),Ie={name:ae($),type:d.type,default_agent:d.defaultAgent,allowed_agents:d.allowedAgents.length>0?d.allowedAgents:void 0,enabled:d.enabled,credential_ref:d.credentialRef,allowed_users:we(d.allowedUsers),per_user_sessions:d.perUserSessions,channel_context:d.channelContext.trim()||void 0,tags:ge(d.tags).length>0?ge(d.tags):void 0,transport:Ce};try{let se=ae($),I=await this.plugin.repository.getAvailablePath(this.plugin.repository.getSubfolder("channels"),se);await this.plugin.app.vault.create(I,H(Ie,d.body.trim())),new b.Notice(`Channel "${se}" created.`),await this.plugin.refreshFromVault(),this.navigate("edit-channel",se)}catch(se){let I=se instanceof Error?se.message:String(se);new b.Notice(`Failed to create channel: ${I}`)}}}renderEditChannelPage(e){let s=e.createDiv({cls:"af-create-agent-page"}),n=this.detailContext;if(!n){this.renderEmptyState(s,"radio","No channel selected","");return}let a=this.plugin.runtime.getSnapshot().channels.find(I=>I.name===n);if(!a){this.renderEmptyState(s,"radio","Channel not found",`Channel "${n}" was not found`);return}let r=this.plugin.runtime.getSnapshot(),o=this.plugin.channelCredentials.list(),c=this.plugin.channelManager?.getChannelStatus(a.name)??"disabled",l=s.createDiv({cls:"af-detail-header"}),d=l.createDiv({cls:"af-detail-header-left"}),h=d.createDiv({cls:`af-agent-card-avatar ${Mo(c)}`});(0,b.setIcon)(h,"radio");let u=d.createDiv();u.createDiv({cls:"af-detail-header-name",text:`Edit Channel: ${a.name}`}),u.createDiv({cls:"af-detail-header-desc",text:`Status: ${c}`}),l.createDiv({cls:"af-detail-header-actions"});let p={type:a.type,defaultAgent:a.defaultAgent,allowedAgents:[...a.allowedAgents],credentialRef:a.credentialRef,allowedUsers:a.allowedUsers.join(`
12010
- `),perUserSessions:a.perUserSessions,channelContext:a.channelContext,enabled:a.enabled,tags:a.tags.join(", "),body:a.body,transportJson:Object.keys(a.transport).length>0?JSON.stringify(a.transport,null,2):""},f=s.createDiv({cls:"af-create-form"}),m=f.createDiv({cls:"af-create-section"}),g=m.createDiv({cls:"af-create-section-header"}),v=g.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(v,"radio"),g.createSpan({text:"Channel Details"});let k=m.createDiv({cls:"af-form-row"});k.createDiv({cls:"af-form-label",text:"Name"});let w=k.createEl("input",{cls:"af-form-input",attr:{type:"text",value:a.name,disabled:"true"}});w.style.opacity="0.6";let y=m.createDiv({cls:"af-form-row"});y.createDiv({cls:"af-form-label",text:"Type"});let C=y.createEl("select",{cls:"af-form-select"});for(let I of["slack","telegram"]){let ne=C.createEl("option",{text:I,attr:{value:I}});I===a.type&&(ne.selected=!0)}C.addEventListener("change",()=>{p.type=C.value});let T=m.createDiv({cls:"af-form-row"}),_=T.createDiv({cls:"af-form-label"});_.setText("Credential"),this.addTooltip(_,"Configured in Settings \u2192 Agent Fleet \u2192 Channel Credentials");let O=T.createEl("select",{cls:"af-form-select"});o.length===0&&O.createEl("option",{text:"(no credentials configured)",attr:{value:""}});for(let I of o){let ne=O.createEl("option",{text:`${I.ref} (${I.entry.type})`,attr:{value:I.ref}});I.ref===a.credentialRef&&(ne.selected=!0)}O.addEventListener("change",()=>{p.credentialRef=O.value});let E=m.createDiv({cls:"af-form-row af-form-row-toggle"});E.createDiv({cls:"af-form-label",text:"Enabled"});let S=E.createDiv({cls:`af-agent-card-toggle${a.enabled?" on":""}`});S.onclick=()=>{let I=S.hasClass("on");S.toggleClass("on",!I),p.enabled=!I};let P=f.createDiv({cls:"af-create-section"}),R=P.createDiv({cls:"af-create-section-header"}),N=R.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(N,"bot"),R.createSpan({text:"Agent Routing"});let L=P.createDiv({cls:"af-form-row"}),G=L.createDiv({cls:"af-form-label"});G.setText("Default agent"),this.addTooltip(G,"Used when no @agent-name prefix is given in a message");let U=L.createEl("select",{cls:"af-form-select"});for(let I of r.agents){let ne=U.createEl("option",{text:I.name,attr:{value:I.name}});I.name===a.defaultAgent&&(ne.selected=!0)}U.addEventListener("change",()=>{p.defaultAgent=U.value});let X=P.createDiv({cls:"af-form-row"}),me=X.createDiv({cls:"af-form-label"});me.setText("Allowed agents"),this.addTooltip(me,"Agents reachable via @prefix. Leave unchecked to allow all agents.");let ye=X.createDiv({cls:"af-form-checkboxes"});for(let I of r.agents){let ne=ye.createEl("label",{cls:"af-form-checkbox-label"}),he=ne.createEl("input",{attr:{type:"checkbox",value:I.name}});a.allowedAgents.includes(I.name)&&(he.checked=!0),ne.appendText(` ${I.name}`),he.addEventListener("change",()=>{he.checked?p.allowedAgents.includes(I.name)||p.allowedAgents.push(I.name):p.allowedAgents=p.allowedAgents.filter(oe=>oe!==I.name)})}let ee=P.createDiv({cls:"af-form-row af-form-row-toggle"}),W=ee.createDiv({cls:"af-form-label"});W.setText("Per-user sessions"),this.addTooltip(W,"Each external user gets their own isolated Claude session");let de=ee.createDiv({cls:`af-agent-card-toggle${a.perUserSessions?" on":""}`});de.onclick=()=>{let I=de.hasClass("on");de.toggleClass("on",!I),p.perUserSessions=!I};let V=f.createDiv({cls:"af-create-section"}),te=V.createDiv({cls:"af-create-section-header"}),Y=te.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(Y,"shield-check"),te.createSpan({text:"Access Control"});let Z=V.createDiv({cls:"af-form-label"});Z.setText("Allowed users"),this.addTooltip(Z,"Slack user IDs (U...), one per line. Only listed users can reach the bot.");let j=V.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:`U0AQW6P37N1
12011
- U0BXYZ12345`,rows:"4"}});j.value=a.allowedUsers.join(`
12012
- `),j.addEventListener("input",()=>{p.allowedUsers=j.value});let fe=f.createDiv({cls:"af-create-section"}),Pe=fe.createDiv({cls:"af-create-section-header"}),Oe=Pe.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(Oe,"message-square");let Ue=Pe.createSpan({text:"Channel Context"});this.addTooltip(Ue,"Extra instructions appended to the agent's system prompt when reached through this channel");let Re=fe.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"You are being contacted via Slack. Keep replies concise...",rows:"6"}});Re.value=a.channelContext,Re.addEventListener("input",()=>{p.channelContext=Re.value}),this.createFormField(m,"Tags","ops, internal","Comma-separated metadata",I=>{p.tags=I},a.tags.join(", "));let Se=f.createDiv({cls:"af-create-section"}),De=Se.createDiv({cls:"af-create-section-header"}),Ne=De.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(Ne,"settings");let $e=De.createSpan({text:"Advanced"});this.addTooltip($e,"Markdown body (shown in the channel detail page) and transport-specific overrides"),Se.createDiv({cls:"af-form-label"}).setText("Body (markdown)");let ie=Se.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"Notes, runbook snippets, escalation contacts\u2026",rows:"4"}});ie.value=a.body,ie.addEventListener("input",()=>{p.body=ie.value});let $=Se.createDiv({cls:"af-form-label"});$.setText("Transport config (JSON)"),this.addTooltip($,"Optional JSON object for transport-specific overrides (e.g. Slack socket_mode). Leave blank for defaults.");let Ce=Se.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:`{
12009
+ }`,rows:"4"}});Ue.addEventListener("input",()=>{d.transportJson=Ue.value});let Ne=s.createDiv({cls:"af-create-footer"}),H=Ne.createEl("button",{cls:"af-btn-sm",text:"Cancel"});H.onclick=()=>this.navigate("channels");let ie=Ne.createEl("button",{cls:"af-btn-sm primary af-create-submit"});E(ie,"plus","af-btn-icon"),ie.appendText(" Create Channel"),ie.onclick=async()=>{let $=d.name.trim();if(!$){new w.Notice("Channel name is required.");return}if(!d.credentialRef){new w.Notice("Select a credential.");return}let Te;if(d.transportJson.trim())try{let re=JSON.parse(d.transportJson);if(re&&typeof re=="object"&&!Array.isArray(re))Te=re;else{new w.Notice("Transport config must be a JSON object.");return}}catch(re){new w.Notice(`Transport JSON is invalid: ${re instanceof Error?re.message:String(re)}`);return}let xe=re=>re.split(/[\n,]+/).map(R=>R.trim()).filter(Boolean),he=re=>re.split(",").map(R=>R.trim()).filter(Boolean),$e={name:oe($),type:d.type,default_agent:d.defaultAgent,allowed_agents:d.allowedAgents.length>0?d.allowedAgents:void 0,enabled:d.enabled,credential_ref:d.credentialRef,allowed_users:xe(d.allowedUsers),per_user_sessions:d.perUserSessions,channel_context:d.channelContext.trim()||void 0,tags:he(d.tags).length>0?he(d.tags):void 0,transport:Te};try{let re=oe($),R=await this.plugin.repository.getAvailablePath(this.plugin.repository.getSubfolder("channels"),re);await this.plugin.app.vault.create(R,W($e,d.body.trim())),new w.Notice(`Channel "${re}" created.`),await this.plugin.refreshFromVault(),this.navigate("edit-channel",re)}catch(re){let R=re instanceof Error?re.message:String(re);new w.Notice(`Failed to create channel: ${R}`)}}}renderEditChannelPage(e){let s=e.createDiv({cls:"af-create-agent-page"}),n=this.detailContext;if(!n){this.renderEmptyState(s,"radio","No channel selected","");return}let a=this.plugin.runtime.getSnapshot().channels.find(R=>R.name===n);if(!a){this.renderEmptyState(s,"radio","Channel not found",`Channel "${n}" was not found`);return}let r=this.plugin.runtime.getSnapshot(),o=this.plugin.channelCredentials.list(),c=this.plugin.channelManager?.getChannelStatus(a.name)??"disabled",l=s.createDiv({cls:"af-detail-header"}),h=l.createDiv({cls:"af-detail-header-left"}),d=h.createDiv({cls:`af-agent-card-avatar ${Lo(c)}`});(0,w.setIcon)(d,"radio");let u=h.createDiv();u.createDiv({cls:"af-detail-header-name",text:`Edit Channel: ${a.name}`}),u.createDiv({cls:"af-detail-header-desc",text:`Status: ${c}`});let p=l.createDiv({cls:"af-detail-header-actions"}),m={type:a.type,defaultAgent:a.defaultAgent,allowedAgents:[...a.allowedAgents],credentialRef:a.credentialRef,allowedUsers:a.allowedUsers.join(`
12010
+ `),perUserSessions:a.perUserSessions,channelContext:a.channelContext,enabled:a.enabled,tags:a.tags.join(", "),body:a.body,transportJson:Object.keys(a.transport).length>0?JSON.stringify(a.transport,null,2):""},f=s.createDiv({cls:"af-create-form"}),g=f.createDiv({cls:"af-create-section"}),v=g.createDiv({cls:"af-create-section-header"}),b=v.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(b,"radio"),v.createSpan({text:"Channel Details"});let k=g.createDiv({cls:"af-form-row"});k.createDiv({cls:"af-form-label",text:"Name"}),k.createEl("input",{cls:"af-form-input",attr:{type:"text",value:a.name,disabled:"true"}}).setCssStyles({opacity:"0.6"});let S=g.createDiv({cls:"af-form-row"});S.createDiv({cls:"af-form-label",text:"Type"});let T=S.createEl("select",{cls:"af-form-select"});for(let R of["slack","telegram"]){let se=T.createEl("option",{text:R,attr:{value:R}});R===a.type&&(se.selected=!0)}T.addEventListener("change",()=>{m.type=T.value});let _=g.createDiv({cls:"af-form-row"}),D=_.createDiv({cls:"af-form-label"});D.setText("Credential"),this.addTooltip(D,"Configured in Settings \u2192 Agent Fleet \u2192 Channel Credentials");let M=_.createEl("select",{cls:"af-form-select"});o.length===0&&M.createEl("option",{text:"(no credentials configured)",attr:{value:""}});for(let R of o){let se=M.createEl("option",{text:`${R.ref} (${R.entry.type})`,attr:{value:R.ref}});R.ref===a.credentialRef&&(se.selected=!0)}M.addEventListener("change",()=>{m.credentialRef=M.value});let C=g.createDiv({cls:"af-form-row af-form-row-toggle"});C.createDiv({cls:"af-form-label",text:"Enabled"});let I=C.createDiv({cls:`af-agent-card-toggle${a.enabled?" on":""}`});I.onclick=()=>{let R=I.hasClass("on");I.toggleClass("on",!R),m.enabled=!R};let P=f.createDiv({cls:"af-create-section"}),L=P.createDiv({cls:"af-create-section-header"}),F=L.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(F,"bot"),L.createSpan({text:"Agent Routing"});let z=P.createDiv({cls:"af-form-row"}),U=z.createDiv({cls:"af-form-label"});U.setText("Default agent"),this.addTooltip(U,"Used when no @agent-name prefix is given in a message");let Z=z.createEl("select",{cls:"af-form-select"});for(let R of r.agents){let se=Z.createEl("option",{text:R.name,attr:{value:R.name}});R.name===a.defaultAgent&&(se.selected=!0)}Z.addEventListener("change",()=>{m.defaultAgent=Z.value});let de=P.createDiv({cls:"af-form-row"}),me=de.createDiv({cls:"af-form-label"});me.setText("Allowed agents"),this.addTooltip(me,"Agents reachable via @prefix. Leave unchecked to allow all agents.");let ye=de.createDiv({cls:"af-form-checkboxes"});for(let R of r.agents){let se=ye.createEl("label",{cls:"af-form-checkbox-label"}),ce=se.createEl("input",{attr:{type:"checkbox",value:R.name}});a.allowedAgents.includes(R.name)&&(ce.checked=!0),se.appendText(` ${R.name}`),ce.addEventListener("change",()=>{ce.checked?m.allowedAgents.includes(R.name)||m.allowedAgents.push(R.name):m.allowedAgents=m.allowedAgents.filter(te=>te!==R.name)})}let X=P.createDiv({cls:"af-form-row af-form-row-toggle"}),j=X.createDiv({cls:"af-form-label"});j.setText("Per-user sessions"),this.addTooltip(j,"Each external user gets their own isolated Claude session");let K=X.createDiv({cls:`af-agent-card-toggle${a.perUserSessions?" on":""}`});K.onclick=()=>{let R=K.hasClass("on");K.toggleClass("on",!R),m.perUserSessions=!R};let ne=f.createDiv({cls:"af-create-section"}),G=ne.createDiv({cls:"af-create-section-header"}),ee=G.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(ee,"shield-check"),G.createSpan({text:"Access Control"});let Q=ne.createDiv({cls:"af-form-label"});Q.setText("Allowed users"),this.addTooltip(Q,"Slack user IDs (U...), one per line. Only listed users can reach the bot.");let ae=ne.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:`U0AQW6P37N1
12011
+ U0BXYZ12345`,rows:"4"}});ae.value=a.allowedUsers.join(`
12012
+ `),ae.addEventListener("input",()=>{m.allowedUsers=ae.value});let ve=f.createDiv({cls:"af-create-section"}),Re=ve.createDiv({cls:"af-create-section-header"}),Le=Re.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(Le,"message-square");let Me=Re.createSpan({text:"Channel Context"});this.addTooltip(Me,"Extra instructions appended to the agent's system prompt when reached through this channel");let Fe=ve.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"You are being contacted via Slack. Keep replies concise...",rows:"6"}});Fe.value=a.channelContext,Fe.addEventListener("input",()=>{m.channelContext=Fe.value}),this.createFormField(g,"Tags","ops, internal","Comma-separated metadata",R=>{m.tags=R},a.tags.join(", "));let ke=f.createDiv({cls:"af-create-section"}),Oe=ke.createDiv({cls:"af-create-section-header"}),Ue=Oe.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(Ue,"settings");let Ne=Oe.createSpan({text:"Advanced"});this.addTooltip(Ne,"Markdown body (shown in the channel detail page) and transport-specific overrides"),ke.createDiv({cls:"af-form-label"}).setText("Body (markdown)");let ie=ke.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"Notes, runbook snippets, escalation contacts\u2026",rows:"4"}});ie.value=a.body,ie.addEventListener("input",()=>{m.body=ie.value});let $=ke.createDiv({cls:"af-form-label"});$.setText("Transport config (JSON)"),this.addTooltip($,"Optional JSON object for transport-specific overrides (e.g. Slack socket_mode). Leave blank for defaults.");let Te=ke.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:`{
12013
12013
  "socket_mode": true
12014
- }`,rows:"4"}});Ce.value=p.transportJson,Ce.addEventListener("input",()=>{p.transportJson=Ce.value});let we=s.createDiv({cls:"af-create-footer"}),ge=we.createEl("button",{cls:"af-btn-sm danger"});D(ge,"trash-2","af-btn-icon"),ge.appendText(" Delete"),ge.onclick=async()=>{await this.plugin.repository.deleteChannel(a.name),new b.Notice(`Channel "${a.name}" deleted.`),await new Promise(I=>setTimeout(I,200)),await this.plugin.refreshFromVault(),this.navigate("channels")},we.createDiv({cls:"af-toolbar-spacer"});let Ie=we.createEl("button",{cls:"af-btn-sm",text:"Cancel"});Ie.onclick=()=>this.navigate("channels");let se=we.createEl("button",{cls:"af-btn-sm primary af-create-submit"});D(se,"check","af-btn-icon"),se.appendText(" Save Changes"),se.onclick=async()=>{let I=oe=>oe.split(/[\n,]+/).map(Me=>Me.trim()).filter(Boolean),ne=oe=>oe.split(",").map(Me=>Me.trim()).filter(Boolean),he;if(p.transportJson.trim())try{let oe=JSON.parse(p.transportJson);if(oe&&typeof oe=="object"&&!Array.isArray(oe))he=oe;else{new b.Notice("Transport config must be a JSON object.");return}}catch(oe){new b.Notice(`Transport JSON is invalid: ${oe instanceof Error?oe.message:String(oe)}`);return}else he={};try{await this.plugin.repository.updateChannel(a.name,{type:p.type,default_agent:p.defaultAgent,allowed_agents:p.allowedAgents.length>0?p.allowedAgents:[],enabled:p.enabled,credential_ref:p.credentialRef,allowed_users:I(p.allowedUsers),per_user_sessions:p.perUserSessions,channel_context:p.channelContext.trim(),tags:ne(p.tags),body:p.body.trim(),transport:he}),new b.Notice(`Channel "${a.name}" updated.`),await this.plugin.refreshFromVault(),this.navigate("channels")}catch(oe){let Me=oe instanceof Error?oe.message:String(oe);new b.Notice(`Failed to update channel: ${Me}`)}}}renderApprovalsPage(e){let s=e.createDiv({cls:"af-approvals-page"}),n=this.plugin.runtime.getRecentRuns(),a=s.createDiv({cls:"af-agents-toolbar"});a.createDiv({cls:"af-page-title",text:"Approvals"}),a.createDiv({cls:"af-toolbar-spacer"});let r=n.filter(c=>(c.approvals??[]).some(l=>l.status==="pending"));if(r.length>0){let c=s.createDiv({cls:"af-section-card"}),d=c.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});D(d,"alert-triangle"),d.appendText(` Pending (${r.length})`);let h=c.createDiv({cls:"af-approvals-list"});for(let u of r)this.renderApprovalItem(h,u,!0)}else{let c=s.createDiv({cls:"af-section-card"});this.renderEmptyState(c,"shield-check","No pending approvals","All clear!")}let o=n.filter(c=>(c.approvals??[]).some(l=>l.status!=="pending"));if(o.length>0){let c=s.createDiv({cls:"af-section-card"}),d=c.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});D(d,"check-circle-2"),d.appendText(" History");let h=c.createDiv({cls:"af-approvals-list"});for(let u of o.slice(0,20))this.renderApprovalItem(h,u,!1)}}renderApprovalItem(e,s,n){for(let a of s.approvals??[]){if(n&&a.status!=="pending"||!n&&a.status==="pending")continue;let r=e.createDiv({cls:"af-approval-item"}),o=r.createDiv({cls:"af-approval-item-icon"});a.status==="pending"?((0,b.setIcon)(o,"shield-check"),o.addClass("pending")):a.status==="approved"?((0,b.setIcon)(o,"check-circle-2"),o.addClass("approved")):((0,b.setIcon)(o,"x-circle"),o.addClass("rejected"));let c=r.createDiv({cls:"af-approval-item-body"});if(c.createDiv({cls:"af-approval-item-title",text:`${s.agent} \u2192 ${a.tool}`}),c.createDiv({cls:"af-approval-item-meta",text:`Task: ${s.task} \xB7 ${a.command??"no command"} \xB7 ${this.formatStarted(s.started)}`}),a.reason&&c.createDiv({cls:"af-approval-item-reason",text:`Reason: ${a.reason}`}),n&&a.status==="pending"){let l=r.createDiv({cls:"af-approval-item-actions"}),d=l.createEl("button",{cls:"af-btn-approve"});D(d,"check-circle-2","af-btn-icon"),d.appendText(" Approve"),d.onclick=()=>void this.plugin.runtime.resolveApproval(s,a.tool,"approved").then(()=>this.render());let h=l.createEl("button",{cls:"af-btn-reject"});D(h,"x-circle","af-btn-icon"),h.appendText(" Reject"),h.onclick=()=>void this.plugin.runtime.resolveApproval(s,a.tool,"rejected").then(()=>this.render())}}}renderTaskDetailPage(e){let s=e.createDiv({cls:"af-task-detail-page"}),n=this.detailContext;if(!n){this.renderEmptyState(s,"circle-dot","No task selected","");return}let a=this.plugin.runtime.getSnapshot().tasks.find(R=>R.taskId===n);if(!a){this.renderEmptyState(s,"circle-dot","Task not found",`Task "${n}" was not found`);return}let r=this.plugin.runtime.getSnapshot(),o=this.plugin.runtime.getRecentRuns().filter(R=>R.task===n),c=r.agents.find(R=>R.name===a.agent),l=s.createDiv({cls:"af-detail-header"}),d=l.createDiv({cls:"af-detail-header-left"}),h=d.createDiv({cls:"af-agent-card-avatar idle"});(0,b.setIcon)(h,"circle-dot");let u=d.createDiv();u.createDiv({cls:"af-detail-header-name",text:a.taskId}),u.createDiv({cls:"af-detail-header-desc",text:`Agent: ${a.agent}`});let p=l.createDiv({cls:"af-detail-header-actions"}),f=p.createEl("button",{cls:"af-btn-sm"});D(f,"edit","af-btn-icon"),f.appendText(" Edit"),f.onclick=()=>this.navigate("edit-task",a.taskId);let m=p.createEl("button",{cls:"af-btn-sm primary"});D(m,"play","af-btn-icon"),m.appendText(" Run Now"),m.onclick=()=>void this.plugin.runtime.runTaskNow(a);let g=s.createDiv({cls:"af-section-card"}),k=g.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});D(k,"file-text"),k.appendText(" Details");let w=g.createDiv({cls:"af-config-form"});this.renderConfigRow(w,"Agent",a.agent),this.renderConfigRow(w,"Priority",a.priority.charAt(0).toUpperCase()+a.priority.slice(1)),this.renderConfigRow(w,"Status",a.enabled?"Enabled":"Disabled");let y=a.schedule?this.humanizeCron(a.schedule):a.runAt??"Manual (run on demand)";this.renderConfigRow(w,"Schedule",y),a.schedule&&this.renderConfigRow(w,"Catch up if missed",a.catchUp?"Yes":"No"),this.renderConfigRow(w,"Created",a.created),this.renderConfigRow(w,"Runs",String(a.runCount)),a.lastRun&&this.renderConfigRow(w,"Last Run",this.formatStarted(a.lastRun));let C=s.createDiv({cls:"af-section-card"}),_=C.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});D(_,"message-square"),_.appendText(" Instructions"),C.createDiv({cls:"af-output-block",text:a.body||"(empty)"});let O=s.createDiv({cls:"af-section-card"}),S=O.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});D(S,"scroll-text"),S.appendText(" Recent Runs");let P=O.createDiv({cls:"af-timeline"});if(o.length===0)this.renderEmptyState(P,"scroll-text","No runs yet","");else for(let R of o.slice(0,10))this.renderTimelineItem(P,R)}handleSearch(e,s){if(s.querySelector(".af-search-results")?.remove(),e.length<2)return;let n=e.toLowerCase(),a=this.plugin.runtime.getSnapshot(),r=this.plugin.runtime.getRecentRuns(),o=[];for(let l of a.agents)(l.name.toLowerCase().includes(n)||(l.description?.toLowerCase().includes(n)??!1))&&o.push({label:`Agent: ${l.name}`,icon:"bot",action:()=>this.navigate("agent-detail",l.name)});for(let l of a.tasks)(l.taskId.toLowerCase().includes(n)||l.body.toLowerCase().includes(n))&&o.push({label:`Task: ${l.taskId}`,icon:"circle-dot",action:()=>this.navigate("task-detail",l.taskId)});for(let l of a.skills)l.name.toLowerCase().includes(n)&&o.push({label:`Skill: ${l.name}`,icon:"puzzle",action:()=>this.navigate("edit-skill",l.name)});for(let l of r.slice(0,20))l.output.toLowerCase().includes(n)&&o.push({label:`Run: ${l.agent} / ${l.task}`,icon:"scroll-text",action:()=>this.openSlideover(l)});if(o.length===0)return;let c=s.createDiv({cls:"af-search-results"});for(let l of o.slice(0,10)){let d=c.createDiv({cls:"af-search-result-item"});D(d,l.icon,"af-search-result-icon"),d.createSpan({text:l.label}),d.onclick=()=>{c.remove(),l.action()}}}openChatSlideover(e){this.plugin.openChatView(e.name)}openSlideover(e){this.contentEl.querySelector(".af-slideover-overlay")?.remove();let s=this.contentEl.createDiv({cls:"af-slideover-overlay"}),n=s.createDiv({cls:"af-slideover"}),a=n.createDiv({cls:"af-slideover-header"});a.createDiv({cls:"af-slideover-title",text:"Run Details"});let r=a.createEl("button",{cls:"clickable-icon"});(0,b.setIcon)(r,"cross"),r.onclick=()=>s.remove();let o=n.createDiv({cls:"af-slideover-body"}),c=o.createDiv({cls:"af-slideover-section"});c.createDiv({cls:"af-slideover-section-title",text:"METADATA"}),this.renderDetailRow(c,"Run ID",e.runId.slice(0,8)),this.renderDetailRow(c,"Agent",e.agent),this.renderDetailRow(c,"Task",e.task);let l=c.createDiv({cls:"af-detail-row"});l.createSpan({cls:"af-detail-label",text:"Status"});let h=l.createSpan({cls:"af-detail-value"}).createSpan({cls:`af-status-badge ${this.statusToBadgeClass(e.status)}`}),u=h.createSpan();(0,b.setIcon)(u,this.statusToIconName(e.status)),h.appendText(` ${this.statusToBadgeText(e.status)}`),this.renderDetailRow(c,"Started",e.started),this.renderDetailRow(c,"Duration",this.formatDuration(e.durationSeconds)),this.renderDetailRow(c,"Tokens",e.tokensUsed?e.tokensUsed.toLocaleString():"\u2014");{let y={task:"from task override",agent:"from agent",settings:"from settings default","cli-default":"CLI default"},C=e.modelSource?` (${y[e.modelSource]??e.modelSource})`:"",T=e.concreteModel&&e.concreteModel!==e.model?` \u2192 ${e.concreteModel}`:"";this.renderDetailRow(c,"Model",`${e.model}${T}${C}`)}let p=5e4,f=y=>y.length>p?y.slice(0,p)+`
12014
+ }`,rows:"4"}});Te.value=m.transportJson,Te.addEventListener("input",()=>{m.transportJson=Te.value});let xe=s.createDiv({cls:"af-create-footer"}),he=xe.createEl("button",{cls:"af-btn-sm danger"});E(he,"trash-2","af-btn-icon"),he.appendText(" Delete"),he.onclick=async()=>{await this.plugin.repository.deleteChannel(a.name),new w.Notice(`Channel "${a.name}" deleted.`),await new Promise(R=>window.setTimeout(R,200)),await this.plugin.refreshFromVault(),this.navigate("channels")},xe.createDiv({cls:"af-toolbar-spacer"});let $e=xe.createEl("button",{cls:"af-btn-sm",text:"Cancel"});$e.onclick=()=>this.navigate("channels");let re=xe.createEl("button",{cls:"af-btn-sm primary af-create-submit"});E(re,"check","af-btn-icon"),re.appendText(" Save Changes"),re.onclick=async()=>{let R=te=>te.split(/[\n,]+/).map(Ze=>Ze.trim()).filter(Boolean),se=te=>te.split(",").map(Ze=>Ze.trim()).filter(Boolean),ce;if(m.transportJson.trim())try{let te=JSON.parse(m.transportJson);if(te&&typeof te=="object"&&!Array.isArray(te))ce=te;else{new w.Notice("Transport config must be a JSON object.");return}}catch(te){new w.Notice(`Transport JSON is invalid: ${te instanceof Error?te.message:String(te)}`);return}else ce={};try{await this.plugin.repository.updateChannel(a.name,{type:m.type,default_agent:m.defaultAgent,allowed_agents:m.allowedAgents.length>0?m.allowedAgents:[],enabled:m.enabled,credential_ref:m.credentialRef,allowed_users:R(m.allowedUsers),per_user_sessions:m.perUserSessions,channel_context:m.channelContext.trim(),tags:se(m.tags),body:m.body.trim(),transport:ce}),new w.Notice(`Channel "${a.name}" updated.`),await this.plugin.refreshFromVault(),this.navigate("channels")}catch(te){let Ze=te instanceof Error?te.message:String(te);new w.Notice(`Failed to update channel: ${Ze}`)}}}renderApprovalsPage(e){let s=e.createDiv({cls:"af-approvals-page"}),n=this.plugin.runtime.getRecentRuns(),a=s.createDiv({cls:"af-agents-toolbar"});a.createDiv({cls:"af-page-title",text:"Approvals"}),a.createDiv({cls:"af-toolbar-spacer"});let r=n.filter(c=>(c.approvals??[]).some(l=>l.status==="pending"));if(r.length>0){let c=s.createDiv({cls:"af-section-card"}),h=c.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});E(h,"alert-triangle"),h.appendText(` Pending (${r.length})`);let d=c.createDiv({cls:"af-approvals-list"});for(let u of r)this.renderApprovalItem(d,u,!0)}else{let c=s.createDiv({cls:"af-section-card"});this.renderEmptyState(c,"shield-check","No pending approvals","All clear!")}let o=n.filter(c=>(c.approvals??[]).some(l=>l.status!=="pending"));if(o.length>0){let c=s.createDiv({cls:"af-section-card"}),h=c.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});E(h,"check-circle-2"),h.appendText(" History");let d=c.createDiv({cls:"af-approvals-list"});for(let u of o.slice(0,20))this.renderApprovalItem(d,u,!1)}}renderApprovalItem(e,s,n){for(let a of s.approvals??[]){if(n&&a.status!=="pending"||!n&&a.status==="pending")continue;let r=e.createDiv({cls:"af-approval-item"}),o=r.createDiv({cls:"af-approval-item-icon"});a.status==="pending"?((0,w.setIcon)(o,"shield-check"),o.addClass("pending")):a.status==="approved"?((0,w.setIcon)(o,"check-circle-2"),o.addClass("approved")):((0,w.setIcon)(o,"x-circle"),o.addClass("rejected"));let c=r.createDiv({cls:"af-approval-item-body"});if(c.createDiv({cls:"af-approval-item-title",text:`${s.agent} \u2192 ${a.tool}`}),c.createDiv({cls:"af-approval-item-meta",text:`Task: ${s.task} \xB7 ${a.command??"no command"} \xB7 ${this.formatStarted(s.started)}`}),a.reason&&c.createDiv({cls:"af-approval-item-reason",text:`Reason: ${a.reason}`}),n&&a.status==="pending"){let l=r.createDiv({cls:"af-approval-item-actions"}),h=l.createEl("button",{cls:"af-btn-approve"});E(h,"check-circle-2","af-btn-icon"),h.appendText(" Approve"),h.onclick=()=>void this.plugin.runtime.resolveApproval(s,a.tool,"approved").then(()=>this.render());let d=l.createEl("button",{cls:"af-btn-reject"});E(d,"x-circle","af-btn-icon"),d.appendText(" Reject"),d.onclick=()=>void this.plugin.runtime.resolveApproval(s,a.tool,"rejected").then(()=>this.render())}}}renderTaskDetailPage(e){let s=e.createDiv({cls:"af-task-detail-page"}),n=this.detailContext;if(!n){this.renderEmptyState(s,"circle-dot","No task selected","");return}let a=this.plugin.runtime.getSnapshot().tasks.find(P=>P.taskId===n);if(!a){this.renderEmptyState(s,"circle-dot","Task not found",`Task "${n}" was not found`);return}let r=this.plugin.runtime.getSnapshot(),o=this.plugin.runtime.getRecentRuns().filter(P=>P.task===n),c=r.agents.find(P=>P.name===a.agent),l=s.createDiv({cls:"af-detail-header"}),h=l.createDiv({cls:"af-detail-header-left"}),d=h.createDiv({cls:"af-agent-card-avatar idle"});(0,w.setIcon)(d,"circle-dot");let u=h.createDiv();u.createDiv({cls:"af-detail-header-name",text:a.taskId}),u.createDiv({cls:"af-detail-header-desc",text:`Agent: ${a.agent}`});let p=l.createDiv({cls:"af-detail-header-actions"}),m=p.createEl("button",{cls:"af-btn-sm"});E(m,"edit","af-btn-icon"),m.appendText(" Edit"),m.onclick=()=>this.navigate("edit-task",a.taskId);let f=p.createEl("button",{cls:"af-btn-sm primary"});E(f,"play","af-btn-icon"),f.appendText(" Run Now"),f.onclick=()=>void this.plugin.runtime.runTaskNow(a);let g=s.createDiv({cls:"af-section-card"}),b=g.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});E(b,"file-text"),b.appendText(" Details");let k=g.createDiv({cls:"af-config-form"});this.renderConfigRow(k,"Agent",a.agent),this.renderConfigRow(k,"Priority",a.priority.charAt(0).toUpperCase()+a.priority.slice(1)),this.renderConfigRow(k,"Status",a.enabled?"Enabled":"Disabled");let y=a.schedule?this.humanizeCron(a.schedule):a.runAt??"Manual (run on demand)";this.renderConfigRow(k,"Schedule",y),a.schedule&&this.renderConfigRow(k,"Catch up if missed",a.catchUp?"Yes":"No"),this.renderConfigRow(k,"Created",a.created),this.renderConfigRow(k,"Runs",String(a.runCount)),a.lastRun&&this.renderConfigRow(k,"Last Run",this.formatStarted(a.lastRun));let S=s.createDiv({cls:"af-section-card"}),_=S.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});E(_,"message-square"),_.appendText(" Instructions"),S.createDiv({cls:"af-output-block",text:a.body||"(empty)"});let D=s.createDiv({cls:"af-section-card"}),C=D.createDiv({cls:"af-section-header"}).createDiv({cls:"af-section-title"});E(C,"scroll-text"),C.appendText(" Recent Runs");let I=D.createDiv({cls:"af-timeline"});if(o.length===0)this.renderEmptyState(I,"scroll-text","No runs yet","");else for(let P of o.slice(0,10))this.renderTimelineItem(I,P)}handleSearch(e,s){if(s.querySelector(".af-search-results")?.remove(),e.length<2)return;let n=e.toLowerCase(),a=this.plugin.runtime.getSnapshot(),r=this.plugin.runtime.getRecentRuns(),o=[];for(let l of a.agents)(l.name.toLowerCase().includes(n)||(l.description?.toLowerCase().includes(n)??!1))&&o.push({label:`Agent: ${l.name}`,icon:"bot",action:()=>this.navigate("agent-detail",l.name)});for(let l of a.tasks)(l.taskId.toLowerCase().includes(n)||l.body.toLowerCase().includes(n))&&o.push({label:`Task: ${l.taskId}`,icon:"circle-dot",action:()=>this.navigate("task-detail",l.taskId)});for(let l of a.skills)l.name.toLowerCase().includes(n)&&o.push({label:`Skill: ${l.name}`,icon:"puzzle",action:()=>this.navigate("edit-skill",l.name)});for(let l of r.slice(0,20))l.output.toLowerCase().includes(n)&&o.push({label:`Run: ${l.agent} / ${l.task}`,icon:"scroll-text",action:()=>this.openSlideover(l)});if(o.length===0)return;let c=s.createDiv({cls:"af-search-results"});for(let l of o.slice(0,10)){let h=c.createDiv({cls:"af-search-result-item"});E(h,l.icon,"af-search-result-icon"),h.createSpan({text:l.label}),h.onclick=()=>{c.remove(),l.action()}}}openChatSlideover(e){this.plugin.openChatView(e.name)}openSlideover(e){this.contentEl.querySelector(".af-slideover-overlay")?.remove();let s=this.contentEl.createDiv({cls:"af-slideover-overlay"}),n=s.createDiv({cls:"af-slideover"}),a=n.createDiv({cls:"af-slideover-header"});a.createDiv({cls:"af-slideover-title",text:"Run Details"});let r=a.createEl("button",{cls:"clickable-icon"});(0,w.setIcon)(r,"cross"),r.onclick=()=>s.remove();let o=n.createDiv({cls:"af-slideover-body"}),c=o.createDiv({cls:"af-slideover-section"});c.createDiv({cls:"af-slideover-section-title",text:"METADATA"}),this.renderDetailRow(c,"Run ID",e.runId.slice(0,8)),this.renderDetailRow(c,"Agent",e.agent),this.renderDetailRow(c,"Task",e.task);let l=c.createDiv({cls:"af-detail-row"});l.createSpan({cls:"af-detail-label",text:"Status"});let d=l.createSpan({cls:"af-detail-value"}).createSpan({cls:`af-status-badge ${this.statusToBadgeClass(e.status)}`}),u=d.createSpan();(0,w.setIcon)(u,this.statusToIconName(e.status)),d.appendText(` ${this.statusToBadgeText(e.status)}`),this.renderDetailRow(c,"Started",e.started),this.renderDetailRow(c,"Duration",this.formatDuration(e.durationSeconds)),this.renderDetailRow(c,"Tokens",e.tokensUsed?e.tokensUsed.toLocaleString():"\u2014");{let y={task:"from task override",agent:"from agent",settings:"from settings default","cli-default":"CLI default"},S=e.modelSource?` (${y[e.modelSource]??e.modelSource})`:"",T=e.concreteModel&&e.concreteModel!==e.model?` \u2192 ${e.concreteModel}`:"";this.renderDetailRow(c,"Model",`${e.model}${T}${S}`)}let p=5e4,m=y=>y.length>p?y.slice(0,p)+`
12015
12015
 
12016
12016
  ---
12017
- *Truncated (${(y.length/1024).toFixed(0)} KB total). Open the run note for full content.*`:y,m=!!(e.finalResult&&e.finalResult.trim()),g=e.output?.trim()??"",v=m&&g.length>0&&g!==e.finalResult.trim();if(m){let y=o.createDiv({cls:"af-slideover-section"});y.createDiv({cls:"af-slideover-section-title",text:"OUTPUT"});let C=y.createDiv({cls:"af-output-block af-compact-md"});if(b.MarkdownRenderer.render(this.app,f(e.finalResult),C,"",this.plugin),v){let T=y.createEl("details",{cls:"af-run-transcript"}),_=T.createEl("summary");(0,b.setIcon)(_.createSpan({cls:"af-run-transcript-icon"}),"file-text"),_.createSpan({text:"Show full transcript"}),_.createSpan({cls:"af-run-transcript-meta"}).setText(`${(g.length/1024).toFixed(1)} KB`);let E=T.createDiv({cls:"af-output-block af-compact-md af-run-transcript-body"});b.MarkdownRenderer.render(this.app,f(g),E,"",this.plugin)}}else if(g){let y=o.createDiv({cls:"af-slideover-section"});y.createDiv({cls:"af-slideover-section-title",text:"OUTPUT"});let C=y.createDiv({cls:"af-output-block af-compact-md"});b.MarkdownRenderer.render(this.app,f(g),C,"",this.plugin)}if(e.toolsUsed.length>0){let y=o.createDiv({cls:"af-slideover-section"});y.createDiv({cls:"af-slideover-section-title",text:"TOOLS USED"}),y.createDiv({cls:"af-output-block",text:e.toolsUsed.join(`
12018
- `)})}let k=o.createDiv({cls:"af-slideover-actions"});if(e.filePath){let y=k.createEl("button",{cls:"af-btn-sm"});D(y,"external-link","af-btn-icon"),y.appendText(" Open Run Note"),y.onclick=()=>void this.plugin.openPath(e.filePath)}let w=k.createEl("button",{cls:"af-btn-sm primary"});D(w,"refresh-cw","af-btn-icon"),w.appendText(" Re-run Task"),w.onclick=()=>void this.plugin.runAgentPrompt(e.agent),s.onclick=y=>{y.target===s&&s.remove()}}renderDetailRow(e,s,n){let a=e.createDiv({cls:"af-detail-row"});a.createSpan({cls:"af-detail-label",text:s}),a.createSpan({cls:"af-detail-value af-mono",text:n})}renderEmptyState(e,s,n,a){let r=e.createDiv({cls:"af-empty-state"}),o=r.createDiv({cls:"af-empty-icon"});(0,b.setIcon)(o,s),r.createDiv({cls:"af-empty-label",text:n}),a&&r.createDiv({cls:"af-empty-sublabel",text:a})}healthToClass(e){switch(e){case"running":return"running";case"error":return"error";case"pending":return"pending";case"disabled":return"disabled";default:return"idle"}}statusToTimelineClass(e){switch(e){case"success":return"success";case"failure":case"timeout":return"error";case"cancelled":return"warning";case"pending_approval":return"pending";default:return"running"}}statusToIconName(e){switch(e){case"success":return"check-circle-2";case"failure":return"x-circle";case"timeout":return"clock";case"pending_approval":return"shield-check";case"cancelled":return"square";default:return"loader-2"}}statusToBadgeClass(e){switch(e){case"success":return"success";case"failure":return"failure";case"timeout":return"timeout";case"pending_approval":return"pending";case"cancelled":return"cancelled";default:return"running"}}statusToBadgeText(e){switch(e){case"success":return"Success";case"failure":return"Failed";case"timeout":return"Timeout";case"pending_approval":return"Pending";case"cancelled":return"Cancelled";case"interrupted":return"Interrupted";default:return e}}formatDuration(e){if(e<60)return`${e}s`;let s=Math.floor(e/60),n=e%60;return n>0?`${s}m ${n}s`:`${s}m`}formatStarted(e){try{let s=new Date(e),n=new Date;if(s.toDateString()===n.toDateString())return s.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"});let a=new Date(n);return a.setDate(a.getDate()-1),s.toDateString()===a.toDateString()?`Yesterday ${s.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}`:s.toLocaleDateString([],{month:"short",day:"numeric"})+` ${s.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}`}catch{return e}}formatNextRun(e){try{let s=new Date(e),n=new Date,a=s.getTime()-n.getTime();if(a<0)return"overdue";let r=Math.round(a/6e4);if(r<60)return`${r}m`;let o=Math.round(r/60);return o<24?`${o}h`:s.toLocaleDateString([],{month:"short",day:"numeric"})}catch{return e}}getNextTaskLabel(e){let n=e.map(r=>r.nextRun).filter(Boolean).sort()[0];return n?`${e.find(r=>r.nextRun===n)?.agent??"unknown"} in ${this.formatNextRun(n)}`:"none"}getInitials(e){return e.split("-").map(s=>s[0]?.toUpperCase()??"").slice(0,2).join("")}renderAgentAvatar(e,s){let n=s.avatar?.trim();if(!n){(0,b.setIcon)(e,"bot");return}/^[a-z][a-z0-9-]*$/.test(n)?(0,b.setIcon)(e,n):e.setText(n)}getSkillIcon(e){return e.includes("git")?"settings":e.includes("summarize")||e.includes("log")?"activity":e.includes("review")||e.includes("check")?"check-circle-2":e.includes("vault")||e.includes("note")?"file-text":"puzzle"}renderInlineSchedule(e,s){let n=this.parseCronComponents(s.schedule),a=e.createDiv({cls:"af-form-row"});a.createDiv({cls:"af-form-label",text:"Frequency"});let r=a.createEl("select",{cls:"af-form-select"}),o=[["every_5m","Every 5 minutes"],["every_15m","Every 15 minutes"],["every_30m","Every 30 minutes"],["every_hour","Every hour"],["every_2h","Every 2 hours"],["daily","Daily"],["weekdays","Weekdays"],["weekly","Weekly"],["monthly","Monthly"]];for(let[y,C]of o){let T=r.createEl("option",{text:C,attr:{value:y}});y===n.freq&&(T.selected=!0)}let c=e.createDiv({cls:"af-form-row af-schedule-time-row"});c.createDiv({cls:"af-form-label",text:"Time"});let l=c.createDiv({cls:"af-schedule-time-selects"}),d=l.createEl("select",{cls:"af-form-select af-form-select-sm"});for(let y=0;y<24;y++){let C=y>=12?"PM":"AM",T=y===0?12:y>12?y-12:y,_=d.createEl("option",{text:`${T} ${C}`,attr:{value:String(y)}});y===n.hour&&(_.selected=!0)}l.createSpan({cls:"af-schedule-colon",text:":"});let h=l.createEl("select",{cls:"af-form-select af-form-select-sm"});for(let y=0;y<60;y+=5){let C=h.createEl("option",{text:String(y).padStart(2,"0"),attr:{value:String(y)}});y===n.minute&&(C.selected=!0)}let u=e.createDiv({cls:"af-form-row af-schedule-day-row"});u.createDiv({cls:"af-form-label",text:"Day"});let p=u.createDiv({cls:"af-schedule-day-buttons"}),f=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],m=new Set(n.days);for(let y=0;y<7;y++){let C=p.createEl("button",{cls:`af-schedule-day-btn${m.has(y)?" active":""}`,text:f[y]});C.onclick=()=>{m.has(y)?m.delete(y):m.add(y),C.toggleClass("active",m.has(y)),w()}}let g=e.createDiv({cls:"af-form-row af-schedule-dom-row"});g.createDiv({cls:"af-form-label",text:"Day of month"});let v=g.createEl("select",{cls:"af-form-select af-form-select-sm"});for(let y=1;y<=28;y++){let C=v.createEl("option",{text:String(y),attr:{value:String(y)}});y===n.dayOfMonth&&(C.selected=!0)}let k=()=>{let y=r.value,C=["daily","weekdays","weekly","monthly"].includes(y),T=y==="weekly",_=y==="monthly";c.style.display=C?"":"none",u.style.display=T?"":"none",g.style.display=_?"":"none"},w=()=>{let y=r.value,C=d.value,T=h.value,_="";switch(y){case"every_5m":_="*/5 * * * *";break;case"every_15m":_="*/15 * * * *";break;case"every_30m":_="*/30 * * * *";break;case"every_hour":_="0 * * * *";break;case"every_2h":_="0 */2 * * *";break;case"daily":_=`${T} ${C} * * *`;break;case"weekdays":_=`${T} ${C} * * 1-5`;break;case"weekly":{let O=Array.from(m).sort().join(",")||"1";_=`${T} ${C} * * ${O}`;break}case"monthly":_=`${T} ${C} ${v.value} * *`;break}s.schedule=_,s.type="recurring"};r.addEventListener("change",()=>{k(),w()}),d.addEventListener("change",w),h.addEventListener("change",w),v.addEventListener("change",w),k()}renderHeartbeatSchedule(e,s){let n=this.parseCronComponents(s.heartbeatSchedule),a=e.createDiv({cls:"af-form-row"});a.createDiv({cls:"af-form-label",text:"Frequency"});let r=a.createEl("select",{cls:"af-form-select"}),o=[["every_5m","Every 5 minutes"],["every_15m","Every 15 minutes"],["every_30m","Every 30 minutes"],["every_hour","Every hour"],["every_2h","Every 2 hours"],["every_4h","Every 4 hours"],["every_6h","Every 6 hours"],["every_12h","Every 12 hours"],["daily","Once a day"]],c="every_hour",l={"*/5 * * * *":"every_5m","*/15 * * * *":"every_15m","*/30 * * * *":"every_30m","0 * * * *":"every_hour","0 */2 * * *":"every_2h","0 */4 * * *":"every_4h","0 */6 * * *":"every_6h","0 */12 * * *":"every_12h"};l[s.heartbeatSchedule]?c=l[s.heartbeatSchedule]:(n.freq==="daily"||n.freq==="weekdays")&&(c="daily");for(let[g,v]of o){let k=r.createEl("option",{text:v,attr:{value:g}});g===c&&(k.selected=!0)}let d=e.createDiv({cls:"af-form-row af-schedule-time-row"});d.createDiv({cls:"af-form-label",text:"Time"});let h=d.createDiv({cls:"af-schedule-time-selects"}),u=h.createEl("select",{cls:"af-form-select af-form-select-sm"});for(let g=0;g<24;g++){let v=g>=12?"PM":"AM",k=g===0?12:g>12?g-12:g,w=u.createEl("option",{text:`${k} ${v}`,attr:{value:String(g)}});g===n.hour&&(w.selected=!0)}h.createSpan({cls:"af-schedule-colon",text:":"});let p=h.createEl("select",{cls:"af-form-select af-form-select-sm"});for(let g=0;g<60;g+=5){let v=p.createEl("option",{text:String(g).padStart(2,"0"),attr:{value:String(g)}});g===n.minute&&(v.selected=!0)}let f=()=>{d.style.display=r.value==="daily"?"":"none"},m=()=>{let g=r.value,v=u.value,k=p.value;switch(g){case"every_5m":s.heartbeatSchedule="*/5 * * * *";break;case"every_15m":s.heartbeatSchedule="*/15 * * * *";break;case"every_30m":s.heartbeatSchedule="*/30 * * * *";break;case"every_hour":s.heartbeatSchedule="0 * * * *";break;case"every_2h":s.heartbeatSchedule="0 */2 * * *";break;case"every_4h":s.heartbeatSchedule="0 */4 * * *";break;case"every_6h":s.heartbeatSchedule="0 */6 * * *";break;case"every_12h":s.heartbeatSchedule="0 */12 * * *";break;case"daily":s.heartbeatSchedule=`${k} ${v} * * *`;break}};r.addEventListener("change",()=>{f(),m()}),u.addEventListener("change",m),p.addEventListener("change",m),f()}parseCronComponents(e){let s={freq:"daily",hour:9,minute:0,days:[1],dayOfMonth:1};if(!e?.trim())return s;let n={"*/5 * * * *":"every_5m","*/15 * * * *":"every_15m","*/30 * * * *":"every_30m","0 * * * *":"every_hour","0 */2 * * *":"every_2h"};if(n[e])return{...s,freq:n[e]};let a=e.trim().split(/\s+/);if(a.length!==5)return s;let[r,o,c,,l]=a,d=parseInt(o??"9",10),h=parseInt(r??"0",10);if(c==="*"&&l==="*")return{...s,freq:"daily",hour:d,minute:h};if(c==="*"&&l==="1-5")return{...s,freq:"weekdays",hour:d,minute:h};if(c==="*"&&l!=="*"){let u=(l??"1").split(",").map(p=>parseInt(p,10));return{...s,freq:"weekly",hour:d,minute:h,days:u}}return l==="*"&&c!=="*"?{...s,freq:"monthly",hour:d,minute:h,dayOfMonth:parseInt(c??"1",10)}:{...s,hour:d,minute:h}}humanizeCron(e){let s={"*/5 * * * *":"Every 5 minutes","*/10 * * * *":"Every 10 minutes","*/15 * * * *":"Every 15 minutes","*/30 * * * *":"Every 30 minutes","0 * * * *":"Every hour","0 */2 * * *":"Every 2 hours"};if(s[e])return s[e];let n=e.toLowerCase().trim();if(n.startsWith("every ")||n.startsWith("daily ")||n==="daily")return e;if(n.startsWith("hourly"))return"Every hour";if(n.startsWith("weekdays")||n.startsWith("weekly")||n.startsWith("monthly"))return e;let a=e.trim().split(/\s+/);if(a.length!==5)return e;let[r,o,c,,l]=a,d=(p,f)=>{let m=parseInt(p??"0",10),g=parseInt(f??"0",10),v=m>=12?"PM":"AM",k=m===0?12:m>12?m-12:m;return g===0?`${k} ${v}`:`${k}:${String(g).padStart(2,"0")} ${v}`},h=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],u=p=>p==="1-5"?"weekdays":p==="0,6"?"weekends":p.split(",").map(m=>parseInt(m,10)).map(m=>h[m]??m).join(", ");return o==="*"&&c==="*"&&l==="*"?r==="*"?"Every minute":`Every hour at :${String(r).padStart(2,"0")}`:c==="*"&&l==="*"&&o!=="*"?`Daily at ${d(o??"0",r??"0")}`:c==="*"&&l==="1-5"&&o!=="*"?`Weekdays at ${d(o??"0",r??"0")}`:c==="*"&&l!=="*"&&o!=="*"?`${u(l??"1")} at ${d(o??"0",r??"0")}`:l==="*"&&c!=="*"&&o!=="*"?`Monthly on the ${c} at ${d(o??"0",r??"0")}`:e}getTagClass(e){return e==="monitoring"?"monitoring":e==="devops"?"devops":e==="sample"?"sample":"default"}renderCreateAgentPage(e){let s=e.createDiv({cls:"af-create-agent-page"}),n=s.createDiv({cls:"af-detail-header"}),a=n.createDiv({cls:"af-detail-header-left"}),r=a.createDiv({cls:"af-agent-card-avatar idle"});(0,b.setIcon)(r,"plus");let o=a.createDiv();o.createDiv({cls:"af-detail-header-name",text:"Create New Agent"}),o.createDiv({cls:"af-detail-header-desc",text:"Configure a new agent for your fleet"});let c=n.createDiv({cls:"af-detail-header-actions"}),l={name:"",description:"",avatar:"",tags:"",systemPrompt:"",model:"default",adapter:"claude-code",cwd:"",timeout:300,permissionMode:"bypassPermissions",effort:"",selectedSkills:new Set,selectedMcpServers:new Set,skillsBody:"",contextBody:"",approvalRequired:"",memory:!0,enabled:!0,allowedCommands:"",blockedCommands:"",heartbeatEnabled:!1,heartbeatSchedule:"0 */6 * * *",heartbeatBody:"",heartbeatNotify:!0,heartbeatChannel:"",autoCompactThreshold:85,wikiReferences:[]},d={none:{label:"None",prompt:""},coding:{label:"Coding Agent",prompt:`You are a coding agent. Review code, write tests, fix bugs, and implement features.
12017
+ *Truncated (${(y.length/1024).toFixed(0)} KB total). Open the run note for full content.*`:y,f=!!(e.finalResult&&e.finalResult.trim()),g=e.output?.trim()??"",v=f&&g.length>0&&g!==e.finalResult.trim();if(f){let y=o.createDiv({cls:"af-slideover-section"});y.createDiv({cls:"af-slideover-section-title",text:"OUTPUT"});let S=y.createDiv({cls:"af-output-block af-compact-md"});if(w.MarkdownRenderer.render(this.app,m(e.finalResult),S,"",this),v){let T=y.createEl("details",{cls:"af-run-transcript"}),_=T.createEl("summary");(0,w.setIcon)(_.createSpan({cls:"af-run-transcript-icon"}),"file-text"),_.createSpan({text:"Show full transcript"}),_.createSpan({cls:"af-run-transcript-meta"}).setText(`${(g.length/1024).toFixed(1)} KB`);let M=T.createDiv({cls:"af-output-block af-compact-md af-run-transcript-body"});w.MarkdownRenderer.render(this.app,m(g),M,"",this)}}else if(g){let y=o.createDiv({cls:"af-slideover-section"});y.createDiv({cls:"af-slideover-section-title",text:"OUTPUT"});let S=y.createDiv({cls:"af-output-block af-compact-md"});w.MarkdownRenderer.render(this.app,m(g),S,"",this)}if(e.toolsUsed.length>0){let y=o.createDiv({cls:"af-slideover-section"});y.createDiv({cls:"af-slideover-section-title",text:"TOOLS USED"}),y.createDiv({cls:"af-output-block",text:e.toolsUsed.join(`
12018
+ `)})}let b=o.createDiv({cls:"af-slideover-actions"});if(e.filePath){let y=b.createEl("button",{cls:"af-btn-sm"});E(y,"external-link","af-btn-icon"),y.appendText(" Open Run Note"),y.onclick=()=>void this.plugin.openPath(e.filePath)}let k=b.createEl("button",{cls:"af-btn-sm primary"});E(k,"refresh-cw","af-btn-icon"),k.appendText(" Re-run Task"),k.onclick=()=>void this.plugin.runAgentPrompt(e.agent),s.onclick=y=>{y.target===s&&s.remove()}}renderDetailRow(e,s,n){let a=e.createDiv({cls:"af-detail-row"});a.createSpan({cls:"af-detail-label",text:s}),a.createSpan({cls:"af-detail-value af-mono",text:n})}renderEmptyState(e,s,n,a){let r=e.createDiv({cls:"af-empty-state"}),o=r.createDiv({cls:"af-empty-icon"});(0,w.setIcon)(o,s),r.createDiv({cls:"af-empty-label",text:n}),a&&r.createDiv({cls:"af-empty-sublabel",text:a})}healthToClass(e){switch(e){case"running":return"running";case"error":return"error";case"pending":return"pending";case"disabled":return"disabled";default:return"idle"}}statusToTimelineClass(e){switch(e){case"success":return"success";case"failure":case"timeout":return"error";case"cancelled":return"warning";case"pending_approval":return"pending";default:return"running"}}statusToIconName(e){switch(e){case"success":return"check-circle-2";case"failure":return"x-circle";case"timeout":return"clock";case"pending_approval":return"shield-check";case"cancelled":return"square";default:return"loader-2"}}statusToBadgeClass(e){switch(e){case"success":return"success";case"failure":return"failure";case"timeout":return"timeout";case"pending_approval":return"pending";case"cancelled":return"cancelled";default:return"running"}}statusToBadgeText(e){switch(e){case"success":return"Success";case"failure":return"Failed";case"timeout":return"Timeout";case"pending_approval":return"Pending";case"cancelled":return"Cancelled";case"interrupted":return"Interrupted";default:return e}}formatDuration(e){if(e<60)return`${e}s`;let s=Math.floor(e/60),n=e%60;return n>0?`${s}m ${n}s`:`${s}m`}formatStarted(e){try{let s=new Date(e),n=new Date;if(s.toDateString()===n.toDateString())return s.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"});let a=new Date(n);return a.setDate(a.getDate()-1),s.toDateString()===a.toDateString()?`Yesterday ${s.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}`:s.toLocaleDateString([],{month:"short",day:"numeric"})+` ${s.toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}`}catch{return e}}formatNextRun(e){try{let s=new Date(e),n=new Date,a=s.getTime()-n.getTime();if(a<0)return"overdue";let r=Math.round(a/6e4);if(r<60)return`${r}m`;let o=Math.round(r/60);return o<24?`${o}h`:s.toLocaleDateString([],{month:"short",day:"numeric"})}catch{return e}}getNextTaskLabel(e){let n=e.map(r=>r.nextRun).filter(Boolean).sort()[0];return n?`${e.find(r=>r.nextRun===n)?.agent??"unknown"} in ${this.formatNextRun(n)}`:"none"}getInitials(e){return e.split("-").map(s=>s[0]?.toUpperCase()??"").slice(0,2).join("")}renderAgentAvatar(e,s){let n=s.avatar?.trim();if(!n){(0,w.setIcon)(e,"bot");return}/^[a-z][a-z0-9-]*$/.test(n)?(0,w.setIcon)(e,n):e.setText(n)}getSkillIcon(e){return e.includes("git")?"settings":e.includes("summarize")||e.includes("log")?"activity":e.includes("review")||e.includes("check")?"check-circle-2":e.includes("vault")||e.includes("note")?"file-text":"puzzle"}renderInlineSchedule(e,s){let n=this.parseCronComponents(s.schedule),a=e.createDiv({cls:"af-form-row"});a.createDiv({cls:"af-form-label",text:"Frequency"});let r=a.createEl("select",{cls:"af-form-select"}),o=[["every_5m","Every 5 minutes"],["every_15m","Every 15 minutes"],["every_30m","Every 30 minutes"],["every_hour","Every hour"],["every_2h","Every 2 hours"],["daily","Daily"],["weekdays","Weekdays"],["weekly","Weekly"],["monthly","Monthly"]];for(let[y,S]of o){let T=r.createEl("option",{text:S,attr:{value:y}});y===n.freq&&(T.selected=!0)}let c=e.createDiv({cls:"af-form-row af-schedule-time-row"});c.createDiv({cls:"af-form-label",text:"Time"});let l=c.createDiv({cls:"af-schedule-time-selects"}),h=l.createEl("select",{cls:"af-form-select af-form-select-sm"});for(let y=0;y<24;y++){let S=y>=12?"PM":"AM",T=y===0?12:y>12?y-12:y,_=h.createEl("option",{text:`${T} ${S}`,attr:{value:String(y)}});y===n.hour&&(_.selected=!0)}l.createSpan({cls:"af-schedule-colon",text:":"});let d=l.createEl("select",{cls:"af-form-select af-form-select-sm"});for(let y=0;y<60;y+=5){let S=d.createEl("option",{text:String(y).padStart(2,"0"),attr:{value:String(y)}});y===n.minute&&(S.selected=!0)}let u=e.createDiv({cls:"af-form-row af-schedule-day-row"});u.createDiv({cls:"af-form-label",text:"Day"});let p=u.createDiv({cls:"af-schedule-day-buttons"}),m=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],f=new Set(n.days);for(let y=0;y<7;y++){let S=p.createEl("button",{cls:`af-schedule-day-btn${f.has(y)?" active":""}`,text:m[y]});S.onclick=()=>{f.has(y)?f.delete(y):f.add(y),S.toggleClass("active",f.has(y)),k()}}let g=e.createDiv({cls:"af-form-row af-schedule-dom-row"});g.createDiv({cls:"af-form-label",text:"Day of month"});let v=g.createEl("select",{cls:"af-form-select af-form-select-sm"});for(let y=1;y<=28;y++){let S=v.createEl("option",{text:String(y),attr:{value:String(y)}});y===n.dayOfMonth&&(S.selected=!0)}let b=()=>{let y=r.value,S=["daily","weekdays","weekly","monthly"].includes(y),T=y==="weekly",_=y==="monthly";c.setCssStyles({display:S?"":"none"}),u.setCssStyles({display:T?"":"none"}),g.setCssStyles({display:_?"":"none"})},k=()=>{let y=r.value,S=h.value,T=d.value,_="";switch(y){case"every_5m":_="*/5 * * * *";break;case"every_15m":_="*/15 * * * *";break;case"every_30m":_="*/30 * * * *";break;case"every_hour":_="0 * * * *";break;case"every_2h":_="0 */2 * * *";break;case"daily":_=`${T} ${S} * * *`;break;case"weekdays":_=`${T} ${S} * * 1-5`;break;case"weekly":{let D=Array.from(f).sort().join(",")||"1";_=`${T} ${S} * * ${D}`;break}case"monthly":_=`${T} ${S} ${v.value} * *`;break}s.schedule=_,s.type="recurring"};r.addEventListener("change",()=>{b(),k()}),h.addEventListener("change",k),d.addEventListener("change",k),v.addEventListener("change",k),b()}renderHeartbeatSchedule(e,s){let n=this.parseCronComponents(s.heartbeatSchedule),a=e.createDiv({cls:"af-form-row"});a.createDiv({cls:"af-form-label",text:"Frequency"});let r=a.createEl("select",{cls:"af-form-select"}),o=[["every_5m","Every 5 minutes"],["every_15m","Every 15 minutes"],["every_30m","Every 30 minutes"],["every_hour","Every hour"],["every_2h","Every 2 hours"],["every_4h","Every 4 hours"],["every_6h","Every 6 hours"],["every_12h","Every 12 hours"],["daily","Once a day"]],c="every_hour",l={"*/5 * * * *":"every_5m","*/15 * * * *":"every_15m","*/30 * * * *":"every_30m","0 * * * *":"every_hour","0 */2 * * *":"every_2h","0 */4 * * *":"every_4h","0 */6 * * *":"every_6h","0 */12 * * *":"every_12h"};l[s.heartbeatSchedule]?c=l[s.heartbeatSchedule]:(n.freq==="daily"||n.freq==="weekdays")&&(c="daily");for(let[g,v]of o){let b=r.createEl("option",{text:v,attr:{value:g}});g===c&&(b.selected=!0)}let h=e.createDiv({cls:"af-form-row af-schedule-time-row"});h.createDiv({cls:"af-form-label",text:"Time"});let d=h.createDiv({cls:"af-schedule-time-selects"}),u=d.createEl("select",{cls:"af-form-select af-form-select-sm"});for(let g=0;g<24;g++){let v=g>=12?"PM":"AM",b=g===0?12:g>12?g-12:g,k=u.createEl("option",{text:`${b} ${v}`,attr:{value:String(g)}});g===n.hour&&(k.selected=!0)}d.createSpan({cls:"af-schedule-colon",text:":"});let p=d.createEl("select",{cls:"af-form-select af-form-select-sm"});for(let g=0;g<60;g+=5){let v=p.createEl("option",{text:String(g).padStart(2,"0"),attr:{value:String(g)}});g===n.minute&&(v.selected=!0)}let m=()=>{h.setCssStyles({display:r.value==="daily"?"":"none"})},f=()=>{let g=r.value,v=u.value,b=p.value;switch(g){case"every_5m":s.heartbeatSchedule="*/5 * * * *";break;case"every_15m":s.heartbeatSchedule="*/15 * * * *";break;case"every_30m":s.heartbeatSchedule="*/30 * * * *";break;case"every_hour":s.heartbeatSchedule="0 * * * *";break;case"every_2h":s.heartbeatSchedule="0 */2 * * *";break;case"every_4h":s.heartbeatSchedule="0 */4 * * *";break;case"every_6h":s.heartbeatSchedule="0 */6 * * *";break;case"every_12h":s.heartbeatSchedule="0 */12 * * *";break;case"daily":s.heartbeatSchedule=`${b} ${v} * * *`;break}};r.addEventListener("change",()=>{m(),f()}),u.addEventListener("change",f),p.addEventListener("change",f),m()}parseCronComponents(e){let s={freq:"daily",hour:9,minute:0,days:[1],dayOfMonth:1};if(!e?.trim())return s;let n={"*/5 * * * *":"every_5m","*/15 * * * *":"every_15m","*/30 * * * *":"every_30m","0 * * * *":"every_hour","0 */2 * * *":"every_2h"};if(n[e])return{...s,freq:n[e]};let a=e.trim().split(/\s+/);if(a.length!==5)return s;let[r,o,c,,l]=a,h=parseInt(o??"9",10),d=parseInt(r??"0",10);if(c==="*"&&l==="*")return{...s,freq:"daily",hour:h,minute:d};if(c==="*"&&l==="1-5")return{...s,freq:"weekdays",hour:h,minute:d};if(c==="*"&&l!=="*"){let u=(l??"1").split(",").map(p=>parseInt(p,10));return{...s,freq:"weekly",hour:h,minute:d,days:u}}return l==="*"&&c!=="*"?{...s,freq:"monthly",hour:h,minute:d,dayOfMonth:parseInt(c??"1",10)}:{...s,hour:h,minute:d}}humanizeCron(e){let s={"*/5 * * * *":"Every 5 minutes","*/10 * * * *":"Every 10 minutes","*/15 * * * *":"Every 15 minutes","*/30 * * * *":"Every 30 minutes","0 * * * *":"Every hour","0 */2 * * *":"Every 2 hours"};if(s[e])return s[e];let n=e.toLowerCase().trim();if(n.startsWith("every ")||n.startsWith("daily ")||n==="daily")return e;if(n.startsWith("hourly"))return"Every hour";if(n.startsWith("weekdays")||n.startsWith("weekly")||n.startsWith("monthly"))return e;let a=e.trim().split(/\s+/);if(a.length!==5)return e;let[r,o,c,,l]=a,h=(p,m)=>{let f=parseInt(p??"0",10),g=parseInt(m??"0",10),v=f>=12?"PM":"AM",b=f===0?12:f>12?f-12:f;return g===0?`${b} ${v}`:`${b}:${String(g).padStart(2,"0")} ${v}`},d=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],u=p=>p==="1-5"?"weekdays":p==="0,6"?"weekends":p.split(",").map(f=>parseInt(f,10)).map(f=>d[f]??f).join(", ");return o==="*"&&c==="*"&&l==="*"?r==="*"?"Every minute":`Every hour at :${String(r).padStart(2,"0")}`:c==="*"&&l==="*"&&o!=="*"?`Daily at ${h(o??"0",r??"0")}`:c==="*"&&l==="1-5"&&o!=="*"?`Weekdays at ${h(o??"0",r??"0")}`:c==="*"&&l!=="*"&&o!=="*"?`${u(l??"1")} at ${h(o??"0",r??"0")}`:l==="*"&&c!=="*"&&o!=="*"?`Monthly on the ${c} at ${h(o??"0",r??"0")}`:e}getTagClass(e){return e==="monitoring"?"monitoring":e==="devops"?"devops":e==="sample"?"sample":"default"}renderCreateAgentPage(e){let s=e.createDiv({cls:"af-create-agent-page"}),n=s.createDiv({cls:"af-detail-header"}),a=n.createDiv({cls:"af-detail-header-left"}),r=a.createDiv({cls:"af-agent-card-avatar idle"});(0,w.setIcon)(r,"plus");let o=a.createDiv();o.createDiv({cls:"af-detail-header-name",text:"Create New Agent"}),o.createDiv({cls:"af-detail-header-desc",text:"Configure a new agent for your fleet"});let c=n.createDiv({cls:"af-detail-header-actions"}),l={name:"",description:"",avatar:"",tags:"",systemPrompt:"",model:"default",adapter:"claude-code",cwd:"",timeout:300,permissionMode:"bypassPermissions",effort:"",selectedSkills:new Set,selectedMcpServers:new Set,skillsBody:"",contextBody:"",approvalRequired:"",memory:!0,enabled:!0,allowedCommands:"",blockedCommands:"",heartbeatEnabled:!1,heartbeatSchedule:"0 */6 * * *",heartbeatBody:"",heartbeatNotify:!0,heartbeatChannel:"",autoCompactThreshold:85,wikiReferences:[]},h={none:{label:"None",prompt:""},coding:{label:"Coding Agent",prompt:`You are a coding agent. Review code, write tests, fix bugs, and implement features.
12019
12019
  Follow existing code conventions. Write clean, well-tested code.
12020
12020
  If something is unclear, ask for clarification instead of guessing.`},monitor:{label:"Monitor",prompt:`You are a monitoring agent. Check system status, alert on failures, and report on health metrics.
12021
12021
  Be concise and factual. Highlight anomalies clearly.
@@ -12023,13 +12023,13 @@ Include timestamps and relevant context in all reports.`},briefing:{label:"Brief
12023
12023
  Prioritize recent and important changes. Keep summaries concise.
12024
12024
  End with explicit next actions if they exist.`},reviewer:{label:"Code Reviewer",prompt:`You are a code review agent. Analyze pull requests, suggest improvements, and flag potential issues.
12025
12025
  Focus on correctness, security, and maintainability.
12026
- Be specific \u2014 reference file names and line numbers.`}},h=s.createDiv({cls:"af-create-form"}),u=h.createDiv({cls:"af-create-section"}),p=u.createDiv({cls:"af-create-section-header"}),f=p.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(f,"user"),p.createSpan({text:"Identity"}),this.createFormField(u,"Name","deploy-watcher","Unique identifier (will be slugified)",B=>{l.name=B}),this.createFormField(u,"Description","Monitors deployments and reports status","",B=>{l.description=B});let m=u.createDiv({cls:"af-form-row"});m.createDiv({cls:"af-form-label",text:"Avatar"});let g=m.createEl("input",{cls:"af-form-input af-form-input-sm",attr:{type:"text",placeholder:"\u{1F6E1}\uFE0F"}});g.addEventListener("input",()=>{l.avatar=g.value}),this.createFormField(u,"Tags","devops, monitoring","Comma-separated",B=>{l.tags=B});let v=u.createDiv({cls:"af-form-row af-form-row-toggle"});v.createDiv({cls:"af-form-label",text:"Enabled"});let k=v.createDiv({cls:"af-agent-card-toggle on"});k.onclick=()=>{let B=k.hasClass("on");k.toggleClass("on",!B),l.enabled=!B};let w=h.createDiv({cls:"af-create-section"}),y=w.createDiv({cls:"af-create-section-header"}),C=y.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(C,"message-square"),y.createSpan({text:"System Prompt"});let T=w.createDiv({cls:"af-form-row"});T.createDiv({cls:"af-form-label",text:"Template"});let _=T.createEl("select",{cls:"af-form-select"});for(let[B,{label:K}]of Object.entries(d))_.createEl("option",{text:K,attr:{value:B}});let O=w.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"You are a deployment monitoring agent...",rows:"10"}});O.addEventListener("input",()=>{l.systemPrompt=O.value}),_.addEventListener("change",()=>{let B=d[_.value];B&&_.value!=="none"&&(l.systemPrompt=B.prompt,O.value=B.prompt)});let E=h.createDiv({cls:"af-create-section"}),S=E.createDiv({cls:"af-create-section-header"}),P=S.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(P,"settings"),S.createSpan({text:"Runtime Config"});let R=E.createDiv({cls:"af-create-config-grid"}),N=R.createDiv({cls:"af-form-row"});N.createDiv({cls:"af-form-label",text:"Adapter"});let L=N.createEl("select",{cls:"af-form-select"});for(let[B,K,Ee]of Io){let ve=L.createEl("option",{text:K,attr:{value:B,...Ee?{disabled:"true"}:{}}});B==="claude-code"&&(ve.selected=!0)}let G=R.createDiv({cls:"af-form-row"}),U=G.createDiv({cls:"af-form-label",text:"Model"});this.addTooltip(U,`Aliases (opus/sonnet/haiku/opusplan) work on any backend. Choose Custom\u2026 for a pinned ID or Bedrock/Vertex/Foundry. Blank = use Settings default (${this.plugin.settings.defaultModel||"CLI default"}).`);let X=G.createDiv({cls:"af-form-field-wrap"}),me=()=>{At(X,{value:l.model,adapter:l.adapter,onChange:B=>{l.model=B}})};me();let ye=()=>{};L.addEventListener("change",()=>{l.adapter=L.value,(Rs(l.adapter)?Ys:Ks).some(K=>K.value===l.model.trim())&&(l.model=""),me(),l.permissionMode=Un(l.permissionMode,l.adapter),ye()});let ee=R.createDiv({cls:"af-form-row"});ee.createDiv({cls:"af-form-label",text:"Working Dir"});let W=ee.createEl("input",{cls:"af-form-input",attr:{type:"text",placeholder:"Leave empty for vault root"}});W.addEventListener("input",()=>{l.cwd=W.value});let de=R.createDiv({cls:"af-form-row"});de.createDiv({cls:"af-form-label",text:"Timeout (sec)"});let V=de.createEl("input",{cls:"af-form-input af-form-input-sm",attr:{type:"number",value:"300"}});V.addEventListener("input",()=>{let B=parseInt(V.value,10);!isNaN(B)&&B>0&&(l.timeout=B)});let te=R.createDiv({cls:"af-form-row"});te.createDiv({cls:"af-form-label",text:"Permission Mode"});let Y=te.createEl("select",{cls:"af-form-select"}),Z=R.createDiv({cls:"af-form-hint",text:""});ye=()=>{l.permissionMode=Un(l.permissionMode,l.adapter);let B=Bn(l.adapter);Y.empty();for(let[K,Ee]of B){let ve=Y.createEl("option",{text:Ee,attr:{value:K}});K===l.permissionMode&&(ve.selected=!0)}Z.textContent=B.find(([K])=>K===Y.value)?.[2]??""},ye(),Y.addEventListener("change",()=>{l.permissionMode=Y.value,Z.textContent=Bn(l.adapter).find(([B])=>B===Y.value)?.[2]??""});let j=R.createDiv({cls:"af-form-row"});j.createDiv({cls:"af-form-label",text:"Effort Level"});let fe=j.createEl("select",{cls:"af-form-select"});for(let[B,K]of[["","Default"],["low","Low"],["medium","Medium"],["high","High"],["max","Max"]])fe.createEl("option",{text:K,attr:{value:B}});fe.addEventListener("change",()=>{l.effort=fe.value}),R.createDiv({cls:"af-form-hint",text:"Controls reasoning depth \u2014 low is fast, max is most thorough"});let Pe=R.createDiv({cls:"af-form-row"}),Oe=Pe.createDiv({cls:"af-form-label",text:"Auto-compact at"});this.addTooltip(Oe,"Percent of context window at which the chat auto-invokes /compact before the next message. 85% is a good default. Set 0 to disable.");let Ue=Pe.createEl("input",{cls:"af-form-input af-form-input-sm",attr:{type:"number",min:"0",max:"100",value:String(l.autoCompactThreshold)}});Ue.addEventListener("input",()=>{let B=parseInt(Ue.value,10);!isNaN(B)&&B>=0&&B<=100&&(l.autoCompactThreshold=B)}),R.createDiv({cls:"af-form-hint",text:"0 disables auto-compact"});{let B=this.plugin.runtime.getSnapshot().agents.filter(K=>K.wikiKeeper!==void 0);if(B.length>0){let K=R.createDiv({cls:"af-form-row af-form-row-toggle"}),Ee=K.createDiv({cls:"af-form-label",text:"Wiki access"});this.addTooltip(Ee,"Lets this agent read + cite from the selected Wiki Keeper scopes (requires the wiki-query skill).");let ve=K.createDiv({cls:"af-form-field-wrap"});for(let Ae of B){let tt=ve.createEl("label",{cls:"af-form-checkbox-row"}),We=tt.createEl("input",{attr:{type:"checkbox"}});tt.createSpan({text:` ${Ae.name}`,cls:"af-form-checkbox-label"}),We.addEventListener("change",()=>{We.checked?l.wikiReferences.includes(Ae.name)||l.wikiReferences.push(Ae.name):l.wikiReferences=l.wikiReferences.filter(St=>St!==Ae.name)})}}}{let B=h.createDiv({cls:"af-create-section"}),K=B.createDiv({cls:"af-create-section-header"}),Ee=K.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(Ee,"heart-pulse");let ve=K.createSpan({text:"Heartbeat"});this.addTooltip(ve,"Autonomous periodic run \u2014 what the agent does when no one is asking");let Ae=B.createDiv({cls:"af-form-row af-form-row-toggle"});Ae.createDiv({cls:"af-form-label",text:"Enabled"});let tt=Ae.createDiv({cls:"af-agent-card-toggle"}),We=B.createDiv();We.style.display="none",tt.onclick=()=>{let ke=tt.hasClass("on");tt.toggleClass("on",!ke),l.heartbeatEnabled=!ke,We.style.display=ke?"none":""},this.renderHeartbeatSchedule(We,l);let St=We.createDiv({cls:"af-form-row af-form-row-toggle"}),Ot=St.createDiv({cls:"af-form-label"});Ot.setText("Notify"),this.addTooltip(Ot,"Show an Obsidian notice when the heartbeat completes");let yt=St.createDiv({cls:"af-agent-card-toggle on"});yt.onclick=()=>{let ke=yt.hasClass("on");yt.toggleClass("on",!ke),l.heartbeatNotify=!ke};let os=this.plugin.runtime.getSnapshot(),Ms=We.createDiv({cls:"af-form-row"}),Nt=Ms.createDiv({cls:"af-form-label"});Nt.setText("Post to channel"),this.addTooltip(Nt,"Heartbeat results are posted to this Slack channel when the run completes");let M=Ms.createEl("select",{cls:"af-form-select"});M.createEl("option",{text:"(none)",attr:{value:""}});for(let ke of os.channels)M.createEl("option",{text:ke.name,attr:{value:ke.name}});M.addEventListener("change",()=>{l.heartbeatChannel=M.value});let J=We.createDiv({cls:"af-form-label"});J.style.width="auto",J.style.marginTop="12px",J.setText("Instruction"),this.addTooltip(J,'What the agent does on each heartbeat. Also used by the "Run Now" button.');let Te=We.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"Check status, scan for issues, report findings...",rows:"8"}});Te.addEventListener("input",()=>{l.heartbeatBody=Te.value})}let Re=h.createDiv({cls:"af-create-section"}),Se=Re.createDiv({cls:"af-create-section-header"}),De=Se.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(De,"puzzle"),Se.createSpan({text:"Skills"});let Ne=this.plugin.runtime.getSnapshot();if(Ne.skills.length>0){Re.createDiv({cls:"af-form-sublabel",text:"Shared Skills"});let B=Re.createDiv({cls:"af-create-skills-grid"});for(let K of Ne.skills){let Ee=B.createDiv({cls:"af-create-skill-item"}),ve=Ee.createEl("input",{cls:"af-form-toggle",attr:{type:"checkbox"}});ve.addEventListener("change",()=>{ve.checked?l.selectedSkills.add(K.name):l.selectedSkills.delete(K.name)});let Ae=Ee.createDiv({cls:"af-create-skill-label"});Ae.createSpan({cls:"af-create-skill-name",text:K.name}),K.description&&Ae.createSpan({cls:"af-create-skill-desc",text:` \u2014 ${K.description}`})}}let $e=Re.createDiv({cls:"af-form-sublabel"});$e.setText("Agent-specific skills"),this.addTooltip($e,"Custom skills/instructions only for this agent, not shared with others");let q=Re.createEl("textarea",{cls:"af-create-textarea",attr:{placeholder:"Custom skills/instructions for this agent...",rows:"4"}});q.addEventListener("input",()=>{l.skillsBody=q.value});{let B=h.createDiv({cls:"af-create-section"}),K=B.createDiv({cls:"af-create-section-header"}),Ee=K.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(Ee,"plug");let ve=K.createSpan({text:"MCP Servers"});this.addTooltip(ve,"Grant agent access to MCP servers"),this.renderAgentMcpPicker(B,l.selectedMcpServers)}let ie=h.createDiv({cls:"af-create-section"}),$=ie.createDiv({cls:"af-create-section-header"}),Ce=$.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(Ce,"file-text");let we=$.createSpan({text:"Context"});this.addTooltip(we,"Project-specific context included in every run");let ge=ie.createEl("textarea",{cls:"af-create-textarea",attr:{placeholder:"Background info, repo structure, conventions...",rows:"4"}});ge.addEventListener("input",()=>{l.contextBody=ge.value});let Ie=h.createDiv({cls:"af-create-section"}),se=Ie.createDiv({cls:"af-create-section-header"}),I=se.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(I,"shield-check"),se.createSpan({text:"Permissions"}),this.createFormField(Ie,"Approval required","git_push, file_delete","Comma-separated tool names",B=>{l.approvalRequired=B});let ne=Ie.createDiv({cls:"af-form-row"});ne.createDiv({cls:"af-form-label",text:"Allowed Commands"});let he=ne.createEl("textarea",{cls:"af-create-textarea",attr:{placeholder:`Bash(curl *)
12026
+ Be specific \u2014 reference file names and line numbers.`}},d=s.createDiv({cls:"af-create-form"}),u=d.createDiv({cls:"af-create-section"}),p=u.createDiv({cls:"af-create-section-header"}),m=p.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(m,"user"),p.createSpan({text:"Identity"}),this.createFormField(u,"Name","deploy-watcher","Unique identifier (will be slugified)",B=>{l.name=B}),this.createFormField(u,"Description","Monitors deployments and reports status","",B=>{l.description=B});let f=u.createDiv({cls:"af-form-row"});f.createDiv({cls:"af-form-label",text:"Avatar"});let g=f.createEl("input",{cls:"af-form-input af-form-input-sm",attr:{type:"text",placeholder:"\u{1F6E1}\uFE0F"}});g.addEventListener("input",()=>{l.avatar=g.value}),this.createFormField(u,"Tags","devops, monitoring","Comma-separated",B=>{l.tags=B});let v=u.createDiv({cls:"af-form-row af-form-row-toggle"});v.createDiv({cls:"af-form-label",text:"Enabled"});let b=v.createDiv({cls:"af-agent-card-toggle on"});b.onclick=()=>{let B=b.hasClass("on");b.toggleClass("on",!B),l.enabled=!B};let k=d.createDiv({cls:"af-create-section"}),y=k.createDiv({cls:"af-create-section-header"}),S=y.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(S,"message-square"),y.createSpan({text:"System Prompt"});let T=k.createDiv({cls:"af-form-row"});T.createDiv({cls:"af-form-label",text:"Template"});let _=T.createEl("select",{cls:"af-form-select"});for(let[B,{label:V}]of Object.entries(h))_.createEl("option",{text:V,attr:{value:B}});let D=k.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"You are a deployment monitoring agent...",rows:"10"}});D.addEventListener("input",()=>{l.systemPrompt=D.value}),_.addEventListener("change",()=>{let B=h[_.value];B&&_.value!=="none"&&(l.systemPrompt=B.prompt,D.value=B.prompt)});let M=d.createDiv({cls:"af-create-section"}),C=M.createDiv({cls:"af-create-section-header"}),I=C.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(I,"settings"),C.createSpan({text:"Runtime Config"});let P=M.createDiv({cls:"af-create-config-grid"}),L=P.createDiv({cls:"af-form-row"});L.createDiv({cls:"af-form-label",text:"Adapter"});let F=L.createEl("select",{cls:"af-form-select"});for(let[B,V,Pe]of Mo){let we=F.createEl("option",{text:V,attr:{value:B,...Pe?{disabled:"true"}:{}}});B==="claude-code"&&(we.selected=!0)}let z=P.createDiv({cls:"af-form-row"}),U=z.createDiv({cls:"af-form-label",text:"Model"});this.addTooltip(U,`Aliases (opus/sonnet/haiku/opusplan) work on any backend. Choose Custom\u2026 for a pinned ID or Bedrock/Vertex/Foundry. Blank = use Settings default (${this.plugin.settings.defaultModel||"CLI default"}).`);let Z=z.createDiv({cls:"af-form-field-wrap"}),de=()=>{At(Z,{value:l.model,adapter:l.adapter,onChange:B=>{l.model=B}})};de();let me=()=>{};F.addEventListener("change",()=>{l.adapter=F.value,(Rs(l.adapter)?Ys:Ks).some(V=>V.value===l.model.trim())&&(l.model=""),de(),l.permissionMode=Un(l.permissionMode,l.adapter),me()});let ye=P.createDiv({cls:"af-form-row"});ye.createDiv({cls:"af-form-label",text:"Working Dir"});let X=ye.createEl("input",{cls:"af-form-input",attr:{type:"text",placeholder:"Leave empty for vault root"}});X.addEventListener("input",()=>{l.cwd=X.value});let j=P.createDiv({cls:"af-form-row"});j.createDiv({cls:"af-form-label",text:"Timeout (sec)"});let K=j.createEl("input",{cls:"af-form-input af-form-input-sm",attr:{type:"number",value:"300"}});K.addEventListener("input",()=>{let B=parseInt(K.value,10);!isNaN(B)&&B>0&&(l.timeout=B)});let ne=P.createDiv({cls:"af-form-row"});ne.createDiv({cls:"af-form-label",text:"Permission Mode"});let G=ne.createEl("select",{cls:"af-form-select"}),ee=P.createDiv({cls:"af-form-hint",text:""});me=()=>{l.permissionMode=Un(l.permissionMode,l.adapter);let B=Bn(l.adapter);G.empty();for(let[V,Pe]of B){let we=G.createEl("option",{text:Pe,attr:{value:V}});V===l.permissionMode&&(we.selected=!0)}ee.textContent=B.find(([V])=>V===G.value)?.[2]??""},me(),G.addEventListener("change",()=>{l.permissionMode=G.value,ee.textContent=Bn(l.adapter).find(([B])=>B===G.value)?.[2]??""});let Q=P.createDiv({cls:"af-form-row"});Q.createDiv({cls:"af-form-label",text:"Effort Level"});let ae=Q.createEl("select",{cls:"af-form-select"});for(let[B,V]of[["","Default"],["low","Low"],["medium","Medium"],["high","High"],["max","Max"]])ae.createEl("option",{text:V,attr:{value:B}});ae.addEventListener("change",()=>{l.effort=ae.value}),P.createDiv({cls:"af-form-hint",text:"Controls reasoning depth \u2014 low is fast, max is most thorough"});let ve=P.createDiv({cls:"af-form-row"}),Re=ve.createDiv({cls:"af-form-label",text:"Auto-compact at"});this.addTooltip(Re,"Percent of context window at which the chat auto-invokes /compact before the next message. 85% is a good default. Set 0 to disable.");let Le=ve.createEl("input",{cls:"af-form-input af-form-input-sm",attr:{type:"number",min:"0",max:"100",value:String(l.autoCompactThreshold)}});Le.addEventListener("input",()=>{let B=parseInt(Le.value,10);!isNaN(B)&&B>=0&&B<=100&&(l.autoCompactThreshold=B)}),P.createDiv({cls:"af-form-hint",text:"0 disables auto-compact"});{let B=this.plugin.runtime.getSnapshot().agents.filter(V=>V.wikiKeeper!==void 0);if(B.length>0){let V=P.createDiv({cls:"af-form-row af-form-row-toggle"}),Pe=V.createDiv({cls:"af-form-label",text:"Wiki access"});this.addTooltip(Pe,"Lets this agent read + cite from the selected Wiki Keeper scopes (requires the wiki-query skill).");let we=V.createDiv({cls:"af-form-field-wrap"});for(let Ee of B){let et=we.createEl("label",{cls:"af-form-checkbox-row"}),We=et.createEl("input",{attr:{type:"checkbox"}});et.createSpan({text:` ${Ee.name}`,cls:"af-form-checkbox-label"}),We.addEventListener("change",()=>{We.checked?l.wikiReferences.includes(Ee.name)||l.wikiReferences.push(Ee.name):l.wikiReferences=l.wikiReferences.filter(St=>St!==Ee.name)})}}}{let B=d.createDiv({cls:"af-create-section"}),V=B.createDiv({cls:"af-create-section-header"}),Pe=V.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(Pe,"heart-pulse");let we=V.createSpan({text:"Heartbeat"});this.addTooltip(we,"Autonomous periodic run \u2014 what the agent does when no one is asking");let Ee=B.createDiv({cls:"af-form-row af-form-row-toggle"});Ee.createDiv({cls:"af-form-label",text:"Enabled"});let et=Ee.createDiv({cls:"af-agent-card-toggle"}),We=B.createDiv();We.setCssStyles({display:"none"}),et.onclick=()=>{let Se=et.hasClass("on");et.toggleClass("on",!Se),l.heartbeatEnabled=!Se,We.setCssStyles({display:Se?"none":""})},this.renderHeartbeatSchedule(We,l);let St=We.createDiv({cls:"af-form-row af-form-row-toggle"}),Ot=St.createDiv({cls:"af-form-label"});Ot.setText("Notify"),this.addTooltip(Ot,"Show an Obsidian notice when the heartbeat completes");let vt=St.createDiv({cls:"af-agent-card-toggle on"});vt.onclick=()=>{let Se=vt.hasClass("on");vt.toggleClass("on",!Se),l.heartbeatNotify=!Se};let os=this.plugin.runtime.getSnapshot(),Ms=We.createDiv({cls:"af-form-row"}),Nt=Ms.createDiv({cls:"af-form-label"});Nt.setText("Post to channel"),this.addTooltip(Nt,"Heartbeat results are posted to this Slack channel when the run completes");let O=Ms.createEl("select",{cls:"af-form-select"});O.createEl("option",{text:"(none)",attr:{value:""}});for(let Se of os.channels)O.createEl("option",{text:Se.name,attr:{value:Se.name}});O.addEventListener("change",()=>{l.heartbeatChannel=O.value});let Y=We.createDiv({cls:"af-form-label"});Y.setCssStyles({width:"auto"}),Y.setCssStyles({marginTop:"12px"}),Y.setText("Instruction"),this.addTooltip(Y,'What the agent does on each heartbeat. Also used by the "Run Now" button.');let _e=We.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"Check status, scan for issues, report findings...",rows:"8"}});_e.addEventListener("input",()=>{l.heartbeatBody=_e.value})}let Me=d.createDiv({cls:"af-create-section"}),Fe=Me.createDiv({cls:"af-create-section-header"}),ke=Fe.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(ke,"puzzle"),Fe.createSpan({text:"Skills"});let Oe=this.plugin.runtime.getSnapshot();if(Oe.skills.length>0){Me.createDiv({cls:"af-form-sublabel",text:"Shared Skills"});let B=Me.createDiv({cls:"af-create-skills-grid"});for(let V of Oe.skills){let Pe=B.createDiv({cls:"af-create-skill-item"}),we=Pe.createEl("input",{cls:"af-form-toggle",attr:{type:"checkbox"}});we.addEventListener("change",()=>{we.checked?l.selectedSkills.add(V.name):l.selectedSkills.delete(V.name)});let Ee=Pe.createDiv({cls:"af-create-skill-label"});Ee.createSpan({cls:"af-create-skill-name",text:V.name}),V.description&&Ee.createSpan({cls:"af-create-skill-desc",text:` \u2014 ${V.description}`})}}let Ue=Me.createDiv({cls:"af-form-sublabel"});Ue.setText("Agent-specific skills"),this.addTooltip(Ue,"Custom skills/instructions only for this agent, not shared with others");let Ne=Me.createEl("textarea",{cls:"af-create-textarea",attr:{placeholder:"Custom skills/instructions for this agent...",rows:"4"}});Ne.addEventListener("input",()=>{l.skillsBody=Ne.value});{let B=d.createDiv({cls:"af-create-section"}),V=B.createDiv({cls:"af-create-section-header"}),Pe=V.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(Pe,"plug");let we=V.createSpan({text:"MCP Servers"});this.addTooltip(we,"Grant agent access to MCP servers"),this.renderAgentMcpPicker(B,l.selectedMcpServers)}let H=d.createDiv({cls:"af-create-section"}),ie=H.createDiv({cls:"af-create-section-header"}),$=ie.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)($,"file-text");let Te=ie.createSpan({text:"Context"});this.addTooltip(Te,"Project-specific context included in every run");let xe=H.createEl("textarea",{cls:"af-create-textarea",attr:{placeholder:"Background info, repo structure, conventions...",rows:"4"}});xe.addEventListener("input",()=>{l.contextBody=xe.value});let he=d.createDiv({cls:"af-create-section"}),$e=he.createDiv({cls:"af-create-section-header"}),re=$e.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(re,"shield-check"),$e.createSpan({text:"Permissions"}),this.createFormField(he,"Approval required","git_push, file_delete","Comma-separated tool names",B=>{l.approvalRequired=B});let R=he.createDiv({cls:"af-form-row"});R.createDiv({cls:"af-form-label",text:"Allowed Commands"});let se=R.createEl("textarea",{cls:"af-create-textarea",attr:{placeholder:`Bash(curl *)
12027
12027
  Bash(python3 *)
12028
12028
  Read
12029
12029
  Edit
12030
- Write`,rows:"4"}});he.addEventListener("input",()=>{l.allowedCommands=he.value});let oe=Ie.createDiv({cls:"af-form-row"});oe.createDiv({cls:"af-form-label",text:"Blocked Commands"});let Me=oe.createEl("textarea",{cls:"af-create-textarea",attr:{placeholder:`Bash(git push *)
12030
+ Write`,rows:"4"}});se.addEventListener("input",()=>{l.allowedCommands=se.value});let ce=he.createDiv({cls:"af-form-row"});ce.createDiv({cls:"af-form-label",text:"Blocked Commands"});let te=ce.createEl("textarea",{cls:"af-create-textarea",attr:{placeholder:`Bash(git push *)
12031
12031
  Bash(rm -rf *)
12032
- Bash(sudo *)`,rows:"4"}});Me.addEventListener("input",()=>{l.blockedCommands=Me.value}),Ie.createDiv({cls:"af-form-hint",text:"On Codex agents these become execpolicy command rules \u2014 only Bash(cmd args *) prefixes are enforced; tool-name rules (Read/Write) and mid-pattern wildcards are ignored, and file/network access is governed by Permission Mode (the sandbox)."});let ns=Ie.createDiv({cls:"af-form-row"});ns.createDiv({cls:"af-form-label",text:"Memory enabled"});let as=ns.createDiv({cls:"af-agent-card-toggle on"});as.onclick=()=>{let B=as.hasClass("on");as.toggleClass("on",!B),l.memory=!B};let is=s.createDiv({cls:"af-create-footer"}),rs=is.createEl("button",{cls:"af-btn-sm",text:"Cancel"});rs.onclick=()=>this.navigate("agents");let Ft=is.createEl("button",{cls:"af-btn-sm primary af-create-submit"});D(Ft,"plus","af-btn-icon"),Ft.appendText(" Create Agent"),Ft.onclick=async()=>{let B=l.name.trim();if(!B){new b.Notice("Agent name is required.");return}let K=ae(B);if(this.plugin.repository.getAgentByName(K)){new b.Notice(`Agent "${K}" already exists.`);return}let Ee=ve=>ve.split(",").map(Ae=>Ae.trim()).filter(Boolean);try{let ve=Ae=>pe(Ae).map(tt=>tt.trim()).filter(Boolean);await this.plugin.repository.createAgentFolder({name:K,description:l.description.trim(),avatar:l.avatar.trim(),tags:Ee(l.tags),systemPrompt:l.systemPrompt.trim(),model:l.model.trim()||"default",adapter:l.adapter,cwd:l.cwd.trim(),timeout:l.timeout,permissionMode:l.permissionMode,effort:l.effort||void 0,approvalRequired:Ee(l.approvalRequired),memory:l.memory,memoryMaxEntries:100,skills:Array.from(l.selectedSkills),mcpServers:Array.from(l.selectedMcpServers),skillsBody:l.skillsBody.trim(),contextBody:l.contextBody.trim(),enabled:l.enabled,permissionRules:{allow:ve(l.allowedCommands),deny:ve(l.blockedCommands)},autoCompactThreshold:l.autoCompactThreshold,wikiReferences:l.wikiReferences}),l.heartbeatEnabled&&l.heartbeatBody.trim()&&await this.plugin.repository.updateHeartbeat(K,{enabled:l.heartbeatEnabled,schedule:l.heartbeatSchedule.trim(),notify:l.heartbeatNotify,channel:l.heartbeatChannel,body:l.heartbeatBody.trim()}),new b.Notice(`Agent "${K}" created.`),await this.plugin.refreshFromVault(),this.navigate("agent-detail",K)}catch(ve){let Ae=ve instanceof Error?ve.message:String(ve);new b.Notice(`Failed to create agent: ${Ae}`)}}}renderCreateSkillPage(e){let s=e.createDiv({cls:"af-create-agent-page"}),n=s.createDiv({cls:"af-detail-header"}),a=n.createDiv({cls:"af-detail-header-left"}),r=a.createDiv({cls:"af-agent-card-avatar idle"});(0,b.setIcon)(r,"plus");let o=a.createDiv();o.createDiv({cls:"af-detail-header-name",text:"Create New Skill"}),o.createDiv({cls:"af-detail-header-desc",text:"Define a reusable skill for your agents"});let c=n.createDiv({cls:"af-detail-header-actions"}),l={name:"",description:"",tags:"",body:"",toolsBody:"",referencesBody:"",examplesBody:""},d={none:{label:"None",prompt:""},cli:{label:"CLI Tool Wrapper",prompt:`You are using the {{tool}} CLI. All operations go through the wrapper script.
12032
+ Bash(sudo *)`,rows:"4"}});te.addEventListener("input",()=>{l.blockedCommands=te.value}),he.createDiv({cls:"af-form-hint",text:"On Codex agents these become execpolicy command rules \u2014 only Bash(cmd args *) prefixes are enforced; tool-name rules (Read/Write) and mid-pattern wildcards are ignored, and file/network access is governed by Permission Mode (the sandbox)."});let Ze=he.createDiv({cls:"af-form-row"});Ze.createDiv({cls:"af-form-label",text:"Memory enabled"});let as=Ze.createDiv({cls:"af-agent-card-toggle on"});as.onclick=()=>{let B=as.hasClass("on");as.toggleClass("on",!B),l.memory=!B};let is=s.createDiv({cls:"af-create-footer"}),rs=is.createEl("button",{cls:"af-btn-sm",text:"Cancel"});rs.onclick=()=>this.navigate("agents");let Ft=is.createEl("button",{cls:"af-btn-sm primary af-create-submit"});E(Ft,"plus","af-btn-icon"),Ft.appendText(" Create Agent"),Ft.onclick=async()=>{let B=l.name.trim();if(!B){new w.Notice("Agent name is required.");return}let V=oe(B);if(this.plugin.repository.getAgentByName(V)){new w.Notice(`Agent "${V}" already exists.`);return}let Pe=we=>we.split(",").map(Ee=>Ee.trim()).filter(Boolean);try{let we=Ee=>ge(Ee).map(et=>et.trim()).filter(Boolean);await this.plugin.repository.createAgentFolder({name:V,description:l.description.trim(),avatar:l.avatar.trim(),tags:Pe(l.tags),systemPrompt:l.systemPrompt.trim(),model:l.model.trim()||"default",adapter:l.adapter,cwd:l.cwd.trim(),timeout:l.timeout,permissionMode:l.permissionMode,effort:l.effort||void 0,approvalRequired:Pe(l.approvalRequired),memory:l.memory,memoryMaxEntries:100,skills:Array.from(l.selectedSkills),mcpServers:Array.from(l.selectedMcpServers),skillsBody:l.skillsBody.trim(),contextBody:l.contextBody.trim(),enabled:l.enabled,permissionRules:{allow:we(l.allowedCommands),deny:we(l.blockedCommands)},autoCompactThreshold:l.autoCompactThreshold,wikiReferences:l.wikiReferences}),l.heartbeatEnabled&&l.heartbeatBody.trim()&&await this.plugin.repository.updateHeartbeat(V,{enabled:l.heartbeatEnabled,schedule:l.heartbeatSchedule.trim(),notify:l.heartbeatNotify,channel:l.heartbeatChannel,body:l.heartbeatBody.trim()}),new w.Notice(`Agent "${V}" created.`),await this.plugin.refreshFromVault(),this.navigate("agent-detail",V)}catch(we){let Ee=we instanceof Error?we.message:String(we);new w.Notice(`Failed to create agent: ${Ee}`)}}}renderCreateSkillPage(e){let s=e.createDiv({cls:"af-create-agent-page"}),n=s.createDiv({cls:"af-detail-header"}),a=n.createDiv({cls:"af-detail-header-left"}),r=a.createDiv({cls:"af-agent-card-avatar idle"});(0,w.setIcon)(r,"plus");let o=a.createDiv();o.createDiv({cls:"af-detail-header-name",text:"Create New Skill"}),o.createDiv({cls:"af-detail-header-desc",text:"Define a reusable skill for your agents"});let c=n.createDiv({cls:"af-detail-header-actions"}),l={name:"",description:"",tags:"",body:"",toolsBody:"",referencesBody:"",examplesBody:""},h={none:{label:"None",prompt:""},cli:{label:"CLI Tool Wrapper",prompt:`You are using the {{tool}} CLI. All operations go through the wrapper script.
12033
12033
 
12034
12034
  Requirements:
12035
12035
  - Ensure required environment variables are set
@@ -12066,36 +12066,36 @@ Key behaviors:
12066
12066
  - Use tables and charts where appropriate
12067
12067
  - Always state the time range and filters applied
12068
12068
  - Flag anomalies and outliers explicitly
12069
- - End with actionable insights, not just observations`}},h=s.createDiv({cls:"af-create-form"}),u=h.createDiv({cls:"af-create-section"}),p=u.createDiv({cls:"af-create-section-header"}),f=p.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(f,"puzzle"),p.createSpan({text:"Identity"}),this.createFormField(u,"Name","todoist","Unique identifier (will be slugified)",V=>{l.name=V}),this.createFormField(u,"Description","Manage tasks and projects via CLI","",V=>{l.description=V}),this.createFormField(u,"Tags","productivity, tasks","Comma-separated",V=>{l.tags=V});let m=h.createDiv({cls:"af-create-section"}),g=m.createDiv({cls:"af-create-section-header"}),v=g.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(v,"file-text"),g.createSpan({text:"Core Instructions"});let k=m.createDiv({cls:"af-form-row"});k.createDiv({cls:"af-form-label",text:"Template"});let w=k.createEl("select",{cls:"af-form-select"});for(let[V,{label:te}]of Object.entries(d))w.createEl("option",{text:te,attr:{value:V}});let y=m.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"Skill instructions \u2014 what does this skill do and how should agents use it?",rows:"10"}});y.addEventListener("input",()=>{l.body=y.value}),w.addEventListener("change",()=>{let V=d[w.value];V&&w.value!=="none"&&(l.body=V.prompt,y.value=V.prompt)});let C=h.createDiv({cls:"af-create-section"}),T=C.createDiv({cls:"af-create-section-header"}),_=T.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(_,"wrench");let O=T.createSpan({text:"Tools"});this.addTooltip(O,"CLI commands, API endpoints, and tool definitions available to agents using this skill");let E=C.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:`## Commands
12069
+ - End with actionable insights, not just observations`}},d=s.createDiv({cls:"af-create-form"}),u=d.createDiv({cls:"af-create-section"}),p=u.createDiv({cls:"af-create-section-header"}),m=p.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(m,"puzzle"),p.createSpan({text:"Identity"}),this.createFormField(u,"Name","todoist","Unique identifier (will be slugified)",K=>{l.name=K}),this.createFormField(u,"Description","Manage tasks and projects via CLI","",K=>{l.description=K}),this.createFormField(u,"Tags","productivity, tasks","Comma-separated",K=>{l.tags=K});let f=d.createDiv({cls:"af-create-section"}),g=f.createDiv({cls:"af-create-section-header"}),v=g.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(v,"file-text"),g.createSpan({text:"Core Instructions"});let b=f.createDiv({cls:"af-form-row"});b.createDiv({cls:"af-form-label",text:"Template"});let k=b.createEl("select",{cls:"af-form-select"});for(let[K,{label:ne}]of Object.entries(h))k.createEl("option",{text:ne,attr:{value:K}});let y=f.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"Skill instructions \u2014 what does this skill do and how should agents use it?",rows:"10"}});y.addEventListener("input",()=>{l.body=y.value}),k.addEventListener("change",()=>{let K=h[k.value];K&&k.value!=="none"&&(l.body=K.prompt,y.value=K.prompt)});let S=d.createDiv({cls:"af-create-section"}),T=S.createDiv({cls:"af-create-section-header"}),_=T.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(_,"wrench");let D=T.createSpan({text:"Tools"});this.addTooltip(D,"CLI commands, API endpoints, and tool definitions available to agents using this skill");let M=S.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:`## Commands
12070
12070
 
12071
12071
  ### list
12072
12072
  Usage: tool list [--filter <query>]
12073
- ...`,rows:"8"}});E.addEventListener("input",()=>{l.toolsBody=E.value});let S=h.createDiv({cls:"af-create-section"}),P=S.createDiv({cls:"af-create-section-header"}),R=P.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(R,"book-open");let N=P.createSpan({text:"References"});this.addTooltip(N,"Background docs, conventions, cheat sheets");let L=S.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"API docs, filter syntax, conventions...",rows:"6"}});L.addEventListener("input",()=>{l.referencesBody=L.value});let G=h.createDiv({cls:"af-create-section"}),U=G.createDiv({cls:"af-create-section-header"}),X=U.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(X,"message-circle");let me=U.createSpan({text:"Examples"});this.addTooltip(me,"Example prompts and ideal outputs showing how to use this skill");let ye=G.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:`## Example: List all tasks
12073
+ ...`,rows:"8"}});M.addEventListener("input",()=>{l.toolsBody=M.value});let C=d.createDiv({cls:"af-create-section"}),I=C.createDiv({cls:"af-create-section-header"}),P=I.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(P,"book-open");let L=I.createSpan({text:"References"});this.addTooltip(L,"Background docs, conventions, cheat sheets");let F=C.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"API docs, filter syntax, conventions...",rows:"6"}});F.addEventListener("input",()=>{l.referencesBody=F.value});let z=d.createDiv({cls:"af-create-section"}),U=z.createDiv({cls:"af-create-section-header"}),Z=U.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(Z,"message-circle");let de=U.createSpan({text:"Examples"});this.addTooltip(de,"Example prompts and ideal outputs showing how to use this skill");let me=z.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:`## Example: List all tasks
12074
12074
 
12075
12075
  User: Show me my tasks for today
12076
12076
 
12077
- Agent: ...`,rows:"6"}});ye.addEventListener("input",()=>{l.examplesBody=ye.value});let ee=s.createDiv({cls:"af-create-footer"}),W=ee.createEl("button",{cls:"af-btn-sm",text:"Cancel"});W.onclick=()=>this.navigate("skills");let de=ee.createEl("button",{cls:"af-btn-sm primary af-create-submit"});D(de,"plus","af-btn-icon"),de.appendText(" Create Skill"),de.onclick=async()=>{let V=l.name.trim();if(!V){new b.Notice("Skill name is required.");return}let te=ae(V);if(this.plugin.repository.getSkillByName(te)){new b.Notice(`Skill "${te}" already exists.`);return}let Y=Z=>Z.split(",").map(j=>j.trim()).filter(Boolean);try{await this.plugin.repository.createSkillFolder({name:te,description:l.description.trim(),tags:Y(l.tags),body:l.body.trim(),toolsBody:l.toolsBody.trim(),referencesBody:l.referencesBody.trim(),examplesBody:l.examplesBody.trim()}),new b.Notice(`Skill "${te}" created.`),await this.plugin.refreshFromVault(),this.navigate("skills")}catch(Z){let j=Z instanceof Error?Z.message:String(Z);new b.Notice(`Failed to create skill: ${j}`)}}}renderEditAgentPage(e){let s=e.createDiv({cls:"af-create-agent-page"}),n=this.detailContext;if(!n){this.renderEmptyState(s,"bot","No agent selected","");return}let a=this.plugin.runtime.getSnapshot().agents.find(M=>M.name===n);if(!a){this.renderEmptyState(s,"bot","Agent not found",`Agent "${n}" was not found`);return}let r=s.createDiv({cls:"af-detail-header"}),o=r.createDiv({cls:"af-detail-header-left"}),c=o.createDiv({cls:"af-agent-card-avatar idle"});(0,b.setIcon)(c,"edit");let l=o.createDiv();l.createDiv({cls:"af-detail-header-name",text:`Edit Agent: ${a.name}`}),l.createDiv({cls:"af-detail-header-desc",text:"Modify agent configuration"});let d=r.createDiv({cls:"af-detail-header-actions"}),h={name:a.name,description:a.description??"",avatar:a.avatar,tags:a.tags.join(", "),systemPrompt:a.body,model:a.model,adapter:a.adapter,cwd:a.cwd??"",timeout:a.timeout,permissionMode:a.permissionMode,effort:a.effort??"",selectedSkills:new Set(a.skills),selectedMcpServers:new Set(a.mcpServers??[]),skillsBody:a.skillsBody,contextBody:a.contextBody,approvalRequired:a.approvalRequired.join(", "),memory:a.memory,memoryTokenBudget:a.memoryTokenBudget,reflectionEnabled:a.reflection.enabled,reflectionProposeSkills:a.reflection.proposeSkills,enabled:a.enabled,allowedCommands:a.permissionRules.allow.join(`
12077
+ Agent: ...`,rows:"6"}});me.addEventListener("input",()=>{l.examplesBody=me.value});let ye=s.createDiv({cls:"af-create-footer"}),X=ye.createEl("button",{cls:"af-btn-sm",text:"Cancel"});X.onclick=()=>this.navigate("skills");let j=ye.createEl("button",{cls:"af-btn-sm primary af-create-submit"});E(j,"plus","af-btn-icon"),j.appendText(" Create Skill"),j.onclick=async()=>{let K=l.name.trim();if(!K){new w.Notice("Skill name is required.");return}let ne=oe(K);if(this.plugin.repository.getSkillByName(ne)){new w.Notice(`Skill "${ne}" already exists.`);return}let G=ee=>ee.split(",").map(Q=>Q.trim()).filter(Boolean);try{await this.plugin.repository.createSkillFolder({name:ne,description:l.description.trim(),tags:G(l.tags),body:l.body.trim(),toolsBody:l.toolsBody.trim(),referencesBody:l.referencesBody.trim(),examplesBody:l.examplesBody.trim()}),new w.Notice(`Skill "${ne}" created.`),await this.plugin.refreshFromVault(),this.navigate("skills")}catch(ee){let Q=ee instanceof Error?ee.message:String(ee);new w.Notice(`Failed to create skill: ${Q}`)}}}renderEditAgentPage(e){let s=e.createDiv({cls:"af-create-agent-page"}),n=this.detailContext;if(!n){this.renderEmptyState(s,"bot","No agent selected","");return}let a=this.plugin.runtime.getSnapshot().agents.find(O=>O.name===n);if(!a){this.renderEmptyState(s,"bot","Agent not found",`Agent "${n}" was not found`);return}let r=s.createDiv({cls:"af-detail-header"}),o=r.createDiv({cls:"af-detail-header-left"}),c=o.createDiv({cls:"af-agent-card-avatar idle"});(0,w.setIcon)(c,"edit");let l=o.createDiv();l.createDiv({cls:"af-detail-header-name",text:`Edit Agent: ${a.name}`}),l.createDiv({cls:"af-detail-header-desc",text:"Modify agent configuration"});let h=r.createDiv({cls:"af-detail-header-actions"}),d={name:a.name,description:a.description??"",avatar:a.avatar,tags:a.tags.join(", "),systemPrompt:a.body,model:a.model,adapter:a.adapter,cwd:a.cwd??"",timeout:a.timeout,permissionMode:a.permissionMode,effort:a.effort??"",selectedSkills:new Set(a.skills),selectedMcpServers:new Set(a.mcpServers??[]),skillsBody:a.skillsBody,contextBody:a.contextBody,approvalRequired:a.approvalRequired.join(", "),memory:a.memory,memoryTokenBudget:a.memoryTokenBudget,reflectionEnabled:a.reflection.enabled,reflectionProposeSkills:a.reflection.proposeSkills,enabled:a.enabled,allowedCommands:a.permissionRules.allow.join(`
12078
12078
  `),blockedCommands:a.permissionRules.deny.join(`
12079
- `),heartbeatEnabled:a.heartbeatEnabled,heartbeatSchedule:a.heartbeatSchedule,heartbeatBody:a.heartbeatBody,heartbeatNotify:a.heartbeatNotify,heartbeatChannel:a.heartbeatChannel,autoCompactThreshold:a.autoCompactThreshold??85,wikiReferences:(a.wikiReferences??[]).map(M=>M.agent)},u=s.createDiv({cls:"af-create-form"}),p=u.createDiv({cls:"af-create-section"}),f=p.createDiv({cls:"af-create-section-header"}),m=f.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(m,"user"),f.createSpan({text:"Identity"});let g=p.createDiv({cls:"af-form-row"});g.createDiv({cls:"af-form-label",text:"Name"});let v=g.createEl("input",{cls:"af-form-input",attr:{type:"text",value:a.name,disabled:"true"}});v.style.opacity="0.6",this.createFormField(p,"Description","Monitors deployments and reports status","",M=>{h.description=M},a.description??"");let k=p.createDiv({cls:"af-form-row"});k.createDiv({cls:"af-form-label",text:"Avatar"});let w=k.createEl("button",{cls:"af-avatar-picker-btn"}),y=w.createDiv({cls:"af-avatar-picker-preview"});this.renderAgentAvatar(y,{...a,avatar:h.avatar??a.avatar}),w.createSpan({cls:"af-avatar-picker-label",text:h.avatar||a.avatar||"Pick icon\u2026"}),w.addEventListener("click",()=>{new On(this.app,h.avatar??a.avatar,M=>{h.avatar=M,y.empty(),(0,b.setIcon)(y,M),w.querySelector(".af-avatar-picker-label")?.setText(M)}).open()}),this.createFormField(p,"Tags","devops, monitoring","Comma-separated",M=>{h.tags=M},a.tags.join(", "));let C=p.createDiv({cls:"af-form-row"});C.createDiv({cls:"af-form-label",text:"Enabled"});let T=C.createDiv({cls:`af-agent-card-toggle${a.enabled?" on":""}`});T.onclick=()=>{let M=T.hasClass("on");T.toggleClass("on",!M),h.enabled=!M};let _=u.createDiv({cls:"af-create-section"}),O=_.createDiv({cls:"af-create-section-header"}),E=O.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(E,"message-square"),O.createSpan({text:"System Prompt"});let S=_.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"System prompt...",rows:"10"}});S.value=a.body,S.addEventListener("input",()=>{h.systemPrompt=S.value});let P=u.createDiv({cls:"af-create-section"}),R=P.createDiv({cls:"af-create-section-header"}),N=R.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(N,"settings"),R.createSpan({text:"Runtime Config"});let L=P.createDiv({cls:"af-create-config-grid"}),G=L.createDiv({cls:"af-form-row"});G.createDiv({cls:"af-form-label",text:"Adapter"});let U=G.createEl("select",{cls:"af-form-select"});for(let[M,J,Te]of Io){let ke=U.createEl("option",{text:J,attr:{value:M,...Te?{disabled:"true"}:{}}});(M===a.adapter||Rs(a.adapter)&&M==="codex")&&(ke.selected=!0)}let X=L.createDiv({cls:"af-form-row"}),me=X.createDiv({cls:"af-form-label",text:"Model"});this.addTooltip(me,`Aliases (opus/sonnet/haiku/opusplan) work on any backend. Choose Custom\u2026 for a pinned ID or Bedrock/Vertex/Foundry. Blank = use Settings default (${this.plugin.settings.defaultModel||"CLI default"}).`);let ye=X.createDiv({cls:"af-form-field-wrap"}),ee=()=>{At(ye,{value:h.model,adapter:h.adapter,onChange:M=>{h.model=M}})};ee();let W=()=>{};U.addEventListener("change",()=>{h.adapter=U.value,(Rs(h.adapter)?Ys:Ks).some(J=>J.value===h.model.trim())&&(h.model=""),ee(),h.permissionMode=Un(h.permissionMode,h.adapter),W()});let de=L.createDiv({cls:"af-form-row"});de.createDiv({cls:"af-form-label",text:"Working Dir"});let V=de.createEl("input",{cls:"af-form-input",attr:{type:"text",placeholder:"Leave empty for vault root",value:a.cwd??""}});V.addEventListener("input",()=>{h.cwd=V.value});let te=L.createDiv({cls:"af-form-row"});te.createDiv({cls:"af-form-label",text:"Timeout (sec)"});let Y=te.createEl("input",{cls:"af-form-input af-form-input-sm",attr:{type:"number",value:String(a.timeout)}});Y.addEventListener("input",()=>{let M=parseInt(Y.value,10);!isNaN(M)&&M>0&&(h.timeout=M)});let Z=L.createDiv({cls:"af-form-row"});Z.createDiv({cls:"af-form-label",text:"Permission Mode"});let j=Z.createEl("select",{cls:"af-form-select"}),fe=L.createDiv({cls:"af-form-hint",text:""});W=()=>{h.permissionMode=Un(h.permissionMode,h.adapter);let M=Bn(h.adapter);j.empty();for(let[J,Te]of M){let ke=j.createEl("option",{text:Te,attr:{value:J}});J===h.permissionMode&&(ke.selected=!0)}fe.textContent=M.find(([J])=>J===j.value)?.[2]??""},W(),j.addEventListener("change",()=>{h.permissionMode=j.value,fe.textContent=Bn(h.adapter).find(([M])=>M===j.value)?.[2]??""});let Pe=L.createDiv({cls:"af-form-row"});Pe.createDiv({cls:"af-form-label",text:"Effort Level"});let Oe=Pe.createEl("select",{cls:"af-form-select"});for(let[M,J]of[["","Default"],["low","Low"],["medium","Medium"],["high","High"],["max","Max"]]){let Te=Oe.createEl("option",{text:J,attr:{value:M}});M===(a.effort??"")&&(Te.selected=!0)}Oe.addEventListener("change",()=>{h.effort=Oe.value}),L.createDiv({cls:"af-form-hint",text:"Controls reasoning depth \u2014 low is fast, max is most thorough"});let Ue=L.createDiv({cls:"af-form-row"}),Re=Ue.createDiv({cls:"af-form-label",text:"Auto-compact at"});this.addTooltip(Re,"Percent of context window at which the chat auto-invokes /compact before the next message. 85% is a good default. Set 0 to disable.");let Se=Ue.createEl("input",{cls:"af-form-input af-form-input-sm",attr:{type:"number",min:"0",max:"100",value:String(h.autoCompactThreshold)}});Se.addEventListener("input",()=>{let M=parseInt(Se.value,10);!isNaN(M)&&M>=0&&M<=100&&(h.autoCompactThreshold=M)}),L.createDiv({cls:"af-form-hint",text:"0 disables auto-compact"});{let M=this.plugin.runtime.getSnapshot().agents.filter(J=>J.wikiKeeper!==void 0);if(M.length>0){let J=L.createDiv({cls:"af-form-row af-form-row-toggle"}),Te=J.createDiv({cls:"af-form-label",text:"Wiki access"});this.addTooltip(Te,"Lets this agent read + cite from the selected Wiki Keeper scopes (requires the wiki-query skill).");let ke=J.createDiv({cls:"af-form-field-wrap"});for(let st of M){let Bt=ke.createEl("label",{cls:"af-form-checkbox-row"}),nt=Bt.createEl("input",{attr:{type:"checkbox"}});h.wikiReferences.includes(st.name)&&(nt.checked=!0),Bt.createSpan({text:` ${st.name}`,cls:"af-form-checkbox-label"}),nt.addEventListener("change",()=>{nt.checked?h.wikiReferences.includes(st.name)||h.wikiReferences.push(st.name):h.wikiReferences=h.wikiReferences.filter(Ls=>Ls!==st.name)})}}}if(a.isFolder){let M=u.createDiv({cls:"af-create-section"}),J=M.createDiv({cls:"af-create-section-header"}),Te=J.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(Te,"heart-pulse");let ke=J.createSpan({text:"Heartbeat"});this.addTooltip(ke,"Autonomous periodic run \u2014 what the agent does when no one is asking");let st=M.createDiv({cls:"af-form-row af-form-row-toggle"});st.createDiv({cls:"af-form-label",text:"Enabled"});let Bt=st.createDiv({cls:`af-agent-card-toggle${h.heartbeatEnabled?" on":""}`}),nt=M.createDiv();nt.style.display=h.heartbeatEnabled?"":"none",Bt.onclick=()=>{let rt=Bt.hasClass("on");Bt.toggleClass("on",!rt),h.heartbeatEnabled=!rt,nt.style.display=rt?"none":""},this.renderHeartbeatSchedule(nt,h);let Ls=nt.createDiv({cls:"af-form-row af-form-row-toggle"}),Ha=Ls.createDiv({cls:"af-form-label"});Ha.setText("Notify"),this.addTooltip(Ha,"Show an Obsidian notice when the heartbeat completes");let Wn=Ls.createDiv({cls:`af-agent-card-toggle${h.heartbeatNotify?" on":""}`});Wn.onclick=()=>{let rt=Wn.hasClass("on");Wn.toggleClass("on",!rt),h.heartbeatNotify=!rt};let Bo=this.plugin.runtime.getSnapshot(),qa=nt.createDiv({cls:"af-form-row"}),za=qa.createDiv({cls:"af-form-label"});za.setText("Post to channel"),this.addTooltip(za,"Heartbeat results are posted to this Slack channel when the run completes");let Fs=qa.createEl("select",{cls:"af-form-select"});Fs.createEl("option",{text:"(none)",attr:{value:""}});for(let rt of Bo.channels){let Uo=Fs.createEl("option",{text:rt.name,attr:{value:rt.name}});rt.name===h.heartbeatChannel&&(Uo.selected=!0)}Fs.addEventListener("change",()=>{h.heartbeatChannel=Fs.value});let Os=nt.createDiv({cls:"af-form-label"});Os.style.width="auto",Os.style.marginTop="12px",Os.setText("Instruction"),this.addTooltip(Os,'What the agent does on each heartbeat. Also used by the "Run Now" button.');let Hn=nt.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"Check status, scan for issues, report findings...",rows:"8"}});Hn.value=h.heartbeatBody,Hn.addEventListener("input",()=>{h.heartbeatBody=Hn.value})}let De=u.createDiv({cls:"af-create-section"}),Ne=De.createDiv({cls:"af-create-section-header"}),$e=Ne.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)($e,"puzzle"),Ne.createSpan({text:"Skills"});let q=this.plugin.runtime.getSnapshot();if(q.skills.length>0){De.createDiv({cls:"af-form-sublabel",text:"Shared Skills"});let M=De.createDiv({cls:"af-create-skills-grid"});for(let J of q.skills){let Te=M.createDiv({cls:"af-create-skill-item"}),ke=Te.createEl("input",{cls:"af-form-toggle",attr:{type:"checkbox"}});ke.checked=h.selectedSkills.has(J.name),ke.addEventListener("change",()=>{ke.checked?h.selectedSkills.add(J.name):h.selectedSkills.delete(J.name)});let st=Te.createDiv({cls:"af-create-skill-label"});st.createSpan({cls:"af-create-skill-name",text:J.name}),J.description&&st.createSpan({cls:"af-create-skill-desc",text:` \u2014 ${J.description}`})}}let ie=De.createDiv({cls:"af-form-sublabel"});ie.setText("Agent-specific skills"),this.addTooltip(ie,"Custom skills/instructions only for this agent, not shared with others");let $=De.createEl("textarea",{cls:"af-create-textarea",attr:{placeholder:"Custom skills/instructions for this agent...",rows:"4"}});$.value=a.skillsBody,$.addEventListener("input",()=>{h.skillsBody=$.value});let Ce=u.createDiv({cls:"af-create-section"}),we=Ce.createDiv({cls:"af-create-section-header"}),ge=we.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(ge,"plug");let Ie=we.createSpan({text:"MCP Servers"});this.addTooltip(Ie,"Grant agent access to MCP servers"),this.renderAgentMcpPicker(Ce,h.selectedMcpServers);let se=u.createDiv({cls:"af-create-section"}),I=se.createDiv({cls:"af-create-section-header"}),ne=I.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(ne,"file-text");let he=I.createSpan({text:"Context"});this.addTooltip(he,"Project-specific context included in every run");let oe=se.createEl("textarea",{cls:"af-create-textarea",attr:{placeholder:"Background info, repo structure, conventions...",rows:"4"}});oe.value=a.contextBody,oe.addEventListener("input",()=>{h.contextBody=oe.value});let Me=u.createDiv({cls:"af-create-section"}),ns=Me.createDiv({cls:"af-create-section-header"}),as=ns.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(as,"shield-check"),ns.createSpan({text:"Permissions"}),this.createFormField(Me,"Approval required","git_push, file_delete","Comma-separated tool names",M=>{h.approvalRequired=M},a.approvalRequired.join(", "));let is=Me.createDiv({cls:"af-form-row"});is.createDiv({cls:"af-form-label",text:"Allowed Commands"});let rs=is.createEl("textarea",{cls:"af-create-textarea",attr:{placeholder:`Bash(curl *)
12079
+ `),heartbeatEnabled:a.heartbeatEnabled,heartbeatSchedule:a.heartbeatSchedule,heartbeatBody:a.heartbeatBody,heartbeatNotify:a.heartbeatNotify,heartbeatChannel:a.heartbeatChannel,autoCompactThreshold:a.autoCompactThreshold??85,wikiReferences:(a.wikiReferences??[]).map(O=>O.agent)},u=s.createDiv({cls:"af-create-form"}),p=u.createDiv({cls:"af-create-section"}),m=p.createDiv({cls:"af-create-section-header"}),f=m.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(f,"user"),m.createSpan({text:"Identity"});let g=p.createDiv({cls:"af-form-row"});g.createDiv({cls:"af-form-label",text:"Name"}),g.createEl("input",{cls:"af-form-input",attr:{type:"text",value:a.name,disabled:"true"}}).setCssStyles({opacity:"0.6"}),this.createFormField(p,"Description","Monitors deployments and reports status","",O=>{d.description=O},a.description??"");let b=p.createDiv({cls:"af-form-row"});b.createDiv({cls:"af-form-label",text:"Avatar"});let k=b.createEl("button",{cls:"af-avatar-picker-btn"}),y=k.createDiv({cls:"af-avatar-picker-preview"});this.renderAgentAvatar(y,{...a,avatar:d.avatar??a.avatar}),k.createSpan({cls:"af-avatar-picker-label",text:d.avatar||a.avatar||"Pick icon\u2026"}),k.addEventListener("click",()=>{new On(this.app,d.avatar??a.avatar,O=>{d.avatar=O,y.empty(),(0,w.setIcon)(y,O),k.querySelector(".af-avatar-picker-label")?.setText(O)}).open()}),this.createFormField(p,"Tags","devops, monitoring","Comma-separated",O=>{d.tags=O},a.tags.join(", "));let S=p.createDiv({cls:"af-form-row"});S.createDiv({cls:"af-form-label",text:"Enabled"});let T=S.createDiv({cls:`af-agent-card-toggle${a.enabled?" on":""}`});T.onclick=()=>{let O=T.hasClass("on");T.toggleClass("on",!O),d.enabled=!O};let _=u.createDiv({cls:"af-create-section"}),D=_.createDiv({cls:"af-create-section-header"}),M=D.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(M,"message-square"),D.createSpan({text:"System Prompt"});let C=_.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"System prompt...",rows:"10"}});C.value=a.body,C.addEventListener("input",()=>{d.systemPrompt=C.value});let I=u.createDiv({cls:"af-create-section"}),P=I.createDiv({cls:"af-create-section-header"}),L=P.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(L,"settings"),P.createSpan({text:"Runtime Config"});let F=I.createDiv({cls:"af-create-config-grid"}),z=F.createDiv({cls:"af-form-row"});z.createDiv({cls:"af-form-label",text:"Adapter"});let U=z.createEl("select",{cls:"af-form-select"});for(let[O,Y,_e]of Mo){let Se=U.createEl("option",{text:Y,attr:{value:O,..._e?{disabled:"true"}:{}}});(O===a.adapter||Rs(a.adapter)&&O==="codex")&&(Se.selected=!0)}let Z=F.createDiv({cls:"af-form-row"}),de=Z.createDiv({cls:"af-form-label",text:"Model"});this.addTooltip(de,`Aliases (opus/sonnet/haiku/opusplan) work on any backend. Choose Custom\u2026 for a pinned ID or Bedrock/Vertex/Foundry. Blank = use Settings default (${this.plugin.settings.defaultModel||"CLI default"}).`);let me=Z.createDiv({cls:"af-form-field-wrap"}),ye=()=>{At(me,{value:d.model,adapter:d.adapter,onChange:O=>{d.model=O}})};ye();let X=()=>{};U.addEventListener("change",()=>{d.adapter=U.value,(Rs(d.adapter)?Ys:Ks).some(Y=>Y.value===d.model.trim())&&(d.model=""),ye(),d.permissionMode=Un(d.permissionMode,d.adapter),X()});let j=F.createDiv({cls:"af-form-row"});j.createDiv({cls:"af-form-label",text:"Working Dir"});let K=j.createEl("input",{cls:"af-form-input",attr:{type:"text",placeholder:"Leave empty for vault root",value:a.cwd??""}});K.addEventListener("input",()=>{d.cwd=K.value});let ne=F.createDiv({cls:"af-form-row"});ne.createDiv({cls:"af-form-label",text:"Timeout (sec)"});let G=ne.createEl("input",{cls:"af-form-input af-form-input-sm",attr:{type:"number",value:String(a.timeout)}});G.addEventListener("input",()=>{let O=parseInt(G.value,10);!isNaN(O)&&O>0&&(d.timeout=O)});let ee=F.createDiv({cls:"af-form-row"});ee.createDiv({cls:"af-form-label",text:"Permission Mode"});let Q=ee.createEl("select",{cls:"af-form-select"}),ae=F.createDiv({cls:"af-form-hint",text:""});X=()=>{d.permissionMode=Un(d.permissionMode,d.adapter);let O=Bn(d.adapter);Q.empty();for(let[Y,_e]of O){let Se=Q.createEl("option",{text:_e,attr:{value:Y}});Y===d.permissionMode&&(Se.selected=!0)}ae.textContent=O.find(([Y])=>Y===Q.value)?.[2]??""},X(),Q.addEventListener("change",()=>{d.permissionMode=Q.value,ae.textContent=Bn(d.adapter).find(([O])=>O===Q.value)?.[2]??""});let ve=F.createDiv({cls:"af-form-row"});ve.createDiv({cls:"af-form-label",text:"Effort Level"});let Re=ve.createEl("select",{cls:"af-form-select"});for(let[O,Y]of[["","Default"],["low","Low"],["medium","Medium"],["high","High"],["max","Max"]]){let _e=Re.createEl("option",{text:Y,attr:{value:O}});O===(a.effort??"")&&(_e.selected=!0)}Re.addEventListener("change",()=>{d.effort=Re.value}),F.createDiv({cls:"af-form-hint",text:"Controls reasoning depth \u2014 low is fast, max is most thorough"});let Le=F.createDiv({cls:"af-form-row"}),Me=Le.createDiv({cls:"af-form-label",text:"Auto-compact at"});this.addTooltip(Me,"Percent of context window at which the chat auto-invokes /compact before the next message. 85% is a good default. Set 0 to disable.");let Fe=Le.createEl("input",{cls:"af-form-input af-form-input-sm",attr:{type:"number",min:"0",max:"100",value:String(d.autoCompactThreshold)}});Fe.addEventListener("input",()=>{let O=parseInt(Fe.value,10);!isNaN(O)&&O>=0&&O<=100&&(d.autoCompactThreshold=O)}),F.createDiv({cls:"af-form-hint",text:"0 disables auto-compact"});{let O=this.plugin.runtime.getSnapshot().agents.filter(Y=>Y.wikiKeeper!==void 0);if(O.length>0){let Y=F.createDiv({cls:"af-form-row af-form-row-toggle"}),_e=Y.createDiv({cls:"af-form-label",text:"Wiki access"});this.addTooltip(_e,"Lets this agent read + cite from the selected Wiki Keeper scopes (requires the wiki-query skill).");let Se=Y.createDiv({cls:"af-form-field-wrap"});for(let tt of O){let Bt=Se.createEl("label",{cls:"af-form-checkbox-row"}),st=Bt.createEl("input",{attr:{type:"checkbox"}});d.wikiReferences.includes(tt.name)&&(st.checked=!0),Bt.createSpan({text:` ${tt.name}`,cls:"af-form-checkbox-label"}),st.addEventListener("change",()=>{st.checked?d.wikiReferences.includes(tt.name)||d.wikiReferences.push(tt.name):d.wikiReferences=d.wikiReferences.filter(Ls=>Ls!==tt.name)})}}}if(a.isFolder){let O=u.createDiv({cls:"af-create-section"}),Y=O.createDiv({cls:"af-create-section-header"}),_e=Y.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(_e,"heart-pulse");let Se=Y.createSpan({text:"Heartbeat"});this.addTooltip(Se,"Autonomous periodic run \u2014 what the agent does when no one is asking");let tt=O.createDiv({cls:"af-form-row af-form-row-toggle"});tt.createDiv({cls:"af-form-label",text:"Enabled"});let Bt=tt.createDiv({cls:`af-agent-card-toggle${d.heartbeatEnabled?" on":""}`}),st=O.createDiv();st.setCssStyles({display:d.heartbeatEnabled?"":"none"}),Bt.onclick=()=>{let ot=Bt.hasClass("on");Bt.toggleClass("on",!ot),d.heartbeatEnabled=!ot,st.setCssStyles({display:ot?"none":""})},this.renderHeartbeatSchedule(st,d);let Ls=st.createDiv({cls:"af-form-row af-form-row-toggle"}),qa=Ls.createDiv({cls:"af-form-label"});qa.setText("Notify"),this.addTooltip(qa,"Show an Obsidian notice when the heartbeat completes");let Wn=Ls.createDiv({cls:`af-agent-card-toggle${d.heartbeatNotify?" on":""}`});Wn.onclick=()=>{let ot=Wn.hasClass("on");Wn.toggleClass("on",!ot),d.heartbeatNotify=!ot};let Uo=this.plugin.runtime.getSnapshot(),za=st.createDiv({cls:"af-form-row"}),Ga=za.createDiv({cls:"af-form-label"});Ga.setText("Post to channel"),this.addTooltip(Ga,"Heartbeat results are posted to this Slack channel when the run completes");let Fs=za.createEl("select",{cls:"af-form-select"});Fs.createEl("option",{text:"(none)",attr:{value:""}});for(let ot of Uo.channels){let $o=Fs.createEl("option",{text:ot.name,attr:{value:ot.name}});ot.name===d.heartbeatChannel&&($o.selected=!0)}Fs.addEventListener("change",()=>{d.heartbeatChannel=Fs.value});let Os=st.createDiv({cls:"af-form-label"});Os.setCssStyles({width:"auto"}),Os.setCssStyles({marginTop:"12px"}),Os.setText("Instruction"),this.addTooltip(Os,'What the agent does on each heartbeat. Also used by the "Run Now" button.');let Hn=st.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"Check status, scan for issues, report findings...",rows:"8"}});Hn.value=d.heartbeatBody,Hn.addEventListener("input",()=>{d.heartbeatBody=Hn.value})}let ke=u.createDiv({cls:"af-create-section"}),Oe=ke.createDiv({cls:"af-create-section-header"}),Ue=Oe.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(Ue,"puzzle"),Oe.createSpan({text:"Skills"});let Ne=this.plugin.runtime.getSnapshot();if(Ne.skills.length>0){ke.createDiv({cls:"af-form-sublabel",text:"Shared Skills"});let O=ke.createDiv({cls:"af-create-skills-grid"});for(let Y of Ne.skills){let _e=O.createDiv({cls:"af-create-skill-item"}),Se=_e.createEl("input",{cls:"af-form-toggle",attr:{type:"checkbox"}});Se.checked=d.selectedSkills.has(Y.name),Se.addEventListener("change",()=>{Se.checked?d.selectedSkills.add(Y.name):d.selectedSkills.delete(Y.name)});let tt=_e.createDiv({cls:"af-create-skill-label"});tt.createSpan({cls:"af-create-skill-name",text:Y.name}),Y.description&&tt.createSpan({cls:"af-create-skill-desc",text:` \u2014 ${Y.description}`})}}let H=ke.createDiv({cls:"af-form-sublabel"});H.setText("Agent-specific skills"),this.addTooltip(H,"Custom skills/instructions only for this agent, not shared with others");let ie=ke.createEl("textarea",{cls:"af-create-textarea",attr:{placeholder:"Custom skills/instructions for this agent...",rows:"4"}});ie.value=a.skillsBody,ie.addEventListener("input",()=>{d.skillsBody=ie.value});let $=u.createDiv({cls:"af-create-section"}),Te=$.createDiv({cls:"af-create-section-header"}),xe=Te.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(xe,"plug");let he=Te.createSpan({text:"MCP Servers"});this.addTooltip(he,"Grant agent access to MCP servers"),this.renderAgentMcpPicker($,d.selectedMcpServers);let $e=u.createDiv({cls:"af-create-section"}),re=$e.createDiv({cls:"af-create-section-header"}),R=re.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(R,"file-text");let se=re.createSpan({text:"Context"});this.addTooltip(se,"Project-specific context included in every run");let ce=$e.createEl("textarea",{cls:"af-create-textarea",attr:{placeholder:"Background info, repo structure, conventions...",rows:"4"}});ce.value=a.contextBody,ce.addEventListener("input",()=>{d.contextBody=ce.value});let te=u.createDiv({cls:"af-create-section"}),Ze=te.createDiv({cls:"af-create-section-header"}),as=Ze.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(as,"shield-check"),Ze.createSpan({text:"Permissions"}),this.createFormField(te,"Approval required","git_push, file_delete","Comma-separated tool names",O=>{d.approvalRequired=O},a.approvalRequired.join(", "));let is=te.createDiv({cls:"af-form-row"});is.createDiv({cls:"af-form-label",text:"Allowed Commands"});let rs=is.createEl("textarea",{cls:"af-create-textarea",attr:{placeholder:`Bash(curl *)
12080
12080
  Bash(python3 *)
12081
12081
  Read
12082
12082
  Edit
12083
12083
  Write`,rows:"4"}});rs.value=a.permissionRules.allow.join(`
12084
- `),rs.addEventListener("input",()=>{h.allowedCommands=rs.value});let Ft=Me.createDiv({cls:"af-form-row"});Ft.createDiv({cls:"af-form-label",text:"Blocked Commands"});let B=Ft.createEl("textarea",{cls:"af-create-textarea",attr:{placeholder:`Bash(git push *)
12084
+ `),rs.addEventListener("input",()=>{d.allowedCommands=rs.value});let Ft=te.createDiv({cls:"af-form-row"});Ft.createDiv({cls:"af-form-label",text:"Blocked Commands"});let B=Ft.createEl("textarea",{cls:"af-create-textarea",attr:{placeholder:`Bash(git push *)
12085
12085
  Bash(rm -rf *)
12086
12086
  Bash(sudo *)`,rows:"4"}});B.value=a.permissionRules.deny.join(`
12087
- `),B.addEventListener("input",()=>{h.blockedCommands=B.value}),Me.createDiv({cls:"af-form-hint",text:"On Codex agents these become execpolicy command rules \u2014 only Bash(cmd args *) prefixes are enforced; tool-name rules (Read/Write) and mid-pattern wildcards are ignored, and file/network access is governed by Permission Mode (the sandbox)."});let K=Me.createDiv({cls:"af-form-row"});K.createDiv({cls:"af-form-label",text:"Memory enabled"});let Ee=K.createDiv({cls:`af-agent-card-toggle${a.memory?" on":""}`});Ee.onclick=()=>{let M=Ee.hasClass("on");Ee.toggleClass("on",!M),h.memory=!M};let ve=Me.createDiv({cls:"af-form-row"});ve.createDiv({cls:"af-form-label",text:"Memory token budget"});let Ae=ve.createEl("input",{cls:"af-create-input",attr:{type:"number",min:"200",step:"100"}});Ae.value=String(h.memoryTokenBudget),Ae.addEventListener("input",()=>{let M=parseInt(Ae.value,10);Number.isFinite(M)&&(h.memoryTokenBudget=M)});let tt=Me.createDiv({cls:"af-form-row"});tt.createDiv({cls:"af-form-label",text:"Nightly reflection"});let We=tt.createDiv({cls:`af-agent-card-toggle${a.reflection.enabled?" on":""}`});We.onclick=()=>{let M=We.hasClass("on");We.toggleClass("on",!M),h.reflectionEnabled=!M};let St=Me.createDiv({cls:"af-form-row"});St.createDiv({cls:"af-form-label",text:"Propose skills from memory"});let Ot=St.createDiv({cls:`af-agent-card-toggle${a.reflection.proposeSkills?" on":""}`});Ot.onclick=()=>{let M=Ot.hasClass("on");Ot.toggleClass("on",!M),h.reflectionProposeSkills=!M};let yt=s.createDiv({cls:"af-create-footer"}),os=yt.createEl("button",{cls:"af-btn-sm danger"});D(os,"trash-2","af-btn-icon"),os.appendText(" Delete"),os.onclick=()=>void this.plugin.deleteAgent(a.name),yt.createDiv({cls:"af-toolbar-spacer"});let Ms=yt.createEl("button",{cls:"af-btn-sm",text:"Cancel"});Ms.onclick=()=>this.navigate("agent-detail",a.name);let Nt=yt.createEl("button",{cls:"af-btn-sm primary af-create-submit"});D(Nt,"check","af-btn-icon"),Nt.appendText(" Save Changes"),Nt.onclick=async()=>{let M=J=>J.split(",").map(Te=>Te.trim()).filter(Boolean);try{let J=Te=>pe(Te).map(ke=>ke.trim()).filter(Boolean);await this.plugin.repository.updateAgent(a.name,{description:h.description.trim(),avatar:h.avatar.trim(),tags:M(h.tags),systemPrompt:h.systemPrompt.trim(),model:h.model.trim()||"default",adapter:h.adapter,cwd:h.cwd.trim(),timeout:h.timeout,permissionMode:h.permissionMode,effort:h.effort||void 0,approvalRequired:M(h.approvalRequired),memory:h.memory,memoryTokenBudget:h.memoryTokenBudget,reflectionEnabled:h.reflectionEnabled,reflectionProposeSkills:h.reflectionProposeSkills,skills:Array.from(h.selectedSkills),mcpServers:Array.from(h.selectedMcpServers),skillsBody:h.skillsBody.trim(),contextBody:h.contextBody.trim(),enabled:h.enabled,permissionRules:{allow:J(h.allowedCommands),deny:J(h.blockedCommands)},autoCompactThreshold:h.autoCompactThreshold,wikiReferences:h.wikiReferences}),a.isFolder&&await this.plugin.repository.updateHeartbeat(a.name,{enabled:h.heartbeatEnabled,schedule:h.heartbeatSchedule.trim(),notify:h.heartbeatNotify,channel:h.heartbeatChannel,body:h.heartbeatBody.trim()}),new b.Notice(`Agent "${a.name}" updated.`),await this.plugin.refreshFromVault(),this.navigate("agent-detail",a.name)}catch(J){let Te=J instanceof Error?J.message:String(J);new b.Notice(`Failed to update agent: ${Te}`)}}}renderCreateTaskPage(e){let s=e.createDiv({cls:"af-create-agent-page"}),n=this.plugin.runtime.getSnapshot(),a=s.createDiv({cls:"af-detail-header"}),r=a.createDiv({cls:"af-detail-header-left"}),o=r.createDiv({cls:"af-agent-card-avatar idle"});(0,b.setIcon)(o,"plus");let c=r.createDiv();c.createDiv({cls:"af-detail-header-name",text:"Create New Task"}),c.createDiv({cls:"af-detail-header-desc",text:"Configure a new task for your fleet"}),a.createDiv({cls:"af-detail-header-actions"});let l={title:"",agent:n.agents[0]?.name??"",priority:"medium",tags:"",body:"",scheduleEnabled:!1,scheduleMode:"recurring",schedule:"0 9 * * *",runAt:"",type:"immediate",enabled:!0,catchUp:!0,effort:"",model:""},d=s.createDiv({cls:"af-create-form"}),h=d.createDiv({cls:"af-create-section"}),u=h.createDiv({cls:"af-create-section-header"}),p=u.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(p,"file-text"),u.createSpan({text:"Task Details"}),this.createFormField(h,"Title","Daily status report","Used as the task identifier",q=>{l.title=q});let f=h.createDiv({cls:"af-form-row"});f.createDiv({cls:"af-form-label",text:"Agent"});let m=f.createEl("select",{cls:"af-form-select"});for(let q of n.agents)m.createEl("option",{text:q.name,attr:{value:q.name}});m.addEventListener("change",()=>{l.agent=m.value});let g=h.createDiv({cls:"af-form-row"});g.createDiv({cls:"af-form-label",text:"Priority"});let v=g.createEl("select",{cls:"af-form-select"}),k=[["low","Low"],["medium","Medium"],["high","High"],["critical","Critical"]];for(let[q,ie]of k){let $=v.createEl("option",{text:ie,attr:{value:q}});q==="medium"&&($.selected=!0)}v.addEventListener("change",()=>{l.priority=v.value}),this.createFormField(h,"Tags","monitoring, devops","Comma-separated",q=>{l.tags=q});let w=d.createDiv({cls:"af-create-section"}),y=w.createDiv({cls:"af-create-section-header"}),C=y.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(C,"message-square"),y.createSpan({text:"Instructions"});let T=w.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"Describe what the agent should do...",rows:"10"}});T.addEventListener("input",()=>{l.body=T.value});let _=d.createDiv({cls:"af-create-section"}),O=_.createDiv({cls:"af-create-section-header"}),E=O.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(E,"clock"),O.createSpan({text:"Schedule"});let S=_.createDiv({cls:"af-form-row af-form-row-toggle"});S.createDiv({cls:"af-form-label",text:"Enable schedule"});let P=S.createDiv({cls:"af-agent-card-toggle"}),R=_.createDiv({cls:"af-schedule-body"});R.style.display="none",P.onclick=()=>{let q=P.hasClass("on");P.toggleClass("on",!q),l.scheduleEnabled=!q,R.style.display=q?"none":"",q?l.type="immediate":l.type=l.scheduleMode==="once"?"once":"recurring"};let N=R.createDiv({cls:"af-form-row"});N.createDiv({cls:"af-form-label",text:"Mode"});let L=N.createEl("select",{cls:"af-form-select"});for(let[q,ie]of[["recurring","Recurring"],["once","One-time"]])L.createEl("option",{text:ie,attr:{value:q}});let G=R.createDiv(),U=R.createDiv();U.style.display="none",this.renderInlineSchedule(G,l);let X=U.createDiv({cls:"af-form-row"});X.createDiv({cls:"af-form-label",text:"Run at"});let me=X.createEl("input",{cls:"af-form-input",attr:{type:"datetime-local",value:this.toDatetimeLocal(new Date(Date.now()+36e5))}});l.runAt=new Date(me.value).toISOString(),me.addEventListener("input",()=>{l.runAt=me.value?new Date(me.value).toISOString():""}),L.addEventListener("change",()=>{l.scheduleMode=L.value,G.style.display=l.scheduleMode==="recurring"?"":"none",U.style.display=l.scheduleMode==="once"?"":"none",l.scheduleEnabled&&(l.type=l.scheduleMode==="once"?"once":"recurring")});let ye=R.createDiv({cls:"af-form-row af-form-row-toggle"});ye.createDiv({cls:"af-form-label",text:"Enabled"});let ee=ye.createDiv({cls:"af-agent-card-toggle on"});ee.onclick=()=>{let q=ee.hasClass("on");ee.toggleClass("on",!q),l.enabled=!q};let W=R.createDiv({cls:"af-form-row af-form-row-toggle"});W.createDiv({cls:"af-form-label"}).setText("Catch up if missed");let V=W.createDiv({cls:`af-agent-card-toggle${l.catchUp?" on":""}`});V.onclick=()=>{let q=V.hasClass("on");V.toggleClass("on",!q),l.catchUp=!q};let te=d.createDiv({cls:"af-create-section"}),Y=te.createDiv({cls:"af-create-section-header"}),Z=Y.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(Z,"gauge"),Y.createSpan({text:"Execution"});let j=te.createDiv({cls:"af-form-row"}),fe=j.createDiv({cls:"af-form-label",text:"Model"}),Pe=j.createDiv({cls:"af-form-field-wrap"}),Oe=q=>{Pe.empty();let ie=n.agents.find($=>$.name===q);At(Pe,{value:l.model,adapter:ie?.adapter,onChange:$=>{l.model=$},allowInherit:!0,inheritPlaceholder:ie?`Inherit from ${ie.name}${ie.model?` (${ie.model})`:""}`:"Inherit from agent"})};Oe(l.agent),m.addEventListener("change",()=>Oe(m.value)),this.addTooltip(fe,"Override the agent\u2019s model for this task only. Useful for routing simple runs to haiku while the agent stays on opus for heavier work.");let Ue=te.createDiv({cls:"af-form-row"}),Re=Ue.createDiv({cls:"af-form-label",text:"Effort"}),Se=Ue.createEl("select",{cls:"af-form-select"});for(let[q,ie]of[["","Agent Default"],["low","Low"],["medium","Medium"],["high","High"],["max","Max"]]){let $=Se.createEl("option",{text:ie,attr:{value:q}});q===l.effort&&($.selected=!0)}Se.addEventListener("change",()=>{l.effort=Se.value}),this.addTooltip(Re,"Overrides the agent\u2019s effort level for this task. Higher effort = more thinking tokens spent.");let De=s.createDiv({cls:"af-create-footer"}),Ne=De.createEl("button",{cls:"af-btn-sm",text:"Cancel"});Ne.onclick=()=>this.navigate("kanban");let $e=De.createEl("button",{cls:"af-btn-sm primary af-create-submit"});D($e,"plus","af-btn-icon"),$e.appendText(" Create Task"),$e.onclick=async()=>{let q=l.title.trim();if(!q){new b.Notice("Task title is required.");return}let ie=ae(q),$=ge=>ge.split(",").map(Ie=>Ie.trim()).filter(Boolean),Ce=l.scheduleEnabled?l.scheduleMode==="once"?"once":"recurring":"immediate",we={task_id:ie,agent:l.agent,type:Ce,priority:l.priority,enabled:l.enabled,created:this.toLocalISO(new Date),run_count:0,catch_up:l.catchUp,effort:l.effort||void 0,model:l.model||void 0,tags:$(l.tags)};if(Ce==="recurring")we.schedule=l.schedule.trim()||"0 9 * * *";else if(Ce==="once"){if(!l.runAt){new b.Notice("Pick a date/time for the one-time run.");return}we.run_at=l.runAt}try{let ge=await this.plugin.repository.getAvailablePath(this.plugin.repository.getSubfolder("tasks"),ie);await this.plugin.app.vault.create(ge,H(we,l.body.trim()||"Describe the task here.")),new b.Notice(`Task "${ie}" created.`),await this.plugin.refreshFromVault(),this.navigate("task-detail",ie)}catch(ge){let Ie=ge instanceof Error?ge.message:String(ge);new b.Notice(`Failed to create task: ${Ie}`)}}}toLocalISO(e){let s=n=>String(n).padStart(2,"0");return`${e.getFullYear()}-${s(e.getMonth()+1)}-${s(e.getDate())}T${s(e.getHours())}:${s(e.getMinutes())}:${s(e.getSeconds())}`}toDatetimeLocal(e){let s=n=>String(n).padStart(2,"0");return`${e.getFullYear()}-${s(e.getMonth()+1)}-${s(e.getDate())}T${s(e.getHours())}:${s(e.getMinutes())}`}renderEditTaskPage(e){let s=e.createDiv({cls:"af-create-agent-page"}),n=this.detailContext;if(!n){this.renderEmptyState(s,"circle-dot","No task selected","");return}let a=this.plugin.runtime.getSnapshot().tasks.find(I=>I.taskId===n);if(!a){this.renderEmptyState(s,"circle-dot","Task not found",`Task "${n}" was not found`);return}let r=this.plugin.runtime.getSnapshot(),o=s.createDiv({cls:"af-detail-header"}),c=o.createDiv({cls:"af-detail-header-left"}),l=c.createDiv({cls:"af-agent-card-avatar idle"});(0,b.setIcon)(l,"edit");let d=c.createDiv();d.createDiv({cls:"af-detail-header-name",text:`Edit Task: ${a.taskId}`}),d.createDiv({cls:"af-detail-header-desc",text:"Modify task configuration"}),o.createDiv({cls:"af-detail-header-actions"});let h=!!(a.schedule||a.runAt),u={agent:a.agent,type:a.type,priority:a.priority,schedule:a.schedule??"0 9 * * *",runAt:a.runAt??"",scheduleEnabled:h,scheduleMode:a.type==="once"?"once":"recurring",enabled:a.enabled,catchUp:a.catchUp,effort:a.effort??"",model:a.model??"",tags:a.tags.join(", "),body:a.body},p=s.createDiv({cls:"af-create-form"}),f=p.createDiv({cls:"af-create-section"}),m=f.createDiv({cls:"af-create-section-header"}),g=m.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(g,"file-text"),m.createSpan({text:"Task Details"});let v=f.createDiv({cls:"af-form-row"});v.createDiv({cls:"af-form-label",text:"Title"});let k=v.createEl("input",{cls:"af-form-input",attr:{type:"text",value:a.taskId,disabled:"true"}});k.style.opacity="0.6";let w=f.createDiv({cls:"af-form-row"});w.createDiv({cls:"af-form-label",text:"Agent"});let y=w.createEl("select",{cls:"af-form-select"});for(let I of r.agents){let ne=y.createEl("option",{text:I.name,attr:{value:I.name}});I.name===a.agent&&(ne.selected=!0)}y.addEventListener("change",()=>{u.agent=y.value});let C=f.createDiv({cls:"af-form-row"});C.createDiv({cls:"af-form-label",text:"Priority"});let T=C.createEl("select",{cls:"af-form-select"}),_=[["low","Low"],["medium","Medium"],["high","High"],["critical","Critical"]];for(let[I,ne]of _){let he=T.createEl("option",{text:ne,attr:{value:I}});I===a.priority&&(he.selected=!0)}T.addEventListener("change",()=>{u.priority=T.value}),this.createFormField(f,"Tags","monitoring, critical","Comma-separated",I=>{u.tags=I},a.tags.join(", "));let O=p.createDiv({cls:"af-create-section"}),E=O.createDiv({cls:"af-create-section-header"}),S=E.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(S,"message-square"),E.createSpan({text:"Instructions"});let P=O.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"Describe what the agent should do...",rows:"10"}});P.value=a.body,P.addEventListener("input",()=>{u.body=P.value});let R=p.createDiv({cls:"af-create-section"}),N=R.createDiv({cls:"af-create-section-header"}),L=N.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(L,"clock"),N.createSpan({text:"Schedule"});let G=R.createDiv({cls:"af-form-row af-form-row-toggle"});G.createDiv({cls:"af-form-label",text:"Enable schedule"});let U=G.createDiv({cls:`af-agent-card-toggle${h?" on":""}`}),X=R.createDiv({cls:"af-schedule-body"});X.style.display=h?"":"none",U.onclick=()=>{let I=U.hasClass("on");U.toggleClass("on",!I),u.scheduleEnabled=!I,X.style.display=I?"none":"",I?u.type="immediate":u.type=u.scheduleMode==="once"?"once":"recurring"};let me=X.createDiv({cls:"af-form-row"});me.createDiv({cls:"af-form-label",text:"Mode"});let ye=me.createEl("select",{cls:"af-form-select"});for(let[I,ne]of[["recurring","Recurring"],["once","One-time"]]){let he=ye.createEl("option",{text:ne,attr:{value:I}});I===u.scheduleMode&&(he.selected=!0)}let ee=X.createDiv(),W=X.createDiv();ee.style.display=u.scheduleMode==="recurring"?"":"none",W.style.display=u.scheduleMode==="once"?"":"none",this.renderInlineSchedule(ee,u);let de=W.createDiv({cls:"af-form-row"});de.createDiv({cls:"af-form-label",text:"Run at"});let V=u.runAt?this.toDatetimeLocal(new Date(u.runAt)):this.toDatetimeLocal(new Date(Date.now()+36e5)),te=de.createEl("input",{cls:"af-form-input",attr:{type:"datetime-local",value:V}});u.runAt||(u.runAt=new Date(te.value).toISOString()),te.addEventListener("input",()=>{u.runAt=te.value?new Date(te.value).toISOString():""}),ye.addEventListener("change",()=>{u.scheduleMode=ye.value,ee.style.display=u.scheduleMode==="recurring"?"":"none",W.style.display=u.scheduleMode==="once"?"":"none",u.scheduleEnabled&&(u.type=u.scheduleMode==="once"?"once":"recurring")});let Y=X.createDiv({cls:"af-form-row af-form-row-toggle"});Y.createDiv({cls:"af-form-label",text:"Enabled"});let Z=Y.createDiv({cls:`af-agent-card-toggle${a.enabled?" on":""}`});Z.onclick=()=>{let I=Z.hasClass("on");Z.toggleClass("on",!I),u.enabled=!I};let j=X.createDiv({cls:"af-form-row af-form-row-toggle"});j.createDiv({cls:"af-form-label"}).setText("Catch up if missed");let Pe=j.createDiv({cls:`af-agent-card-toggle${u.catchUp?" on":""}`});Pe.onclick=()=>{let I=Pe.hasClass("on");Pe.toggleClass("on",!I),u.catchUp=!I};let Oe=p.createDiv({cls:"af-create-section"}),Ue=Oe.createDiv({cls:"af-create-section-header"}),Re=Ue.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(Re,"gauge"),Ue.createSpan({text:"Execution"});let Se=Oe.createDiv({cls:"af-form-row"}),De=Se.createDiv({cls:"af-form-label",text:"Effort"}),Ne=Se.createEl("select",{cls:"af-form-select"}),$e=[["","Agent Default"],["low","Low"],["medium","Medium"],["high","High"],["max","Max"]];for(let[I,ne]of $e){let he=Ne.createEl("option",{text:ne,attr:{value:I}});I===u.effort&&(he.selected=!0)}Ne.addEventListener("change",()=>{u.effort=Ne.value}),this.addTooltip(De,"Overrides the agent\u2019s effort level for this task. Higher effort = more thinking tokens spent.");let q=Oe.createDiv({cls:"af-form-row"}),ie=q.createDiv({cls:"af-form-label",text:"Model"}),$=q.createDiv({cls:"af-form-field-wrap"}),Ce=I=>{$.empty();let ne=r.agents.find(he=>he.name===I);At($,{value:u.model,adapter:ne?.adapter,onChange:he=>{u.model=he},allowInherit:!0,inheritPlaceholder:ne?`Inherit from ${ne.name}${ne.model?` (${ne.model})`:""}`:"Inherit from agent"})};Ce(u.agent),y.addEventListener("change",()=>Ce(y.value)),this.addTooltip(ie,"Override the agent\u2019s model for this task only. Useful for routing simple runs to haiku while the agent stays on opus for heavier work.");let we=s.createDiv({cls:"af-create-footer"}),ge=we.createEl("button",{cls:"af-btn-sm danger"});D(ge,"trash-2","af-btn-icon"),ge.appendText(" Delete"),ge.onclick=async()=>{await this.plugin.repository.deleteTask(a.taskId),new b.Notice(`Task "${a.taskId}" deleted.`),await new Promise(I=>setTimeout(I,200)),await this.plugin.refreshFromVault(),this.navigate("kanban")},we.createDiv({cls:"af-toolbar-spacer"});let Ie=we.createEl("button",{cls:"af-btn-sm",text:"Cancel"});Ie.onclick=()=>this.navigate("task-detail",a.taskId);let se=we.createEl("button",{cls:"af-btn-sm primary af-create-submit"});D(se,"check","af-btn-icon"),se.appendText(" Save Changes"),se.onclick=async()=>{let I=he=>he.split(",").map(oe=>oe.trim()).filter(Boolean),ne=u.scheduleEnabled?u.scheduleMode==="once"?"once":"recurring":"immediate";if(ne==="once"&&!u.runAt){new b.Notice("Pick a date/time for the one-time run.");return}try{await this.plugin.repository.updateTask(a.taskId,{agent:u.agent,type:ne,priority:u.priority,schedule:ne==="recurring"?u.schedule.trim():"",runAt:ne==="once"?u.runAt:"",enabled:u.enabled,catch_up:u.catchUp,effort:u.effort||void 0,model:u.model||"",tags:I(u.tags),body:u.body.trim()}),new b.Notice(`Task "${a.taskId}" updated.`),await this.plugin.refreshFromVault(),this.navigate("task-detail",a.taskId)}catch(he){let oe=he instanceof Error?he.message:String(he);new b.Notice(`Failed to update task: ${oe}`)}}}renderEditSkillPage(e){let s=e.createDiv({cls:"af-create-agent-page"}),n=this.detailContext;if(!n){this.renderEmptyState(s,"puzzle","No skill selected","");return}let a=this.plugin.runtime.getSnapshot().skills.find(Y=>Y.name===n);if(!a){this.renderEmptyState(s,"puzzle","Skill not found",`Skill "${n}" was not found`);return}let r=s.createDiv({cls:"af-detail-header"}),o=r.createDiv({cls:"af-detail-header-left"}),c=o.createDiv({cls:"af-agent-card-avatar idle"});(0,b.setIcon)(c,"edit");let l=o.createDiv();l.createDiv({cls:"af-detail-header-name",text:`Edit Skill: ${a.name}`}),l.createDiv({cls:"af-detail-header-desc",text:"Modify skill definition"});let d=r.createDiv({cls:"af-detail-header-actions"}),h={description:a.description??"",tags:a.tags.join(", "),body:a.body,toolsBody:a.toolsBody,referencesBody:a.referencesBody,examplesBody:a.examplesBody},u=s.createDiv({cls:"af-create-form"}),p=u.createDiv({cls:"af-create-section"}),f=p.createDiv({cls:"af-create-section-header"}),m=f.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(m,"puzzle"),f.createSpan({text:"Identity"});let g=p.createDiv({cls:"af-form-row"});g.createDiv({cls:"af-form-label",text:"Name"});let v=g.createEl("input",{cls:"af-form-input",attr:{type:"text",value:a.name,disabled:"true"}});v.style.opacity="0.6",this.createFormField(p,"Description","Manage tasks and projects via CLI","",Y=>{h.description=Y},a.description??""),this.createFormField(p,"Tags","productivity, tasks","Comma-separated",Y=>{h.tags=Y},a.tags.join(", "));let k=u.createDiv({cls:"af-create-section"}),w=k.createDiv({cls:"af-create-section-header"}),y=w.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(y,"file-text"),w.createSpan({text:"Core Instructions"});let C=k.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"Skill instructions...",rows:"10"}});C.value=a.body,C.addEventListener("input",()=>{h.body=C.value});let T=u.createDiv({cls:"af-create-section"}),_=T.createDiv({cls:"af-create-section-header"}),O=_.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(O,"wrench");let E=_.createSpan({text:"Tools"});this.addTooltip(E,"CLI commands, API endpoints, and tool definitions available to agents using this skill");let S=T.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:`## Commands
12087
+ `),B.addEventListener("input",()=>{d.blockedCommands=B.value}),te.createDiv({cls:"af-form-hint",text:"On Codex agents these become execpolicy command rules \u2014 only Bash(cmd args *) prefixes are enforced; tool-name rules (Read/Write) and mid-pattern wildcards are ignored, and file/network access is governed by Permission Mode (the sandbox)."});let V=te.createDiv({cls:"af-form-row"});V.createDiv({cls:"af-form-label",text:"Memory enabled"});let Pe=V.createDiv({cls:`af-agent-card-toggle${a.memory?" on":""}`});Pe.onclick=()=>{let O=Pe.hasClass("on");Pe.toggleClass("on",!O),d.memory=!O};let we=te.createDiv({cls:"af-form-row"});we.createDiv({cls:"af-form-label",text:"Memory token budget"});let Ee=we.createEl("input",{cls:"af-create-input",attr:{type:"number",min:"200",step:"100"}});Ee.value=String(d.memoryTokenBudget),Ee.addEventListener("input",()=>{let O=parseInt(Ee.value,10);Number.isFinite(O)&&(d.memoryTokenBudget=O)});let et=te.createDiv({cls:"af-form-row"});et.createDiv({cls:"af-form-label",text:"Nightly reflection"});let We=et.createDiv({cls:`af-agent-card-toggle${a.reflection.enabled?" on":""}`});We.onclick=()=>{let O=We.hasClass("on");We.toggleClass("on",!O),d.reflectionEnabled=!O};let St=te.createDiv({cls:"af-form-row"});St.createDiv({cls:"af-form-label",text:"Propose skills from memory"});let Ot=St.createDiv({cls:`af-agent-card-toggle${a.reflection.proposeSkills?" on":""}`});Ot.onclick=()=>{let O=Ot.hasClass("on");Ot.toggleClass("on",!O),d.reflectionProposeSkills=!O};let vt=s.createDiv({cls:"af-create-footer"}),os=vt.createEl("button",{cls:"af-btn-sm danger"});E(os,"trash-2","af-btn-icon"),os.appendText(" Delete"),os.onclick=()=>void this.plugin.deleteAgent(a.name),vt.createDiv({cls:"af-toolbar-spacer"});let Ms=vt.createEl("button",{cls:"af-btn-sm",text:"Cancel"});Ms.onclick=()=>this.navigate("agent-detail",a.name);let Nt=vt.createEl("button",{cls:"af-btn-sm primary af-create-submit"});E(Nt,"check","af-btn-icon"),Nt.appendText(" Save Changes"),Nt.onclick=async()=>{let O=Y=>Y.split(",").map(_e=>_e.trim()).filter(Boolean);try{let Y=_e=>ge(_e).map(Se=>Se.trim()).filter(Boolean);await this.plugin.repository.updateAgent(a.name,{description:d.description.trim(),avatar:d.avatar.trim(),tags:O(d.tags),systemPrompt:d.systemPrompt.trim(),model:d.model.trim()||"default",adapter:d.adapter,cwd:d.cwd.trim(),timeout:d.timeout,permissionMode:d.permissionMode,effort:d.effort||void 0,approvalRequired:O(d.approvalRequired),memory:d.memory,memoryTokenBudget:d.memoryTokenBudget,reflectionEnabled:d.reflectionEnabled,reflectionProposeSkills:d.reflectionProposeSkills,skills:Array.from(d.selectedSkills),mcpServers:Array.from(d.selectedMcpServers),skillsBody:d.skillsBody.trim(),contextBody:d.contextBody.trim(),enabled:d.enabled,permissionRules:{allow:Y(d.allowedCommands),deny:Y(d.blockedCommands)},autoCompactThreshold:d.autoCompactThreshold,wikiReferences:d.wikiReferences}),a.isFolder&&await this.plugin.repository.updateHeartbeat(a.name,{enabled:d.heartbeatEnabled,schedule:d.heartbeatSchedule.trim(),notify:d.heartbeatNotify,channel:d.heartbeatChannel,body:d.heartbeatBody.trim()}),new w.Notice(`Agent "${a.name}" updated.`),await this.plugin.refreshFromVault(),this.navigate("agent-detail",a.name)}catch(Y){let _e=Y instanceof Error?Y.message:String(Y);new w.Notice(`Failed to update agent: ${_e}`)}}}renderCreateTaskPage(e){let s=e.createDiv({cls:"af-create-agent-page"}),n=this.plugin.runtime.getSnapshot(),a=s.createDiv({cls:"af-detail-header"}),r=a.createDiv({cls:"af-detail-header-left"}),o=r.createDiv({cls:"af-agent-card-avatar idle"});(0,w.setIcon)(o,"plus");let c=r.createDiv();c.createDiv({cls:"af-detail-header-name",text:"Create New Task"}),c.createDiv({cls:"af-detail-header-desc",text:"Configure a new task for your fleet"});let l=a.createDiv({cls:"af-detail-header-actions"}),h={title:"",agent:n.agents[0]?.name??"",priority:"medium",tags:"",body:"",scheduleEnabled:!1,scheduleMode:"recurring",schedule:"0 9 * * *",runAt:"",type:"immediate",enabled:!0,catchUp:!0,effort:"",model:""},d=s.createDiv({cls:"af-create-form"}),u=d.createDiv({cls:"af-create-section"}),p=u.createDiv({cls:"af-create-section-header"}),m=p.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(m,"file-text"),p.createSpan({text:"Task Details"}),this.createFormField(u,"Title","Daily status report","Used as the task identifier",H=>{h.title=H});let f=u.createDiv({cls:"af-form-row"});f.createDiv({cls:"af-form-label",text:"Agent"});let g=f.createEl("select",{cls:"af-form-select"});for(let H of n.agents)g.createEl("option",{text:H.name,attr:{value:H.name}});g.addEventListener("change",()=>{h.agent=g.value});let v=u.createDiv({cls:"af-form-row"});v.createDiv({cls:"af-form-label",text:"Priority"});let b=v.createEl("select",{cls:"af-form-select"}),k=[["low","Low"],["medium","Medium"],["high","High"],["critical","Critical"]];for(let[H,ie]of k){let $=b.createEl("option",{text:ie,attr:{value:H}});H==="medium"&&($.selected=!0)}b.addEventListener("change",()=>{h.priority=b.value}),this.createFormField(u,"Tags","monitoring, devops","Comma-separated",H=>{h.tags=H});let y=d.createDiv({cls:"af-create-section"}),S=y.createDiv({cls:"af-create-section-header"}),T=S.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(T,"message-square"),S.createSpan({text:"Instructions"});let _=y.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"Describe what the agent should do...",rows:"10"}});_.addEventListener("input",()=>{h.body=_.value});let D=d.createDiv({cls:"af-create-section"}),M=D.createDiv({cls:"af-create-section-header"}),C=M.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(C,"clock"),M.createSpan({text:"Schedule"});let I=D.createDiv({cls:"af-form-row af-form-row-toggle"});I.createDiv({cls:"af-form-label",text:"Enable schedule"});let P=I.createDiv({cls:"af-agent-card-toggle"}),L=D.createDiv({cls:"af-schedule-body"});L.setCssStyles({display:"none"}),P.onclick=()=>{let H=P.hasClass("on");P.toggleClass("on",!H),h.scheduleEnabled=!H,L.setCssStyles({display:H?"none":""}),H?h.type="immediate":h.type=h.scheduleMode==="once"?"once":"recurring"};let F=L.createDiv({cls:"af-form-row"});F.createDiv({cls:"af-form-label",text:"Mode"});let z=F.createEl("select",{cls:"af-form-select"});for(let[H,ie]of[["recurring","Recurring"],["once","One-time"]])z.createEl("option",{text:ie,attr:{value:H}});let U=L.createDiv(),Z=L.createDiv();Z.setCssStyles({display:"none"}),this.renderInlineSchedule(U,h);let de=Z.createDiv({cls:"af-form-row"});de.createDiv({cls:"af-form-label",text:"Run at"});let me=de.createEl("input",{cls:"af-form-input",attr:{type:"datetime-local",value:this.toDatetimeLocal(new Date(Date.now()+36e5))}});h.runAt=new Date(me.value).toISOString(),me.addEventListener("input",()=>{h.runAt=me.value?new Date(me.value).toISOString():""}),z.addEventListener("change",()=>{h.scheduleMode=z.value,U.setCssStyles({display:h.scheduleMode==="recurring"?"":"none"}),Z.setCssStyles({display:h.scheduleMode==="once"?"":"none"}),h.scheduleEnabled&&(h.type=h.scheduleMode==="once"?"once":"recurring")});let ye=L.createDiv({cls:"af-form-row af-form-row-toggle"});ye.createDiv({cls:"af-form-label",text:"Enabled"});let X=ye.createDiv({cls:"af-agent-card-toggle on"});X.onclick=()=>{let H=X.hasClass("on");X.toggleClass("on",!H),h.enabled=!H};let j=L.createDiv({cls:"af-form-row af-form-row-toggle"});j.createDiv({cls:"af-form-label"}).setText("Catch up if missed");let ne=j.createDiv({cls:`af-agent-card-toggle${h.catchUp?" on":""}`});ne.onclick=()=>{let H=ne.hasClass("on");ne.toggleClass("on",!H),h.catchUp=!H};let G=d.createDiv({cls:"af-create-section"}),ee=G.createDiv({cls:"af-create-section-header"}),Q=ee.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(Q,"gauge"),ee.createSpan({text:"Execution"});let ae=G.createDiv({cls:"af-form-row"}),ve=ae.createDiv({cls:"af-form-label",text:"Model"}),Re=ae.createDiv({cls:"af-form-field-wrap"}),Le=H=>{Re.empty();let ie=n.agents.find($=>$.name===H);At(Re,{value:h.model,adapter:ie?.adapter,onChange:$=>{h.model=$},allowInherit:!0,inheritPlaceholder:ie?`Inherit from ${ie.name}${ie.model?` (${ie.model})`:""}`:"Inherit from agent"})};Le(h.agent),g.addEventListener("change",()=>Le(g.value)),this.addTooltip(ve,"Override the agent\u2019s model for this task only. Useful for routing simple runs to haiku while the agent stays on opus for heavier work.");let Me=G.createDiv({cls:"af-form-row"}),Fe=Me.createDiv({cls:"af-form-label",text:"Effort"}),ke=Me.createEl("select",{cls:"af-form-select"});for(let[H,ie]of[["","Agent Default"],["low","Low"],["medium","Medium"],["high","High"],["max","Max"]]){let $=ke.createEl("option",{text:ie,attr:{value:H}});H===h.effort&&($.selected=!0)}ke.addEventListener("change",()=>{h.effort=ke.value}),this.addTooltip(Fe,"Overrides the agent\u2019s effort level for this task. Higher effort = more thinking tokens spent.");let Oe=s.createDiv({cls:"af-create-footer"}),Ue=Oe.createEl("button",{cls:"af-btn-sm",text:"Cancel"});Ue.onclick=()=>this.navigate("kanban");let Ne=Oe.createEl("button",{cls:"af-btn-sm primary af-create-submit"});E(Ne,"plus","af-btn-icon"),Ne.appendText(" Create Task"),Ne.onclick=async()=>{let H=h.title.trim();if(!H){new w.Notice("Task title is required.");return}let ie=oe(H),$=he=>he.split(",").map($e=>$e.trim()).filter(Boolean),Te=h.scheduleEnabled?h.scheduleMode==="once"?"once":"recurring":"immediate",xe={task_id:ie,agent:h.agent,type:Te,priority:h.priority,enabled:h.enabled,created:this.toLocalISO(new Date),run_count:0,catch_up:h.catchUp,effort:h.effort||void 0,model:h.model||void 0,tags:$(h.tags)};if(Te==="recurring")xe.schedule=h.schedule.trim()||"0 9 * * *";else if(Te==="once"){if(!h.runAt){new w.Notice("Pick a date/time for the one-time run.");return}xe.run_at=h.runAt}try{let he=await this.plugin.repository.getAvailablePath(this.plugin.repository.getSubfolder("tasks"),ie);await this.plugin.app.vault.create(he,W(xe,h.body.trim()||"Describe the task here.")),new w.Notice(`Task "${ie}" created.`),await this.plugin.refreshFromVault(),this.navigate("task-detail",ie)}catch(he){let $e=he instanceof Error?he.message:String(he);new w.Notice(`Failed to create task: ${$e}`)}}}toLocalISO(e){let s=n=>String(n).padStart(2,"0");return`${e.getFullYear()}-${s(e.getMonth()+1)}-${s(e.getDate())}T${s(e.getHours())}:${s(e.getMinutes())}:${s(e.getSeconds())}`}toDatetimeLocal(e){let s=n=>String(n).padStart(2,"0");return`${e.getFullYear()}-${s(e.getMonth()+1)}-${s(e.getDate())}T${s(e.getHours())}:${s(e.getMinutes())}`}renderEditTaskPage(e){let s=e.createDiv({cls:"af-create-agent-page"}),n=this.detailContext;if(!n){this.renderEmptyState(s,"circle-dot","No task selected","");return}let a=this.plugin.runtime.getSnapshot().tasks.find(R=>R.taskId===n);if(!a){this.renderEmptyState(s,"circle-dot","Task not found",`Task "${n}" was not found`);return}let r=this.plugin.runtime.getSnapshot(),o=s.createDiv({cls:"af-detail-header"}),c=o.createDiv({cls:"af-detail-header-left"}),l=c.createDiv({cls:"af-agent-card-avatar idle"});(0,w.setIcon)(l,"edit");let h=c.createDiv();h.createDiv({cls:"af-detail-header-name",text:`Edit Task: ${a.taskId}`}),h.createDiv({cls:"af-detail-header-desc",text:"Modify task configuration"});let d=o.createDiv({cls:"af-detail-header-actions"}),u=!!(a.schedule||a.runAt),p={agent:a.agent,type:a.type,priority:a.priority,schedule:a.schedule??"0 9 * * *",runAt:a.runAt??"",scheduleEnabled:u,scheduleMode:a.type==="once"?"once":"recurring",enabled:a.enabled,catchUp:a.catchUp,effort:a.effort??"",model:a.model??"",tags:a.tags.join(", "),body:a.body},m=s.createDiv({cls:"af-create-form"}),f=m.createDiv({cls:"af-create-section"}),g=f.createDiv({cls:"af-create-section-header"}),v=g.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(v,"file-text"),g.createSpan({text:"Task Details"});let b=f.createDiv({cls:"af-form-row"});b.createDiv({cls:"af-form-label",text:"Title"}),b.createEl("input",{cls:"af-form-input",attr:{type:"text",value:a.taskId,disabled:"true"}}).setCssStyles({opacity:"0.6"});let y=f.createDiv({cls:"af-form-row"});y.createDiv({cls:"af-form-label",text:"Agent"});let S=y.createEl("select",{cls:"af-form-select"});for(let R of r.agents){let se=S.createEl("option",{text:R.name,attr:{value:R.name}});R.name===a.agent&&(se.selected=!0)}S.addEventListener("change",()=>{p.agent=S.value});let T=f.createDiv({cls:"af-form-row"});T.createDiv({cls:"af-form-label",text:"Priority"});let _=T.createEl("select",{cls:"af-form-select"}),D=[["low","Low"],["medium","Medium"],["high","High"],["critical","Critical"]];for(let[R,se]of D){let ce=_.createEl("option",{text:se,attr:{value:R}});R===a.priority&&(ce.selected=!0)}_.addEventListener("change",()=>{p.priority=_.value}),this.createFormField(f,"Tags","monitoring, critical","Comma-separated",R=>{p.tags=R},a.tags.join(", "));let M=m.createDiv({cls:"af-create-section"}),C=M.createDiv({cls:"af-create-section-header"}),I=C.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(I,"message-square"),C.createSpan({text:"Instructions"});let P=M.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"Describe what the agent should do...",rows:"10"}});P.value=a.body,P.addEventListener("input",()=>{p.body=P.value});let L=m.createDiv({cls:"af-create-section"}),F=L.createDiv({cls:"af-create-section-header"}),z=F.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(z,"clock"),F.createSpan({text:"Schedule"});let U=L.createDiv({cls:"af-form-row af-form-row-toggle"});U.createDiv({cls:"af-form-label",text:"Enable schedule"});let Z=U.createDiv({cls:`af-agent-card-toggle${u?" on":""}`}),de=L.createDiv({cls:"af-schedule-body"});de.setCssStyles({display:u?"":"none"}),Z.onclick=()=>{let R=Z.hasClass("on");Z.toggleClass("on",!R),p.scheduleEnabled=!R,de.setCssStyles({display:R?"none":""}),R?p.type="immediate":p.type=p.scheduleMode==="once"?"once":"recurring"};let me=de.createDiv({cls:"af-form-row"});me.createDiv({cls:"af-form-label",text:"Mode"});let ye=me.createEl("select",{cls:"af-form-select"});for(let[R,se]of[["recurring","Recurring"],["once","One-time"]]){let ce=ye.createEl("option",{text:se,attr:{value:R}});R===p.scheduleMode&&(ce.selected=!0)}let X=de.createDiv(),j=de.createDiv();X.setCssStyles({display:p.scheduleMode==="recurring"?"":"none"}),j.setCssStyles({display:p.scheduleMode==="once"?"":"none"}),this.renderInlineSchedule(X,p);let K=j.createDiv({cls:"af-form-row"});K.createDiv({cls:"af-form-label",text:"Run at"});let ne=p.runAt?this.toDatetimeLocal(new Date(p.runAt)):this.toDatetimeLocal(new Date(Date.now()+36e5)),G=K.createEl("input",{cls:"af-form-input",attr:{type:"datetime-local",value:ne}});p.runAt||(p.runAt=new Date(G.value).toISOString()),G.addEventListener("input",()=>{p.runAt=G.value?new Date(G.value).toISOString():""}),ye.addEventListener("change",()=>{p.scheduleMode=ye.value,X.setCssStyles({display:p.scheduleMode==="recurring"?"":"none"}),j.setCssStyles({display:p.scheduleMode==="once"?"":"none"}),p.scheduleEnabled&&(p.type=p.scheduleMode==="once"?"once":"recurring")});let ee=de.createDiv({cls:"af-form-row af-form-row-toggle"});ee.createDiv({cls:"af-form-label",text:"Enabled"});let Q=ee.createDiv({cls:`af-agent-card-toggle${a.enabled?" on":""}`});Q.onclick=()=>{let R=Q.hasClass("on");Q.toggleClass("on",!R),p.enabled=!R};let ae=de.createDiv({cls:"af-form-row af-form-row-toggle"});ae.createDiv({cls:"af-form-label"}).setText("Catch up if missed");let Re=ae.createDiv({cls:`af-agent-card-toggle${p.catchUp?" on":""}`});Re.onclick=()=>{let R=Re.hasClass("on");Re.toggleClass("on",!R),p.catchUp=!R};let Le=m.createDiv({cls:"af-create-section"}),Me=Le.createDiv({cls:"af-create-section-header"}),Fe=Me.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(Fe,"gauge"),Me.createSpan({text:"Execution"});let ke=Le.createDiv({cls:"af-form-row"}),Oe=ke.createDiv({cls:"af-form-label",text:"Effort"}),Ue=ke.createEl("select",{cls:"af-form-select"}),Ne=[["","Agent Default"],["low","Low"],["medium","Medium"],["high","High"],["max","Max"]];for(let[R,se]of Ne){let ce=Ue.createEl("option",{text:se,attr:{value:R}});R===p.effort&&(ce.selected=!0)}Ue.addEventListener("change",()=>{p.effort=Ue.value}),this.addTooltip(Oe,"Overrides the agent\u2019s effort level for this task. Higher effort = more thinking tokens spent.");let H=Le.createDiv({cls:"af-form-row"}),ie=H.createDiv({cls:"af-form-label",text:"Model"}),$=H.createDiv({cls:"af-form-field-wrap"}),Te=R=>{$.empty();let se=r.agents.find(ce=>ce.name===R);At($,{value:p.model,adapter:se?.adapter,onChange:ce=>{p.model=ce},allowInherit:!0,inheritPlaceholder:se?`Inherit from ${se.name}${se.model?` (${se.model})`:""}`:"Inherit from agent"})};Te(p.agent),S.addEventListener("change",()=>Te(S.value)),this.addTooltip(ie,"Override the agent\u2019s model for this task only. Useful for routing simple runs to haiku while the agent stays on opus for heavier work.");let xe=s.createDiv({cls:"af-create-footer"}),he=xe.createEl("button",{cls:"af-btn-sm danger"});E(he,"trash-2","af-btn-icon"),he.appendText(" Delete"),he.onclick=async()=>{await this.plugin.repository.deleteTask(a.taskId),new w.Notice(`Task "${a.taskId}" deleted.`),await new Promise(R=>window.setTimeout(R,200)),await this.plugin.refreshFromVault(),this.navigate("kanban")},xe.createDiv({cls:"af-toolbar-spacer"});let $e=xe.createEl("button",{cls:"af-btn-sm",text:"Cancel"});$e.onclick=()=>this.navigate("task-detail",a.taskId);let re=xe.createEl("button",{cls:"af-btn-sm primary af-create-submit"});E(re,"check","af-btn-icon"),re.appendText(" Save Changes"),re.onclick=async()=>{let R=ce=>ce.split(",").map(te=>te.trim()).filter(Boolean),se=p.scheduleEnabled?p.scheduleMode==="once"?"once":"recurring":"immediate";if(se==="once"&&!p.runAt){new w.Notice("Pick a date/time for the one-time run.");return}try{await this.plugin.repository.updateTask(a.taskId,{agent:p.agent,type:se,priority:p.priority,schedule:se==="recurring"?p.schedule.trim():"",runAt:se==="once"?p.runAt:"",enabled:p.enabled,catch_up:p.catchUp,effort:p.effort||void 0,model:p.model||"",tags:R(p.tags),body:p.body.trim()}),new w.Notice(`Task "${a.taskId}" updated.`),await this.plugin.refreshFromVault(),this.navigate("task-detail",a.taskId)}catch(ce){let te=ce instanceof Error?ce.message:String(ce);new w.Notice(`Failed to update task: ${te}`)}}}renderEditSkillPage(e){let s=e.createDiv({cls:"af-create-agent-page"}),n=this.detailContext;if(!n){this.renderEmptyState(s,"puzzle","No skill selected","");return}let a=this.plugin.runtime.getSnapshot().skills.find(G=>G.name===n);if(!a){this.renderEmptyState(s,"puzzle","Skill not found",`Skill "${n}" was not found`);return}let r=s.createDiv({cls:"af-detail-header"}),o=r.createDiv({cls:"af-detail-header-left"}),c=o.createDiv({cls:"af-agent-card-avatar idle"});(0,w.setIcon)(c,"edit");let l=o.createDiv();l.createDiv({cls:"af-detail-header-name",text:`Edit Skill: ${a.name}`}),l.createDiv({cls:"af-detail-header-desc",text:"Modify skill definition"});let h=r.createDiv({cls:"af-detail-header-actions"}),d={description:a.description??"",tags:a.tags.join(", "),body:a.body,toolsBody:a.toolsBody,referencesBody:a.referencesBody,examplesBody:a.examplesBody},u=s.createDiv({cls:"af-create-form"}),p=u.createDiv({cls:"af-create-section"}),m=p.createDiv({cls:"af-create-section-header"}),f=m.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(f,"puzzle"),m.createSpan({text:"Identity"});let g=p.createDiv({cls:"af-form-row"});g.createDiv({cls:"af-form-label",text:"Name"}),g.createEl("input",{cls:"af-form-input",attr:{type:"text",value:a.name,disabled:"true"}}).setCssStyles({opacity:"0.6"}),this.createFormField(p,"Description","Manage tasks and projects via CLI","",G=>{d.description=G},a.description??""),this.createFormField(p,"Tags","productivity, tasks","Comma-separated",G=>{d.tags=G},a.tags.join(", "));let b=u.createDiv({cls:"af-create-section"}),k=b.createDiv({cls:"af-create-section-header"}),y=k.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(y,"file-text"),k.createSpan({text:"Core Instructions"});let S=b.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"Skill instructions...",rows:"10"}});S.value=a.body,S.addEventListener("input",()=>{d.body=S.value});let T=u.createDiv({cls:"af-create-section"}),_=T.createDiv({cls:"af-create-section-header"}),D=_.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(D,"wrench");let M=_.createSpan({text:"Tools"});this.addTooltip(M,"CLI commands, API endpoints, and tool definitions available to agents using this skill");let C=T.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:`## Commands
12088
12088
 
12089
12089
  ### list
12090
- ...`,rows:"8"}});S.value=a.toolsBody,S.addEventListener("input",()=>{h.toolsBody=S.value});let P=u.createDiv({cls:"af-create-section"}),R=P.createDiv({cls:"af-create-section-header"}),N=R.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(N,"book-open");let L=R.createSpan({text:"References"});this.addTooltip(L,"Background docs, conventions, cheat sheets");let G=P.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"API docs, filter syntax, conventions...",rows:"6"}});G.value=a.referencesBody,G.addEventListener("input",()=>{h.referencesBody=G.value});let U=u.createDiv({cls:"af-create-section"}),X=U.createDiv({cls:"af-create-section-header"}),me=X.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(me,"message-circle");let ye=X.createSpan({text:"Examples"});this.addTooltip(ye,"Example prompts and ideal outputs showing how to use this skill");let ee=U.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:`## Example: List all tasks
12091
- ...`,rows:"6"}});ee.value=a.examplesBody,ee.addEventListener("input",()=>{h.examplesBody=ee.value});let W=s.createDiv({cls:"af-create-footer"}),de=W.createEl("button",{cls:"af-btn-sm danger"});D(de,"trash-2","af-btn-icon"),de.appendText(" Delete"),de.onclick=async()=>{await this.plugin.repository.deleteSkill(a.name),new b.Notice(`Skill "${a.name}" deleted.`),await new Promise(Y=>setTimeout(Y,200)),await this.plugin.refreshFromVault(),this.navigate("skills")},W.createDiv({cls:"af-toolbar-spacer"});let V=W.createEl("button",{cls:"af-btn-sm",text:"Cancel"});V.onclick=()=>this.navigate("skills");let te=W.createEl("button",{cls:"af-btn-sm primary af-create-submit"});D(te,"check","af-btn-icon"),te.appendText(" Save Changes"),te.onclick=async()=>{let Y=Z=>Z.split(",").map(j=>j.trim()).filter(Boolean);try{await this.plugin.repository.updateSkill(a.name,{description:h.description.trim(),tags:Y(h.tags),body:h.body.trim(),toolsBody:h.toolsBody.trim(),referencesBody:h.referencesBody.trim(),examplesBody:h.examplesBody.trim()}),new b.Notice(`Skill "${a.name}" updated.`),await this.plugin.refreshFromVault(),this.navigate("skills")}catch(Z){let j=Z instanceof Error?Z.message:String(Z);new b.Notice(`Failed to update skill: ${j}`)}}}renderAgentMcpPicker(e,s){e.createDiv({cls:"af-form-hint",text:"Servers from the MCP Servers tab. Checked servers are available to this agent on any adapter (Claude or Codex). Leave all unchecked to grant every enabled server."});let n=this.plugin.repository.getMcpServers();if(n.length===0){let r=e.createDiv({cls:"af-form-hint"});r.appendText("No MCP servers registered yet. ");let o=r.createEl("a",{cls:"af-link",text:"Add one in the MCP Servers tab."});o.onclick=c=>{c.preventDefault(),this.navigate("mcp")};return}let a=e.createDiv({cls:"af-create-skills-grid"});for(let r of n){let o=a.createDiv({cls:"af-mcp-agent-item"}),c=o.createEl("input",{cls:"af-form-toggle",attr:{type:"checkbox"}});c.checked=s.has(r.name),c.addEventListener("change",()=>{c.checked?s.add(r.name):s.delete(r.name)});let d=o.createDiv({cls:"af-mcp-agent-label"}).createDiv({cls:"af-mcp-agent-name-row"}),h=d.createSpan({cls:`af-mcp-status-dot ${r.enabled?"idle":"disabled"}`});h.title=r.enabled?"enabled":"disabled",d.createSpan({cls:"af-create-skill-name",text:r.name}),d.createSpan({cls:"af-mcp-agent-tool-count",text:r.type}),r.enabled||d.createSpan({cls:"af-mcp-agent-tool-count af-muted",text:"disabled"})}}renderMcpPage(e){let s=e.createDiv({cls:"af-agents-page"}),n=s.createDiv({cls:"af-agents-toolbar"});n.createDiv({cls:"af-page-title",text:"MCP Servers"}),n.createDiv({cls:"af-toolbar-spacer"});let a=n.createEl("button",{cls:"af-btn-sm primary"});D(a,"plus","af-btn-icon"),a.appendText(" Add Server"),a.onclick=()=>this.navigate("add-mcp-server");let r=this.plugin.repository.getMcpServers();if(r.length===0){this.renderEmptyState(s,"plug","No MCP servers registered","Click 'Add Server' above to register one.");return}let o=s.createDiv({cls:"af-agents-grid"});for(let c of r)this.renderMcpCard(o,c)}mcpProbeCache=new Map;mcpHasToken(e){return this.plugin.mcpAuth.hasToken(e.name)}mcpNeedsAuth(e){return e.type!=="stdio"&&(e.auth==="oauth"||e.auth==="bearer")&&!this.mcpHasToken(e)}renderMcpCard(e,s){let n=e.createDiv({cls:`af-mcp-card${s.enabled?"":" af-mcp-card-disabled"}`}),a=this.mcpNeedsAuth(s),r=n.createDiv({cls:"af-agent-card-header"}),o=s.enabled?a?"pending":"idle":"disabled",c=r.createDiv({cls:`af-agent-card-avatar ${o}`});(0,b.setIcon)(c,"plug");let l=r.createDiv({cls:"af-agent-card-titleblock"});l.createDiv({cls:"af-agent-card-name",text:s.name});let d=l.createDiv({cls:"af-agent-card-desc af-mcp-meta"});d.createSpan({cls:"af-mcp-type-badge",text:s.type}),s.source==="imported"&&d.createSpan({cls:"af-badge",text:"imported"});let h=r.createDiv({cls:`af-agent-card-toggle${s.enabled?" on":""}`});h.onclick=g=>{g.stopPropagation(),this.plugin.repository.setMcpServerEnabled(s.name,!s.enabled).then(async()=>{await this.plugin.refreshFromVault(),this.render()})};let u=n.createDiv({cls:`af-mcp-status-badge ${s.enabled?a?"needs-auth":"connected":"disabled"}`}),p=u.createSpan();if(s.enabled?a?((0,b.setIcon)(p,"alert-circle"),u.createSpan({text:" Needs auth"})):((0,b.setIcon)(p,"check-circle"),u.createSpan({text:s.type==="stdio"?" Enabled":" Authenticated"})):((0,b.setIcon)(p,"pause"),u.createSpan({text:" Disabled"})),s.description){let g=this.truncateDescription(s.description,120);n.createDiv({cls:"af-mcp-description",text:g})}let f=s.url??s.command??"";f&&n.createDiv({cls:"af-mcp-command",text:Ut(f,60)});let m=this.mcpProbeCache.get(s.name);if(m&&m.length>0){let g=n.createDiv({cls:"af-mcp-tool-footer"}),v=g.createDiv({cls:"af-mcp-tool-count"}),k=v.createSpan();(0,b.setIcon)(k,"wrench"),v.createSpan({text:` ${m.length} tools`});let w=g.createDiv({cls:"af-mcp-tool-chips"});for(let y of m.slice(0,4))w.createSpan({cls:"af-mcp-tool-chip",text:y.name});m.length>4&&w.createSpan({cls:"af-mcp-tool-chip af-mcp-tool-chip-more",text:`+${m.length-4}`})}if(this.authenticatingServers.has(s.name)){let v=n.createDiv({cls:"af-mcp-auth-row"}).createEl("button",{cls:"af-btn-sm primary",attr:{disabled:"true"}}),k=v.createSpan({cls:"af-spin"});(0,b.setIcon)(k,"loader-2"),v.appendText(" Authenticating\u2026")}else if(s.enabled&&a&&s.auth==="oauth"){let v=n.createDiv({cls:"af-mcp-auth-row"}).createEl("button",{cls:"af-btn-sm primary"}),k=v.createSpan();(0,b.setIcon)(k,"key"),v.appendText(" Authenticate"),v.onclick=w=>{w.stopPropagation(),this.authenticateMcpServer(s)}}n.onclick=()=>this.openMcpDetailSlideover(s)}async authenticateMcpServer(e){if(!e.url){new b.Notice("No URL found for this server \u2014 can't authenticate.");return}this.authenticatingServers.add(e.name),this.render(),new b.Notice(`Authenticating ${e.name}\u2026 Complete authorization in your browser.`,1e4);try{let s=e.type==="sse"?"sse":"http";await this.plugin.mcpManager.authenticateServer(e.name,e.url,s),new b.Notice(`${e.name} authenticated successfully!`)}catch(s){let n=s instanceof Error?s.message:String(s);new b.Notice(`Authentication failed: ${n}`,8e3)}finally{this.authenticatingServers.delete(e.name),this.render()}}async probeMcpServer(e){try{let s=await this.plugin.mcpManager.probeServer(e);this.mcpProbeCache.set(e.name,s),s.length===0&&new b.Notice(`No tools discovered for ${e.name}.`)}catch(s){let n=s instanceof Error?s.message:String(s);new b.Notice(`Probe failed: ${n}`)}}truncateDescription(e,s){let n=pe(e)[0]??e,a=n.split(/(?<=[.!?])\s/)[0]??n,r=a.length<n.length?a:n;return r.length<=s?r:r.slice(0,s-1)+"\u2026"}openMcpDetailSlideover(e){this.contentEl.querySelector(".af-slideover-overlay")?.remove();let s=this.contentEl.createDiv({cls:"af-slideover-overlay"}),n=s.createDiv({cls:"af-slideover"}),a=n.createDiv({cls:"af-slideover-header"});a.createDiv({cls:"af-slideover-title",text:e.name});let r=a.createEl("button",{cls:"clickable-icon"});(0,b.setIcon)(r,"cross"),r.onclick=()=>s.remove(),s.onclick=v=>{v.target===s&&s.remove()};let o=n.createDiv({cls:"af-slideover-body"});if(e.description){let v=o.createDiv({cls:"af-slideover-section"});v.createDiv({cls:"af-slideover-section-title",text:"DESCRIPTION"}),v.createDiv({cls:"af-mcp-detail-description",text:e.description})}let c=o.createDiv({cls:"af-slideover-section"});c.createDiv({cls:"af-slideover-section-title",text:"SERVER INFO"}),this.renderDetailRow(c,"Name",e.name),this.renderDetailRow(c,"Transport",e.type),this.renderDetailRow(c,"Enabled",e.enabled?"yes":"no"),e.type!=="stdio"&&(this.renderDetailRow(c,"Auth",e.auth??"none"),this.renderDetailRow(c,"Authenticated",this.mcpHasToken(e)?"yes":"no")),e.source&&this.renderDetailRow(c,"Source",e.source),e.url&&this.renderDetailRow(c,"URL",e.url),e.command&&this.renderDetailRow(c,"Command",e.command),e.args&&e.args.length>0&&this.renderDetailRow(c,"Args",e.args.join(" "));let l=this.mcpProbeCache.get(e.name)??[],d=o.createDiv({cls:"af-slideover-section"});d.createDiv({cls:"af-slideover-section-title"}).setText(`TOOLS (${l.length})`);let u=d.createEl("button",{cls:"af-btn-sm"}),p=u.createSpan();if((0,b.setIcon)(p,"wrench"),u.appendText(" Probe tools"),u.onclick=async()=>{u.disabled=!0,u.setText(" Probing\u2026"),await this.probeMcpServer(e),s.remove(),this.openMcpDetailSlideover(e)},l.length>0)for(let v of l){let k=d.createDiv({cls:"af-mcp-tool-detail"}),w=k.createDiv({cls:"af-mcp-tool-detail-header"}),y=w.createSpan({cls:"af-mcp-tool-detail-name"}),C=y.createSpan();if((0,b.setIcon)(C,"wrench"),y.createSpan({text:` ${v.name}`}),v.inputSchema){let T=v.inputSchema.required??[];T.length>0&&w.createSpan({cls:"af-mcp-tool-param-count",text:`${T.length} param${T.length!==1?"s":""}`})}if(v.description){let T=pe(v.description).filter(E=>E.trim()),_=T.slice(0,2).join(" ").trim();if(T.length>2){let E=k.createEl("details",{cls:"af-mcp-tool-detail-desc"});E.createEl("summary",{text:this.truncateDescription(_,200)}),E.createDiv({cls:"af-mcp-tool-detail-full",text:v.description})}else k.createDiv({cls:"af-mcp-tool-detail-desc",text:_})}if(v.inputSchema){let T=v.inputSchema.properties,_=new Set(v.inputSchema.required??[]);if(T&&Object.keys(T).length>0){let O=k.createDiv({cls:"af-mcp-tool-params"});for(let[E,S]of Object.entries(T)){let P=O.createDiv({cls:"af-mcp-tool-param"});P.createSpan({cls:"af-mcp-tool-param-name",text:E}),S.type&&P.createSpan({cls:"af-mcp-tool-param-type",text:S.type}),_.has(E)&&P.createSpan({cls:"af-mcp-tool-param-required",text:"required"}),S.description&&P.createSpan({cls:"af-mcp-tool-param-desc",text:Ut(S.description,80)})}}}}else d.createDiv({cls:"af-form-hint",text:'Click "Probe tools" to discover the tools this server exposes.'});let f=o.createDiv({cls:"af-slideover-section"});if(f.createDiv({cls:"af-slideover-section-title",text:"ACTIONS"}),e.enabled&&e.url&&e.auth==="oauth"&&!this.mcpHasToken(e)){let v=f.createEl("button",{cls:"af-btn-sm primary"}),k=v.createSpan();(0,b.setIcon)(k,"key"),v.appendText(" Authenticate"),v.onclick=()=>{s.remove(),this.authenticateMcpServer(e)}}let m=f.createEl("button",{cls:"af-btn-sm danger"}),g=m.createSpan();(0,b.setIcon)(g,"trash-2"),m.appendText(" Remove Server"),m.onclick=async()=>{try{await this.plugin.repository.deleteMcpServer(e.name),this.plugin.mcpAuth.removeToken(e.name),this.mcpProbeCache.delete(e.name),new b.Notice(`Server "${e.name}" removed.`),s.remove(),await this.plugin.refreshFromVault(),this.render()}catch(v){let k=v instanceof Error?v.message:String(v);new b.Notice(`Failed to remove server: ${k}`)}}}renderAddMcpServerPage(e){let s=e.createDiv({cls:"af-create-agent-page"}),n=s.createDiv({cls:"af-detail-header"}),a=n.createDiv({cls:"af-detail-header-left"}),r=a.createDiv({cls:"af-agent-card-avatar idle"});(0,b.setIcon)(r,"plus");let o=a.createDiv();o.createDiv({cls:"af-detail-header-name",text:"Add MCP Server"}),o.createDiv({cls:"af-detail-header-desc",text:"Register a new MCP server for agents to use"}),n.createDiv({cls:"af-detail-header-actions"});let c={name:"",transport:"stdio",description:"",command:"",args:"",envVars:"",url:"",headers:"",auth:"none",bearerToken:""},l=s.createDiv({cls:"af-create-form"}),d=l.createDiv({cls:"af-create-section"}),h=d.createDiv({cls:"af-create-section-header"}),u=h.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(u,"plug"),h.createSpan({text:"Server Details"}),this.createFormField(d,"Name","my-server","Unique name for this MCP server",W=>{c.name=W});let p=d.createDiv({cls:"af-form-row"}),f=p.createDiv({cls:"af-form-label"});f.setText("Transport"),this.addTooltip(f,"stdio: local process, http/sse: remote server");let m=p.createEl("select",{cls:"af-form-select"});m.createEl("option",{text:"stdio",attr:{value:"stdio"}}),m.createEl("option",{text:"http",attr:{value:"http"}}),m.createEl("option",{text:"sse",attr:{value:"sse"}}),this.createFormField(d,"Description","What this server does (optional)","Shown on the server card",W=>{c.description=W});let g=l.createDiv({cls:"af-create-section"}),v=g.createDiv({cls:"af-create-section-header"}),k=v.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(k,"terminal"),v.createSpan({text:"Process Configuration"}),this.createFormField(g,"Command","npx @anthropic-ai/mcp-server-memory","The command to run",W=>{c.command=W}),this.createFormField(g,"Arguments","--port 3000","Space-separated arguments (optional)",W=>{c.args=W});let w=g.createDiv({cls:"af-form-label"});w.setText("Environment variables"),this.addTooltip(w,"One KEY=VALUE per line");let y=g.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:`API_KEY=sk-...
12092
- DEBUG=true`,rows:"3"}});y.addEventListener("input",()=>{c.envVars=y.value});let C=l.createDiv({cls:"af-create-section"}),T=C.createDiv({cls:"af-create-section-header"}),_=T.createSpan({cls:"af-create-section-icon"});(0,b.setIcon)(_,"globe"),T.createSpan({text:"Remote Server Configuration"}),this.createFormField(C,"URL","https://mcp.example.com/sse","Server endpoint URL",W=>{c.url=W});let O=C.createDiv({cls:"af-form-label"});O.setText("Custom headers"),this.addTooltip(O,"One Header: Value per line (optional, non-secret)");let E=C.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"X-Custom-Header: value",rows:"2"}});E.addEventListener("input",()=>{c.headers=E.value});let S=C.createDiv({cls:"af-form-row"}),P=S.createDiv({cls:"af-form-label"});P.setText("Authentication"),this.addTooltip(P,"none, a static bearer token, or OAuth (authenticate after saving)");let R=S.createEl("select",{cls:"af-form-select"});R.createEl("option",{text:"None",attr:{value:"none"}}),R.createEl("option",{text:"Bearer token",attr:{value:"bearer"}}),R.createEl("option",{text:"OAuth",attr:{value:"oauth"}});let N=C.createDiv({cls:"af-form-row"}),L=N.createDiv({cls:"af-form-label"});L.setText("Bearer token"),this.addTooltip(L,"Stored securely in the OS keychain, never written to the vault");let G=N.createEl("input",{cls:"af-form-input",attr:{type:"password",placeholder:"sk-\u2026"}});G.addEventListener("input",()=>{c.bearerToken=G.value});let U=()=>{N.style.display=c.auth==="bearer"?"":"none"};R.addEventListener("change",()=>{c.auth=R.value,U()}),U();let X=()=>{g.style.display=c.transport==="stdio"?"":"none",C.style.display=c.transport!=="stdio"?"":"none"};m.addEventListener("change",()=>{c.transport=m.value,X()}),X();let me=s.createDiv({cls:"af-create-footer"}),ye=me.createEl("button",{cls:"af-btn-sm",text:"Cancel"});ye.onclick=()=>this.navigate("mcp");let ee=me.createEl("button",{cls:"af-btn-sm primary af-create-submit"});D(ee,"plus","af-btn-icon"),ee.appendText(" Add Server"),ee.onclick=async()=>{let W=c.name.trim();if(!W){new b.Notice("Server name is required.");return}if(c.transport==="stdio"){if(!c.command.trim()){new b.Notice("Command is required for stdio servers.");return}}else if(!c.url.trim()){new b.Notice("URL is required for HTTP/SSE servers.");return}let de={};if(c.envVars.trim())for(let Z of pe(c.envVars)){let j=Z.trim();if(!j)continue;let fe=j.indexOf("=");if(fe<=0){new b.Notice(`Invalid env var: ${j}`);return}de[j.slice(0,fe)]=j.slice(fe+1)}let V={};if(c.headers.trim())for(let Z of pe(c.headers)){let j=Z.trim();if(!j)continue;let fe=j.indexOf(":");if(fe<=0){new b.Notice(`Invalid header: ${j}`);return}V[j.slice(0,fe).trim()]=j.slice(fe+1).trim()}let te=c.args.trim()?c.args.trim().split(/\s+/):void 0;if(this.plugin.repository.getMcpServerByName(W)){new b.Notice(`An MCP server named "${W}" already exists.`);return}if(c.transport!=="stdio"&&c.auth==="bearer"&&!c.bearerToken.trim()){new b.Notice("Enter a bearer token, or choose a different auth method.");return}ee.disabled=!0,ee.setText("Adding...");let Y={name:W,type:c.transport,enabled:!0,source:"manual",status:"disconnected",scope:"user",tools:[],toolDetails:[]};c.transport==="stdio"?(Y.command=c.command.trim(),te&&(Y.args=te),Object.keys(de).length>0&&(Y.env=de)):(Y.url=c.url.trim(),Object.keys(V).length>0&&(Y.headers=V),Y.auth=c.auth);try{await this.plugin.repository.saveMcpServer(Y,c.description.trim()),c.transport!=="stdio"&&c.auth==="bearer"&&c.bearerToken.trim()&&this.plugin.mcpAuth.storeStaticToken(W,c.bearerToken.trim()),new b.Notice(`Server "${W}" added.`),await this.plugin.refreshFromVault(),this.navigate("mcp")}catch(Z){let j=Z instanceof Error?Z.message:String(Z);new b.Notice(`Failed to add server: ${j}`),ee.disabled=!1,ee.setText(""),D(ee,"plus","af-btn-icon"),ee.appendText(" Add Server")}}}createFormField(e,s,n,a,r,o){let c=e.createDiv({cls:"af-form-row"}),l=c.createDiv({cls:"af-form-label"});l.setText(s),a&&this.addTooltip(l,a);let d=c.createEl("input",{cls:"af-form-input",attr:{type:"text",placeholder:n}});o!==void 0&&(d.value=o),d.addEventListener("input",()=>r(d.value))}addTooltip(e,s){let n=e.createSpan({cls:"af-form-tooltip"});(0,b.setIcon)(n,"info"),n.createSpan({cls:"af-tooltip-text",text:s})}};function Mo(i){switch(i){case"connected":return"idle";case"connecting":case"reconnecting":return"pending";case"needs-auth":case"error":return"error";case"stopped":case"disabled":default:return"disabled"}}function $a(i){return i>=1e6?`${(i/1e6).toFixed(1)}M`:i>=1e4?`${Math.round(i/1e3)}K`:i>=1e3?`${(i/1e3).toFixed(1)}K`:String(i)}function Nd(i){if(!i?.trim())return"not set";let t={"*/5 * * * *":"Every 5 minutes","*/10 * * * *":"Every 10 minutes","*/15 * * * *":"Every 15 minutes","*/30 * * * *":"Every 30 minutes","0 * * * *":"Every hour","0 */2 * * *":"Every 2 hours","0 */4 * * *":"Every 4 hours","0 */6 * * *":"Every 6 hours","0 */12 * * *":"Every 12 hours"};if(t[i])return t[i];let e=i.trim().split(/\s+/);if(e.length===5){let[s,n,a,,r]=e;if(a==="*"&&n&&s){let o=Number(n),c=Number(s);if(!isNaN(o)&&!isNaN(c)){let l=o>=12?"PM":"AM",h=`${o===0?12:o>12?o-12:o}:${String(c).padStart(2,"0")} ${l}`;return r==="*"?`Daily at ${h}`:r==="1-5"?`Weekdays at ${h}`:`${h} on days ${r}`}}}return i}function Bd(i){switch(i){case"connected":return"green";case"connecting":case"reconnecting":return"blue";case"needs-auth":case"error":return"red";case"stopped":case"disabled":default:return""}}var z=require("obsidian");function $n(i,t){return`${i}::${t}`}function Oo(){return Math.random().toString(16).slice(2,10)}function No(){return`New chat ${new Date().toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}`}function Ud(i){let t=new Date(i).getTime();if(!Number.isFinite(t))return"";let e=Date.now()-t,s=60*1e3,n=60*s,a=24*n;return e<s?"just now":e<n?`${Math.floor(e/s)}m`:e<a?`${Math.floor(e/n)}h`:e<2*a?"yesterday":e<7*a?`${Math.floor(e/a)}d`:new Date(t).toLocaleDateString(void 0,{month:"short",day:"numeric"})}var $d=480,jd='<svg class="svg-icon af-convo-toggle-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="1" y="2" width="22" height="20" rx="4"></rect><rect class="af-convo-toggle-bar" x="4" y="5" width="2" height="14" rx="2" fill="currentColor"></rect></svg>',ss=class i extends z.ItemView{constructor(e,s){super(e);this.plugin=s}selectedAgentName=null;selectedConversationId="";sessions=new Map;conversationsCache=[];convoPanelEl=null;collapseBtn=null;convoPanelCollapsed=!1;userToggledCollapse=!1;resizeObserver=null;headerEl;agentSelect;messagesEl;messagesInner;textarea;sendBtn;attachStopBtn;isInStopMode=!1;attachedFiles=[];attachedImages=[];pillsRow;activityEl=null;streamingDot=null;activityUnsub=null;statsEl;statsUnsub=null;statsSourceSession=null;threadExpanded=new Map;getViewType(){return Xe}getDisplayText(){if(!this.selectedAgentName)return"Agent Chat";let e=this.getCurrentConversationName();return!e||this.conversationsCache.length<=1?`Chat: ${this.selectedAgentName}`:`Chat: ${this.selectedAgentName} \xB7 ${e}`}getIcon(){return"message-circle"}getState(){return{agentName:this.selectedAgentName??null,conversationId:this.selectedConversationId,convoPanelCollapsed:this.convoPanelCollapsed}}async setState(e,s){await super.setState(e,s);let n=typeof e?.conversationId=="string"&&e.conversationId?e.conversationId:void 0;typeof e?.convoPanelCollapsed=="boolean"&&(this.convoPanelCollapsed=e.convoPanelCollapsed,this.userToggledCollapse=!0,this.applyCollapsedClass()),e?.agentName&&typeof e.agentName=="string"&&this.selectAgent(e.agentName,n)}getCurrentConversationName(){return this.conversationsCache.find(s=>s.id===this.selectedConversationId)?.name??""}async onOpen(){this.plugin.subscribeView(this),this.buildShell(),await this.render(),this.observeContainerWidth()}async onClose(){for(let{session:e}of this.sessions.values())e.abort();this.sessions.clear(),this.statsUnsub?.(),this.statsUnsub=null,this.activityUnsub?.(),this.activityUnsub=null,this.resizeObserver?.disconnect(),this.resizeObserver=null,this.plugin.unsubscribeView(this)}observeContainerWidth(){typeof ResizeObserver>"u"||(this.resizeObserver=new ResizeObserver(e=>{if(!this.userToggledCollapse)for(let s of e){let a=s.contentRect.width<$d;a!==this.convoPanelCollapsed&&(this.convoPanelCollapsed=a,this.applyCollapsedClass())}}),this.resizeObserver.observe(this.contentEl))}selectAgent(e,s){if(s){let n=this.plugin.app.workspace.getLeavesOfType(Xe);for(let a of n)if(a.view!==this&&a.view instanceof i&&a.view.selectedAgentName===e&&a.view.selectedConversationId===s){this.plugin.app.workspace.revealLeaf(a);return}}this.selectedAgentName=e,s&&(this.selectedConversationId=s),this.agentSelect&&(this.agentSelect.value=e),this.leaf.updateHeader(),this.switchToAgent(e,s)}buildShell(){let e=this.contentEl;e.empty(),e.addClass("af-root");let s=e.createDiv({cls:"af-chat-view-container"});this.headerEl=s.createDiv({cls:"af-chat-view-header"}),this.collapseBtn=this.headerEl.createEl("button",{cls:"clickable-icon af-chat-convo-collapse-btn",attr:{title:"Toggle conversations panel","aria-label":"Toggle conversations panel"}}),this.collapseBtn.innerHTML=jd,this.collapseBtn.toggleClass("is-collapsed",this.convoPanelCollapsed),this.collapseBtn.onclick=()=>this.toggleConvoPanel(),this.agentSelect=this.headerEl.createEl("select",{cls:"af-chat-view-agent-select"});let n=this.headerEl.createEl("button",{cls:"af-btn-sm af-chat-view-new-btn"});D(n,"plus","af-btn-icon"),n.appendText(" New Chat"),n.onclick=()=>void this.handleNewChat();let a=s.createDiv({cls:"af-chat-view-body"});this.convoPanelEl=a.createDiv({cls:"af-chat-convo-panel"}),this.convoPanelCollapsed&&this.convoPanelEl.addClass("collapsed");let r=a.createDiv({cls:"af-chat-main"});this.agentSelect.onchange=()=>{let d=this.agentSelect.value;d&&(this.selectedConversationId="",this.textarea.disabled=!1,this.textarea.placeholder="Message the agent\u2026 (Ctrl+Enter to send)",this.switchToAgent(d))},this.messagesEl=r.createDiv({cls:"af-chat-messages"}),this.messagesInner=this.messagesEl.createDiv({cls:"af-chat-messages-inner"});let o=r.createDiv({cls:"af-chat-input-area"});this.pillsRow=o.createDiv({cls:"af-chat-pills-row"}),this.pillsRow.style.display="none";let c=o.createDiv({cls:"af-chat-input-row"});this.attachStopBtn=c.createEl("button",{cls:"af-chat-attach-btn"}),D(this.attachStopBtn,"plus","af-btn-icon"),this.attachStopBtn.title="Attach active document",this.attachStopBtn.onclick=()=>{this.isInStopMode?this.handleStop():this.attachActiveDocument()},this.textarea=c.createEl("textarea",{cls:"af-chat-input",attr:{placeholder:"Message the agent\u2026 (Ctrl+Enter to send)",rows:"1"}}),this.sendBtn=c.createEl("button",{cls:"af-chat-send-btn"}),D(this.sendBtn,"arrow-up","af-btn-icon"),this.sendBtn.style.display="none";let l=()=>{this.textarea.style.height="auto";let d=Math.min(this.textarea.scrollHeight,160);this.textarea.style.height=`${d}px`,this.textarea.style.overflowY=this.textarea.scrollHeight>160?"auto":"hidden",this.sendBtn.style.display=this.textarea.value.trim()?"flex":"none"};this.textarea.addEventListener("input",l),this.textarea.addEventListener("focus",()=>{let d=this.getCurrentSession();d&&this.setStatsSource(d.session)}),this.sendBtn.onclick=()=>void this.handleSend(),this.textarea.onkeydown=d=>{d.key==="Enter"&&(d.ctrlKey||d.metaKey)&&(d.preventDefault(),this.handleSend())},this.textarea.addEventListener("paste",d=>{let h=d.clipboardData?.items;if(h)for(let u=0;u<h.length;u++){let p=h[u];if(p.type.startsWith("image/")){d.preventDefault();let f=p.getAsFile();f&&this.attachImageBlob(f);return}}}),o.addEventListener("dragover",d=>{d.preventDefault(),d.stopPropagation(),o.addClass("af-chat-input-dragover")}),o.addEventListener("dragleave",()=>{o.removeClass("af-chat-input-dragover")}),o.addEventListener("drop",d=>{d.preventDefault(),d.stopPropagation(),o.removeClass("af-chat-input-dragover");let h=d.dataTransfer?.files;if(h)for(let u=0;u<h.length;u++){let p=h[u];p.type.startsWith("image/")&&this.attachImageBlob(p)}}),this.statsEl=o.createDiv({cls:"af-chat-stats"}),this.renderStats(null)}async render(){this.populateAgentDropdown()}setStatsSource(e){this.statsSourceSession!==e&&(this.statsUnsub?.(),this.statsSourceSession=e,this.statsUnsub=e.onStatsChange(s=>this.renderStats(s)))}renderStats(e){if(this.statsEl.empty(),!e||!e.concreteModel){this.statsEl.createSpan({cls:"af-chat-stats-muted",text:"\xA0"});return}let s=this.statsEl.createSpan({cls:"af-chat-stats-line"});if(s.createSpan({cls:"af-chat-stats-model",text:e.concreteModel}),e.contextWindow&&e.contextTokensUsed){let n=Math.min(100,Math.round(e.contextTokensUsed/e.contextWindow*100)),a=10,r=Math.min(a,Math.max(0,Math.round(n/100*a))),o="\u2593".repeat(r)+"\u2591".repeat(a-r),c=s.createSpan({cls:`af-chat-stats-ctx${n>=80?" warn":""}`});c.createSpan({cls:"af-chat-stats-bar",text:o}),c.createSpan({cls:"af-chat-stats-pct",text:`${n}%`}),c.title=`Context: ${ts(e.contextTokensUsed)} / ${ts(e.contextWindow)} tokens (${n}%)
12090
+ ...`,rows:"8"}});C.value=a.toolsBody,C.addEventListener("input",()=>{d.toolsBody=C.value});let I=u.createDiv({cls:"af-create-section"}),P=I.createDiv({cls:"af-create-section-header"}),L=P.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(L,"book-open");let F=P.createSpan({text:"References"});this.addTooltip(F,"Background docs, conventions, cheat sheets");let z=I.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"API docs, filter syntax, conventions...",rows:"6"}});z.value=a.referencesBody,z.addEventListener("input",()=>{d.referencesBody=z.value});let U=u.createDiv({cls:"af-create-section"}),Z=U.createDiv({cls:"af-create-section-header"}),de=Z.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(de,"message-circle");let me=Z.createSpan({text:"Examples"});this.addTooltip(me,"Example prompts and ideal outputs showing how to use this skill");let ye=U.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:`## Example: List all tasks
12091
+ ...`,rows:"6"}});ye.value=a.examplesBody,ye.addEventListener("input",()=>{d.examplesBody=ye.value});let X=s.createDiv({cls:"af-create-footer"}),j=X.createEl("button",{cls:"af-btn-sm danger"});E(j,"trash-2","af-btn-icon"),j.appendText(" Delete"),j.onclick=async()=>{await this.plugin.repository.deleteSkill(a.name),new w.Notice(`Skill "${a.name}" deleted.`),await new Promise(G=>window.setTimeout(G,200)),await this.plugin.refreshFromVault(),this.navigate("skills")},X.createDiv({cls:"af-toolbar-spacer"});let K=X.createEl("button",{cls:"af-btn-sm",text:"Cancel"});K.onclick=()=>this.navigate("skills");let ne=X.createEl("button",{cls:"af-btn-sm primary af-create-submit"});E(ne,"check","af-btn-icon"),ne.appendText(" Save Changes"),ne.onclick=async()=>{let G=ee=>ee.split(",").map(Q=>Q.trim()).filter(Boolean);try{await this.plugin.repository.updateSkill(a.name,{description:d.description.trim(),tags:G(d.tags),body:d.body.trim(),toolsBody:d.toolsBody.trim(),referencesBody:d.referencesBody.trim(),examplesBody:d.examplesBody.trim()}),new w.Notice(`Skill "${a.name}" updated.`),await this.plugin.refreshFromVault(),this.navigate("skills")}catch(ee){let Q=ee instanceof Error?ee.message:String(ee);new w.Notice(`Failed to update skill: ${Q}`)}}}renderAgentMcpPicker(e,s){e.createDiv({cls:"af-form-hint",text:"Servers from the MCP Servers tab. Checked servers are available to this agent on any adapter (Claude or Codex). Leave all unchecked to grant every enabled server."});let n=this.plugin.repository.getMcpServers();if(n.length===0){let r=e.createDiv({cls:"af-form-hint"});r.appendText("No MCP servers registered yet. ");let o=r.createEl("a",{cls:"af-link",text:"Add one in the MCP Servers tab."});o.onclick=c=>{c.preventDefault(),this.navigate("mcp")};return}let a=e.createDiv({cls:"af-create-skills-grid"});for(let r of n){let o=a.createDiv({cls:"af-mcp-agent-item"}),c=o.createEl("input",{cls:"af-form-toggle",attr:{type:"checkbox"}});c.checked=s.has(r.name),c.addEventListener("change",()=>{c.checked?s.add(r.name):s.delete(r.name)});let h=o.createDiv({cls:"af-mcp-agent-label"}).createDiv({cls:"af-mcp-agent-name-row"}),d=h.createSpan({cls:`af-mcp-status-dot ${r.enabled?"idle":"disabled"}`});d.title=r.enabled?"enabled":"disabled",h.createSpan({cls:"af-create-skill-name",text:r.name}),h.createSpan({cls:"af-mcp-agent-tool-count",text:r.type}),r.enabled||h.createSpan({cls:"af-mcp-agent-tool-count af-muted",text:"disabled"})}}renderMcpPage(e){let s=e.createDiv({cls:"af-agents-page"}),n=s.createDiv({cls:"af-agents-toolbar"});n.createDiv({cls:"af-page-title",text:"MCP Servers"}),n.createDiv({cls:"af-toolbar-spacer"});let a=n.createEl("button",{cls:"af-btn-sm primary"});E(a,"plus","af-btn-icon"),a.appendText(" Add Server"),a.onclick=()=>this.navigate("add-mcp-server");let r=this.plugin.repository.getMcpServers();if(r.length===0){this.renderEmptyState(s,"plug","No MCP servers registered","Click 'Add Server' above to register one.");return}let o=s.createDiv({cls:"af-agents-grid"});for(let c of r)this.renderMcpCard(o,c)}mcpProbeCache=new Map;mcpHasToken(e){return this.plugin.mcpAuth.hasToken(e.name)}mcpNeedsAuth(e){return e.type!=="stdio"&&(e.auth==="oauth"||e.auth==="bearer")&&!this.mcpHasToken(e)}renderMcpCard(e,s){let n=e.createDiv({cls:`af-mcp-card${s.enabled?"":" af-mcp-card-disabled"}`}),a=this.mcpNeedsAuth(s),r=n.createDiv({cls:"af-agent-card-header"}),o=s.enabled?a?"pending":"idle":"disabled",c=r.createDiv({cls:`af-agent-card-avatar ${o}`});(0,w.setIcon)(c,"plug");let l=r.createDiv({cls:"af-agent-card-titleblock"});l.createDiv({cls:"af-agent-card-name",text:s.name});let h=l.createDiv({cls:"af-agent-card-desc af-mcp-meta"});h.createSpan({cls:"af-mcp-type-badge",text:s.type}),s.source==="imported"&&h.createSpan({cls:"af-badge",text:"imported"});let d=r.createDiv({cls:`af-agent-card-toggle${s.enabled?" on":""}`});d.onclick=g=>{g.stopPropagation(),this.plugin.repository.setMcpServerEnabled(s.name,!s.enabled).then(async()=>{await this.plugin.refreshFromVault(),this.render()})};let u=n.createDiv({cls:`af-mcp-status-badge ${s.enabled?a?"needs-auth":"connected":"disabled"}`}),p=u.createSpan();if(s.enabled?a?((0,w.setIcon)(p,"alert-circle"),u.createSpan({text:" Needs auth"})):((0,w.setIcon)(p,"check-circle"),u.createSpan({text:s.type==="stdio"?" Enabled":" Authenticated"})):((0,w.setIcon)(p,"pause"),u.createSpan({text:" Disabled"})),s.description){let g=this.truncateDescription(s.description,120);n.createDiv({cls:"af-mcp-description",text:g})}let m=s.url??s.command??"";m&&n.createDiv({cls:"af-mcp-command",text:$t(m,60)});let f=this.mcpProbeCache.get(s.name);if(f&&f.length>0){let g=n.createDiv({cls:"af-mcp-tool-footer"}),v=g.createDiv({cls:"af-mcp-tool-count"}),b=v.createSpan();(0,w.setIcon)(b,"wrench"),v.createSpan({text:` ${f.length} tools`});let k=g.createDiv({cls:"af-mcp-tool-chips"});for(let y of f.slice(0,4))k.createSpan({cls:"af-mcp-tool-chip",text:y.name});f.length>4&&k.createSpan({cls:"af-mcp-tool-chip af-mcp-tool-chip-more",text:`+${f.length-4}`})}if(this.authenticatingServers.has(s.name)){let v=n.createDiv({cls:"af-mcp-auth-row"}).createEl("button",{cls:"af-btn-sm primary",attr:{disabled:"true"}}),b=v.createSpan({cls:"af-spin"});(0,w.setIcon)(b,"loader-2"),v.appendText(" Authenticating\u2026")}else if(s.enabled&&a&&s.auth==="oauth"){let v=n.createDiv({cls:"af-mcp-auth-row"}).createEl("button",{cls:"af-btn-sm primary"}),b=v.createSpan();(0,w.setIcon)(b,"key"),v.appendText(" Authenticate"),v.onclick=k=>{k.stopPropagation(),this.authenticateMcpServer(s)}}n.onclick=()=>this.openMcpDetailSlideover(s)}async authenticateMcpServer(e){if(!e.url){new w.Notice("No URL found for this server \u2014 can't authenticate.");return}this.authenticatingServers.add(e.name),this.render(),new w.Notice(`Authenticating ${e.name}\u2026 Complete authorization in your browser.`,1e4);try{let s=e.type==="sse"?"sse":"http";await this.plugin.mcpManager.authenticateServer(e.name,e.url,s),new w.Notice(`${e.name} authenticated successfully!`)}catch(s){let n=s instanceof Error?s.message:String(s);new w.Notice(`Authentication failed: ${n}`,8e3)}finally{this.authenticatingServers.delete(e.name),this.render()}}async probeMcpServer(e){try{let s=await this.plugin.mcpManager.probeServer(e);this.mcpProbeCache.set(e.name,s),s.length===0&&new w.Notice(`No tools discovered for ${e.name}.`)}catch(s){let n=s instanceof Error?s.message:String(s);new w.Notice(`Probe failed: ${n}`)}}truncateDescription(e,s){let n=ge(e)[0]??e,a=n.split(/(?<=[.!?])\s/)[0]??n,r=a.length<n.length?a:n;return r.length<=s?r:r.slice(0,s-1)+"\u2026"}openMcpDetailSlideover(e){this.contentEl.querySelector(".af-slideover-overlay")?.remove();let s=this.contentEl.createDiv({cls:"af-slideover-overlay"}),n=s.createDiv({cls:"af-slideover"}),a=n.createDiv({cls:"af-slideover-header"});a.createDiv({cls:"af-slideover-title",text:e.name});let r=a.createEl("button",{cls:"clickable-icon"});(0,w.setIcon)(r,"cross"),r.onclick=()=>s.remove(),s.onclick=v=>{v.target===s&&s.remove()};let o=n.createDiv({cls:"af-slideover-body"});if(e.description){let v=o.createDiv({cls:"af-slideover-section"});v.createDiv({cls:"af-slideover-section-title",text:"DESCRIPTION"}),v.createDiv({cls:"af-mcp-detail-description",text:e.description})}let c=o.createDiv({cls:"af-slideover-section"});c.createDiv({cls:"af-slideover-section-title",text:"SERVER INFO"}),this.renderDetailRow(c,"Name",e.name),this.renderDetailRow(c,"Transport",e.type),this.renderDetailRow(c,"Enabled",e.enabled?"yes":"no"),e.type!=="stdio"&&(this.renderDetailRow(c,"Auth",e.auth??"none"),this.renderDetailRow(c,"Authenticated",this.mcpHasToken(e)?"yes":"no")),e.source&&this.renderDetailRow(c,"Source",e.source),e.url&&this.renderDetailRow(c,"URL",e.url),e.command&&this.renderDetailRow(c,"Command",e.command),e.args&&e.args.length>0&&this.renderDetailRow(c,"Args",e.args.join(" "));let l=this.mcpProbeCache.get(e.name)??[],h=o.createDiv({cls:"af-slideover-section"});h.createDiv({cls:"af-slideover-section-title"}).setText(`TOOLS (${l.length})`);let u=h.createEl("button",{cls:"af-btn-sm"}),p=u.createSpan();if((0,w.setIcon)(p,"wrench"),u.appendText(" Probe tools"),u.onclick=async()=>{u.disabled=!0,u.setText(" Probing\u2026"),await this.probeMcpServer(e),s.remove(),this.openMcpDetailSlideover(e)},l.length>0)for(let v of l){let b=h.createDiv({cls:"af-mcp-tool-detail"}),k=b.createDiv({cls:"af-mcp-tool-detail-header"}),y=k.createSpan({cls:"af-mcp-tool-detail-name"}),S=y.createSpan();if((0,w.setIcon)(S,"wrench"),y.createSpan({text:` ${v.name}`}),v.inputSchema){let T=v.inputSchema.required??[];T.length>0&&k.createSpan({cls:"af-mcp-tool-param-count",text:`${T.length} param${T.length!==1?"s":""}`})}if(v.description){let T=ge(v.description).filter(M=>M.trim()),_=T.slice(0,2).join(" ").trim();if(T.length>2){let M=b.createEl("details",{cls:"af-mcp-tool-detail-desc"});M.createEl("summary",{text:this.truncateDescription(_,200)}),M.createDiv({cls:"af-mcp-tool-detail-full",text:v.description})}else b.createDiv({cls:"af-mcp-tool-detail-desc",text:_})}if(v.inputSchema){let T=v.inputSchema.properties,_=new Set(v.inputSchema.required??[]);if(T&&Object.keys(T).length>0){let D=b.createDiv({cls:"af-mcp-tool-params"});for(let[M,C]of Object.entries(T)){let I=D.createDiv({cls:"af-mcp-tool-param"});I.createSpan({cls:"af-mcp-tool-param-name",text:M}),C.type&&I.createSpan({cls:"af-mcp-tool-param-type",text:C.type}),_.has(M)&&I.createSpan({cls:"af-mcp-tool-param-required",text:"required"}),C.description&&I.createSpan({cls:"af-mcp-tool-param-desc",text:$t(C.description,80)})}}}}else h.createDiv({cls:"af-form-hint",text:'Click "Probe tools" to discover the tools this server exposes.'});let m=o.createDiv({cls:"af-slideover-section"});if(m.createDiv({cls:"af-slideover-section-title",text:"ACTIONS"}),e.enabled&&e.url&&e.auth==="oauth"&&!this.mcpHasToken(e)){let v=m.createEl("button",{cls:"af-btn-sm primary"}),b=v.createSpan();(0,w.setIcon)(b,"key"),v.appendText(" Authenticate"),v.onclick=()=>{s.remove(),this.authenticateMcpServer(e)}}let f=m.createEl("button",{cls:"af-btn-sm danger"}),g=f.createSpan();(0,w.setIcon)(g,"trash-2"),f.appendText(" Remove Server"),f.onclick=async()=>{try{await this.plugin.repository.deleteMcpServer(e.name),this.plugin.mcpAuth.removeToken(e.name),this.mcpProbeCache.delete(e.name),new w.Notice(`Server "${e.name}" removed.`),s.remove(),await this.plugin.refreshFromVault(),this.render()}catch(v){let b=v instanceof Error?v.message:String(v);new w.Notice(`Failed to remove server: ${b}`)}}}renderAddMcpServerPage(e){let s=e.createDiv({cls:"af-create-agent-page"}),n=s.createDiv({cls:"af-detail-header"}),a=n.createDiv({cls:"af-detail-header-left"}),r=a.createDiv({cls:"af-agent-card-avatar idle"});(0,w.setIcon)(r,"plus");let o=a.createDiv();o.createDiv({cls:"af-detail-header-name",text:"Add MCP Server"}),o.createDiv({cls:"af-detail-header-desc",text:"Register a new MCP server for agents to use"});let c=n.createDiv({cls:"af-detail-header-actions"}),l={name:"",transport:"stdio",description:"",command:"",args:"",envVars:"",url:"",headers:"",auth:"none",bearerToken:""},h=s.createDiv({cls:"af-create-form"}),d=h.createDiv({cls:"af-create-section"}),u=d.createDiv({cls:"af-create-section-header"}),p=u.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(p,"plug"),u.createSpan({text:"Server Details"}),this.createFormField(d,"Name","my-server","Unique name for this MCP server",j=>{l.name=j});let m=d.createDiv({cls:"af-form-row"}),f=m.createDiv({cls:"af-form-label"});f.setText("Transport"),this.addTooltip(f,"stdio: local process, http/sse: remote server");let g=m.createEl("select",{cls:"af-form-select"});g.createEl("option",{text:"stdio",attr:{value:"stdio"}}),g.createEl("option",{text:"http",attr:{value:"http"}}),g.createEl("option",{text:"sse",attr:{value:"sse"}}),this.createFormField(d,"Description","What this server does (optional)","Shown on the server card",j=>{l.description=j});let v=h.createDiv({cls:"af-create-section"}),b=v.createDiv({cls:"af-create-section-header"}),k=b.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(k,"terminal"),b.createSpan({text:"Process Configuration"}),this.createFormField(v,"Command","npx @anthropic-ai/mcp-server-memory","The command to run",j=>{l.command=j}),this.createFormField(v,"Arguments","--port 3000","Space-separated arguments (optional)",j=>{l.args=j});let y=v.createDiv({cls:"af-form-label"});y.setText("Environment variables"),this.addTooltip(y,"One KEY=VALUE per line");let S=v.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:`API_KEY=sk-...
12092
+ DEBUG=true`,rows:"3"}});S.addEventListener("input",()=>{l.envVars=S.value});let T=h.createDiv({cls:"af-create-section"}),_=T.createDiv({cls:"af-create-section-header"}),D=_.createSpan({cls:"af-create-section-icon"});(0,w.setIcon)(D,"globe"),_.createSpan({text:"Remote Server Configuration"}),this.createFormField(T,"URL","https://mcp.example.com/sse","Server endpoint URL",j=>{l.url=j});let M=T.createDiv({cls:"af-form-label"});M.setText("Custom headers"),this.addTooltip(M,"One Header: Value per line (optional, non-secret)");let C=T.createEl("textarea",{cls:"af-create-prompt-textarea",attr:{placeholder:"X-Custom-Header: value",rows:"2"}});C.addEventListener("input",()=>{l.headers=C.value});let I=T.createDiv({cls:"af-form-row"}),P=I.createDiv({cls:"af-form-label"});P.setText("Authentication"),this.addTooltip(P,"none, a static bearer token, or OAuth (authenticate after saving)");let L=I.createEl("select",{cls:"af-form-select"});L.createEl("option",{text:"None",attr:{value:"none"}}),L.createEl("option",{text:"Bearer token",attr:{value:"bearer"}}),L.createEl("option",{text:"OAuth",attr:{value:"oauth"}});let F=T.createDiv({cls:"af-form-row"}),z=F.createDiv({cls:"af-form-label"});z.setText("Bearer token"),this.addTooltip(z,"Stored securely in the OS keychain, never written to the vault");let U=F.createEl("input",{cls:"af-form-input",attr:{type:"password",placeholder:"sk-\u2026"}});U.addEventListener("input",()=>{l.bearerToken=U.value});let Z=()=>{F.setCssStyles({display:l.auth==="bearer"?"":"none"})};L.addEventListener("change",()=>{l.auth=L.value,Z()}),Z();let de=()=>{v.setCssStyles({display:l.transport==="stdio"?"":"none"}),T.setCssStyles({display:l.transport!=="stdio"?"":"none"})};g.addEventListener("change",()=>{l.transport=g.value,de()}),de();let me=s.createDiv({cls:"af-create-footer"}),ye=me.createEl("button",{cls:"af-btn-sm",text:"Cancel"});ye.onclick=()=>this.navigate("mcp");let X=me.createEl("button",{cls:"af-btn-sm primary af-create-submit"});E(X,"plus","af-btn-icon"),X.appendText(" Add Server"),X.onclick=async()=>{let j=l.name.trim();if(!j){new w.Notice("Server name is required.");return}if(l.transport==="stdio"){if(!l.command.trim()){new w.Notice("Command is required for stdio servers.");return}}else if(!l.url.trim()){new w.Notice("URL is required for HTTP/SSE servers.");return}let K={};if(l.envVars.trim())for(let Q of ge(l.envVars)){let ae=Q.trim();if(!ae)continue;let ve=ae.indexOf("=");if(ve<=0){new w.Notice(`Invalid env var: ${ae}`);return}K[ae.slice(0,ve)]=ae.slice(ve+1)}let ne={};if(l.headers.trim())for(let Q of ge(l.headers)){let ae=Q.trim();if(!ae)continue;let ve=ae.indexOf(":");if(ve<=0){new w.Notice(`Invalid header: ${ae}`);return}ne[ae.slice(0,ve).trim()]=ae.slice(ve+1).trim()}let G=l.args.trim()?l.args.trim().split(/\s+/):void 0;if(this.plugin.repository.getMcpServerByName(j)){new w.Notice(`An MCP server named "${j}" already exists.`);return}if(l.transport!=="stdio"&&l.auth==="bearer"&&!l.bearerToken.trim()){new w.Notice("Enter a bearer token, or choose a different auth method.");return}X.disabled=!0,X.setText("Adding...");let ee={name:j,type:l.transport,enabled:!0,source:"manual",status:"disconnected",scope:"user",tools:[],toolDetails:[]};l.transport==="stdio"?(ee.command=l.command.trim(),G&&(ee.args=G),Object.keys(K).length>0&&(ee.env=K)):(ee.url=l.url.trim(),Object.keys(ne).length>0&&(ee.headers=ne),ee.auth=l.auth);try{await this.plugin.repository.saveMcpServer(ee,l.description.trim()),l.transport!=="stdio"&&l.auth==="bearer"&&l.bearerToken.trim()&&this.plugin.mcpAuth.storeStaticToken(j,l.bearerToken.trim()),new w.Notice(`Server "${j}" added.`),await this.plugin.refreshFromVault(),this.navigate("mcp")}catch(Q){let ae=Q instanceof Error?Q.message:String(Q);new w.Notice(`Failed to add server: ${ae}`),X.disabled=!1,X.setText(""),E(X,"plus","af-btn-icon"),X.appendText(" Add Server")}}}createFormField(e,s,n,a,r,o){let c=e.createDiv({cls:"af-form-row"}),l=c.createDiv({cls:"af-form-label"});l.setText(s),a&&this.addTooltip(l,a);let h=c.createEl("input",{cls:"af-form-input",attr:{type:"text",placeholder:n}});o!==void 0&&(h.value=o),h.addEventListener("input",()=>r(h.value))}addTooltip(e,s){let n=e.createSpan({cls:"af-form-tooltip"});(0,w.setIcon)(n,"info"),n.createSpan({cls:"af-tooltip-text",text:s})}};function Lo(i){switch(i){case"connected":return"idle";case"connecting":case"reconnecting":return"pending";case"needs-auth":case"error":return"error";case"stopped":case"disabled":default:return"disabled"}}function $a(i){return i>=1e6?`${(i/1e6).toFixed(1)}M`:i>=1e4?`${Math.round(i/1e3)}K`:i>=1e3?`${(i/1e3).toFixed(1)}K`:String(i)}function Bd(i){if(!i?.trim())return"not set";let t={"*/5 * * * *":"Every 5 minutes","*/10 * * * *":"Every 10 minutes","*/15 * * * *":"Every 15 minutes","*/30 * * * *":"Every 30 minutes","0 * * * *":"Every hour","0 */2 * * *":"Every 2 hours","0 */4 * * *":"Every 4 hours","0 */6 * * *":"Every 6 hours","0 */12 * * *":"Every 12 hours"};if(t[i])return t[i];let e=i.trim().split(/\s+/);if(e.length===5){let[s,n,a,,r]=e;if(a==="*"&&n&&s){let o=Number(n),c=Number(s);if(!isNaN(o)&&!isNaN(c)){let l=o>=12?"PM":"AM",d=`${o===0?12:o>12?o-12:o}:${String(c).padStart(2,"0")} ${l}`;return r==="*"?`Daily at ${d}`:r==="1-5"?`Weekdays at ${d}`:`${d} on days ${r}`}}}return i}function Ud(i){switch(i){case"connected":return"green";case"connecting":case"reconnecting":return"blue";case"needs-auth":case"error":return"red";case"stopped":case"disabled":default:return""}}var q=require("obsidian");function $n(i,t){return`${i}::${t}`}function No(){return Math.random().toString(16).slice(2,10)}function Bo(){return`New chat ${new Date().toLocaleString(void 0,{month:"short",day:"numeric",hour:"2-digit",minute:"2-digit"})}`}function $d(i){let t=new Date(i).getTime();if(!Number.isFinite(t))return"";let e=Date.now()-t,s=60*1e3,n=60*s,a=24*n;return e<s?"just now":e<n?`${Math.floor(e/s)}m`:e<a?`${Math.floor(e/n)}h`:e<2*a?"yesterday":e<7*a?`${Math.floor(e/a)}d`:new Date(t).toLocaleDateString(void 0,{month:"short",day:"numeric"})}var jd=480,ja="http://www.w3.org/2000/svg";function Wd(i){let t=activeDocument.createElementNS(ja,"svg");t.setAttribute("class","svg-icon af-convo-toggle-icon"),t.setAttribute("viewBox","0 0 24 24"),t.setAttribute("fill","none"),t.setAttribute("stroke","currentColor"),t.setAttribute("stroke-width","2"),t.setAttribute("stroke-linecap","round"),t.setAttribute("stroke-linejoin","round");let e=activeDocument.createElementNS(ja,"rect");for(let[n,a]of Object.entries({x:"1",y:"2",width:"22",height:"20",rx:"4"}))e.setAttribute(n,a);let s=activeDocument.createElementNS(ja,"rect");s.setAttribute("class","af-convo-toggle-bar");for(let[n,a]of Object.entries({x:"4",y:"5",width:"2",height:"14",rx:"2",fill:"currentColor"}))s.setAttribute(n,a);t.appendChild(e),t.appendChild(s),i.appendChild(t)}var ns=class i extends q.ItemView{constructor(e,s){super(e);this.plugin=s}selectedAgentName=null;selectedConversationId="";sessions=new Map;conversationsCache=[];convoPanelEl=null;collapseBtn=null;convoPanelCollapsed=!1;userToggledCollapse=!1;resizeObserver=null;headerEl;agentSelect;messagesEl;messagesInner;textarea;sendBtn;attachStopBtn;isInStopMode=!1;attachedFiles=[];attachedImages=[];pillsRow;activityEl=null;streamingDot=null;activityUnsub=null;statsEl;statsUnsub=null;statsSourceSession=null;threadExpanded=new Map;getViewType(){return nt}getDisplayText(){if(!this.selectedAgentName)return"Agent Chat";let e=this.getCurrentConversationName();return!e||this.conversationsCache.length<=1?`Chat: ${this.selectedAgentName}`:`Chat: ${this.selectedAgentName} \xB7 ${e}`}getIcon(){return"message-circle"}getState(){return{agentName:this.selectedAgentName??null,conversationId:this.selectedConversationId,convoPanelCollapsed:this.convoPanelCollapsed}}async setState(e,s){await super.setState(e,s);let n=typeof e?.conversationId=="string"&&e.conversationId?e.conversationId:void 0;typeof e?.convoPanelCollapsed=="boolean"&&(this.convoPanelCollapsed=e.convoPanelCollapsed,this.userToggledCollapse=!0,this.applyCollapsedClass()),e?.agentName&&typeof e.agentName=="string"&&this.selectAgent(e.agentName,n)}getCurrentConversationName(){return this.conversationsCache.find(s=>s.id===this.selectedConversationId)?.name??""}async onOpen(){this.plugin.subscribeView(this),this.buildShell(),await this.render(),this.observeContainerWidth()}async onClose(){for(let{session:e}of this.sessions.values())e.abort();this.sessions.clear(),this.statsUnsub?.(),this.statsUnsub=null,this.activityUnsub?.(),this.activityUnsub=null,this.resizeObserver?.disconnect(),this.resizeObserver=null,this.plugin.unsubscribeView(this)}observeContainerWidth(){typeof ResizeObserver>"u"||(this.resizeObserver=new ResizeObserver(e=>{if(!this.userToggledCollapse)for(let s of e){let a=s.contentRect.width<jd;a!==this.convoPanelCollapsed&&(this.convoPanelCollapsed=a,this.applyCollapsedClass())}}),this.resizeObserver.observe(this.contentEl))}selectAgent(e,s){if(s){let n=this.plugin.app.workspace.getLeavesOfType(nt);for(let a of n)if(a.view!==this&&a.view instanceof i&&a.view.selectedAgentName===e&&a.view.selectedConversationId===s){this.plugin.app.workspace.revealLeaf(a);return}}this.selectedAgentName=e,s&&(this.selectedConversationId=s),this.agentSelect&&(this.agentSelect.value=e),this.leaf.updateHeader(),this.switchToAgent(e,s)}buildShell(){let e=this.contentEl;e.empty(),e.addClass("af-root");let s=e.createDiv({cls:"af-chat-view-container"});this.headerEl=s.createDiv({cls:"af-chat-view-header"}),this.collapseBtn=this.headerEl.createEl("button",{cls:"clickable-icon af-chat-convo-collapse-btn",attr:{title:"Toggle conversations panel","aria-label":"Toggle conversations panel"}}),Wd(this.collapseBtn),this.collapseBtn.toggleClass("is-collapsed",this.convoPanelCollapsed),this.collapseBtn.onclick=()=>this.toggleConvoPanel(),this.agentSelect=this.headerEl.createEl("select",{cls:"af-chat-view-agent-select"});let n=this.headerEl.createEl("button",{cls:"af-btn-sm af-chat-view-new-btn"});E(n,"plus","af-btn-icon"),n.appendText(" New Chat"),n.onclick=()=>void this.handleNewChat();let a=s.createDiv({cls:"af-chat-view-body"});this.convoPanelEl=a.createDiv({cls:"af-chat-convo-panel"}),this.convoPanelCollapsed&&this.convoPanelEl.addClass("collapsed");let r=a.createDiv({cls:"af-chat-main"});this.agentSelect.onchange=()=>{let h=this.agentSelect.value;h&&(this.selectedConversationId="",this.textarea.disabled=!1,this.textarea.placeholder="Message the agent\u2026 (Ctrl+Enter to send)",this.switchToAgent(h))},this.messagesEl=r.createDiv({cls:"af-chat-messages"}),this.messagesInner=this.messagesEl.createDiv({cls:"af-chat-messages-inner"});let o=r.createDiv({cls:"af-chat-input-area"});this.pillsRow=o.createDiv({cls:"af-chat-pills-row"}),this.pillsRow.setCssStyles({display:"none"});let c=o.createDiv({cls:"af-chat-input-row"});this.attachStopBtn=c.createEl("button",{cls:"af-chat-attach-btn"}),E(this.attachStopBtn,"plus","af-btn-icon"),this.attachStopBtn.title="Attach active document",this.attachStopBtn.onclick=()=>{this.isInStopMode?this.handleStop():this.attachActiveDocument()},this.textarea=c.createEl("textarea",{cls:"af-chat-input",attr:{placeholder:"Message the agent\u2026 (Ctrl+Enter to send)",rows:"1"}}),this.sendBtn=c.createEl("button",{cls:"af-chat-send-btn"}),E(this.sendBtn,"arrow-up","af-btn-icon"),this.sendBtn.setCssStyles({display:"none"});let l=()=>{this.textarea.setCssStyles({height:"auto"});let h=Math.min(this.textarea.scrollHeight,160);this.textarea.setCssStyles({height:`${h}px`}),this.textarea.setCssStyles({overflowY:this.textarea.scrollHeight>160?"auto":"hidden"}),this.sendBtn.setCssStyles({display:this.textarea.value.trim()?"flex":"none"})};this.textarea.addEventListener("input",l),this.textarea.addEventListener("focus",()=>{let h=this.getCurrentSession();h&&this.setStatsSource(h.session)}),this.sendBtn.onclick=()=>void this.handleSend(),this.textarea.onkeydown=h=>{h.key==="Enter"&&(h.ctrlKey||h.metaKey)&&(h.preventDefault(),this.handleSend())},this.textarea.addEventListener("paste",h=>{let d=h.clipboardData?.items;if(d)for(let u=0;u<d.length;u++){let p=d[u];if(p.type.startsWith("image/")){h.preventDefault();let m=p.getAsFile();m&&this.attachImageBlob(m);return}}}),o.addEventListener("dragover",h=>{h.preventDefault(),h.stopPropagation(),o.addClass("af-chat-input-dragover")}),o.addEventListener("dragleave",()=>{o.removeClass("af-chat-input-dragover")}),o.addEventListener("drop",h=>{h.preventDefault(),h.stopPropagation(),o.removeClass("af-chat-input-dragover");let d=h.dataTransfer?.files;if(d)for(let u=0;u<d.length;u++){let p=d[u];p.type.startsWith("image/")&&this.attachImageBlob(p)}}),this.statsEl=o.createDiv({cls:"af-chat-stats"}),this.renderStats(null)}async render(){this.populateAgentDropdown()}setStatsSource(e){this.statsSourceSession!==e&&(this.statsUnsub?.(),this.statsSourceSession=e,this.statsUnsub=e.onStatsChange(s=>this.renderStats(s)))}renderStats(e){if(this.statsEl.empty(),!e||!e.concreteModel){this.statsEl.createSpan({cls:"af-chat-stats-muted",text:"\xA0"});return}let s=this.statsEl.createSpan({cls:"af-chat-stats-line"});if(s.createSpan({cls:"af-chat-stats-model",text:e.concreteModel}),e.contextWindow&&e.contextTokensUsed){let n=Math.min(100,Math.round(e.contextTokensUsed/e.contextWindow*100)),a=10,r=Math.min(a,Math.max(0,Math.round(n/100*a))),o="\u2593".repeat(r)+"\u2591".repeat(a-r),c=s.createSpan({cls:`af-chat-stats-ctx${n>=80?" warn":""}`});c.createSpan({cls:"af-chat-stats-bar",text:o}),c.createSpan({cls:"af-chat-stats-pct",text:`${n}%`}),c.title=`Context: ${ss(e.contextTokensUsed)} / ${ss(e.contextWindow)} tokens (${n}%)
12093
12093
 
12094
12094
  Includes the agent's system prompt, attached skills, tool schemas, memory, and prior turns. A fresh chat starts non-zero because all of that is loaded on turn 1.
12095
12095
 
12096
- To get 1M context on Opus, set the agent's model to claude-opus-4-7[1m] (or us.anthropic.claude-opus-4-7[1m] on Bedrock).`}if(e.lastCompact){let{preTokens:n,postTokens:a}=e.lastCompact,r=s.createSpan({cls:"af-chat-stats-compact"});r.setText(`compacted ${ts(n)} \u2192 ${ts(a)}`),r.title=`Conversation was summarized to free up context. ${ts(n)} tokens reduced to ${ts(a)}.`}}populateAgentDropdown(){let e=this.plugin.runtime.getSnapshot().agents,s=this.agentSelect.value;if(this.agentSelect.empty(),e.length===0){let a=this.agentSelect.createEl("option",{text:"No agents available",attr:{value:"",disabled:"true"}});a.selected=!0,this.textarea.disabled=!0,this.showEmptyState();return}if(!this.selectedAgentName){let a=this.agentSelect.createEl("option",{text:"Select agent\u2026",attr:{value:"",disabled:"true"}});a.selected=!0}for(let a of e){let r=a.avatar?.trim(),o=r&&!/^[a-z][a-z0-9-]*$/.test(r)?`${r} `:"";this.agentSelect.createEl("option",{text:`${o}${a.name}`,attr:{value:a.name}})}if(this.selectedAgentName&&e.some(a=>a.name===this.selectedAgentName))this.agentSelect.value=this.selectedAgentName,this.textarea.disabled=!1;else if(s&&e.some(a=>a.name===s))this.agentSelect.value=s,this.selectedAgentName=s,this.textarea.disabled=!1;else{this.selectedAgentName=null,this.leaf.updateHeader(),this.textarea.disabled=!0,this.textarea.placeholder="Select an agent to start chatting\u2026",this.showEmptyState();return}this.leaf.updateHeader(),this.textarea.placeholder="Message the agent\u2026 (Ctrl+Enter to send)";let n=this.messagesInner.querySelector(".af-chat-bubble")!==null;this.selectedAgentName&&!n&&this.switchToAgent(this.selectedAgentName,this.selectedConversationId||void 0)}showEmptyState(){this.messagesInner.empty();let e=this.messagesInner.createDiv({cls:"af-chat-view-empty"}),s=e.createDiv({cls:"af-chat-view-empty-icon"});this.plugin.runtime.getSnapshot().agents.length===0?((0,z.setIcon)(s,"bot"),e.createDiv({cls:"af-chat-view-empty-text",text:"No agents available"}),e.createDiv({cls:"af-chat-view-empty-hint",text:"Create an agent to start chatting"})):((0,z.setIcon)(s,"message-circle"),e.createDiv({cls:"af-chat-view-empty-text",text:"Select an agent to start"}),e.createDiv({cls:"af-chat-view-empty-hint",text:"Choose an agent from the dropdown above"}))}async switchToAgent(e,s){let a=this.plugin.runtime.getSnapshot().agents.find(d=>d.name===e);if(!a)return;await this.loadConversations(a);let r;if(s&&this.conversationsCache.some(d=>d.id===s))r=s;else if(this.conversationsCache.length>0)r=this.conversationsCache[0].id;else{r=Oo();try{await this.plugin.repository.createConversation(a,r,No())}catch(d){new z.Notice(`Couldn't create conversation: ${d instanceof Error?d.message:String(d)}`);return}await this.loadConversations(a)}if(!s||s!==r){let d=this.plugin.app.workspace.getLeavesOfType(Xe);for(let h of d)if(h.view!==this&&h.view instanceof i&&h.view.selectedAgentName===e&&h.view.selectedConversationId===r){this.plugin.app.workspace.revealLeaf(h);return}}this.selectedAgentName=e,this.selectedConversationId=r,this.leaf.updateHeader(),this.activityEl=null,this.streamingDot=null,this.messagesInner.empty(),this.threadExpanded.clear(),this.renderConvoPanel();let o=$n(e,r),c=this.sessions.get(o);if(!c){let d=new qt(a,this.plugin.settings,this.plugin.repository,this.app.vault,{inAppConversationId:r,mcpAuth:this.plugin.mcpAuth});c={session:d},this.sessions.set(o,c),await d.loadPersistedState()}this.setStatsSource(c.session);for(let d of c.session.messages)if(d.role==="user")this.addBubble("user",d.content,d.attachments);else{let h=this.addBubble("assistant");if(this.renderMarkdownBubble(h,d.content),h._setRawText?.(d.content),this.attachThreadAffordance(h,d.id,c.session),d.toolCalls&&d.toolCalls.length>0){let u=this.getOrCreateAffordancesRow(h);this.buildToolSummary(d.toolCalls,u)}}this.activityUnsub?.();let l=c.session;this.activityUnsub=l.onActivityChange(()=>{this.getCurrentSession()?.session===l&&this.renderIndicators(l)}),this.textarea.disabled=!1,this.textarea.focus()}getCurrentSession(){if(this.selectedAgentName)return this.sessions.get($n(this.selectedAgentName,this.selectedConversationId))}async loadConversations(e){this.conversationsCache=await this.plugin.repository.listConversations(e)}async refreshConversationsList(e){await this.loadConversations(e),this.renderConvoPanel(),this.leaf.updateHeader()}renderConvoPanel(){if(!this.convoPanelEl||(this.convoPanelEl.empty(),!this.selectedAgentName))return;this.convoPanelEl.createDiv({cls:"af-chat-convo-header",text:"Conversations"});let e=this.convoPanelEl.createDiv({cls:"af-chat-convo-new"}),s=e.createSpan({cls:"af-chat-convo-new-icon"});(0,z.setIcon)(s,"plus"),e.createSpan({cls:"af-chat-convo-new-label",text:"New chat"}),e.onclick=()=>void this.handleNewChat();let n=this.convoPanelEl.createDiv({cls:"af-chat-convo-list"});for(let a of this.conversationsCache)this.renderConvoRow(n,a)}renderConvoRow(e,s){let n=s.id===this.selectedConversationId,a=e.createDiv({cls:`af-chat-convo-item${n?" active":""}`}),r=a.createDiv({cls:"af-chat-convo-name",text:s.name});r.title=s.name,r.ondblclick=d=>{d.stopPropagation(),this.beginInlineRename(r,s)};let o=a.createDiv({cls:"af-chat-convo-meta"}),c=s.messageCount===1?"1 msg":`${s.messageCount} msgs`;o.appendText(`${c} \xB7 ${Ud(s.lastActive)}`);let l=a.createEl("button",{cls:"af-chat-convo-trash",attr:{title:"Delete conversation","aria-label":"Delete conversation"}});(0,z.setIcon)(l,"trash-2"),l.onclick=d=>{d.stopPropagation(),this.handleDeleteConversation(s)},a.onclick=()=>{s.id!==this.selectedConversationId&&this.handleConvoSelected(s.id)}}beginInlineRename(e,s){let n=s.name,a=document.createElement("input");a.type="text",a.value=n,a.className="af-chat-convo-name-input",e.replaceWith(a),a.focus(),a.select();let r=!1,o=l=>{let d=document.createElement("div");return d.className="af-chat-convo-name",d.textContent=l??n,d.title=l??n,d.ondblclick=h=>{h.stopPropagation();let u=this.conversationsCache.find(p=>p.id===s.id)??s;this.beginInlineRename(d,u)},a.replaceWith(d),d},c=async()=>{if(r)return;r=!0;let l=a.value.trim();if(!l||l===n){o(null);return}try{await this.saveConversationName(s.id,l)}catch(d){new z.Notice(`Couldn't rename: ${d instanceof Error?d.message:String(d)}`),o(null);return}this.renderConvoPanel(),this.leaf.updateHeader()};a.addEventListener("keydown",l=>{l.key==="Enter"?(l.preventDefault(),c()):l.key==="Escape"&&(l.preventDefault(),r=!0,o(null))}),a.addEventListener("blur",()=>{c()})}async saveConversationName(e,s){if(!this.selectedAgentName)return;let a=this.plugin.runtime.getSnapshot().agents.find(l=>l.name===this.selectedAgentName);if(!a)return;try{await this.plugin.repository.renameConversation(a,e,s)}catch{}let r=$n(this.selectedAgentName,e),o=this.sessions.get(r);o&&await o.session.setConversationName(s);let c=this.conversationsCache.findIndex(l=>l.id===e);c>=0&&(this.conversationsCache[c]={...this.conversationsCache[c],name:s})}async handleConvoSelected(e){if(!this.selectedAgentName)return;let s=this.plugin.app.workspace.getLeavesOfType(Xe);for(let n of s)if(n.view!==this&&n.view instanceof i&&n.view.selectedAgentName===this.selectedAgentName&&n.view.selectedConversationId===e){this.plugin.app.workspace.revealLeaf(n);return}await this.switchToAgent(this.selectedAgentName,e)}async handleDeleteConversation(e){if(!this.selectedAgentName)return;let n=this.plugin.runtime.getSnapshot().agents.find(o=>o.name===this.selectedAgentName);if(!n||!window.confirm(`Delete conversation "${e.name}"?
12096
+ To get 1M context on Opus, set the agent's model to claude-opus-4-7[1m] (or us.anthropic.claude-opus-4-7[1m] on Bedrock).`}if(e.lastCompact){let{preTokens:n,postTokens:a}=e.lastCompact,r=s.createSpan({cls:"af-chat-stats-compact"});r.setText(`compacted ${ss(n)} \u2192 ${ss(a)}`),r.title=`Conversation was summarized to free up context. ${ss(n)} tokens reduced to ${ss(a)}.`}}populateAgentDropdown(){let e=this.plugin.runtime.getSnapshot().agents,s=this.agentSelect.value;if(this.agentSelect.empty(),e.length===0){let a=this.agentSelect.createEl("option",{text:"No agents available",attr:{value:"",disabled:"true"}});a.selected=!0,this.textarea.disabled=!0,this.showEmptyState();return}if(!this.selectedAgentName){let a=this.agentSelect.createEl("option",{text:"Select agent\u2026",attr:{value:"",disabled:"true"}});a.selected=!0}for(let a of e){let r=a.avatar?.trim(),o=r&&!/^[a-z][a-z0-9-]*$/.test(r)?`${r} `:"";this.agentSelect.createEl("option",{text:`${o}${a.name}`,attr:{value:a.name}})}if(this.selectedAgentName&&e.some(a=>a.name===this.selectedAgentName))this.agentSelect.value=this.selectedAgentName,this.textarea.disabled=!1;else if(s&&e.some(a=>a.name===s))this.agentSelect.value=s,this.selectedAgentName=s,this.textarea.disabled=!1;else{this.selectedAgentName=null,this.leaf.updateHeader(),this.textarea.disabled=!0,this.textarea.placeholder="Select an agent to start chatting\u2026",this.showEmptyState();return}this.leaf.updateHeader(),this.textarea.placeholder="Message the agent\u2026 (Ctrl+Enter to send)";let n=this.messagesInner.querySelector(".af-chat-bubble")!==null;this.selectedAgentName&&!n&&this.switchToAgent(this.selectedAgentName,this.selectedConversationId||void 0)}showEmptyState(){this.messagesInner.empty();let e=this.messagesInner.createDiv({cls:"af-chat-view-empty"}),s=e.createDiv({cls:"af-chat-view-empty-icon"});this.plugin.runtime.getSnapshot().agents.length===0?((0,q.setIcon)(s,"bot"),e.createDiv({cls:"af-chat-view-empty-text",text:"No agents available"}),e.createDiv({cls:"af-chat-view-empty-hint",text:"Create an agent to start chatting"})):((0,q.setIcon)(s,"message-circle"),e.createDiv({cls:"af-chat-view-empty-text",text:"Select an agent to start"}),e.createDiv({cls:"af-chat-view-empty-hint",text:"Choose an agent from the dropdown above"}))}async switchToAgent(e,s){let a=this.plugin.runtime.getSnapshot().agents.find(h=>h.name===e);if(!a)return;await this.loadConversations(a);let r;if(s&&this.conversationsCache.some(h=>h.id===s))r=s;else if(this.conversationsCache.length>0)r=this.conversationsCache[0].id;else{r=No();try{await this.plugin.repository.createConversation(a,r,Bo())}catch(h){new q.Notice(`Couldn't create conversation: ${h instanceof Error?h.message:String(h)}`);return}await this.loadConversations(a)}if(!s||s!==r){let h=this.plugin.app.workspace.getLeavesOfType(nt);for(let d of h)if(d.view!==this&&d.view instanceof i&&d.view.selectedAgentName===e&&d.view.selectedConversationId===r){this.plugin.app.workspace.revealLeaf(d);return}}this.selectedAgentName=e,this.selectedConversationId=r,this.leaf.updateHeader(),this.activityEl=null,this.streamingDot=null,this.messagesInner.empty(),this.threadExpanded.clear(),this.renderConvoPanel();let o=$n(e,r),c=this.sessions.get(o);if(!c){let h=new zt(a,this.plugin.settings,this.plugin.repository,this.app.vault,{inAppConversationId:r,mcpAuth:this.plugin.mcpAuth});c={session:h},this.sessions.set(o,c),await h.loadPersistedState()}this.setStatsSource(c.session);for(let h of c.session.messages)if(h.role==="user")this.addBubble("user",h.content,h.attachments);else{let d=this.addBubble("assistant");if(this.renderMarkdownBubble(d,h.content),d._setRawText?.(h.content),this.attachThreadAffordance(d,h.id,c.session),h.toolCalls&&h.toolCalls.length>0){let u=this.getOrCreateAffordancesRow(d);this.buildToolSummary(h.toolCalls,u)}}this.activityUnsub?.();let l=c.session;this.activityUnsub=l.onActivityChange(()=>{this.getCurrentSession()?.session===l&&this.renderIndicators(l)}),this.textarea.disabled=!1,this.textarea.focus()}getCurrentSession(){if(this.selectedAgentName)return this.sessions.get($n(this.selectedAgentName,this.selectedConversationId))}async loadConversations(e){this.conversationsCache=await this.plugin.repository.listConversations(e)}async refreshConversationsList(e){await this.loadConversations(e),this.renderConvoPanel(),this.leaf.updateHeader()}renderConvoPanel(){if(!this.convoPanelEl||(this.convoPanelEl.empty(),!this.selectedAgentName))return;this.convoPanelEl.createDiv({cls:"af-chat-convo-header",text:"Conversations"});let e=this.convoPanelEl.createDiv({cls:"af-chat-convo-new"}),s=e.createSpan({cls:"af-chat-convo-new-icon"});(0,q.setIcon)(s,"plus"),e.createSpan({cls:"af-chat-convo-new-label",text:"New chat"}),e.onclick=()=>void this.handleNewChat();let n=this.convoPanelEl.createDiv({cls:"af-chat-convo-list"});for(let a of this.conversationsCache)this.renderConvoRow(n,a)}renderConvoRow(e,s){let n=s.id===this.selectedConversationId,a=e.createDiv({cls:`af-chat-convo-item${n?" active":""}`}),r=a.createDiv({cls:"af-chat-convo-name",text:s.name});r.title=s.name,r.ondblclick=h=>{h.stopPropagation(),this.beginInlineRename(r,s)};let o=a.createDiv({cls:"af-chat-convo-meta"}),c=s.messageCount===1?"1 msg":`${s.messageCount} msgs`;o.appendText(`${c} \xB7 ${$d(s.lastActive)}`);let l=a.createEl("button",{cls:"af-chat-convo-trash",attr:{title:"Delete conversation","aria-label":"Delete conversation"}});(0,q.setIcon)(l,"trash-2"),l.onclick=h=>{h.stopPropagation(),this.handleDeleteConversation(s)},a.onclick=()=>{s.id!==this.selectedConversationId&&this.handleConvoSelected(s.id)}}beginInlineRename(e,s){let n=s.name,a=activeDocument.createElement("input");a.type="text",a.value=n,a.className="af-chat-convo-name-input",e.replaceWith(a),a.focus(),a.select();let r=!1,o=l=>{let h=activeDocument.createElement("div");return h.className="af-chat-convo-name",h.textContent=l??n,h.title=l??n,h.ondblclick=d=>{d.stopPropagation();let u=this.conversationsCache.find(p=>p.id===s.id)??s;this.beginInlineRename(h,u)},a.replaceWith(h),h},c=async()=>{if(r)return;r=!0;let l=a.value.trim();if(!l||l===n){o(null);return}try{await this.saveConversationName(s.id,l)}catch(h){new q.Notice(`Couldn't rename: ${h instanceof Error?h.message:String(h)}`),o(null);return}this.renderConvoPanel(),this.leaf.updateHeader()};a.addEventListener("keydown",l=>{l.key==="Enter"?(l.preventDefault(),c()):l.key==="Escape"&&(l.preventDefault(),r=!0,o(null))}),a.addEventListener("blur",()=>{c()})}async saveConversationName(e,s){if(!this.selectedAgentName)return;let a=this.plugin.runtime.getSnapshot().agents.find(l=>l.name===this.selectedAgentName);if(!a)return;try{await this.plugin.repository.renameConversation(a,e,s)}catch{}let r=$n(this.selectedAgentName,e),o=this.sessions.get(r);o&&await o.session.setConversationName(s);let c=this.conversationsCache.findIndex(l=>l.id===e);c>=0&&(this.conversationsCache[c]={...this.conversationsCache[c],name:s})}async handleConvoSelected(e){if(!this.selectedAgentName)return;let s=this.plugin.app.workspace.getLeavesOfType(nt);for(let n of s)if(n.view!==this&&n.view instanceof i&&n.view.selectedAgentName===this.selectedAgentName&&n.view.selectedConversationId===e){this.plugin.app.workspace.revealLeaf(n);return}await this.switchToAgent(this.selectedAgentName,e)}async handleDeleteConversation(e){if(!this.selectedAgentName)return;let n=this.plugin.runtime.getSnapshot().agents.find(o=>o.name===this.selectedAgentName);if(!n||!window.confirm(`Delete conversation "${e.name}"?
12097
12097
 
12098
- This removes its message history. The agent and its other conversations are untouched.`))return;let r=$n(this.selectedAgentName,e.id);this.sessions.get(r)?.session.dispose(),this.sessions.delete(r);try{await this.plugin.repository.deleteConversation(n,e.id)}catch(o){new z.Notice(`Couldn't delete: ${o instanceof Error?o.message:String(o)}`);return}if(await this.refreshConversationsList(n),e.id===this.selectedConversationId){let o=this.conversationsCache[0]?.id;await this.switchToAgent(this.selectedAgentName,o)}}toggleConvoPanel(){this.convoPanelCollapsed=!this.convoPanelCollapsed,this.userToggledCollapse=!0,this.applyCollapsedClass(),this.leaf.updateHeader()}applyCollapsedClass(){this.convoPanelEl&&(this.convoPanelCollapsed?this.convoPanelEl.addClass("collapsed"):this.convoPanelEl.removeClass("collapsed")),this.collapseBtn&&this.collapseBtn.toggleClass("is-collapsed",this.convoPanelCollapsed)}renderMarkdownBubble(e,s){let n=e.querySelector(".af-chat-copy-btn"),a=n?.parentNode?.removeChild(n)??null;e.empty(),e.addClass("af-compact-md"),z.MarkdownRenderer.render(this.app,s,e,"",this.plugin).then(()=>{a&&e.appendChild(a),this.wireBubbleLinks(e),e.querySelectorAll("pre").forEach(r=>{r.querySelector(".copy-code-button")?.remove();let o=r.querySelector("code");if(!o)return;let c=document.createElement("button");c.className="af-code-copy-btn",c.setAttribute("aria-label","Copy code"),(0,z.setIcon)(c,"copy"),c.onclick=l=>{l.stopPropagation(),navigator.clipboard.writeText(o.textContent??"").then(()=>{c.addClass("copied"),(0,z.setIcon)(c,"check"),setTimeout(()=>{c.removeClass("copied"),(0,z.setIcon)(c,"copy")},1500)})},r.style.position="relative",r.appendChild(c)})})}wireBubbleLinks(e){e.addEventListener("click",s=>{let n=s.target.closest("a");if(!n)return;if(n.classList.contains("internal-link")){s.preventDefault(),s.stopPropagation();let r=n.getAttribute("data-href")||n.getAttribute("href")||n.textContent||"";if(!r)return;let o=s.shiftKey?"split":"tab";this.app.workspace.openLinkText(r,"",o);return}let a=n.getAttribute("href")||"";if(a.startsWith("obsidian://")){s.preventDefault(),s.stopPropagation(),window.location.href=a;return}if(n.classList.contains("external-link")||/^https?:\/\//.test(a)){s.preventDefault(),s.stopPropagation(),window.open(a,"_blank");return}})}addCopyBtn(e,s){let n=e.createEl("button",{cls:"af-chat-copy-btn",attr:{"aria-label":"Copy message"}});(0,z.setIcon)(n,"copy"),n.onclick=a=>{a.stopPropagation(),navigator.clipboard.writeText(s()).then(()=>{n.addClass("copied"),(0,z.setIcon)(n,"check"),setTimeout(()=>{n.removeClass("copied"),(0,z.setIcon)(n,"copy")},1500)})}}addBubble(e,s,n){if(e==="user"&&n&&n.length>0){let r=this.messagesInner.createDiv({cls:"af-chat-bubble-attachments"});for(let o of n){let c=r.createSpan({cls:"af-chat-pill af-chat-pill-inline"}),l=c.createSpan({cls:"af-chat-pill-icon"}),d=/\.(png|jpe?g|gif|webp|svg|bmp)$/i.test(o);(0,z.setIcon)(l,d?"image":"file-text"),c.createSpan({cls:"af-chat-pill-name",text:o})}}let a=this.messagesInner.createDiv({cls:`af-chat-bubble af-chat-bubble-${e}`});if(s&&(e==="assistant"?this.renderMarkdownBubble(a,s):a.setText(s)),e==="assistant"){let r=s??"";this.addCopyBtn(a,()=>r),a._setRawText=o=>{r=o}}return this.messagesEl.scrollTop=this.messagesEl.scrollHeight,a}getOrCreateAffordancesRow(e){let s=e.parentElement;if(!s)throw new Error("bubble has no parent");let n=e.nextElementSibling;if(n&&n.classList.contains("af-chat-affordances"))return n;let a=document.createElement("div");return a.className="af-chat-affordances",s.insertBefore(a,e.nextSibling),a}attachThreadAffordance(e,s,n){let a=e.parentElement;if(!a)return;let r=this.getOrCreateAffordancesRow(e);if(r.querySelector(".af-thread-badge"))return;let o=document.createElement("div");o.className="af-thread-badge",o.setAttribute("role","button"),o.setAttribute("tabindex","0"),r.appendChild(o),(0,z.setIcon)(o,"message-circle");let c=o.createSpan({cls:"af-thread-badge-label"}),l=document.createElement("div");l.className="af-thread-container",l.style.display="none",a.insertBefore(l,r.nextSibling);let d=()=>{let m=n.getThreadIndex()[s]?.messageCount??0;m<=0?c.setText("Thread"):c.setText(`${m} ${m===1?"reply":"replies"}`),m>0&&o.addClass("has-replies")};d();let h=!1,u=async()=>{if(this.threadExpanded.get(s)===!0){l.style.display="none",this.threadExpanded.set(s,!1),o.removeClass("expanded"),this.setStatsSource(n);return}if(this.threadExpanded.set(s,!0),l.style.display="",o.addClass("expanded"),!h)try{let f=await n.openOrCreateThread(s);this.renderThreadContainer(l,f,n,d),h=!0}catch(f){l.setText(`Failed to open thread: ${f instanceof Error?f.message:String(f)}`)}};o.onclick=()=>void u(),o.onkeydown=p=>{(p.key==="Enter"||p.key===" ")&&(p.preventDefault(),u())}}renderThreadContainer(e,s,n,a){e.empty();let r=e.createDiv({cls:"af-thread-wrap"}),o=r.createDiv({cls:"af-thread-messages"}),c=null,l=null,d=S=>{S?(c||(c=o.createDiv({cls:"af-chat-activity"})),c.setText(`Working\u2026 (${S})`)):c&&(c.remove(),c=null)},h=S=>{if(S&&!l){l=o.createDiv({cls:"af-chat-streaming-dot"});for(let P=0;P<3;P++)l.createSpan()}else!S&&l&&(l.remove(),l=null)},u=(S,P,R)=>{if(S==="user"&&R&&R.length>0){let L=o.createDiv({cls:"af-chat-bubble-attachments"});for(let G of R){let U=L.createSpan({cls:"af-chat-pill af-chat-pill-inline"}),X=U.createSpan({cls:"af-chat-pill-icon"});(0,z.setIcon)(X,G.match(/\.(png|jpe?g|gif|webp|svg)$/i)?"image":"file-text"),U.createSpan({cls:"af-chat-pill-name",text:G})}}let N=o.createDiv({cls:`af-thread-bubble af-thread-bubble-${S}`});return S==="assistant"?this.renderMarkdownBubble(N,P):N.setText(P),N};for(let S of s.messages)u(S.role,S.content,S.attachments);let p=[],f=[],m=r.createDiv({cls:"af-thread-composer-wrap"}),g=m.createDiv({cls:"af-chat-pills-row af-thread-pills-row"});g.style.display="none";let v=()=>{if(g.empty(),p.length===0&&f.length===0){g.style.display="none";return}g.style.display="flex";for(let S of p){let P=g.createDiv({cls:"af-chat-pill"}),R=P.createSpan({cls:"af-chat-pill-icon"});(0,z.setIcon)(R,"file-text"),P.createSpan({cls:"af-chat-pill-name",text:S.name});let N=P.createSpan({cls:"af-chat-pill-remove"});(0,z.setIcon)(N,"x"),N.onclick=L=>{L.stopPropagation();let G=p.findIndex(U=>U.path===S.path);G>=0&&p.splice(G,1),v()}}for(let S of f){let P=g.createDiv({cls:"af-chat-pill"}),R=P.createSpan({cls:"af-chat-pill-icon"});(0,z.setIcon)(R,"image"),P.createSpan({cls:"af-chat-pill-name",text:S.name});let N=P.createSpan({cls:"af-chat-pill-remove"});(0,z.setIcon)(N,"x"),N.onclick=L=>{L.stopPropagation();let G=f.findIndex(U=>U.path===S.path);G>=0&&f.splice(G,1),v()}}},k=()=>{let S=this.app.workspace.getActiveFile();if(!S){new z.Notice("No active document to attach");return}if(p.some(R=>R.path===S.path)){new z.Notice(`"${S.name}" is already attached`);return}if(!new Set(["md","txt","json","yaml","yml","toml","csv","xml","html","css","js","ts","py","sh","sql","env","cfg","ini","log"]).has(S.extension.toLowerCase())){new z.Notice(`Can't attach "${S.name}" \u2014 only text files are supported`);return}p.push(S),v()},w=async S=>{let P=S.type.split("/")[1]?.replace("jpeg","jpg")??"png",R=S.name&&S.name!=="image"?S.name:`pasted-${Date.now()}.${P}`;if(f.some(L=>L.name===R)){new z.Notice(`"${R}" is already attached`);return}let N=await this.saveImageBlobToVault(S);N&&(f.push(N),v())},y=m.createDiv({cls:"af-chat-input-row af-thread-composer"}),C=y.createEl("button",{cls:"af-chat-attach-btn"});D(C,"plus","af-btn-icon"),C.title="Attach active document",C.onclick=S=>{S.preventDefault(),k()};let T=y.createEl("textarea",{cls:"af-chat-input af-thread-input",attr:{placeholder:"Message in thread\u2026 (Ctrl+Enter to send)",rows:"1"}});T.addEventListener("paste",S=>{let P=S.clipboardData?.items;if(P)for(let R=0;R<P.length;R++){let N=P[R];if(N.type.startsWith("image/")){S.preventDefault();let L=N.getAsFile();L&&w(L);return}}}),m.addEventListener("dragover",S=>{S.preventDefault(),S.stopPropagation(),m.addClass("af-chat-input-dragover")}),m.addEventListener("dragleave",()=>{m.removeClass("af-chat-input-dragover")}),m.addEventListener("drop",S=>{S.preventDefault(),S.stopPropagation(),m.removeClass("af-chat-input-dragover");let P=S.dataTransfer?.files;if(P)for(let R=0;R<P.length;R++){let N=P[R];N.type.startsWith("image/")&&w(N)}});let _=y.createEl("button",{cls:"af-chat-send-btn"});D(_,"arrow-up","af-btn-icon"),_.style.display="none";let O=()=>{T.style.height="auto",T.style.height=`${Math.min(T.scrollHeight,120)}px`,_.style.display=T.value.trim()?"flex":"none"};T.addEventListener("input",O),T.addEventListener("focus",()=>this.setStatsSource(s));let E=async()=>{let S=T.value.trim();if(!S||s.isStreaming)return;let P=await this.buildAttachmentContextFor(p,f),R=[...p.map(U=>U.name),...f.map(U=>U.name)],N=P?`${P}${S}`:void 0;T.value="",O(),p.length=0,f.length=0,v(),u("user",S,R.length>0?R:void 0),h(!0);let L=null,G="";try{await s.sendMessage(S,U=>{if(U.type==="text"){L||(h(!1),d(),L=u("assistant",""),L.empty()),G+=U.content;let X=L.querySelector(".af-chat-stream-text");X||(X=L.createDiv({cls:"af-chat-stream-text"})),X.setText(G)}else U.type==="tool_use"?d(U.toolName):U.type==="result"&&(d(),h(!1),L&&this.renderMarkdownBubble(L,ls(G)))},N,R.length>0?R:void 0),a()}catch(U){h(!1),d();let X=U instanceof Error?U.message:String(U);o.createDiv({cls:"af-thread-error",text:`Error: ${X}`})}};_.onclick=()=>void E(),T.onkeydown=S=>{S.key==="Enter"&&(S.ctrlKey||S.metaKey)&&(S.preventDefault(),E())}}buildToolSummary(e,s){let a=(s??this.messagesInner).createDiv({cls:"af-chat-tool-summary"}),r=a.createEl("details"),o=r.createEl("summary"),c=new Map;for(let h of e){let u=c.get(h.name)??[];h.command&&u.push(h.command),c.set(h.name,u)}let l=o.createSpan({cls:"af-chat-tool-icon"});(0,z.setIcon)(l,"wrench"),o.appendText(` ${e.length} tool call${e.length!==1?"s":""}`);let d=r.createDiv({cls:"af-chat-tool-list"});for(let[h,u]of c){let p=u.length||(c.get(h)?.length??1),f=d.createDiv({cls:"af-chat-tool-item"}),m=p>1?`${h} (\xD7${p})`:h;f.createSpan({cls:"af-chat-tool-name",text:m}),u.length===1&&u[0]&&f.createSpan({cls:"af-chat-tool-cmd",text:u[0]})}return a}renderIndicators(e){let s=e.isStreaming,n=e.currentToolName,a=e.hasCurrentTurnText,r=!!this.messagesInner.querySelector(".af-chat-stream-text"),o=null;if(s&&n?o=`Working\u2026 (${n})`:s&&a&&!r&&(o="Replying\u2026"),o?(this.activityEl?(this.activityEl.parentElement!==this.messagesInner||this.activityEl.nextElementSibling!==null)&&this.messagesInner.appendChild(this.activityEl):this.activityEl=this.messagesInner.createDiv({cls:"af-chat-activity"}),this.activityEl.textContent!==o&&this.activityEl.setText(o)):this.activityEl&&(this.activityEl.remove(),this.activityEl=null),s&&!n&&!a)if(this.streamingDot)(this.streamingDot.parentElement!==this.messagesInner||this.streamingDot.nextElementSibling!==null)&&this.messagesInner.appendChild(this.streamingDot);else{this.streamingDot=this.messagesInner.createDiv({cls:"af-chat-streaming-dot"});for(let l=0;l<3;l++)this.streamingDot.createSpan()}else this.streamingDot&&(this.streamingDot.remove(),this.streamingDot=null);this.setAttachStopMode(s)}setAttachStopMode(e){e!==this.isInStopMode&&(this.isInStopMode=e,this.attachStopBtn.empty(),e?(D(this.attachStopBtn,"square","af-btn-icon"),this.attachStopBtn.title="Stop generation",this.attachStopBtn.addClass("af-chat-stop-mode")):(D(this.attachStopBtn,"plus","af-btn-icon"),this.attachStopBtn.title="Attach active document",this.attachStopBtn.removeClass("af-chat-stop-mode")))}handleStop(){let e=this.getCurrentSession();e&&(e.session.abort(),this.addBubble("error","Generation stopped"))}attachActiveDocument(){let e=this.app.workspace.getActiveFile();if(!e){new z.Notice("No active document to attach");return}if(this.attachedFiles.some(a=>a.path===e.path)){new z.Notice(`"${e.name}" is already attached`);return}let s=e.extension.toLowerCase();if(!new Set(["md","txt","json","yaml","yml","toml","csv","xml","html","css","js","ts","py","sh","sql","env","cfg","ini","log"]).has(s)){new z.Notice(`Can't attach "${e.name}" \u2014 only text files are supported`);return}this.attachedFiles.push(e),this.renderPills()}async saveImageBlobToVault(e){let s=e.type.split("/")[1]?.replace("jpeg","jpg")??"png",n=Date.now(),a=e.name&&e.name!=="image"?e.name:`pasted-${n}.${s}`,r=`${this.plugin.settings.fleetFolder}/chat-images`,o=`${r}/${n}-${a}`;try{this.app.vault.getAbstractFileByPath(r)||await this.app.vault.createFolder(r);let c=await e.arrayBuffer();await this.app.vault.createBinary(o,c);let d=this.app.vault.adapter.getBasePath?.()??"";return{name:a,path:`${d}/${o}`}}catch(c){let l=c instanceof Error?c.message:String(c);return new z.Notice(`Failed to save image: ${l}`),null}}async buildAttachmentContextFor(e,s){if(e.length===0&&s.length===0)return"";let n=[];for(let a of e)try{let r=await this.app.vault.cachedRead(a);n.push(`### ${a.name}
12098
+ This removes its message history. The agent and its other conversations are untouched.`))return;let r=$n(this.selectedAgentName,e.id);this.sessions.get(r)?.session.dispose(),this.sessions.delete(r);try{await this.plugin.repository.deleteConversation(n,e.id)}catch(o){new q.Notice(`Couldn't delete: ${o instanceof Error?o.message:String(o)}`);return}if(await this.refreshConversationsList(n),e.id===this.selectedConversationId){let o=this.conversationsCache[0]?.id;await this.switchToAgent(this.selectedAgentName,o)}}toggleConvoPanel(){this.convoPanelCollapsed=!this.convoPanelCollapsed,this.userToggledCollapse=!0,this.applyCollapsedClass(),this.leaf.updateHeader()}applyCollapsedClass(){this.convoPanelEl&&(this.convoPanelCollapsed?this.convoPanelEl.addClass("collapsed"):this.convoPanelEl.removeClass("collapsed")),this.collapseBtn&&this.collapseBtn.toggleClass("is-collapsed",this.convoPanelCollapsed)}renderMarkdownBubble(e,s){let n=e.querySelector(".af-chat-copy-btn"),a=n?.parentNode?.removeChild(n)??null;e.empty(),e.addClass("af-compact-md"),q.MarkdownRenderer.render(this.app,s,e,"",this).then(()=>{a&&e.appendChild(a),this.wireBubbleLinks(e),e.querySelectorAll("pre").forEach(r=>{r.querySelector(".copy-code-button")?.remove();let o=r.querySelector("code");if(!o)return;let c=activeDocument.createElement("button");c.className="af-code-copy-btn",c.setAttribute("aria-label","Copy code"),(0,q.setIcon)(c,"copy"),c.onclick=l=>{l.stopPropagation(),navigator.clipboard.writeText(o.textContent??"").then(()=>{c.addClass("copied"),(0,q.setIcon)(c,"check"),window.setTimeout(()=>{c.removeClass("copied"),(0,q.setIcon)(c,"copy")},1500)})},r.setCssStyles({position:"relative"}),r.appendChild(c)})})}wireBubbleLinks(e){e.addEventListener("click",s=>{let n=s.target.closest("a");if(!n)return;if(n.classList.contains("internal-link")){s.preventDefault(),s.stopPropagation();let r=n.getAttribute("data-href")||n.getAttribute("href")||n.textContent||"";if(!r)return;let o=s.shiftKey?"split":"tab";this.app.workspace.openLinkText(r,"",o);return}let a=n.getAttribute("href")||"";if(a.startsWith("obsidian://")){s.preventDefault(),s.stopPropagation(),window.location.href=a;return}if(n.classList.contains("external-link")||/^https?:\/\//.test(a)){s.preventDefault(),s.stopPropagation(),window.open(a,"_blank");return}})}addCopyBtn(e,s){let n=e.createEl("button",{cls:"af-chat-copy-btn",attr:{"aria-label":"Copy message"}});(0,q.setIcon)(n,"copy"),n.onclick=a=>{a.stopPropagation(),navigator.clipboard.writeText(s()).then(()=>{n.addClass("copied"),(0,q.setIcon)(n,"check"),window.setTimeout(()=>{n.removeClass("copied"),(0,q.setIcon)(n,"copy")},1500)})}}addBubble(e,s,n){if(e==="user"&&n&&n.length>0){let r=this.messagesInner.createDiv({cls:"af-chat-bubble-attachments"});for(let o of n){let c=r.createSpan({cls:"af-chat-pill af-chat-pill-inline"}),l=c.createSpan({cls:"af-chat-pill-icon"}),h=/\.(png|jpe?g|gif|webp|svg|bmp)$/i.test(o);(0,q.setIcon)(l,h?"image":"file-text"),c.createSpan({cls:"af-chat-pill-name",text:o})}}let a=this.messagesInner.createDiv({cls:`af-chat-bubble af-chat-bubble-${e}`});if(s&&(e==="assistant"?this.renderMarkdownBubble(a,s):a.setText(s)),e==="assistant"){let r=s??"";this.addCopyBtn(a,()=>r),a._setRawText=o=>{r=o}}return this.messagesEl.scrollTop=this.messagesEl.scrollHeight,a}getOrCreateAffordancesRow(e){let s=e.parentElement;if(!s)throw new Error("bubble has no parent");let n=e.nextElementSibling;if(n&&n.classList.contains("af-chat-affordances"))return n;let a=activeDocument.createElement("div");return a.className="af-chat-affordances",s.insertBefore(a,e.nextSibling),a}attachThreadAffordance(e,s,n){let a=e.parentElement;if(!a)return;let r=this.getOrCreateAffordancesRow(e);if(r.querySelector(".af-thread-badge"))return;let o=activeDocument.createElement("div");o.className="af-thread-badge",o.setAttribute("role","button"),o.setAttribute("tabindex","0"),r.appendChild(o),(0,q.setIcon)(o,"message-circle");let c=o.createSpan({cls:"af-thread-badge-label"}),l=activeDocument.createElement("div");l.className="af-thread-container",l.setCssStyles({display:"none"}),a.insertBefore(l,r.nextSibling);let h=()=>{let f=n.getThreadIndex()[s]?.messageCount??0;f<=0?c.setText("Thread"):c.setText(`${f} ${f===1?"reply":"replies"}`),f>0&&o.addClass("has-replies")};h();let d=!1,u=async()=>{if(this.threadExpanded.get(s)===!0){l.setCssStyles({display:"none"}),this.threadExpanded.set(s,!1),o.removeClass("expanded"),this.setStatsSource(n);return}if(this.threadExpanded.set(s,!0),l.setCssStyles({display:""}),o.addClass("expanded"),!d)try{let m=await n.openOrCreateThread(s);this.renderThreadContainer(l,m,n,h),d=!0}catch(m){l.setText(`Failed to open thread: ${m instanceof Error?m.message:String(m)}`)}};o.onclick=()=>void u(),o.onkeydown=p=>{(p.key==="Enter"||p.key===" ")&&(p.preventDefault(),u())}}renderThreadContainer(e,s,n,a){e.empty();let r=e.createDiv({cls:"af-thread-wrap"}),o=r.createDiv({cls:"af-thread-messages"}),c=null,l=null,h=C=>{C?(c||(c=o.createDiv({cls:"af-chat-activity"})),c.setText(`Working\u2026 (${C})`)):c&&(c.remove(),c=null)},d=C=>{if(C&&!l){l=o.createDiv({cls:"af-chat-streaming-dot"});for(let I=0;I<3;I++)l.createSpan()}else!C&&l&&(l.remove(),l=null)},u=(C,I,P)=>{if(C==="user"&&P&&P.length>0){let F=o.createDiv({cls:"af-chat-bubble-attachments"});for(let z of P){let U=F.createSpan({cls:"af-chat-pill af-chat-pill-inline"}),Z=U.createSpan({cls:"af-chat-pill-icon"});(0,q.setIcon)(Z,z.match(/\.(png|jpe?g|gif|webp|svg)$/i)?"image":"file-text"),U.createSpan({cls:"af-chat-pill-name",text:z})}}let L=o.createDiv({cls:`af-thread-bubble af-thread-bubble-${C}`});return C==="assistant"?this.renderMarkdownBubble(L,I):L.setText(I),L};for(let C of s.messages)u(C.role,C.content,C.attachments);let p=[],m=[],f=r.createDiv({cls:"af-thread-composer-wrap"}),g=f.createDiv({cls:"af-chat-pills-row af-thread-pills-row"});g.setCssStyles({display:"none"});let v=()=>{if(g.empty(),p.length===0&&m.length===0){g.setCssStyles({display:"none"});return}g.setCssStyles({display:"flex"});for(let C of p){let I=g.createDiv({cls:"af-chat-pill"}),P=I.createSpan({cls:"af-chat-pill-icon"});(0,q.setIcon)(P,"file-text"),I.createSpan({cls:"af-chat-pill-name",text:C.name});let L=I.createSpan({cls:"af-chat-pill-remove"});(0,q.setIcon)(L,"x"),L.onclick=F=>{F.stopPropagation();let z=p.findIndex(U=>U.path===C.path);z>=0&&p.splice(z,1),v()}}for(let C of m){let I=g.createDiv({cls:"af-chat-pill"}),P=I.createSpan({cls:"af-chat-pill-icon"});(0,q.setIcon)(P,"image"),I.createSpan({cls:"af-chat-pill-name",text:C.name});let L=I.createSpan({cls:"af-chat-pill-remove"});(0,q.setIcon)(L,"x"),L.onclick=F=>{F.stopPropagation();let z=m.findIndex(U=>U.path===C.path);z>=0&&m.splice(z,1),v()}}},b=()=>{let C=this.app.workspace.getActiveFile();if(!C){new q.Notice("No active document to attach");return}if(p.some(P=>P.path===C.path)){new q.Notice(`"${C.name}" is already attached`);return}if(!new Set(["md","txt","json","yaml","yml","toml","csv","xml","html","css","js","ts","py","sh","sql","env","cfg","ini","log"]).has(C.extension.toLowerCase())){new q.Notice(`Can't attach "${C.name}" \u2014 only text files are supported`);return}p.push(C),v()},k=async C=>{let I=C.type.split("/")[1]?.replace("jpeg","jpg")??"png",P=C.name&&C.name!=="image"?C.name:`pasted-${Date.now()}.${I}`;if(m.some(F=>F.name===P)){new q.Notice(`"${P}" is already attached`);return}let L=await this.saveImageBlobToVault(C);L&&(m.push(L),v())},y=f.createDiv({cls:"af-chat-input-row af-thread-composer"}),S=y.createEl("button",{cls:"af-chat-attach-btn"});E(S,"plus","af-btn-icon"),S.title="Attach active document",S.onclick=C=>{C.preventDefault(),b()};let T=y.createEl("textarea",{cls:"af-chat-input af-thread-input",attr:{placeholder:"Message in thread\u2026 (Ctrl+Enter to send)",rows:"1"}});T.addEventListener("paste",C=>{let I=C.clipboardData?.items;if(I)for(let P=0;P<I.length;P++){let L=I[P];if(L.type.startsWith("image/")){C.preventDefault();let F=L.getAsFile();F&&k(F);return}}}),f.addEventListener("dragover",C=>{C.preventDefault(),C.stopPropagation(),f.addClass("af-chat-input-dragover")}),f.addEventListener("dragleave",()=>{f.removeClass("af-chat-input-dragover")}),f.addEventListener("drop",C=>{C.preventDefault(),C.stopPropagation(),f.removeClass("af-chat-input-dragover");let I=C.dataTransfer?.files;if(I)for(let P=0;P<I.length;P++){let L=I[P];L.type.startsWith("image/")&&k(L)}});let _=y.createEl("button",{cls:"af-chat-send-btn"});E(_,"arrow-up","af-btn-icon"),_.setCssStyles({display:"none"});let D=()=>{T.setCssStyles({height:"auto"}),T.setCssStyles({height:`${Math.min(T.scrollHeight,120)}px`}),_.setCssStyles({display:T.value.trim()?"flex":"none"})};T.addEventListener("input",D),T.addEventListener("focus",()=>this.setStatsSource(s));let M=async()=>{let C=T.value.trim();if(!C||s.isStreaming)return;let I=await this.buildAttachmentContextFor(p,m),P=[...p.map(U=>U.name),...m.map(U=>U.name)],L=I?`${I}${C}`:void 0;T.value="",D(),p.length=0,m.length=0,v(),u("user",C,P.length>0?P:void 0),d(!0);let F=null,z="";try{await s.sendMessage(C,U=>{if(U.type==="text"){F||(d(!1),h(),F=u("assistant",""),F.empty()),z+=U.content;let Z=F.querySelector(".af-chat-stream-text");Z||(Z=F.createDiv({cls:"af-chat-stream-text"})),Z.setText(z)}else U.type==="tool_use"?h(U.toolName):U.type==="result"&&(h(),d(!1),F&&this.renderMarkdownBubble(F,ls(z)))},L,P.length>0?P:void 0),a()}catch(U){d(!1),h();let Z=U instanceof Error?U.message:String(U);o.createDiv({cls:"af-thread-error",text:`Error: ${Z}`})}};_.onclick=()=>void M(),T.onkeydown=C=>{C.key==="Enter"&&(C.ctrlKey||C.metaKey)&&(C.preventDefault(),M())}}buildToolSummary(e,s){let a=(s??this.messagesInner).createDiv({cls:"af-chat-tool-summary"}),r=a.createEl("details"),o=r.createEl("summary"),c=new Map;for(let d of e){let u=c.get(d.name)??[];d.command&&u.push(d.command),c.set(d.name,u)}let l=o.createSpan({cls:"af-chat-tool-icon"});(0,q.setIcon)(l,"wrench"),o.appendText(` ${e.length} tool call${e.length!==1?"s":""}`);let h=r.createDiv({cls:"af-chat-tool-list"});for(let[d,u]of c){let p=u.length||(c.get(d)?.length??1),m=h.createDiv({cls:"af-chat-tool-item"}),f=p>1?`${d} (\xD7${p})`:d;m.createSpan({cls:"af-chat-tool-name",text:f}),u.length===1&&u[0]&&m.createSpan({cls:"af-chat-tool-cmd",text:u[0]})}return a}renderIndicators(e){let s=e.isStreaming,n=e.currentToolName,a=e.hasCurrentTurnText,r=!!this.messagesInner.querySelector(".af-chat-stream-text"),o=null;if(s&&n?o=`Working\u2026 (${n})`:s&&a&&!r&&(o="Replying\u2026"),o?(this.activityEl?(this.activityEl.parentElement!==this.messagesInner||this.activityEl.nextElementSibling!==null)&&this.messagesInner.appendChild(this.activityEl):this.activityEl=this.messagesInner.createDiv({cls:"af-chat-activity"}),this.activityEl.textContent!==o&&this.activityEl.setText(o)):this.activityEl&&(this.activityEl.remove(),this.activityEl=null),s&&!n&&!a)if(this.streamingDot)(this.streamingDot.parentElement!==this.messagesInner||this.streamingDot.nextElementSibling!==null)&&this.messagesInner.appendChild(this.streamingDot);else{this.streamingDot=this.messagesInner.createDiv({cls:"af-chat-streaming-dot"});for(let l=0;l<3;l++)this.streamingDot.createSpan()}else this.streamingDot&&(this.streamingDot.remove(),this.streamingDot=null);this.setAttachStopMode(s)}setAttachStopMode(e){e!==this.isInStopMode&&(this.isInStopMode=e,this.attachStopBtn.empty(),e?(E(this.attachStopBtn,"square","af-btn-icon"),this.attachStopBtn.title="Stop generation",this.attachStopBtn.addClass("af-chat-stop-mode")):(E(this.attachStopBtn,"plus","af-btn-icon"),this.attachStopBtn.title="Attach active document",this.attachStopBtn.removeClass("af-chat-stop-mode")))}handleStop(){let e=this.getCurrentSession();e&&(e.session.abort(),this.addBubble("error","Generation stopped"))}attachActiveDocument(){let e=this.app.workspace.getActiveFile();if(!e){new q.Notice("No active document to attach");return}if(this.attachedFiles.some(a=>a.path===e.path)){new q.Notice(`"${e.name}" is already attached`);return}let s=e.extension.toLowerCase();if(!new Set(["md","txt","json","yaml","yml","toml","csv","xml","html","css","js","ts","py","sh","sql","env","cfg","ini","log"]).has(s)){new q.Notice(`Can't attach "${e.name}" \u2014 only text files are supported`);return}this.attachedFiles.push(e),this.renderPills()}async saveImageBlobToVault(e){let s=e.type.split("/")[1]?.replace("jpeg","jpg")??"png",n=Date.now(),a=e.name&&e.name!=="image"?e.name:`pasted-${n}.${s}`,r=`${this.plugin.settings.fleetFolder}/chat-images`,o=`${r}/${n}-${a}`;try{this.app.vault.getAbstractFileByPath(r)||await this.app.vault.createFolder(r);let c=await e.arrayBuffer();await this.app.vault.createBinary(o,c);let h=this.app.vault.adapter.getBasePath?.()??"";return{name:a,path:`${h}/${o}`}}catch(c){let l=c instanceof Error?c.message:String(c);return new q.Notice(`Failed to save image: ${l}`),null}}async buildAttachmentContextFor(e,s){if(e.length===0&&s.length===0)return"";let n=[];for(let a of e)try{let r=await this.app.vault.cachedRead(a);n.push(`### ${a.name}
12099
12099
  \`\`\`
12100
12100
  ${r}
12101
12101
  \`\`\``)}catch{n.push(`### ${a.name}
@@ -12109,6 +12109,6 @@ ${n.join(`
12109
12109
 
12110
12110
  ---
12111
12111
 
12112
- `}async attachImageBlob(e){let s=e.type.split("/")[1]?.replace("jpeg","jpg")??"png",n=e.name&&e.name!=="image"?e.name:`pasted-${Date.now()}.${s}`;if(this.attachedImages.some(r=>r.name===n)){new z.Notice(`"${n}" is already attached`);return}let a=await this.saveImageBlobToVault(e);a&&(this.attachedImages.push(a),this.renderPills())}removeAttachment(e){this.attachedFiles=this.attachedFiles.filter(s=>s.path!==e),this.attachedImages=this.attachedImages.filter(s=>s.path!==e),this.renderPills()}renderPills(){if(this.pillsRow.empty(),this.attachedFiles.length+this.attachedImages.length===0){this.pillsRow.style.display="none";return}this.pillsRow.style.display="flex";for(let s of this.attachedFiles){let n=this.pillsRow.createDiv({cls:"af-chat-pill"}),a=n.createSpan({cls:"af-chat-pill-icon"});(0,z.setIcon)(a,"file-text"),n.createSpan({cls:"af-chat-pill-name",text:s.name});let r=n.createSpan({cls:"af-chat-pill-remove"});(0,z.setIcon)(r,"x"),r.onclick=o=>{o.stopPropagation(),this.removeAttachment(s.path)}}for(let s of this.attachedImages){let n=this.pillsRow.createDiv({cls:"af-chat-pill"}),a=n.createSpan({cls:"af-chat-pill-icon"});(0,z.setIcon)(a,"image"),n.createSpan({cls:"af-chat-pill-name",text:s.name});let r=n.createSpan({cls:"af-chat-pill-remove"});(0,z.setIcon)(r,"x"),r.onclick=o=>{o.stopPropagation(),this.removeAttachment(s.path)}}}buildAttachmentContext(){return this.buildAttachmentContextFor(this.attachedFiles,this.attachedImages)}async handleSend(){let e=this.getCurrentSession();if(!e)return;let s=this.textarea.value.trim();if(!s)return;let n=await this.buildAttachmentContext(),a=[...this.attachedFiles.map(u=>u.name),...this.attachedImages.map(u=>u.name)];this.textarea.value="",this.textarea.style.height="auto",this.sendBtn.style.display="none",this.attachedFiles=[],this.attachedImages=[],this.renderPills();let r=n?`${n}${s}`:void 0;if(this.addBubble("user",s,a.length>0?a:void 0),e.session.isStreaming){e.session.injectMessage(s,r,a.length>0?a:void 0);return}let o=null,c="",l=!1,d=e.session,h=()=>this.getCurrentSession()?.session===d;try{await e.session.sendMessage(s,u=>{if(!h()){o=null,l=!1,c="";return}if(u.type==="text"){(!l||!o||!o.isConnected)&&(o=this.addBubble("assistant"),l=!0),c+=u.content;let p=o.querySelector(".af-chat-stream-text");p||(p=o.createDiv({cls:"af-chat-stream-text"})),p.setText(c)}else if(u.type==="error"){let p=u.errorMessage?.trim()||"The agent's run ended with an error.";this.addBubble("error",`Error: ${p}`)}else if(u.type!=="compacted"){if(u.type==="result"){if(l&&o&&o.isConnected){let p=ls(c);this.renderMarkdownBubble(o,p),o._setRawText?.(p);let f=e.session.messages[e.session.messages.length-1];if(f&&f.role==="assistant"&&(this.attachThreadAffordance(o,f.id,e.session),u.toolCalls&&u.toolCalls.length>0)){let m=this.getOrCreateAffordancesRow(o);this.buildToolSummary(u.toolCalls,m)}}else u.toolCalls&&u.toolCalls.length>0&&this.buildToolSummary(u.toolCalls);c="",l=!1,o=null}}},r,a.length>0?a:void 0)}catch(u){let p=u instanceof Error?u.message:String(u);p!=="Aborted"&&this.addBubble("error",`Error: ${p}`)}}async handleNewChat(){if(!this.selectedAgentName)return;let s=this.plugin.runtime.getSnapshot().agents.find(a=>a.name===this.selectedAgentName);if(!s)return;let n=Oo();try{await this.plugin.repository.createConversation(s,n,No())}catch(a){new z.Notice(`Couldn't create conversation: ${a instanceof Error?a.message:String(a)}`);return}await this.switchToAgent(this.selectedAgentName,n)}startFreshIntro(e){let s="",n=null,a=!1;e.sendMessage("Please introduce yourself and briefly describe your capabilities and what you can help with.",r=>{r.type==="text"&&(a||(n=this.addBubble("assistant"),a=!0),s+=r.content,n.setText(s))}).then(r=>{a&&n?(this.renderMarkdownBubble(n,s),n._setRawText?.(s)):r.text.trim()&&(n=this.addBubble("assistant"),this.renderMarkdownBubble(n,r.text),n._setRawText?.(r.text)),r.toolCalls.length>0&&this.buildToolSummary(r.toolCalls),this.textarea.focus()}).catch(r=>{let o=r instanceof Error?r.message:String(r);o!=="Aborted"&&this.addBubble("error",`Error: ${o}`)})}};function ts(i){return i>=1e3?`${(i/1e3).toFixed(i>=1e4?0:1)}k`:`${i}`}var jn=class extends xe.Plugin{settings={...at};repository;runtime;get mcpManager(){return this.runtime.mcpManager}mcpAuth=new un;channelCredentials=new yn;channelManager;secretStore;statusBarEl;subscribedViews=new Set;vaultChangeTimer;suppressVaultEvents=!1;suppressTimer;runtimeUnsubscribe;async onload(){await this.loadSettings(),this.settings.claudeCliPath=await this.resolveClaudeCliPath(this.settings.claudeCliPath),this.repository=new ds(this.app.vault,this.settings),this.repository.setChannelCredentialGetter(()=>this.channelCredentials.toRecord()),this.runtime=new vs(this.repository,this.settings,this.mcpAuth),this.registerView(vt,n=>new Ds(n,this)),this.registerView(Ct,n=>new Fn(n,this)),this.registerView(Xe,n=>new ss(n,this)),this.addSettingTab(new Js(this)),await this.repository.ensureFleetStructure()&&await this.repository.ensureSamples();let e=await this.repository.updateDefaults(this.settings.defaultFileHashes??{});JSON.stringify(e)!==JSON.stringify(this.settings.defaultFileHashes??{})&&(this.settings.defaultFileHashes=e,await this.saveData(this.settings)),await this.runtime.initialize(),await this.verifyClaudeCli(!1),await this.maybeResolveCodexCliPath(),this.addRibbonIcon("bot","Agent Fleet Dashboard",()=>void this.activateDashboardView()),this.addRibbonIcon("message-circle","Agent Chat",()=>{let n=this.app.workspace.getLeavesOfType(Xe);n.length>0?this.app.workspace.revealLeaf(n[0]):this.openChatView()}),this.addCommands(),this.registerVaultHandlers(),this.registerRuntimeListeners();let s=this.app.secretStorage;if(this.secretStore=new hn(s),this.channelCredentials.setSecretStore(this.secretStore),this.mcpAuth.setSecretStore(this.secretStore),!this.settings.secretsMigrated&&this.secretStore.available){this.channelCredentials.loadCredentials(this.settings.channelCredentials??{});for(let[n,a]of Object.entries(this.settings.mcpApiKeys??{}))typeof a=="string"&&a.trim()&&this.mcpAuth.storeStaticToken(n,a);this.settings.mcpTokens={},this.settings.mcpApiKeys={},this.settings.channelCredentials={},this.settings.secretsMigrated=!0,await this.saveData(this.settings)}else this.channelCredentials.loadCredentials(this.secretStore.available?void 0:this.settings.channelCredentials??{});this.secretStore.available||this.channelCredentials.onChanged(n=>{this.settings.channelCredentials=n,this.saveSettings()}),this.channelManager=new gn({getRepository:()=>this.repository,vault:this.app.vault,getSettings:()=>this.settings,getChannelCredentials:()=>this.channelCredentials.toRecord(),getMcpAuth:()=>this.mcpAuth,adapterFactory:(n,a)=>{if(n.type==="slack")return new Mn(n,a);if(n.type==="telegram")return new Ln(n,a);throw new Error(`Channel type \`${n.type}\` is not yet supported in this version.`)}});try{await this.channelManager.start(this.runtime.getSnapshot())}catch(n){console.error("Agent Fleet: channel manager failed to start",n),new xe.Notice("Agent Fleet: channel manager failed to start \u2014 check console.")}this.runtime.onHeartbeatResult((n,a,r)=>{this.channelManager?.broadcastToChannel(a,`*Heartbeat \u2014 ${n}*
12112
+ `}async attachImageBlob(e){let s=e.type.split("/")[1]?.replace("jpeg","jpg")??"png",n=e.name&&e.name!=="image"?e.name:`pasted-${Date.now()}.${s}`;if(this.attachedImages.some(r=>r.name===n)){new q.Notice(`"${n}" is already attached`);return}let a=await this.saveImageBlobToVault(e);a&&(this.attachedImages.push(a),this.renderPills())}removeAttachment(e){this.attachedFiles=this.attachedFiles.filter(s=>s.path!==e),this.attachedImages=this.attachedImages.filter(s=>s.path!==e),this.renderPills()}renderPills(){if(this.pillsRow.empty(),this.attachedFiles.length+this.attachedImages.length===0){this.pillsRow.setCssStyles({display:"none"});return}this.pillsRow.setCssStyles({display:"flex"});for(let s of this.attachedFiles){let n=this.pillsRow.createDiv({cls:"af-chat-pill"}),a=n.createSpan({cls:"af-chat-pill-icon"});(0,q.setIcon)(a,"file-text"),n.createSpan({cls:"af-chat-pill-name",text:s.name});let r=n.createSpan({cls:"af-chat-pill-remove"});(0,q.setIcon)(r,"x"),r.onclick=o=>{o.stopPropagation(),this.removeAttachment(s.path)}}for(let s of this.attachedImages){let n=this.pillsRow.createDiv({cls:"af-chat-pill"}),a=n.createSpan({cls:"af-chat-pill-icon"});(0,q.setIcon)(a,"image"),n.createSpan({cls:"af-chat-pill-name",text:s.name});let r=n.createSpan({cls:"af-chat-pill-remove"});(0,q.setIcon)(r,"x"),r.onclick=o=>{o.stopPropagation(),this.removeAttachment(s.path)}}}buildAttachmentContext(){return this.buildAttachmentContextFor(this.attachedFiles,this.attachedImages)}async handleSend(){let e=this.getCurrentSession();if(!e)return;let s=this.textarea.value.trim();if(!s)return;let n=await this.buildAttachmentContext(),a=[...this.attachedFiles.map(u=>u.name),...this.attachedImages.map(u=>u.name)];this.textarea.value="",this.textarea.setCssStyles({height:"auto"}),this.sendBtn.setCssStyles({display:"none"}),this.attachedFiles=[],this.attachedImages=[],this.renderPills();let r=n?`${n}${s}`:void 0;if(this.addBubble("user",s,a.length>0?a:void 0),e.session.isStreaming){e.session.injectMessage(s,r,a.length>0?a:void 0);return}let o=null,c="",l=!1,h=e.session,d=()=>this.getCurrentSession()?.session===h;try{await e.session.sendMessage(s,u=>{if(!d()){o=null,l=!1,c="";return}if(u.type==="text"){(!l||!o||!o.isConnected)&&(o=this.addBubble("assistant"),l=!0),c+=u.content;let p=o.querySelector(".af-chat-stream-text");p||(p=o.createDiv({cls:"af-chat-stream-text"})),p.setText(c)}else if(u.type==="error"){let p=u.errorMessage?.trim()||"The agent's run ended with an error.";this.addBubble("error",`Error: ${p}`)}else if(u.type!=="compacted"){if(u.type==="result"){if(l&&o&&o.isConnected){let p=ls(c);this.renderMarkdownBubble(o,p),o._setRawText?.(p);let m=e.session.messages[e.session.messages.length-1];if(m&&m.role==="assistant"&&(this.attachThreadAffordance(o,m.id,e.session),u.toolCalls&&u.toolCalls.length>0)){let f=this.getOrCreateAffordancesRow(o);this.buildToolSummary(u.toolCalls,f)}}else u.toolCalls&&u.toolCalls.length>0&&this.buildToolSummary(u.toolCalls);c="",l=!1,o=null}}},r,a.length>0?a:void 0)}catch(u){let p=u instanceof Error?u.message:String(u);p!=="Aborted"&&this.addBubble("error",`Error: ${p}`)}}async handleNewChat(){if(!this.selectedAgentName)return;let s=this.plugin.runtime.getSnapshot().agents.find(a=>a.name===this.selectedAgentName);if(!s)return;let n=No();try{await this.plugin.repository.createConversation(s,n,Bo())}catch(a){new q.Notice(`Couldn't create conversation: ${a instanceof Error?a.message:String(a)}`);return}await this.switchToAgent(this.selectedAgentName,n)}startFreshIntro(e){let s="",n=null,a=!1;e.sendMessage("Please introduce yourself and briefly describe your capabilities and what you can help with.",r=>{r.type==="text"&&(a||(n=this.addBubble("assistant"),a=!0),s+=r.content,n.setText(s))}).then(r=>{a&&n?(this.renderMarkdownBubble(n,s),n._setRawText?.(s)):r.text.trim()&&(n=this.addBubble("assistant"),this.renderMarkdownBubble(n,r.text),n._setRawText?.(r.text)),r.toolCalls.length>0&&this.buildToolSummary(r.toolCalls),this.textarea.focus()}).catch(r=>{let o=r instanceof Error?r.message:String(r);o!=="Aborted"&&this.addBubble("error",`Error: ${o}`)})}};function ss(i){return i>=1e3?`${(i/1e3).toFixed(i>=1e4?0:1)}k`:`${i}`}var jn=class extends Ce.Plugin{settings={...at};repository;runtime;get mcpManager(){return this.runtime.mcpManager}mcpAuth=new un;channelCredentials=new yn;channelManager;secretStore;statusBarEl;subscribedViews=new Set;vaultChangeTimer;suppressVaultEvents=!1;suppressTimer;runtimeUnsubscribe;async onload(){await this.loadSettings(),this.settings.claudeCliPath=await this.resolveClaudeCliPath(this.settings.claudeCliPath),this.repository=new ds(this.app,this.settings),this.repository.setChannelCredentialGetter(()=>this.channelCredentials.toRecord()),this.runtime=new vs(this.repository,this.settings,this.mcpAuth),this.registerView(Ct,n=>new Ds(n,this)),this.registerView(Ut,n=>new Fn(n,this)),this.registerView(nt,n=>new ns(n,this)),this.addSettingTab(new Js(this)),await this.repository.ensureFleetStructure()&&await this.repository.ensureSamples();let e=await this.repository.updateDefaults(this.settings.defaultFileHashes??{});JSON.stringify(e)!==JSON.stringify(this.settings.defaultFileHashes??{})&&(this.settings.defaultFileHashes=e,await this.saveData(this.settings)),await this.runtime.initialize(),await this.verifyClaudeCli(!1),await this.maybeResolveCodexCliPath(),this.addRibbonIcon("bot","Agent Fleet Dashboard",()=>void this.activateDashboardView()),this.addRibbonIcon("message-circle","Agent Chat",()=>{let n=this.app.workspace.getLeavesOfType(nt);n.length>0?this.app.workspace.revealLeaf(n[0]):this.openChatView()}),this.addCommands(),this.registerVaultHandlers(),this.registerRuntimeListeners();let s=this.app.secretStorage;if(this.secretStore=new hn(s),this.channelCredentials.setSecretStore(this.secretStore),this.mcpAuth.setSecretStore(this.secretStore),!this.settings.secretsMigrated&&this.secretStore.available){this.channelCredentials.loadCredentials(this.settings.channelCredentials??{});for(let[n,a]of Object.entries(this.settings.mcpApiKeys??{}))typeof a=="string"&&a.trim()&&this.mcpAuth.storeStaticToken(n,a);this.settings.mcpTokens={},this.settings.mcpApiKeys={},this.settings.channelCredentials={},this.settings.secretsMigrated=!0,await this.saveData(this.settings)}else this.channelCredentials.loadCredentials(this.secretStore.available?void 0:this.settings.channelCredentials??{});this.secretStore.available||this.channelCredentials.onChanged(n=>{this.settings.channelCredentials=n,this.saveSettings()}),this.channelManager=new gn({getRepository:()=>this.repository,vault:this.app.vault,getSettings:()=>this.settings,getChannelCredentials:()=>this.channelCredentials.toRecord(),getMcpAuth:()=>this.mcpAuth,adapterFactory:(n,a)=>{if(n.type==="slack")return new Mn(n,a);if(n.type==="telegram")return new Ln(n,a);throw new Error(`Channel type \`${n.type}\` is not yet supported in this version.`)}});try{await this.channelManager.start(this.runtime.getSnapshot())}catch(n){console.error("Agent Fleet: channel manager failed to start",n),new Ce.Notice("Agent Fleet: channel manager failed to start \u2014 check console.")}this.runtime.onHeartbeatResult((n,a,r)=>{this.channelManager?.broadcastToChannel(a,`*Heartbeat \u2014 ${n}*
12113
12113
 
12114
- ${r}`).catch(o=>{console.warn(`Agent Fleet: heartbeat channel post failed for ${n}`,o)})}),this.refreshStatusBar(),this.importNativeMcpServers(),this.registerInterval(window.setInterval(()=>void this.mcpManager.refreshProbeTokens(),30*6e4)),new xe.Notice("Agent Fleet loaded.")}async importNativeMcpServers(){if(this.settings.mcpImported)return;if(this.repository.getMcpServers().length>0){this.settings.mcpImported=!0,await this.saveData(this.settings);return}let t=n=>{try{return(0,Is.existsSync)(n)?(0,Is.readFileSync)(n,"utf-8"):null}catch{return null}},e=t((0,Wa.join)((0,ja.homedir)(),".claude.json")),s=t((0,Wa.join)((0,ja.homedir)(),".codex","config.toml"));try{let n=mr(e?ur(e):{servers:[],tokens:{}},s?pr(s):{servers:[],tokens:{}}),a=0;for(let r of n.servers)try{await this.repository.saveMcpServer(r,r.description??"");let o=n.tokens[r.name];o&&this.mcpAuth.storeStaticToken(r.name,o),a++}catch(o){console.warn(`Agent Fleet: failed to import MCP server "${r.name}":`,o)}this.settings.mcpImported=!0,await this.saveData(this.settings),a>0&&(await this.refreshFromVault(),new xe.Notice(`Agent Fleet: imported ${a} MCP server${a===1?"":"s"}.`))}catch(n){console.error("Agent Fleet: MCP import failed",n)}}onunload(){this.runtimeUnsubscribe?.(),this.runtimeUnsubscribe=void 0,this.vaultChangeTimer&&(clearTimeout(this.vaultChangeTimer),this.vaultChangeTimer=void 0),this.suppressTimer&&(clearTimeout(this.suppressTimer),this.suppressTimer=void 0),this.app.workspace.detachLeavesOfType(vt),this.app.workspace.detachLeavesOfType(Ct),this.app.workspace.detachLeavesOfType(Xe),this.runtime?.shutdown(),this.channelManager?.stop(),$i()}async loadSettings(){this.settings={...at,...await this.loadData()}}async saveSettings(){this.settings.claudeCliPath=await this.resolveClaudeCliPath(this.settings.claudeCliPath),await this.maybeResolveCodexCliPath(),ji(),await this.saveData(this.settings),this.repository&&this.runtime&&(this.runtime.shutdown(),this.repository=new ds(this.app.vault,this.settings),this.repository.setChannelCredentialGetter(()=>this.channelCredentials.toRecord()),this.runtime=new vs(this.repository,this.settings,this.mcpAuth),await this.repository.ensureFleetStructure(),await this.runtime.initialize(),this.registerRuntimeListeners(),this.notifyViews(),this.refreshStatusBar(),this.channelCredentials.loadCredentials(this.secretStore.available?void 0:this.settings.channelCredentials??{}),this.channelManager?.reconcile(this.runtime.getSnapshot()))}subscribeView(t){this.subscribedViews.add(t)}unsubscribeView(t){this.subscribedViews.delete(t)}async activateDashboardView(){let t=this.app.workspace.getLeavesOfType(vt);if(t.length>0){this.app.workspace.revealLeaf(t[0]);return}await this.app.workspace.getLeaf(!0).setViewState({type:vt,active:!0})}async navigateDashboard(t,e){await this.activateDashboardView();let n=this.app.workspace.getLeavesOfType(vt)[0];if(n){let a=n.view;a instanceof Ds&&a.navigateTo(t,e)}}async activateAgentsView(){let t=this.getLeafForView(Ct,"left");await t.setViewState({type:Ct,active:!0}),this.app.workspace.revealLeaf(t)}async openChatView(t){if(t){let s=this.app.workspace.getLeavesOfType(Xe);for(let n of s)if(n.view instanceof ss&&n.view.selectedAgentName===t){this.app.workspace.revealLeaf(n);return}}let e=this.app.workspace.getRightLeaf(!1)??this.app.workspace.getLeaf(!0);await e.setViewState({type:Xe,active:!0,state:t?{agentName:t}:{}}),this.app.workspace.revealLeaf(e),t&&e.view instanceof ss&&e.view.selectAgent(t)}async refreshFromVault(){this.suppressVaultEvents=!0;try{await this.runtime.refreshFromVault(),this.notifyViews(),this.refreshStatusBar(),this.channelManager?.reconcile(this.runtime.getSnapshot())}finally{this.suppressTimer&&clearTimeout(this.suppressTimer),this.suppressTimer=setTimeout(()=>{this.suppressTimer=void 0,this.suppressVaultEvents=!1},500)}}refreshStatusBar(){if(!this.settings.showStatusBar){this.statusBarEl?.detach(),this.statusBarEl=void 0;return}this.statusBarEl||(this.statusBarEl=this.addStatusBarItem(),this.statusBarEl.onclick=()=>void this.activateDashboardView());let t=this.runtime.getFleetStatus();this.statusBarEl.setText(`\u{1F916} ${t.running} running \xB7 ${t.pending} pending \xB7 ${t.completedToday} completed today`)}async verifyClaudeCli(t=!0){let e=await this.resolveClaudeCliPath(this.settings.claudeCliPath);return this.settings.claudeCliPath=e,await this.verifyCliBinary(e,"Claude",t)}async verifyCodexCli(t=!0){let e=await this.resolveCliPathFrom(Kn(this.settings.codexCliPath),this.settings.codexCliPath);return this.settings.codexCliPath=e,await this.verifyCliBinary(e,"Codex",t)}async verifyCliBinary(t,e,s){return await new Promise(n=>{let a=ot(t,["--version"]),r="";a.stderr.on("data",o=>{r+=o.toString()}),a.on("close",o=>{let c=o===0;c||console.error(`Agent Fleet: ${e} CLI verification failed`,r),s&&new xe.Notice(c?`${e} CLI available.`:`${e} CLI verification failed \u2014 check ${e} CLI Path in settings.`),n(c)}),a.on("error",o=>{console.error(`Agent Fleet: ${e} CLI verification error`,o),s&&new xe.Notice(`${e} CLI verification failed \u2014 check ${e} CLI Path in settings.`),n(!1)})})}async openPath(t){let e=this.app.vault.getAbstractFileByPath((0,xe.normalizePath)(t));e instanceof xe.TFile&&await this.app.workspace.getLeaf(!0).openFile(e)}async createAgentTemplate(){await this.navigateDashboard("create-agent")}async createSkillTemplate(){await this.navigateDashboard("create-skill")}async openCreateTask(){await this.navigateDashboard("create-task")}async runAgentPrompt(t){let e=this.repository.getAgentByName(t);if(!e){new xe.Notice(`Unknown agent: ${t}`);return}await this.runtime.runAgentNow(e,"Run now and summarize the current state.")}async chatWithAgent(t){if(!this.repository.getAgentByName(t)){new xe.Notice(`Unknown agent: ${t}`);return}await this.openChatView(t)}async deleteAgent(t){if(!this.repository.getAgentByName(t)){new xe.Notice(`Unknown agent: ${t}`);return}let s=this.repository.getTasksForAgent(t),n=this.runtime.getRecentRuns().filter(o=>o.agent===t),a=this.repository.getMemoryPath(t),r=!!this.app.vault.getAbstractFileByPath(a);new Gs(this.app,{agentName:t,taskCount:s.length,runCount:n.length,hasMemory:r},async o=>{let c=await this.repository.deleteAgent(t,o);await new Promise(l=>setTimeout(l,200)),await this.refreshFromVault(),new xe.Notice(`Deleted agent "${t}" (${c.trashedFiles.length} files moved to trash)`),await this.navigateDashboard("agents")}).open()}async toggleAgent(t,e){let s=this.repository.getAgentByName(t);if(!s)return;let n=this.app.vault.getAbstractFileByPath(s.filePath);if(!(n instanceof xe.TFile))return;let a=await this.app.vault.cachedRead(n),{frontmatter:r,body:o}=Q(a);r.enabled=e,await this.app.vault.modify(n,H(r,o)),await this.refreshFromVault()}addCommands(){this.addCommand({id:"open-dashboard",name:"Open Dashboard",callback:()=>void this.activateDashboardView()}),this.addCommand({id:"open-agents-panel",name:"Open Agents Panel",callback:()=>void this.activateAgentsView()}),this.addCommand({id:"open-chat",name:"Open Agent Chat",callback:()=>{let t=this.app.workspace.getLeavesOfType(Xe);t.length>0?this.app.workspace.revealLeaf(t[0]):this.openChatView()}}),this.addCommand({id:"new-chat-tab",name:"New Chat Tab",callback:()=>void this.openChatView()}),this.addCommand({id:"new-agent",name:"New Agent",callback:()=>void this.createAgentTemplate()}),this.addCommand({id:"new-skill",name:"New Skill",callback:()=>void this.createSkillTemplate()}),this.addCommand({id:"new-task",name:"New Task",callback:()=>void this.openCreateTask()}),this.addCommand({id:"run-agent-now",name:"Run Agent Now",callback:()=>{let t=this.runtime.getSnapshot().agents[0];t?this.runAgentPrompt(t.name):new xe.Notice("No agents configured.")}}),this.addCommand({id:"pause-all",name:"Pause All",callback:()=>{this.runtime.scheduler.pauseAll(),new xe.Notice("Agent Fleet paused.")}}),this.addCommand({id:"resume-all",name:"Resume All",callback:()=>{this.runtime.scheduler.resumeAll(),new xe.Notice("Agent Fleet resumed.")}}),this.addCommand({id:"view-fleet-status",name:"View Fleet Status",callback:()=>{let t=this.runtime.getFleetStatus();new xe.Notice(`${t.running} running \xB7 ${t.pending} pending \xB7 ${t.completedToday} completed today`)}})}debouncedVaultRefresh(){this.suppressVaultEvents||(this.vaultChangeTimer&&clearTimeout(this.vaultChangeTimer),this.vaultChangeTimer=setTimeout(()=>{this.suppressVaultEvents||this.refreshFromVault()},500))}registerVaultHandlers(){this.registerEvent(this.app.vault.on("create",t=>{t instanceof xe.TFile&&t.path.startsWith(`${this.settings.fleetFolder}/`)&&this.debouncedVaultRefresh()})),this.registerEvent(this.app.vault.on("modify",t=>{t instanceof xe.TFile&&t.path.startsWith(`${this.settings.fleetFolder}/`)&&this.debouncedVaultRefresh()})),this.registerEvent(this.app.vault.on("rename",t=>{t.path.startsWith(`${this.settings.fleetFolder}/`)&&this.debouncedVaultRefresh()})),this.registerEvent(this.app.vault.on("delete",t=>{t.path.startsWith(`${this.settings.fleetFolder}/`)&&this.debouncedVaultRefresh()}))}registerRuntimeListeners(){this.runtimeUnsubscribe?.(),this.runtimeUnsubscribe=this.runtime.subscribe(()=>{this.notifyViews(),this.refreshStatusBar()})}notifyViews(){for(let t of this.subscribedViews)t.render()}async resolveClaudeCliPath(t){return this.resolveCliPathFrom(pi(t),t)}async maybeResolveCodexCliPath(){this.runtime?.getSnapshot().agents.some(e=>bt(e.adapter)==="codex")&&(this.settings.codexCliPath=await this.resolveCliPathFrom(Kn(this.settings.codexCliPath),this.settings.codexCliPath))}async resolveCliPathFrom(t,e){for(let s of t)if(Jn(s)&&(0,Is.existsSync)(s)||!Jn(s)&&await new Promise(a=>{let r=ot(s,["--version"]);r.on("close",o=>a(o===0)),r.on("error",()=>a(!1))}))return s;return e}getLeafForView(t,e){let s=this.app.workspace.getLeavesOfType(t)[0];return s||(e==="right"?this.app.workspace.getRightLeaf(!1)??this.app.workspace.getLeaf(!0):this.app.workspace.getLeftLeaf(!1)??this.app.workspace.getLeaf(!1))}};
12114
+ ${r}`).catch(o=>{console.warn(`Agent Fleet: heartbeat channel post failed for ${n}`,o)})}),this.refreshStatusBar(),this.importNativeMcpServers(),this.registerInterval(window.setInterval(()=>void this.mcpManager.refreshProbeTokens(),30*6e4)),new Ce.Notice("Agent Fleet loaded.")}async importNativeMcpServers(){if(this.settings.mcpImported)return;if(this.repository.getMcpServers().length>0){this.settings.mcpImported=!0,await this.saveData(this.settings);return}let t=n=>{try{return(0,Is.existsSync)(n)?(0,Is.readFileSync)(n,"utf-8"):null}catch{return null}},e=t((0,Ha.join)((0,Wa.homedir)(),".claude.json")),s=t((0,Ha.join)((0,Wa.homedir)(),".codex","config.toml"));try{let n=fr(e?pr(e):{servers:[],tokens:{}},s?mr(s):{servers:[],tokens:{}}),a=0;for(let r of n.servers)try{await this.repository.saveMcpServer(r,r.description??"");let o=n.tokens[r.name];o&&this.mcpAuth.storeStaticToken(r.name,o),a++}catch(o){console.warn(`Agent Fleet: failed to import MCP server "${r.name}":`,o)}this.settings.mcpImported=!0,await this.saveData(this.settings),a>0&&(await this.refreshFromVault(),new Ce.Notice(`Agent Fleet: imported ${a} MCP server${a===1?"":"s"}.`))}catch(n){console.error("Agent Fleet: MCP import failed",n)}}onunload(){this.runtimeUnsubscribe?.(),this.runtimeUnsubscribe=void 0,this.vaultChangeTimer&&(window.clearTimeout(this.vaultChangeTimer),this.vaultChangeTimer=void 0),this.suppressTimer&&(window.clearTimeout(this.suppressTimer),this.suppressTimer=void 0),this.runtime?.shutdown(),this.channelManager?.stop(),ji()}async loadSettings(){this.settings={...at,...await this.loadData()}}async saveSettings(){this.settings.claudeCliPath=await this.resolveClaudeCliPath(this.settings.claudeCliPath),await this.maybeResolveCodexCliPath(),Wi(),await this.saveData(this.settings),this.repository&&this.runtime&&(this.runtime.shutdown(),this.repository=new ds(this.app,this.settings),this.repository.setChannelCredentialGetter(()=>this.channelCredentials.toRecord()),this.runtime=new vs(this.repository,this.settings,this.mcpAuth),await this.repository.ensureFleetStructure(),await this.runtime.initialize(),this.registerRuntimeListeners(),this.notifyViews(),this.refreshStatusBar(),this.channelCredentials.loadCredentials(this.secretStore.available?void 0:this.settings.channelCredentials??{}),this.channelManager?.reconcile(this.runtime.getSnapshot()))}subscribeView(t){this.subscribedViews.add(t)}unsubscribeView(t){this.subscribedViews.delete(t)}async activateDashboardView(){let t=this.app.workspace.getLeavesOfType(Ct);if(t.length>0){this.app.workspace.revealLeaf(t[0]);return}await this.app.workspace.getLeaf(!0).setViewState({type:Ct,active:!0})}async navigateDashboard(t,e){await this.activateDashboardView();let n=this.app.workspace.getLeavesOfType(Ct)[0];if(n){let a=n.view;a instanceof Ds&&a.navigateTo(t,e)}}async activateAgentsView(){let t=this.getLeafForView(Ut,"left");await t.setViewState({type:Ut,active:!0}),this.app.workspace.revealLeaf(t)}async openChatView(t){if(t){let s=this.app.workspace.getLeavesOfType(nt);for(let n of s)if(n.view instanceof ns&&n.view.selectedAgentName===t){this.app.workspace.revealLeaf(n);return}}let e=this.app.workspace.getRightLeaf(!1)??this.app.workspace.getLeaf(!0);await e.setViewState({type:nt,active:!0,state:t?{agentName:t}:{}}),this.app.workspace.revealLeaf(e),t&&e.view instanceof ns&&e.view.selectAgent(t)}async refreshFromVault(){this.suppressVaultEvents=!0;try{await this.runtime.refreshFromVault(),this.notifyViews(),this.refreshStatusBar(),this.channelManager?.reconcile(this.runtime.getSnapshot())}finally{this.suppressTimer&&window.clearTimeout(this.suppressTimer),this.suppressTimer=window.setTimeout(()=>{this.suppressTimer=void 0,this.suppressVaultEvents=!1},500)}}refreshStatusBar(){if(!this.settings.showStatusBar){this.statusBarEl?.detach(),this.statusBarEl=void 0;return}this.statusBarEl||(this.statusBarEl=this.addStatusBarItem(),this.statusBarEl.onclick=()=>void this.activateDashboardView());let t=this.runtime.getFleetStatus();this.statusBarEl.setText(`\u{1F916} ${t.running} running \xB7 ${t.pending} pending \xB7 ${t.completedToday} completed today`)}async verifyClaudeCli(t=!0){let e=await this.resolveClaudeCliPath(this.settings.claudeCliPath);return this.settings.claudeCliPath=e,await this.verifyCliBinary(e,"Claude",t)}async verifyCodexCli(t=!0){let e=await this.resolveCliPathFrom(Kn(this.settings.codexCliPath),this.settings.codexCliPath);return this.settings.codexCliPath=e,await this.verifyCliBinary(e,"Codex",t)}async verifyCliBinary(t,e,s){return await new Promise(n=>{let a=lt(t,["--version"]),r="";a.stderr.on("data",o=>{r+=o.toString()}),a.on("close",o=>{let c=o===0;c||console.error(`Agent Fleet: ${e} CLI verification failed`,r),s&&new Ce.Notice(c?`${e} CLI available.`:`${e} CLI verification failed \u2014 check ${e} CLI Path in settings.`),n(c)}),a.on("error",o=>{console.error(`Agent Fleet: ${e} CLI verification error`,o),s&&new Ce.Notice(`${e} CLI verification failed \u2014 check ${e} CLI Path in settings.`),n(!1)})})}async openPath(t){let e=this.app.vault.getAbstractFileByPath((0,Ce.normalizePath)(t));e instanceof Ce.TFile&&await this.app.workspace.getLeaf(!0).openFile(e)}async createAgentTemplate(){await this.navigateDashboard("create-agent")}async createSkillTemplate(){await this.navigateDashboard("create-skill")}async openCreateTask(){await this.navigateDashboard("create-task")}async runAgentPrompt(t){let e=this.repository.getAgentByName(t);if(!e){new Ce.Notice(`Unknown agent: ${t}`);return}await this.runtime.runAgentNow(e,"Run now and summarize the current state.")}async chatWithAgent(t){if(!this.repository.getAgentByName(t)){new Ce.Notice(`Unknown agent: ${t}`);return}await this.openChatView(t)}async deleteAgent(t){if(!this.repository.getAgentByName(t)){new Ce.Notice(`Unknown agent: ${t}`);return}let s=this.repository.getTasksForAgent(t),n=this.runtime.getRecentRuns().filter(o=>o.agent===t),a=this.repository.getMemoryPath(t),r=!!this.app.vault.getAbstractFileByPath(a);new Gs(this.app,{agentName:t,taskCount:s.length,runCount:n.length,hasMemory:r},async o=>{let c=await this.repository.deleteAgent(t,o);await new Promise(l=>window.setTimeout(l,200)),await this.refreshFromVault(),new Ce.Notice(`Deleted agent "${t}" (${c.trashedFiles.length} files moved to trash)`),await this.navigateDashboard("agents")}).open()}async toggleAgent(t,e){let s=this.repository.getAgentByName(t);if(!s)return;let n=this.app.vault.getAbstractFileByPath(s.filePath);if(!(n instanceof Ce.TFile))return;let a=await this.app.vault.cachedRead(n),{frontmatter:r,body:o}=J(a);r.enabled=e,await this.app.vault.modify(n,W(r,o)),await this.refreshFromVault()}addCommands(){this.addCommand({id:"open-dashboard",name:"Open dashboard",callback:()=>void this.activateDashboardView()}),this.addCommand({id:"open-agents-panel",name:"Open agents panel",callback:()=>void this.activateAgentsView()}),this.addCommand({id:"open-chat",name:"Open agent chat",callback:()=>{let t=this.app.workspace.getLeavesOfType(nt);t.length>0?this.app.workspace.revealLeaf(t[0]):this.openChatView()}}),this.addCommand({id:"new-chat-tab",name:"New chat tab",callback:()=>void this.openChatView()}),this.addCommand({id:"new-agent",name:"New agent",callback:()=>void this.createAgentTemplate()}),this.addCommand({id:"new-skill",name:"New skill",callback:()=>void this.createSkillTemplate()}),this.addCommand({id:"new-task",name:"New task",callback:()=>void this.openCreateTask()}),this.addCommand({id:"run-agent-now",name:"Run agent now",callback:()=>{let t=this.runtime.getSnapshot().agents[0];t?this.runAgentPrompt(t.name):new Ce.Notice("No agents configured.")}}),this.addCommand({id:"pause-all",name:"Pause all",callback:()=>{this.runtime.scheduler.pauseAll(),new Ce.Notice("Agent Fleet paused.")}}),this.addCommand({id:"resume-all",name:"Resume all",callback:()=>{this.runtime.scheduler.resumeAll(),new Ce.Notice("Agent Fleet resumed.")}}),this.addCommand({id:"view-fleet-status",name:"View status",callback:()=>{let t=this.runtime.getFleetStatus();new Ce.Notice(`${t.running} running \xB7 ${t.pending} pending \xB7 ${t.completedToday} completed today`)}})}debouncedVaultRefresh(){this.suppressVaultEvents||(this.vaultChangeTimer&&window.clearTimeout(this.vaultChangeTimer),this.vaultChangeTimer=window.setTimeout(()=>{this.suppressVaultEvents||this.refreshFromVault()},500))}registerVaultHandlers(){this.registerEvent(this.app.vault.on("create",t=>{t instanceof Ce.TFile&&t.path.startsWith(`${this.settings.fleetFolder}/`)&&this.debouncedVaultRefresh()})),this.registerEvent(this.app.vault.on("modify",t=>{t instanceof Ce.TFile&&t.path.startsWith(`${this.settings.fleetFolder}/`)&&this.debouncedVaultRefresh()})),this.registerEvent(this.app.vault.on("rename",t=>{t.path.startsWith(`${this.settings.fleetFolder}/`)&&this.debouncedVaultRefresh()})),this.registerEvent(this.app.vault.on("delete",t=>{t.path.startsWith(`${this.settings.fleetFolder}/`)&&this.debouncedVaultRefresh()}))}registerRuntimeListeners(){this.runtimeUnsubscribe?.(),this.runtimeUnsubscribe=this.runtime.subscribe(()=>{this.notifyViews(),this.refreshStatusBar()})}notifyViews(){for(let t of this.subscribedViews)t.render()}async resolveClaudeCliPath(t){return this.resolveCliPathFrom(mi(t),t)}async maybeResolveCodexCliPath(){this.runtime?.getSnapshot().agents.some(e=>wt(e.adapter)==="codex")&&(this.settings.codexCliPath=await this.resolveCliPathFrom(Kn(this.settings.codexCliPath),this.settings.codexCliPath))}async resolveCliPathFrom(t,e){for(let s of t)if(Jn(s)&&(0,Is.existsSync)(s)||!Jn(s)&&await new Promise(a=>{let r=lt(s,["--version"]);r.on("close",o=>a(o===0)),r.on("error",()=>a(!1))}))return s;return e}getLeafForView(t,e){let s=this.app.workspace.getLeavesOfType(t)[0];return s||(e==="right"?this.app.workspace.getRightLeaf(!1)??this.app.workspace.getLeaf(!0):this.app.workspace.getLeftLeaf(!1)??this.app.workspace.getLeaf(!1))}};