@devicelink/dlink 0.4.0 → 0.4.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +4 -4
  2. package/index.js +6 -6
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -71,7 +71,7 @@ npm install -g @devicelink/dlink
71
71
 
72
72
  ### 1. Create your account
73
73
 
74
- Sign in at [devicelink.ai](https://devicelink.ai) with Google. A workspace is created for you automatically.
74
+ Sign in at [devicelink.ai](https://devicelink.ai) and choose a sign-in method. A workspace is created for you automatically.
75
75
 
76
76
  ### 2. Install and run the agent
77
77
 
@@ -81,7 +81,7 @@ Open a terminal in the folder you want to share, install using either method abo
81
81
  dlink
82
82
  ```
83
83
 
84
- Type `signin` in the agent console and sign in with the same Google account.
84
+ Type `signin` in the agent console and sign in with the same account.
85
85
 
86
86
  ### 3. Connect an AI platform
87
87
 
@@ -94,7 +94,7 @@ https://api.devicelink.ai/mcp
94
94
  - **Claude** - Settings → Integrations → Add connector
95
95
  - **ChatGPT** - Settings → Connected apps → Add custom connector
96
96
 
97
- Sign in with the same Google account when prompted. Then ask the AI to list your files.
97
+ Sign in with the same account when prompted. Then ask the AI to list your files.
98
98
 
99
99
  ## Commands
100
100
 
@@ -162,7 +162,7 @@ any of them applied.
162
162
  ## How it works
163
163
 
164
164
  1. **Run the agent** from the folder you want to share.
165
- 2. **Sign in** with Google when the browser opens.
165
+ 2. **Sign in** when the browser opens.
166
166
  3. **Approve your device** when prompted in the terminal.
167
167
  4. **Connect an AI** using the MCP endpoint above.
168
168
  5. **Stop anytime** by closing the agent. All access stops instantly.
package/index.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import dc from"node:crypto";var Ae=class{debug;headless;headlessReason;constructor(e,t=!1,r=""){this.debug=e,this.headless=t,this.headlessReason=r}};var we=class{name;concurrency;constructor(e,t){this.name=e,this.concurrency=t}};var De=class n{status;output;error;constructor(e,t,r){this.status=e,this.output=t,this.error=r}static success(e){return new n("success",e,null)}static failure(e){return new n("failure",null,e)}static cancelled(e){return new n("cancelled",null,e)}},Bt=class{promise;resolveFn;rejectFn;constructor(){this.promise=new Promise((e,t)=>{this.resolveFn=e,this.rejectFn=t})}resolve(e){this.resolveFn(e)}reject(e){this.rejectFn(e)}};var z=class{name;lane;priority;locks;maxAttempts;cancellable;constructor(e){this.name=e.name,this.lane=e.lane,this.priority=e.priority,this.locks=e.locks,this.maxAttempts=e.maxAttempts,this.cancellable=e.cancellable}},Y=class{options;constructor(e){this.options=e}},pe=class{type;input;constructor(e,t){this.type=e,this.input=t}},Kt=class{bus;logger;notifier;flags;signal;engine;get headless(){return this.flags.headless}dispatchFn;constructor(e){this.bus=e.bus,this.engine=e.engine,this.logger=e.logger,this.notifier=e.notifier,this.flags=e.flags,this.signal=e.signal,this.dispatchFn=e.dispatch}dispatch(e,t){let r=t||new pt(null,null,null,null);return this.dispatchFn(e,r)}};var jt=class{ts;message;constructor(e,t){this.ts=t?.ts??Date.now(),this.message=e}},ye=class{id;ts;groupKey;kind;scope;message;category;constructor(e,t){this.id=crypto.randomUUID(),this.ts=t?.ts??Date.now(),this.kind=t?.kind??"info",this.scope=t?.scope??"default",this.message=e,this.groupKey=t?.groupKey,this.category=t?.category??[]}},Vt=class{ts;jobId;jobType;state;attempt;maxAttempts;lane;priority;error;nextRunAt;constructor(e){this.ts=e.ts,this.jobId=e.jobId,this.jobType=e.jobType,this.state=e.state,this.attempt=e.attempt,this.maxAttempts=e.maxAttempts,this.lane=e.lane,this.priority=e.priority,this.error=e.error,this.nextRunAt=e.nextRunAt}};var Le=class{jobs;constructor(e){this.jobs=e}},mt=class{id;jobType;inputJson;state;lane;priority;locks;attempts;maxAttempts;nextRunAt;cancellable;parentId;dedupeKey;lastError;createdAt;updatedAt;constructor(e){this.id=e.id,this.jobType=e.jobType,this.inputJson=e.inputJson,this.state=e.state,this.lane=e.lane,this.priority=e.priority,this.locks=e.locks,this.attempts=e.attempts,this.maxAttempts=e.maxAttempts,this.nextRunAt=e.nextRunAt,this.cancellable=e.cancellable,this.parentId=e.parentId,this.dedupeKey=e.dedupeKey,this.lastError=e.lastError,this.createdAt=e.createdAt,this.updatedAt=e.updatedAt}};var qt=class{state;constructor(e){this.state=e??new Le({})}async load(){return new Le(structuredClone(this.state.jobs))}async save(e){this.state=new Le(structuredClone(e.jobs))}};var Ge=class{engine;bus;logger;notifier;flags;signal;get headless(){return this.flags.headless}constructor(e){this.engine=e.engine,this.bus=e.bus,this.logger=e.logger,this.notifier=e.notifier,this.flags=e.flags,this.signal=e.signal}on(e,t){return this.bus.on(e,t)}};var Wt=class{version=1;controlBaseUrl;bridgeWsUrl;directories;device;tokens;discovery;constructor(){this.directories=[]}},Gt=class{_configuration;loader;get configuration(){return this._configuration}constructor(e,t){this._configuration=e,this.loader=t}apply(e){this._configuration=e}};import Ue from"node:path";import ci from"node:os";import Dn from"node:fs";import Qs from"node:path";import Xs from"env-paths";var Zs="DeviceLink",ea=Xs(Zs,{suffix:""});function ta(){if(process.env.DEVICELINK_DATA_DIR)return process.env.DEVICELINK_DATA_DIR;let n=process.env.DEVICELINK_ENV,e=ea.config;return!n||n==="production"?e:Qs.join(e,n)}function Z(){return ta()}import In from"dotenv";import Re from"lodash/get.js";import or from"lodash/isArray.js";import On from"lodash/isObject.js";import li from"lodash/isString.js";import Ce from"lodash/isEmpty.js";import uc from"lodash/defaultTo.js";import{createRequire as ra}from"node:module";var na=ra(import.meta.url),oa=na("node-machine-id");function Ht(n=!0){try{let e=oa.machineIdSync(n);if(e&&typeof e=="string"&&e.trim().length>0)return e.trim()}catch{}}import Oo from"node:path";import on from"node:fs";import sn from"node:crypto";import an from"lodash/get.js";import Ie from"lodash/isEmpty.js";var Jt=class{_notifier;argv;envFile;processEnv;configFileContent;getPrivateKey;_lastGeneratedPrivateKey;constructor(e){this._notifier=e.notifier,this.argv=e.argv,this.envFile=e.envFile,this.processEnv=e.processEnv,this.configFileContent=e.configFileContent,this.getPrivateKey=e.getPrivateKey}getLastGeneratedPrivateKey(){let e=this._lastGeneratedPrivateKey;return this._lastGeneratedPrivateKey=void 0,e}ensureDeviceKeys(){let e=this.getDevicePrivateKey(),t=this.getDevicePublicKey();if(e&&t)return{publicKey:t,privateKey:e};if(e&&!t)try{let a=sn.createPrivateKey(e);return t=sn.createPublicKey(a).export({format:"pem",type:"spki"}).toString("utf8"),this._notifier.info("Derived public key from private key",{scope:"system"}),{publicKey:t,privateKey:e}}catch{this._notifier.warn("Failed to derive public key from private key, generating new keypair",{scope:"system"})}t&&!e&&this._notifier.warn("Public key found but no private key, generating new keypair",{scope:"system"}),this._notifier.info("Generating new Ed25519 keypair...",{scope:"system"});let{publicKey:r,privateKey:o}=sn.generateKeyPairSync("ed25519"),i=r.export({format:"pem",type:"spki"}).toString("utf8"),s=o.export({format:"pem",type:"pkcs8"}).toString("utf8");return this._lastGeneratedPrivateKey=s,this._notifier.info("Generated new Ed25519 keypair",{scope:"system"}),{publicKey:i,privateKey:s}}getDevicePrivateKey(){if(this.getPrivateKey){let r=this.getPrivateKey();if(r&&!Ie(r))return this._notifier.info("Using private key from secret storage cache",{scope:"system"}),r}if(this.argv?.privateKeyFile){let r=this.loadKeyFromFile(this.argv.privateKeyFile);if(r)return this._notifier.info(`Found private key from --private-key-file: ${this.argv.privateKeyFile}`,{scope:"system"}),r;this._notifier.warn(`Failed to load private key from file: ${this.argv.privateKeyFile}`,{scope:"system"})}let e=this.safeGetEnvValue("DLINK_DEVICE_PRIVATE_KEY");if(e&&!Ie(e))return this._notifier.info("Found private key in env file",{scope:"system"}),e;let t=this.processEnv.DLINK_DEVICE_PRIVATE_KEY;if(t&&!Ie(t))return this._notifier.info("Found private key in process env",{scope:"system"}),t}getDevicePublicKey(){if(this.argv?.publicKeyFile){let o=this.loadKeyFromFile(this.argv.publicKeyFile);if(o)return this._notifier.info(`Found public key from --public-key-file: ${this.argv.publicKeyFile}`,{scope:"system"}),o;this._notifier.warn(`Failed to load public key from file: ${this.argv.publicKeyFile}`,{scope:"system"})}let e=an(this.safeGetConfigValue("device"),"keys.public");if(e&&!Ie(String(e)))return this._notifier.info("Found public key in config file",{scope:"system"}),String(e);let t=this.safeGetEnvValue("DLINK_DEVICE_PUBLIC_KEY");if(t&&!Ie(t))return this._notifier.info("Found public key in env file",{scope:"system"}),t;let r=this.processEnv.DLINK_DEVICE_PUBLIC_KEY;if(r&&!Ie(r))return this._notifier.info("Found public key in process env",{scope:"system"}),r}loadKeyFromFile(e){if(!e||Ie(e))return;let t=this.getApplicationConfigFolder(),r=[e,Oo.join(t,e)];for(let o of r)try{let i=Oo.resolve(o);if(on.existsSync(i))if(on.statSync(i).isFile()){let a=on.readFileSync(i,"utf8").trim();if(Ie(a))this._notifier.warn(`Key file is empty: ${i}`,{scope:"system"});else return this._notifier.info(`Loaded key from file: ${i}`,{scope:"system"}),a}else this._notifier.warn(`Path is not a file: ${i}`,{scope:"system"})}catch(i){let s=i instanceof Error?i.message:String(i);this._notifier.warn(`Failed to read key file ${o}: ${s}`,{scope:"system"})}this._notifier.warn(`Key file not found: ${e} (tried: ${r.join(", ")})`,{scope:"system"})}safeGetEnvValue(e){try{return an(this.envFile,`parsed.${e}`)}catch{return}}safeGetConfigValue(e){try{return an(this.configFileContent,e)}catch{return}}getApplicationConfigFolder(){return Z()}};import No from"node:crypto";function Po(n){let e=n.trim();e=e.replace(/\\/g,"/"),e=e.replace(/(^\/\/+)|\/{2,}/g,(l,d)=>d?"//":"/"),e.length>1&&e.endsWith("/")&&(e=e.replace(/\/+$/g,"")),e===""&&(e="/"),e=e.replace(/^([a-zA-Z]):(?=\/|$)/,(l,d)=>`${String(d).toUpperCase()}:`);let t=e.startsWith("/")||e.startsWith("//")||/^[A-Z]:\//.test(e),r=e.startsWith("//")?"//":e.startsWith("/")?"/":"",o="",i=e.match(/^([A-Z]:)(\/|$)/);i?(o=i[1],e=e.slice(o.length),e.startsWith("/")&&(e=e.slice(1))):e=e.replace(/^\/+/,"");let s=e.split("/").filter(Boolean),a=[];for(let l of s)if(l!=="."){if(l===".."){a.length>0&&a[a.length-1]!==".."?a.pop():t||a.push("..");continue}a.push(l)}let c=a.join("/");return o?c=`${o}/${c}`.replace(/\/+$/g,""):t&&(c=`${r}${c}`.replace(/\/+$/g,"")),c=c.toLowerCase(),c}function ht(n,e=[3,3,3,3]){let t=Po(n),o=No.createHash("sha256").update(t,"utf8").digest("base64url").replace(/[^a-zA-Z0-9]/g,"").toLowerCase(),i=e.reduce((c,l)=>c+l,0),s=o.length>=i?o:o.padEnd(i,o),a=0;return e.map(c=>s.slice(a,a+=c)).join("-")}function gt(n){let e=Po(n),r=No.createHash("sha256").update(e,"utf8").digest("hex").slice(0,32),o=r.slice(0,8),i=r.slice(8,12),s=r.slice(12,16),a=r.slice(16,20),c=r.slice(20,32);return`${o}-${i}-${s}-${a}-${c}`}import*as ae from"node:crypto";function cn(n){let e=ae.createPublicKey(n);if(e.asymmetricKeyType!=="ed25519")throw new Error(`Unexpected key type: ${e.asymmetricKeyType}`);let t=e.export({format:"der",type:"spki"});return ae.createHash("sha256").update(t).digest("base64url").slice(0,16).toUpperCase()}function ln(n){let e=Buffer.from(`${n.deviceId}|${n.ts}|${n.nonce}`,"utf8"),t=ae.createPrivateKey(n.privateKeyPem);return ae.sign(null,e,t).toString("base64")}function un(n){let e=ae.createHash("sha256").update(n.refreshToken,"utf8").digest("hex"),t=Buffer.from(`${n.deviceId}|${n.ts}|${n.nonce}|${e}`,"utf8"),r=ae.createPrivateKey(n.privateKeyPem);return ae.sign(null,t,r).toString("base64")}function yt(n){return new Promise(e=>setTimeout(e,n))}import*as Fo from"node:path";var Lo=process.platform==="win32";function dn(n){let e=Fo.resolve(n);return Lo?e.toLowerCase():e}import*as be from"node:path";import*as Mo from"node:os";function Me(n){return n.replace(/\\/g,"/")}function $o(n){return/^[A-Za-z]:[\\/]/.test(n)||/^[A-Za-z]:$/.test(n.trim())}function aa(n){return $o(n)?n.replace(/\//g,"\\"):n}function pn(n){if(n==null)return;let e=String(n).trim();if(e==="")return;if(e.startsWith("~"))return Me(e);if(!$o(e))try{let l=be.resolve(e),d=be.resolve(Mo.homedir()),f=be.relative(d,l);if(!f.startsWith("..")&&!be.isAbsolute(f))return f===""?"~":"~/"+Me(f)}catch{}let r=aa(e).match(/^([A-Za-z]:)\\(?:[Uu][Ss][Ee][Rr][Ss])\\([^\\]+)(\\.*)?$/);if(r){let l=(r[3]??"").replace(/\\/g,"/");return l?"~"+l:"~"}let o=e.match(/^\/mnt\/[a-z]\/(?:[Uu][Ss][Ee][Rr][Ss])\/[^/]+(\/.*)?$/i);if(o){let l=o[1]??"";return l?"~"+Me(l):"~"}let i=e.match(/^\/Users\/[^/]+(\/.*)?$/);if(i){let l=i[1]??"";return l?"~"+Me(l):"~"}let s=e.match(/^\/home\/[^/]+(\/.*)?$/);if(s){let l=s[1]??"";return l?"~"+Me(l):"~"}let a=e.match(/^\/usr\/home\/[^/]+(\/.*)?$/);if(a){let l=a[1]??"";return l?"~"+Me(l):"~"}let c=e.match(/^\/export\/home\/[^/]+(\/.*)?$/);if(c){let l=c[1]??"";return l?"~"+Me(l):"~"}try{return be.basename(be.resolve(e))}catch{return e.split(/[/\\]/).pop()??e}}import ca from"lodash/isString.js";var Uo="<path>",la=/(['"`])((?:[A-Za-z]:[\\/]|\\\\|~?\/)[^'"`\n]*)\1/g,ua=/(^|[\s'"`([{=,;])(?:\\\\[^\s'"`<>|?*\n]+|[A-Za-z]:[\\/][^\s'"`<>|?*\n]*|~?\/[^\s'"`<>|?*\n:]*\/[^\s'"`<>|?*\n:]*)/g;function fn(n){return!ca(n)||n.length===0?n:n.replace(la,(e,t)=>`${t}${Uo}${t}`).replace(ua,(e,t)=>`${t}${Uo}`)}var da=/^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;function ve(n){if(typeof n!="string")return null;let e=n.trim().match(da);return e?{major:Number(e[1]),minor:Number(e[2]),patch:Number(e[3]),prerelease:e[4]??null}:null}function pa(n,e){if(n===e)return 0;if(n===null)return 1;if(e===null)return-1;let t=n.split("."),r=e.split("."),o=Math.max(t.length,r.length);for(let i=0;i<o;i+=1){let s=t[i],a=r[i];if(s===void 0)return-1;if(a===void 0)return 1;let c=/^\d+$/.test(s),l=/^\d+$/.test(a);if(c&&l){let d=Number(s)-Number(a);if(d!==0)return d<0?-1:1;continue}if(c!==l)return c?-1:1;if(s!==a)return s<a?-1:1}return 0}function zt(n,e){let t=ve(n),r=ve(e);if(!t)throw new Error(`not a version: ${n}`);if(!r)throw new Error(`not a version: ${e}`);for(let i of["major","minor","patch"]){let s=t[i]-r[i];if(s!==0)return s<0?-1:1}let o=pa(t.prerelease,r.prerelease);return o===0?0:o<0?-1:1}function mn(n,e){let t=ve(n),r=ve(e);return!t||!r?!1:zt(n,e)<0}function hn(n,e){let t=ve(n),r=ve(e);return!t||!r?!1:t.major===r.major}import gn from"lodash/get.js";import fa from"lodash/isObject.js";import Yt from"lodash/isString.js";function B(n){if(n instanceof Error)return n.message;let e=gn(n,"message");return Yt(e)?e:String(n)}function fe(n){if(!fa(n))return;let e=gn(n,"code");return Yt(e)?e:void 0}function ne(n){return Yt(fe(n))&&Yt(gn(n,"message"))}function K(n,e={}){return{code:fe(n)??e.code??"INTERNAL",message:B(n)||e.message||"An unexpected error occurred."}}import ma from"lodash/isBoolean.js";import Bo from"lodash/isFinite.js";import ha from"lodash/isInteger.js";import Vo from"lodash/isPlainObject.js";import Ko from"lodash/isString.js";import yn from"lodash/isUndefined.js";import ga from"lodash/omit.js";import ya from"lodash/omitBy.js";import ba from"lodash/toNumber.js";var va=/^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/;function jo(n){return Vo(n)?n:{}}var Qt=class{_found;constructor(e){this._found=e}exists(){return!yn(this._found)}unknown(){return this._found}string(){return Ko(this._found)?this._found:null}number(){if(Bo(this._found))return this._found;if(!Ko(this._found)||!va.test(this._found.trim()))return null;let e=ba(this._found);return Bo(e)?e:null}integer(){let e=this.number();return e!==null&&ha(e)?e:null}boolean(){return ma(this._found)?this._found:this._found==="true"?!0:this._found==="false"?!1:null}object(){return Vo(this._found)?this._found:null}list(){return Array.isArray(this._found)?this._found:null}},Xt=class n{_value;constructor(e){this._value=jo(e)}set(e,t){return yn(t)?this:new n({...this._value,[e]:t})}merge(e){return new n({...this._value,...ya(jo(e),yn)})}drop(e){return new n(ga(this._value,e))}has(e){return e in this._value}property(e){return new Qt(this._value[e])}string(e){return this.property(e).string()}value(){return this._value}toJSON(){return this._value}};function bn(n){return new Xt(n)}import Sa from"lodash/isUndefined.js";import Ea from"lodash/omitBy.js";function vn(n){return Ea(n,Sa)}import ac from"lodash/isPlainObject.js";import ze from"lodash/isString.js";import le from"lodash/trim.js";var Lp=Math.ceil(300);var G={FILE_POLICIES:"file_policies",CONTEXT_V2:"context_v2",QUIESCE_V2:"quiesce.v2",TELEMETRY_RELAY_V1:"telemetry.relay.v1",ENDPOINT_DISCOVERY_V1:"endpoint.discovery.v1",RESULT_REDELIVERY_V1:"result.redelivery.v1"},qo=[G.FILE_POLICIES,G.CONTEXT_V2,G.QUIESCE_V2,G.TELEMETRY_RELAY_V1,G.ENDPOINT_DISCOVERY_V1,G.RESULT_REDELIVERY_V1],$p=[G.FILE_POLICIES,G.CONTEXT_V2,G.QUIESCE_V2,G.TELEMETRY_RELAY_V1,G.ENDPOINT_DISCOVERY_V1,G.RESULT_REDELIVERY_V1];function He(n,e){return!!n&&n.includes(e)}import{z as u}from"zod";var _a=u.object({name:u.string().min(1),description:u.string().optional(),inputSchema:u.any().optional(),outputSchema:u.any().optional(),defaults:u.record(u.string(),u.unknown()).optional(),version:u.string().optional(),errorCodes:u.array(u.string()).optional()}),ka=u.object({id:u.string().min(1),name:u.string().min(1),path:u.string().optional(),path_hint:u.string().optional(),policy:u.any().optional()});var Ta=["USE_NEW","KEEP_OLD"];var Wo=["SESSION_REPLACED","SERVER_DRAINING","REBALANCE","ENDPOINT_MOVED"],Je=u.object({code:u.string().min(1),message:u.string().min(1)}).passthrough(),wa=u.object({type:u.literal("connect"),device_id:u.string().min(1),agent_version:u.string().min(1),protocol_version:u.number().int().min(1).default(2),capabilities:u.array(u.string()).default([]),platform:u.string().optional(),hostname:u.string().optional(),device_tag:u.string().optional(),ts:u.number(),nonce:u.string().min(8),sig:u.string().min(16),access_token:u.string().optional(),refresh_token:u.string().min(20).optional(),public_key_pem:u.string().optional()}).passthrough(),Ra=u.object({type:u.literal("connect_ack"),ok:u.literal(!0),session_id:u.string().min(1),device_id:u.string().min(1),server_time:u.number(),auth:u.object({device_proof:u.string().min(1),access_token:u.string().min(1)}).passthrough(),next:u.array(u.string().min(1)).min(1),workspace_id:u.string().optional()}).passthrough(),Ca=u.object({type:u.literal("connect_ack"),ok:u.literal(!1),session_id:u.string().optional(),server_time:u.number(),error:Je}).passthrough(),xa=u.union([Ra,Ca]),Aa=u.object({type:u.literal("refresh_access_token"),device_id:u.string().min(1),ts:u.number(),nonce:u.string().min(8),refresh_token:u.string().min(20),sig:u.string().min(16),session_id:u.string().min(1).optional()}).strict(),Da=u.object({type:u.literal("refresh_access_token_ack"),ok:u.literal(!0),access_token:u.string().min(1),refresh_token:u.string().min(20),expires_in_sec:u.number().int().positive().optional(),next:u.array(u.string().min(1)).default(["session_init"])}).passthrough(),Ia=u.object({type:u.literal("refresh_access_token_ack"),ok:u.literal(!1),error:Je}).passthrough(),Oa=u.union([Da,Ia]),Na=u.object({type:u.literal("session_init"),device_id:u.string().min(1),session_id:u.string().min(1)}).strict(),Pa=u.object({type:u.literal("session_init_ack"),ok:u.literal(!0),device_id:u.string().min(1),session_id:u.string().min(1),mode:u.string().min(1),reason:u.string().optional(),server_time:u.number(),next:u.array(u.string().min(1)).optional(),analytics_session_id:u.string().uuid().optional(),capabilities:u.array(u.string()).optional(),server_protocol_version:u.number().default(2),min_agent_version:u.string().optional(),target_agent_version:u.string().optional(),update_policy:u.string().min(1).optional(),upgrade_message:u.string().optional(),upgrade_url:u.string().optional()}).passthrough(),Fa=u.object({type:u.literal("session_init_ack"),ok:u.literal(!1),device_id:u.string().min(1),server_time:u.number(),error:Je,min_agent_version:u.string().optional(),target_agent_version:u.string().optional(),update_policy:u.string().min(1).optional(),upgrade_message:u.string().optional(),upgrade_url:u.string().optional()}).passthrough(),La=u.union([Pa,Fa]),Ma=u.object({type:u.literal("session_conflict"),device_id:u.string().min(1),new_session_id:u.string().min(1),max_sessions:u.number().int().positive(),active_count:u.number().int().nonnegative(),deadline_ms:u.number().int().positive(),message:u.string().min(1),choices:u.array(u.object({id:u.string().min(1),default:u.boolean().optional(),prompt:u.string().optional()}).passthrough()).min(1)}).passthrough(),$a=u.object({type:u.literal("session_conflict_resolve"),device_id:u.string().min(1),new_session_id:u.string().min(1),choice:u.enum(Ta)}).strict(),Ua=u.object({type:u.literal("session_conflict_resolve_ack"),ok:u.literal(!0),device_id:u.string().min(1),choice:u.string().min(1),next:u.array(u.string().min(1)).optional()}).passthrough(),Ba=u.object({type:u.literal("session_conflict_resolve_ack"),ok:u.literal(!1),device_id:u.string().min(1),error:Je}).passthrough(),Ka=u.union([Ua,Ba]),ja=u.object({after_ms:u.number().optional(),url:u.string().optional(),discover:u.boolean().optional()}).passthrough(),Va=u.object({type:u.literal("quiesce"),session_id:u.string().min(1),reason:u.string().min(1),deadline_ms:u.number().int().positive(),reconnect:ja.optional()}).passthrough(),qa=u.object({type:u.literal("quiesce_ack"),session_id:u.string().min(1),status:u.enum(["IDLE","BUSY"])}).strict(),Sn=1,En=20;var Wa=u.object({kind:u.string().min(1),severity:u.string().min(1).optional(),at:u.number().optional(),props:u.record(u.string(),u.unknown()).optional()}).strict(),Ga=u.object({type:u.literal("agent_event"),schema_version:u.number().int().optional(),events:u.array(Wa)}).strict(),Ha=u.object({type:u.literal("tools_publish"),device_id:u.string().min(1),workspace_id:u.string().optional(),tools:u.array(_a).default([]),tools_version:u.string().optional()}).strict(),Ja=u.object({type:u.literal("tools_publish_ack"),ok:u.boolean(),device_id:u.string().min(1),tools_version:u.string().optional(),error:Je.optional()}).passthrough(),za=u.object({type:u.literal("directories_publish"),device_id:u.string().min(1),workspace_id:u.string().optional(),directories:u.array(ka).default([])}).strict(),Ya=u.object({type:u.literal("directories_publish_ack"),ok:u.boolean(),device_id:u.string().min(1),error:Je.optional()}).passthrough(),Qa=u.object({blocked_extensions:u.array(u.string()).default([]),allowed_extensions:u.array(u.string()).default([]),blocked_patterns:u.array(u.string()).default([]),max_file_size_bytes:u.number().default(10485760)}).passthrough(),_n=u.object({workspace_id:u.string(),organization_id:u.string(),workspace_name:u.string().optional(),user_id:u.string(),user_email:u.string().optional(),connector:u.string().optional(),connector_policies:u.object({max_response_chars:u.number(),timeout_ms:u.number()}).passthrough().optional(),file_policies:Qa.optional()}).passthrough(),Zt=u.object({type:u.literal("tool_call"),job_id:u.string().min(1),device_id:u.string().min(1).optional(),workspace_id:u.string().optional(),tool:u.string().min(1),args:u.record(u.string(),u.unknown()).default({}),context:_n.optional()}).passthrough(),Xa=u.object({type:u.enum(["error","warning","info"]),description:u.string().min(1)}),er=u.object({type:u.literal("tool_result"),job_id:u.string().min(1),tool:u.string().min(1),ok:u.boolean(),result:u.unknown().optional(),error:u.unknown().optional(),messages:u.array(Xa).optional(),timing:u.object({execution_ms:u.number(),execution_sec:u.number()}).optional()}).strict().superRefine((n,e)=>{n.ok&&n.result===void 0&&e.addIssue({code:u.ZodIssueCode.custom,message:"tool_result ok=true should include result",path:["result"]}),!n.ok&&n.error===void 0&&e.addIssue({code:u.ZodIssueCode.custom,message:"tool_result ok=false should include error",path:["error"]})}),Go=u.object({type:u.literal("disconnect_notice"),code:u.number().int(),reason:u.string(),at:u.number()}).passthrough(),Ho=u.object({type:u.literal("promoted_active"),workspaceId:u.string().min(1)}).passthrough(),Jo=u.object({type:u.literal("demoted_standby"),workspaceId:u.string().min(1)}).passthrough(),Kp=u.union([wa,Aa,Na,$a,Ha,za,Zt,er,qa,Ga,Go,Ho,Jo]),zo=u.union([xa,Oa,La,Ma,Ka,Ja,Ya,Zt,Va,Go,Ho,Jo]),Za=["connect_ack","refresh_access_token_ack","session_init_ack","session_conflict","session_conflict_resolve_ack","tools_publish_ack","directories_publish_ack","tool_call","quiesce","disconnect_notice","promoted_active","demoted_standby"];function tr(n){if(typeof n!="object"||n===null)return;let e=n.type;return typeof e=="string"?e:void 0}function Yo(n){return n===void 0?!1:Za.includes(n)}import{z as v}from"zod";import{z as ce}from"zod";var ec=ce.object({url:ce.string().optional()}).passthrough(),tc=ce.object({urls:ce.array(ce.string()).optional()}).passthrough(),rr=ce.object({schema:ce.number().int().optional(),issued_at:ce.number().int().optional(),control:ec.optional(),bridge:tc.optional(),ttl_seconds:ce.number().optional(),capabilities:ce.array(ce.string()).optional(),notice:ce.string().nullable().optional()}).passthrough(),Zo="/.well-known/devicelink-endpoints",Qo=300,Xo=86400;function ei(n){if(typeof n!="number"||!Number.isFinite(n))return 3600;let t=Math.floor(n);return t<Qo?Qo:t>Xo?Xo:t}var rc=v.object({device_id:v.string().optional(),device_name:v.string().optional(),platform:v.string().optional(),agent_version:v.string().optional(),public_key_pem:v.string().min(1)}),Hp=v.object({device_code:v.string(),user_code:v.string(),verification_uri:v.string(),verification_uri_complete:v.string(),expires_in:v.number(),interval:v.number(),challenge_id:v.string(),challenge:v.string()}),Jp=rc.extend({enrollment_jws:v.string().min(1)}),zp=v.union([v.object({status:v.literal("pending"),needs_proof:v.boolean()}),v.object({status:v.literal("approved"),needs_proof:v.boolean()}),v.object({error:v.literal("access_denied")}),v.object({error:v.literal("expired_token")})]),Yp=v.object({device_code:v.string(),challenge_id:v.string(),challenge:v.string(),signature_b64:v.string()}),Qp=v.object({ok:v.literal(!0)}),Xp=v.object({device_code:v.string(),install_id:v.string().min(8).max(64).optional()}),Zp=v.object({access_token:v.string(),refresh_token:v.string(),token_type:v.literal("Bearer"),expires_in:v.number(),device_id:v.string(),endpoints:rr.optional()}),ef=v.object({device_id:v.string().min(1),refresh_token:v.string().min(1),ts:v.number().int(),nonce:v.string().min(8),sig:v.string().min(16)}),nc=v.object({ok:v.literal(!0),access_token:v.string().min(10),refresh_token:v.string().min(10),expires_in_sec:v.number().int().positive(),device_id:v.string().min(1)}),oc=v.object({ok:v.literal(!1),error:v.object({code:v.string(),message:v.string(),drift_ms:v.number().optional()})}),tf=v.union([nc,oc]);import{z as R}from"zod";var ic=R.object({code:R.string().min(1),message:R.string(),hint:R.string().optional()}),sc=R.object({execution_ms:R.number().optional(),execution_sec:R.number().optional()}),cf=R.object({v:R.literal(1),dispatch_id:R.string().min(1),request_id:R.string().min(1),device_id:R.string().min(1),workspace_id:R.string().min(1),user_id:R.string().min(1),tool:R.string().min(1),args:R.record(R.string(),R.unknown()).default({}),context:_n.optional()}).passthrough(),lf=R.object({v:R.literal(1),dispatch_id:R.string().min(1),request_id:R.string().min(1),device_id:R.string().min(1),workspace_id:R.string().min(1),instance_id:R.string().optional(),ok:R.boolean(),result:R.unknown().optional(),error:ic.optional(),timing:sc.optional()}).passthrough().superRefine((n,e)=>{n.ok===!1&&!n.error&&e.addIssue({code:R.ZodIssueCode.custom,path:["error"],message:"A failed dispatch reply must name an error"})});var uf=R.object({v:R.literal(1),session_id:R.string().min(1),user_id:R.string().min(1),workspace_id:R.string().min(1),reason:R.literal("SESSION_REPLACED"),deadline_ms:R.number().int().positive(),replaced_by_session_id:R.string().min(1).optional(),requested_by_instance:R.string().min(1).optional()}).passthrough();function ti(n){return{ok:!0,data:n}}function $e(n){return{ok:!1,error:n}}var Tn={PENDING:"PENDING",APPLIED:"APPLIED",FAILED:"FAILED",VOID:"VOID"};var Af=[Tn.APPLIED,Tn.FAILED,Tn.VOID];var cc=2e3,wn=2;function Rn(){return Math.floor(Date.now()/1e3)}function ri(n=process.env){let e=le(n.DEVICELINK_ENV??"");return e!=="production"&&e!=="staging"}function nr(n,e=process.env){if(!ze(n))return!1;let t=le(n);return t===""?!1:/^wss:\/\/.+/.test(t)?!0:ri(e)&&/^ws:\/\/.+/.test(t)}function ni(n){if(!ze(n))return!1;let e=le(n);return/^https:\/\/.+/.test(e)?!0:ri()&&/^http:\/\/.+/.test(e)}function Cn(n){let e=rr.safeParse(n);return e.success?e.data:null}function xn(n,e,t=Rn(),r=process.env){if(!n)return null;let o=(n.bridge?.urls??[]).filter(c=>nr(c,r)).map(c=>le(c)),i=ni(n.control?.url)?le(String(n.control?.url)):void 0,s=ei(n.ttl_seconds),a={expiresAt:t+s,source:e};return typeof n.schema=="number"&&(a.schema=n.schema),typeof n.issued_at=="number"&&(a.issuedAt=n.issued_at),o.length>0&&(a.bridgeUrls=o),i&&(a.controlUrl=i),n.capabilities&&n.capabilities.length>0&&(a.capabilities=n.capabilities.filter(ze)),ze(n.notice)&&le(n.notice)!==""&&(a.notice=le(n.notice)),!a.bridgeUrls&&!a.controlUrl&&!a.notice?null:a}function oi(n){if(!ac(n))return null;let e=n,t=e.expiresAt;if(typeof t!="number"||!Number.isFinite(t))return null;let r={expiresAt:t};typeof e.schema=="number"&&(r.schema=e.schema),typeof e.issuedAt=="number"&&(r.issuedAt=e.issuedAt);let o=e.bridgeUrls;if(Array.isArray(o)){let a=o.filter(c=>nr(c)).map(c=>le(String(c)));a.length>0&&(r.bridgeUrls=a)}ni(e.controlUrl)&&(r.controlUrl=le(String(e.controlUrl)));let i=e.capabilities;Array.isArray(i)&&(r.capabilities=i.filter(ze)),ze(e.notice)&&le(e.notice)!==""&&(r.notice=le(e.notice));let s=e.source;return(s==="well_known"||s==="token")&&(r.source=s),!r.bridgeUrls&&!r.controlUrl&&!r.notice?null:r}function An(n,e=Rn()){return!!n&&n.expiresAt>e}function ii(n,e){if(!n)return e??null;if(!e)return n;let t=n.issuedAt??-1;return(e.issuedAt??-1)>t?e:n}function si(n,e=Rn()){if(An(n,e))return n?.bridgeUrls?.[0]}function lc(n){return`${n.replace(/\/+$/,"")}${Zo}`}async function ai(n,e=cc){if(!n||le(n)==="")return null;let t=new AbortController,r=setTimeout(()=>t.abort(),e);r.unref?.();try{let o=await fetch(lc(n),{method:"GET",headers:{accept:"application/json"},signal:t.signal});return o.ok?Cn(await o.json()):null}catch{return null}finally{clearTimeout(r)}}var Ye={version:1,controlBaseUrl:"",bridgeWsUrl:"",directories:[],device:void 0},ir=class{_notifier;argv;config=Ye;envFile=In.config({quiet:!0});processEnv={};productionEnv={};configFileContent={};_privateKeyCache=void 0;_privateKeyToStore=void 0;_discovery=null;_bridgeEndpointSource=void 0;constructor(e){this._notifier=e,this.loadProductionEnv()}loadProductionEnv(){let e=[Ue.resolve(Ue.dirname(process.argv[1]??"."),".env.production"),Ue.resolve(process.cwd(),".env.production")];for(let t of e)try{if(Dn.existsSync(t)){let r=In.config({path:t,quiet:!0});r.parsed&&(this.productionEnv=r.parsed);return}}catch{}}setPrivateKeyCache(e){this._privateKeyCache=e}getPrivateKeyToStore(){return this._privateKeyToStore}withDiscoveryCache(e){return this._discovery=e??oi(this.safeGetConfigValue("discovery")),this}getDiscoveryCache(){return this._discovery}getBridgeEndpointSource(){return this._bridgeEndpointSource}getBundledBridgeWsUrl(){return this.firstSet(this.productionEnv.DLINK_BRIDGE_URL)}withDefaultConfig(){return this.config.version=Ye.version,this.config.controlBaseUrl=Ye.controlBaseUrl,this.config.bridgeWsUrl=Ye.bridgeWsUrl,this.config.directories=Ye.directories,this.config.device=Ye.device,this}withProcessEnv(){return this.processEnv={NODE_ENV:process.env.NODE_ENV,APPDATA:process.env.APPDATA,npm_package_version:process.env.npm_package_version,DLINK_DEVICE_ID:process.env.DLINK_DEVICE_ID,DLINK_DEVICE_NAME:process.env.DLINK_DEVICE_NAME,DLINK_DEVICE_TAG:process.env.DLINK_DEVICE_TAG,DLINK_CONTROL_URL:process.env.DLINK_CONTROL_URL,DLINK_BRIDGE_URL:process.env.DLINK_BRIDGE_URL,DLINK_DIRECTORIES:process.env.DLINK_DIRECTORIES},this}withArgv(e){return this.argv=e,this}withEnviromentFile(e){return this.envFile=In.config({path:e,quiet:!0}),this}withConfigFile(e){try{let t=this.getApplicationConfigFolder(),r=Ue.join(t,e);if(Dn.existsSync(r)){let o=Dn.readFileSync(r,"utf8"),i=JSON.parse(o);On(i)&&!or(i)?this.configFileContent=i:this._notifier.warn(`Config file ${e} does not contain a valid object`,{scope:"system"})}}catch(t){let r=t instanceof Error?t.message:String(t);this._notifier.warn(`Failed to load config file ${e}: ${r}`,{scope:"system"})}return this}build(){return this.config.controlBaseUrl=this.getControlBaseUrl(),this.config.bridgeWsUrl=this.getBridgeWsUrl(),this.config.discovery=this._discovery??void 0,this.config.directories=this.getDirectories(),this.config.device=this.getDevice(),this.config.tokens=this.getTokens(),this.config}getConfigValue(e,t){let r=this.safeGetConfigValue(e);return r===void 0?t?.defaultValue:r}firstSet(...e){return e.find(t=>t!=null&&String(t).trim()!=="")}getControlBaseUrl(){return this.firstSet(this.argv?.controlUrl,this.safeGetEnvValue("DLINK_CONTROL_URL"),this.safeGetConfigValue("controlBaseUrl"),this.processEnv.DLINK_CONTROL_URL,this.productionEnv.DLINK_CONTROL_URL)}resolveBridgeWsUrl(e=this._discovery){let t=[["argv",this.argv?.bridgeWsUrl],["env-file",this.safeGetEnvValue("DLINK_BRIDGE_URL")],["process-env",this.processEnv.DLINK_BRIDGE_URL],["discovered",si(e)],["config-file",this.safeGetConfigValue("bridgeWsUrl")],["bundled",this.productionEnv.DLINK_BRIDGE_URL]];for(let[r,o]of t){let i=this.firstSet(o);if(i)return{url:i,source:r}}return{url:void 0,source:void 0}}getBridgeWsUrl(){let{url:e,source:t}=this.resolveBridgeWsUrl(this._discovery);return this._bridgeEndpointSource=t,e}getDirectories(){let e=[];if(e.push(this.createDirectoryFromPath(process.cwd())),this.argv?.rootPath)try{e.push(...this.parseDirectoriesFromString(this.argv.rootPath))}catch{e.push(this.createDirectoryFromPath(this.argv.rootPath))}let t=this.safeGetEnvValue("DLINK_DIRECTORIES")??this.safeGetEnvValue("DLINK_ROOTS");if(t)try{e.push(...this.parseDirectoriesFromString(t))}catch{}let r=this.safeGetConfigValue("directories")??this.safeGetConfigValue("roots");if(r)try{e.push(...this.parseDirectoriesFromValue(r))}catch{}let o=this.processEnv.DLINK_DIRECTORIES??this.processEnv.DLINK_ROOTS;if(o)try{e.push(...this.parseDirectoriesFromString(o))}catch{}return this.deduplicateDirectories(e)}deduplicateDirectories(e){let t=new Set,r=[];for(let o of e){let i=dn(o.path);t.has(i)||(t.add(i),r.push(o))}return r}getDevice(){let e=this.getDeviceId();if(!e){this._notifier.warn("No device ID found from any source (argv, env, config, process env, or machine ID)",{scope:"system"});return}let t=this.getDeviceName();t||(t=ci.hostname()||"Unknown Device");let r=this.getDeviceTag(),o=new Jt({notifier:this._notifier,argv:this.argv,envFile:this.envFile,processEnv:this.processEnv,configFileContent:this.configFileContent,getPrivateKey:()=>this._privateKeyCache}),{publicKey:i}=o.ensureDeviceKeys();this._privateKeyToStore=o.getLastGeneratedPrivateKey();let s={id:e,name:t,tag:r||"",keys:{public:i}};return this._notifier.info(`Created device: id=${s.id?.substring(0,8)}..., name=${s.name}, tag=${s.tag||"(empty)"}`,{scope:"system"}),s}getDeviceId(){this._notifier.info("Checking env file for DLINK_DEVICE_ID...",{scope:"system"});let e=this.safeGetEnvValue("DLINK_DEVICE_ID");if(e&&!Ce(e))return this._notifier.info(`Found device ID in env file: ${e.substring(0,8)}...`,{scope:"system"}),e;this._notifier.info("Checking config file for deviceId...",{scope:"system"});let t=this.safeGetConfigValue("deviceId")??Re(this.safeGetConfigValue("device"),"id");if(t&&!Ce(String(t)))return this._notifier.info(`Found device ID in config file: ${String(t).substring(0,8)}...`,{scope:"system"}),String(t);this._notifier.info("Checking process env for DLINK_DEVICE_ID...",{scope:"system"});let r=this.processEnv.DLINK_DEVICE_ID;if(r&&!Ce(r))return this._notifier.info(`Found device ID in process env: ${r.substring(0,8)}...`,{scope:"system"}),r;this._notifier.info("Trying machine ID as fallback...",{scope:"system"});let o=Ht(!0);if(o)return this._notifier.info(`Using machine ID: ${o.substring(0,8)}...`,{scope:"system"}),o;this._notifier.error("Failed to get machine ID in getDeviceId()",{scope:"system"}),this._notifier.warn("No device ID found in any source",{scope:"system"})}getDeviceName(){let e=this.safeGetEnvValue("DLINK_DEVICE_NAME");if(e&&!Ce(e))return e;let t=Re(this.safeGetConfigValue("device"),"name");if(t&&!Ce(String(t)))return String(t);let r=this.processEnv.DLINK_DEVICE_NAME;if(r&&!Ce(r))return r;let o=ci.hostname();if(o&&!Ce(o))return o}getDeviceTag(){let e=this.safeGetEnvValue("DLINK_DEVICE_TAG");if(e)return e;let t=Re(this.safeGetConfigValue("device"),"tag");if(t)return String(t);let r=this.processEnv.DLINK_DEVICE_TAG;if(r)return r}getTokens(){let e=this.safeGetConfigValue("tokens");if(!e||!On(e)||or(e))return;let t=e,r={},o=Re(t,"accessTokenExpSec");if(typeof o=="number"&&(r.accessTokenExpSec=o),r.accessTokenExpSec!==void 0)return r}safeGetEnvValue(e){try{return Re(this.envFile,`parsed.${e}`)}catch{return}}safeGetConfigValue(e){try{return Re(this.configFileContent,e)}catch{return}}parseDirectoriesFromString(e){try{let t=JSON.parse(e);return this.parseDirectoriesFromValue(t)}catch{return[this.createDirectoryFromPath(e)]}}parseDirectoriesFromValue(e){if(or(e))return e.map(r=>this.parseDirectoryFromValue(r)).filter(r=>r!==null);if(li(e))return[this.createDirectoryFromPath(e)];let t=this.parseDirectoryFromValue(e);return t?[t]:[]}parseDirectoryFromValue(e){if(li(e))return this.createDirectoryFromPath(e);if(On(e)&&!or(e)){let t=e,r=gt(Re(t,"path")),o=Re(t,"path"),i=uc(Re(t,"name"),o?Ue.basename(o):"");if(!Ce(r)&&!Ce(o)){let s=ht(o);return{id:String(r),name:String(i),path:String(o),tag:s}}}return null}createDirectoryFromPath(e){let t=Ue.resolve(e),r=gt(t),o=Ue.basename(t),i=ht(t);return{id:r,name:o,path:t,tag:i}}getApplicationConfigFolder(){return Z()}};var pt=class{dedupeKey;parentId;overridePriority;overrideLane;constructor(e,t,r,o){this.dedupeKey=e,this.parentId=t,this.overridePriority=r,this.overrideLane=o}},Nn=class{phase;flags;constructor(e){this.phase="idle",this.flags=e??new Ae(!1)}},sr=class{argv;configurationContext;bus;notifier;logger;storage;secrets;secretsReport;runtime;lanes;laneActive;registry;orchestrators;orchestratorSubscriptions=new Map;orchestratorAbort;jobs;queue;locksHeldBy;completions;dedupeIndex;engineAbort;jobAbort;stopping;running;wakeFn;wakePromise;constructor(e){this.argv=e.argv,this.bus=e.bus,this.logger=e.logger,this.notifier=e.notifier,this.storage=e.storage,this.secrets=e.secrets,this.secretsReport=e.secretsReport,this.runtime=new Nn(e.flags),this.lanes=new Map;for(let o of e.lanes)this.lanes.set(o.name,o);this.laneActive=new Map;for(let o of e.lanes)this.laneActive.set(o.name,0);this.registry=new Map,this.orchestrators=[],this.orchestratorAbort=new AbortController,this.jobs=new Map,this.queue=[],this.locksHeldBy=new Map,this.completions=new Map,this.dedupeIndex=new Map,this.engineAbort=new AbortController,this.jobAbort=new Map,this.stopping=!1,this.running=!1,this.wakeFn=null,this.wakePromise=this.resetWake();let t=new Wt,r=new ir(this.notifier);this.configurationContext=new Gt(t,r)}applyConfiguration(e){this.configurationContext.apply(e)}setPhase(e){this.runtime.phase=e}getBus(){return this.bus}hasRunningJobs(){for(let[,e]of this.laneActive)if(e>0)return!0;return!1}register(e){let t=e.options.name;if(this.registry.has(t))throw new Error(`JobType already registered: ${t}`);this.registry.set(t,e)}registerOrchestrator(e){if(this.orchestrators.some(o=>o.name===e.name))throw new Error(`Orchestrator already registered: ${e.name}`);let r=new Ge({engine:this,bus:this.bus,logger:this.logger,notifier:this.notifier,flags:this.runtime.flags,signal:this.orchestratorAbort.signal});e.onRegister?.(r),this.setupOrchestratorSubscriptions(e,r),this.orchestrators.push(e)}setupOrchestratorSubscriptions(e,t){let r=e.handlers?.();if(r){let o=[];Object.keys(r).forEach(i=>{let s=r[i];s&&o.push(this.bus.on(i,a=>{Promise.resolve(s(a,t)).catch(c=>{let l=c instanceof Error?c.message:String(c);this.logger.error(`handler error (${e.name}/${String(i)}): ${l}`),this.notifier.error(`handler error (${e.name}/${String(i)}): ${l}`,{scope:"system"})})}))}),this.orchestratorSubscriptions.set(e.name,o)}}async init(){let e=await this.storage.load();for(let[t,r]of Object.entries(e.jobs))this.jobs.set(t,new mt(r));for(let t of this.jobs.values())t.state==="running"&&(t.state="queued",t.nextRunAt=Date.now(),t.updatedAt=Date.now()),t.dedupeKey&&this.dedupeIndex.set(t.dedupeKey,t.id),t.state==="queued"&&this.queue.push(t.id)}async start(){if(!this.running){this.running=!0,this.runtime.phase="running",process.on("uncaughtException",e=>{this.notifier.error(`uncaughtException: ${e.stack?e.stack:String(e)}`,{scope:"system"}),this.bus.emit("engine:crashed",{reason:"uncaughtException",detail:e instanceof Error?`${e.name}: ${e.message}`:String(e)}),this.requestStop("uncaughtException")}),process.on("unhandledRejection",e=>{this.notifier.error(`unhandledRejection: ${String(e)}`,{scope:"system"}),this.bus.emit("engine:crashed",{reason:"unhandledRejection",detail:String(e)})}),this.bus.emit("engine:started",Date.now());try{await this.startOrchestratorsSafe(),await this.loopGuarded()}finally{await this.stopOrchestratorsSafe(),await this.persist(),this.bus.emit("engine:stopped",Date.now())}}}requestStop(e){if(!this.stopping){this.stopping=!0,this.runtime.phase="stopping",this.bus.emit("engine:stopping",e),this.engineAbort.abort(new Error(`Stopping: ${e}`)),this.orchestratorAbort.abort(new Error(`Stopping: ${e}`));for(let[t,r]of this.jobAbort.entries())this.jobs.get(t)?.cancellable&&r.abort(new Error("Cancelled by user"));this.wake()}}async dispatch(e,t){let r=t||new pt(null,null,null,null),o=e.type.options.name;if(!this.registry.has(o)){let f=new Error(`JobType not registered: ${o}`);return De.failure(f)}if(r.dedupeKey){let f=this.dedupeIndex.get(r.dedupeKey);if(f){let p=this.jobs.get(f);if(p&&(p.state==="queued"||p.state==="running")){let m=this.completions.get(f);if(m)return await m.promise}}}let i=this.newId(),s=new Bt;this.completions.set(i,s);let a=r.overrideLane?r.overrideLane:e.type.options.lane,c=r.overridePriority!==null?r.overridePriority:e.type.options.priority,l=new mt({id:i,jobType:o,inputJson:e.input===void 0?"null":JSON.stringify(e.input),state:"queued",lane:a,priority:c,locks:e.type.options.locks,attempts:0,maxAttempts:e.type.options.maxAttempts,nextRunAt:Date.now(),cancellable:e.type.options.cancellable,parentId:r.parentId,dedupeKey:r.dedupeKey,lastError:null,createdAt:Date.now(),updatedAt:Date.now()});return this.jobs.set(i,l),this.queue.push(i),r.dedupeKey&&this.dedupeIndex.set(r.dedupeKey,i),this.emitJobEvent(l,"queued",null,null),await this.persist(),this.wake(),await s.promise}async loopGuarded(){for(;!this.stopping;)try{await this.loopOnce()}catch(e){this.notifier.error(`Engine loop error: ${String(e)}`,{scope:"system"}),await new Promise(t=>setTimeout(t,250))}}async loopOnce(){let e=0;for(;;){let t=this.pickNextRunnable();if(!t)break;e+=1,this.runJobSafe(t)}e===0&&(await this.wakePromise,this.wakePromise=this.resetWake())}async runJobSafe(e){try{await this.runJobInternal(e)}catch(t){this.notifier.error(`runJobInternal crashed: ${String(t)}`,{scope:"system"});let r=this.completions.get(e);r&&r.resolve(De.failure(new Error(String(t))))}finally{this.wake()}}pickNextRunnable(){let e=Date.now(),t=null,r=Number.NEGATIVE_INFINITY,o=Number.POSITIVE_INFINITY;for(let s of this.queue){let a=this.jobs.get(s);a&&a.state==="queued"&&(this.stopping&&a.lane!=="console"||a.nextRunAt>e||this.canRunInLane(a.lane)&&this.canAcquireLocks(a)&&(a.priority>r||a.priority===r&&a.nextRunAt<o)&&(r=a.priority,o=a.nextRunAt,t=s))}if(!t)return null;let i=this.queue.indexOf(t);return i>=0&&this.queue.splice(i,1),t}canRunInLane(e){let t=this.lanes.get(e);if(!t)return!1;let r=this.laneActive.get(e);return r===void 0?!1:r<t.concurrency}canAcquireLocks(e){for(let t of e.locks){let r=this.locksHeldBy.get(t);if(r&&r!==e.id&&!(e.parentId&&r===e.parentId))return!1}return!0}acquireLocks(e){for(let t of e.locks)this.locksHeldBy.get(t)||this.locksHeldBy.set(t,e.id)}releaseLocks(e){for(let t of e.locks)this.locksHeldBy.get(t)===e.id&&this.locksHeldBy.delete(t)}async runJobInternal(e){let t=this.jobs.get(e);if(!t)return;let r=this.registry.get(t.jobType);if(!r){this.completeFailure(e,new Error(`No registered JobType: ${t.jobType}`));return}let o=this.laneActive.get(t.lane);if(o===void 0){this.completeFailure(e,new Error(`Unknown lane: ${t.lane}`));return}let i=new AbortController;if(this.jobAbort.set(e,i),t.cancellable){let a=this.engineAbort.signal;a.aborted?i.abort(a.reason instanceof Error?a.reason:new Error("Stopped")):a.addEventListener("abort",()=>i.abort(a.reason instanceof Error?a.reason:new Error("Stopped")),{once:!0})}this.laneActive.set(t.lane,o+1),this.acquireLocks(t),t.state="running",t.updatedAt=Date.now(),await this.persist(),this.emitJobEvent(t,"running",null,null);let s=new Kt({engine:this,bus:this.bus,logger:this.logger,notifier:this.notifier,flags:this.runtime.flags,signal:i.signal,dispatch:async(a,c)=>this.dispatch(a,c)});try{let a=JSON.parse(t.inputJson),c=a===null?void 0:a,l=await r.run(c,s);t.state="succeeded",t.updatedAt=Date.now(),t.lastError=null,await this.persist(),this.emitJobEvent(t,"succeeded",null,null),this.completeSuccess(e,l)}catch(a){let c=a instanceof Error?a:new Error("Unknown error");if(t.attempts+=1,t.updatedAt=Date.now(),t.lastError=c.message,i.signal.aborted)t.state="failed",await this.persist(),this.emitJobEvent(t,"failed",c.message,null),this.notifier.error(`Job ${t.jobType} (${e.substring(0,8)}) cancelled: ${c.message}`),this.completeCancelled(e,c);else if(t.attempts<t.maxAttempts&&!this.stopping){let f=pc(t.attempts);t.state="queued",t.nextRunAt=Date.now()+f,await this.persist(),this.queue.push(t.id),this.emitJobEvent(t,"queued",c.message,t.nextRunAt),this.notifier.warn(`Job ${t.jobType} (${e.substring(0,8)}) failed, retrying in ${f}ms (attempt ${t.attempts}/${t.maxAttempts}): ${c.message}`)}else t.state="failed",await this.persist(),this.emitJobEvent(t,"failed",c.message,null),this.notifier.error(`Job ${t.jobType} (${e.substring(0,8)}) failed after ${t.attempts} attempt(s): ${c.message}`),this.completeFailure(e,c)}finally{this.releaseLocks(t);let a=this.laneActive.get(t.lane);a!==void 0&&this.laneActive.set(t.lane,Math.max(0,a-1)),this.jobAbort.delete(e),this.wake()}}async startOrchestratorsSafe(){let e=new Ge({engine:this,bus:this.bus,logger:this.logger,notifier:this.notifier,flags:this.runtime.flags,signal:this.orchestratorAbort.signal});for(let t of this.orchestrators)Promise.resolve().then(()=>t.onStart?.(e)).then(()=>t.onStarted?.(e)).catch(r=>this.notifier.error(`Orchestrator start failed (${t.name}): ${String(r)}`,{scope:"system"}))}async stopOrchestratorsSafe(){let e=new Ge({engine:this,bus:this.bus,logger:this.logger,notifier:this.notifier,flags:this.runtime.flags,signal:this.orchestratorAbort.signal});for(let t=this.orchestrators.length-1;t>=0;t--){let r=this.orchestrators[t];try{await r.onStop?.(e),r.onStopped?.(e)}catch(i){this.notifier.error(`Orchestrator stop failed (${r.name}): ${String(i)}`,{scope:"system"})}let o=this.orchestratorSubscriptions.get(r.name);if(o){for(let i of o)i.unsubscribe();this.orchestratorSubscriptions.delete(r.name)}}}emitJobEvent(e,t,r,o){this.bus.emit("job:event",new Vt({ts:Date.now(),jobId:e.id,jobType:e.jobType,state:t,attempt:e.attempts,maxAttempts:e.maxAttempts,lane:e.lane,priority:e.priority,error:r,nextRunAt:o}))}completeSuccess(e,t){let r=this.completions.get(e);r&&r.resolve(De.success(t))}completeFailure(e,t){let r=this.completions.get(e);r&&r.resolve(De.failure(t))}completeCancelled(e,t){let r=this.completions.get(e);r&&r.resolve(De.cancelled(t))}async persist(){let e={};for(let[t,r]of this.jobs.entries())e[t]=r;await this.storage.save(new Le(e))}wake(){this.wakeFn&&this.wakeFn()}resetWake(){return new Promise(e=>{this.wakeFn=e})}newId(){return dc.randomBytes(8).toString("hex")}};function pc(n){let r=Math.min(3e4,300*2**(n-1)),o=Math.floor(Math.random()*200);return r+o}var ar=class{handlers;constructor(){this.handlers=new Map}on(e,t){let r=this.handlers.get(e),o=r||[];return o.push(t),this.handlers.set(e,o),{unsubscribe:()=>{let i=this.handlers.get(e);if(!i)return;let s=i.filter(a=>a!==t);this.handlers.set(e,s)}}}emit(e,t){let r=this.handlers.get(e);if(r)for(let o of r)o(t)}};import*as Si from"node:path";import*as Oe from"node:fs/promises";import*as lr from"node:path";var ui={DevicePrivateKey:"devicePrivateKey",RefreshToken:"refreshToken"},di=[ui.DevicePrivateKey,ui.RefreshToken],N={MacosKeychain:"macos-keychain",LinuxSecretService:"linux-secret-service",WindowsDpapi:"windows-dpapi",Passphrase:"passphrase",MachineId:"machine-id-file"},F={WrongPlatform:"wrong_platform",ToolMissing:"tool_missing",NoSessionBus:"no_session_bus",Locked:"locked",Timeout:"timeout",NotConfigured:"not_configured",RoundTripFailed:"round_trip_failed"},P=class extends Error{backend;constructor(e,t){super(t),this.name="SecretsUnreadableError",this.backend=e}};var fc="secrets.backend",mc=Object.values(N),cr=class{filePath;platform;constructor(e,t=process.platform){this.filePath=lr.join(e,fc),this.platform=t}async read(){try{let e=(await Oe.readFile(this.filePath,"utf8")).trim();return mc.includes(e)?e:void 0}catch{return}}async write(e){try{await Oe.mkdir(lr.dirname(this.filePath),{recursive:!0,mode:448}),await Oe.writeFile(this.filePath,`${e}
3
- `,{encoding:"utf8",mode:384}),this.platform!=="win32"&&await Oe.chmod(this.filePath,384).catch(()=>{})}catch{return}}};import{spawn as hc}from"node:child_process";var bt=5e3,ur=class{run(e,t={}){let r=t.timeoutMs??bt;return new Promise(o=>{let i="",s="",a=!1,c=!1,l=hc(e.command,[...e.args],{stdio:["pipe","pipe","pipe"],windowsHide:!0,env:t.env?{...process.env,...t.env}:void 0}),d=setTimeout(()=>{a=!0,l.kill("SIGKILL")},r);d.unref();let f=p=>{c||(c=!0,clearTimeout(d),o(p))};l.stdout?.setEncoding("utf8"),l.stdout?.on("data",p=>{i+=p}),l.stderr?.setEncoding("utf8"),l.stderr?.on("data",p=>{s+=p}),l.on("error",()=>{f({code:null,stdout:i,stderr:s,timedOut:a,spawnFailed:!0})}),l.on("close",p=>{f({code:p,stdout:i,stderr:s,timedOut:a,spawnFailed:!1})}),l.stdin?.on("error",()=>{}),l.stdin?.end(t.stdin??"","utf8")})}};var dr=class{async migrate(e,t,r=di){if(e.id===t.id)return{migrated:!1,reason:"same_backend"};if(await this.hasAny(t,r))return{migrated:!1,reason:"target_populated"};let o;try{o=await this.read(e,r)}catch{return{migrated:!1,reason:"source_unreadable"}}if(o.length===0)return{migrated:!1,reason:"source_empty"};try{for(let i of o)await t.set(i.key,i.value)}catch{return{migrated:!1,reason:"target_write_failed"}}if(!await this.verify(t,o))return{migrated:!1,reason:"verify_failed"};for(let i of o)await e.delete(i.key).catch(()=>{});return{migrated:!0,from:e.id,keys:o.map(i=>i.key)}}async hasAny(e,t){for(let r of t)if((await e.get(r).catch(()=>({ok:!1}))).ok)return!0;return!1}async read(e,t){let r=[];for(let o of t){let i=await e.get(o);i.ok&&r.push({key:o,value:i.value})}return r}async verify(e,t){for(let r of t){let o=await e.get(r.key).catch(()=>({ok:!1}));if(!o.ok||o.value!==r.value)return!1}return!0}};var pi="DeviceLink",pr=class{service;constructor(e){let t=(e??"").trim().toLowerCase();this.service=t===""||t==="production"?pi:`${pi}-${t}`}account(e){return e}label(e){return`${this.service} ${e}`}attributes(e){return["service",this.service,"key",this.account(e)]}};import*as Se from"node:fs/promises";import*as hi from"node:path";var fi=448,mi=384,Ne=class{filePath;platform;cache=null;constructor(e){this.filePath=e.filePath,this.platform=e.platform??process.platform}async get(e){let r=(await this.load())[e];return r===void 0?{ok:!1}:{ok:!0,value:r}}async set(e,t){let r=await this.load();r[e]=t,await this.save(r)}async delete(e){let t=await this.load();t[e]!==void 0&&(delete t[e],await this.save(t))}async load(){if(this.cache!==null)return this.cache;let e;try{e=await Se.readFile(this.filePath,"utf8")}catch(t){if(gc(t))return this.cache={},this.cache;throw new P(this.id,`${this.label} could not read its secret store`)}try{this.cache=JSON.parse(await this.unprotect(e))}catch(t){throw t instanceof P?t:new P(this.id,`${this.label} could not decrypt its secret store. The store exists but is unreadable with the current key, so it has been left untouched.`)}return this.cache}async save(e){let t=hi.dirname(this.filePath);await Se.mkdir(t,{recursive:!0,mode:fi}),await this.hardenPath(t,fi);let r=await this.protect(JSON.stringify(e)),o=`${this.filePath}.tmp`;await Se.writeFile(o,r,{encoding:"utf8",mode:mi}),await Se.rename(o,this.filePath),await this.hardenPath(this.filePath,mi)}async hardenPath(e,t){this.platform!=="win32"&&await Se.chmod(e,t).catch(()=>{})}};function gc(n){return typeof n=="object"&&n!==null&&n.code==="ENOENT"}var yc=["powershell.exe","pwsh"],gi=['$ErrorActionPreference = "Stop"',"Add-Type -AssemblyName System.Security","$in = [Console]::In.ReadToEnd()","$bytes = [Text.Encoding]::UTF8.GetBytes($in)",'$out = [Security.Cryptography.ProtectedData]::Protect($bytes, $null, "CurrentUser")',"[Console]::Out.Write([Convert]::ToBase64String($out))"].join("; "),yi=['$ErrorActionPreference = "Stop"',"Add-Type -AssemblyName System.Security","$in = [Console]::In.ReadToEnd()","$bytes = [Convert]::FromBase64String($in.Trim())",'$out = [Security.Cryptography.ProtectedData]::Unprotect($bytes, $null, "CurrentUser")',"[Console]::Out.Write([Text.Encoding]::UTF8.GetString($out))"].join("; "),fr=class extends Ne{id=N.WindowsDpapi;label="Windows DPAPI";runner;shell;timeoutMs;constructor(e){super(e),this.runner=e.runner,this.shell=e.shell??yc[0],this.timeoutMs=e.timeoutMs??bt}async probe(){if(this.platform!=="win32")return{available:!1,reason:F.WrongPlatform};let e="dlink-dpapi-probe",t=await this.invoke(gi,e);if(t.timedOut)return{available:!1,reason:F.Timeout};if(t.spawnFailed)return{available:!1,reason:F.ToolMissing,detail:`${this.shell} is not available`};if(t.code!==0)return{available:!1,reason:F.RoundTripFailed,detail:"DPAPI could not protect a value"};let r=await this.invoke(yi,t.stdout);return r.code!==0||r.stdout!==e?{available:!1,reason:F.RoundTripFailed,detail:"DPAPI could not read back a value"}:{available:!0}}async protect(e){let t=await this.invoke(gi,e);if(t.code!==0||t.timedOut||t.spawnFailed)throw new P(this.id,"DPAPI could not protect the secret store.");return t.stdout.trim()}async unprotect(e){let t=await this.invoke(yi,e);if(t.timedOut||t.spawnFailed)throw new P(this.id,"DPAPI did not respond while reading the secret store.");if(t.code!==0)throw new P(this.id,"DPAPI could not decrypt the secret store. A DPAPI store is bound to one user on one machine, so a copied or roamed profile cannot be read; nothing has been changed.");return t.stdout}invoke(e,t){let r={command:this.shell,args:["-NoProfile","-NonInteractive","-Command",e],secretVia:"stdin"};return this.runner.run(r,{stdin:t,timeoutMs:this.timeoutMs})}};var Fn="__DLINK_SECRET__",Qe=class{runner;namespace;timeoutMs;constructor(e){this.runner=e.runner,this.namespace=e.namespace,this.timeoutMs=e.timeoutMs??bt}normaliseValue(e){return e.replace(/\r?\n$/,"")}encodeValue(e){return Buffer.from(e,"utf8").toString("base64url")}decodeValue(e){let t=Buffer.from(e,"base64url").toString("utf8");if(Buffer.from(t,"utf8").toString("base64url")!==e)throw new P(this.id,`${this.label} holds an item this agent did not write, so it cannot be read safely.`);return t}runEnv(){}runOptions(e={}){return{...e,timeoutMs:this.timeoutMs,env:this.runEnv()}}async probe(){let e=await this.runner.run(this.probeCommand(),this.runOptions());return this.interpretProbe(e)}async get(e){let t=await this.runner.run(this.readCommand(e),this.runOptions());return this.isMissing(t)?{ok:!1}:(this.assertUsable(t,`read ${e}`),{ok:!0,value:this.decodeValue(this.normaliseValue(t.stdout))})}async set(e,t){let r=this.writeCommand(e),o=r.secretVia!=="argv",i=this.encodeValue(t),s=await this.runner.run(o?r:{...r,args:bc(r.args,i)},o?this.runOptions({stdin:i}):this.runOptions());this.assertUsable(s,`write ${e}`);let a=await this.get(e);if(!a.ok||a.value!==t)throw new P(this.id,`${this.label} accepted ${e} but did not store it correctly, so it has not been trusted.`)}async delete(e){let t=await this.runner.run(this.deleteCommand(e),this.runOptions());this.isMissing(t)||this.assertUsable(t,`delete ${e}`)}assertUsable(e,t){if(e.timedOut)throw new P(this.id,`${this.label} timed out trying to ${t}`);if(e.spawnFailed)throw new P(this.id,`${this.label} is no longer available (could not ${t})`);if(e.code!==0)throw new P(this.id,`${this.label} failed to ${t} (exit ${String(e.code)})`)}};function bc(n,e){return n.map(t=>t===Fn?e:t)}var mr="secret-tool",vc="__dlink_probe__",Sc="DBUS_SESSION_BUS_ADDRESS",Ec=1,_c=/could not connect|cannot autolaunch|not provided by any \.service/i,hr=class extends Qe{id=N.LinuxSecretService;label="Linux Secret Service";env;constructor(e){super(e),this.env=e.env??process.env}async probe(){let e=this.env[Sc];return e===void 0||e.trim()===""?{available:!1,reason:F.NoSessionBus}:super.probe()}runEnv(){return this.env}readCommand(e){return{command:mr,args:["lookup",...this.namespace.attributes(e)]}}writeCommand(e){return{command:mr,args:["store",`--label=${this.namespace.label(e)}`,...this.namespace.attributes(e)],secretVia:"stdin"}}deleteCommand(e){return{command:mr,args:["clear",...this.namespace.attributes(e)]}}probeCommand(){return{command:mr,args:["lookup","service",this.namespace.service,"key",vc]}}isMissing(e){return e.timedOut||e.spawnFailed?!1:e.code===Ec&&e.stdout.trim()===""&&e.stderr.trim()===""}interpretProbe(e){return e.timedOut?{available:!1,reason:F.Timeout,detail:"the keyring did not respond"}:e.spawnFailed?{available:!1,reason:F.ToolMissing,detail:"secret-tool is not installed"}:_c.test(e.stderr)?{available:!1,reason:F.NoSessionBus,detail:"the Secret Service could not be reached"}:e.code===0||this.isMissing(e)?{available:!0}:{available:!1,reason:F.Locked,detail:`secret-tool exited ${String(e.code)}`}}};import*as bi from"node:crypto";import*as Ze from"node:crypto";var vt=12,gr=16,yr=32,Xe=class{key;constructor(e){this.key=e}encrypt(e){let t=Ze.randomBytes(vt),r=Ze.createCipheriv("aes-256-gcm",this.key,t,{authTagLength:gr}),o=Buffer.concat([r.update(e,"utf8"),r.final()]),i=r.getAuthTag();return Buffer.concat([t,i,o]).toString("base64url")}decrypt(e){let t=Buffer.from(e,"base64url"),r=t.subarray(0,vt),o=t.subarray(vt,vt+gr),i=t.subarray(vt+gr),s=Ze.createDecipheriv("aes-256-gcm",this.key,r,{authTagLength:gr});return s.setAuthTag(o),Buffer.concat([s.update(i),s.final()]).toString("utf8")}};var kc="DeviceLink-SecretStorage-v1",Tc=1e5;function wc(n){return bi.pbkdf2Sync(n,kc,Tc,yr,"sha256")}var br=class extends Ne{id=N.MachineId;label="encrypted file (machine-derived key)";codec;constructor(e){super(e);let t=e.machineId?.trim();this.codec=t?new Xe(wc(t)):null}probe(){return this.codec===null?Promise.resolve({available:!1,reason:F.NotConfigured}):Promise.resolve({available:!0})}protect(e){return Promise.resolve(this.requireCodec().encrypt(e))}unprotect(e){return Promise.resolve(this.requireCodec().decrypt(e))}requireCodec(){if(this.codec===null)throw new P(this.id,"Secret storage requires a machine ID");return this.codec}};var vr="/usr/bin/security",Rc=44,Cc="__dlink_probe__",xc=/could not be found/i,Ac=/interaction is not allowed/i,Sr=class extends Qe{id=N.MacosKeychain;label="macOS Keychain";readCommand(e){return{command:vr,args:["find-generic-password","-s",this.namespace.service,"-a",this.namespace.account(e),"-w"]}}writeCommand(e){return{command:vr,args:["add-generic-password","-s",this.namespace.service,"-a",this.namespace.account(e),"-U","-w",Fn],secretVia:"argv"}}deleteCommand(e){return{command:vr,args:["delete-generic-password","-s",this.namespace.service,"-a",this.namespace.account(e)]}}probeCommand(){return{command:vr,args:["find-generic-password","-s",this.namespace.service,"-a",Cc,"-w"]}}isMissing(e){return e.timedOut||e.spawnFailed?!1:e.code===Rc||xc.test(e.stderr)}interpretProbe(e){return e.timedOut?{available:!1,reason:F.Timeout}:e.spawnFailed?{available:!1,reason:F.ToolMissing}:Ac.test(e.stderr)?{available:!1,reason:F.Locked,detail:"the login keychain is locked"}:e.code===0||this.isMissing(e)?{available:!0}:{available:!1,reason:F.Locked,detail:`security exited ${String(e.code)}`}}};import*as _r from"node:crypto";var St={N:32768,r:8,p:1,maxmem:64*1024*1024},Dc=16,Ic=1,vi="scrypt";function Oc(n,e,t){return new Promise((r,o)=>{_r.scrypt(n,e,yr,{N:t.N,r:t.r,p:t.p,maxmem:St.maxmem},(i,s)=>{if(i){o(i);return}r(s)})})}var Er=class extends Ne{id=N.Passphrase;label="encrypted file (operator passphrase)";passphrase;salt=null;codec=null;codecSalt=null;codecParams=null;constructor(e){super(e);let t=e.passphrase??"";this.passphrase=t.trim().length>0?t:null}probe(){return this.passphrase===null?Promise.resolve({available:!1,reason:F.NotConfigured}):Promise.resolve({available:!0})}async protect(e){let t=this.requirePassphrase();this.salt===null&&(this.salt=_r.randomBytes(Dc));let r=await this.codecFor(t,this.salt,St),o={v:Ic,kdf:vi,salt:this.salt.toString("base64url"),N:St.N,r:St.r,p:St.p,blob:r.encrypt(e)};return JSON.stringify(o)}async unprotect(e){let t=this.requirePassphrase(),r=this.parseEnvelope(e),o=Buffer.from(r.salt,"base64url"),i=await this.codecFor(t,o,r);this.salt=o;try{return i.decrypt(r.blob)}catch{throw new P(this.id,"The stored secrets could not be decrypted with DLINK_PASSPHRASE. The passphrase is wrong or the store belongs to another passphrase; nothing has been changed.")}}parseEnvelope(e){let t;try{t=JSON.parse(e)}catch{throw new P(this.id,"The secret store is not a passphrase-protected store.")}let r=t;if(r.kdf!==vi||typeof r.salt!="string"||typeof r.blob!="string")throw new P(this.id,"The secret store is not a passphrase-protected store.");if(typeof r.N!="number"||typeof r.r!="number"||typeof r.p!="number")throw new P(this.id,"The passphrase store does not record its key derivation parameters.");return r}async codecFor(e,t,r){return this.codec!==null&&this.codecSalt!==null&&this.codecSalt.equals(t)&&this.codecParams!==null&&this.codecParams.N===r.N&&this.codecParams.r===r.r&&this.codecParams.p===r.p?this.codec:(this.codec=new Xe(await Oc(e,t,r)),this.codecSalt=t,this.codecParams={N:r.N,r:r.r,p:r.p},this.codec)}requirePassphrase(){if(this.passphrase===null)throw new P(this.id,"DLINK_PASSPHRASE is not set, so the secret store cannot be opened.");return this.passphrase}};var kr=class extends Error{attempts;constructor(e){super("No secret backend is available, so the agent cannot store its device key."),this.name="NoSecretBackendError",this.attempts=e}},Tr=class{async resolve(e){let t=[];for(let r of e){let o=await this.safeProbe(r);if(t.push(Nc(r,o)),o.available)return{provider:r,attempts:t}}throw new kr(t)}async safeProbe(e){try{return await e.probe()}catch{return{available:!1,reason:F.RoundTripFailed}}}};function Nc(n,e){return e.available?{id:n.id,available:!0}:{id:n.id,available:!1,reason:e.reason}}var Pc="secrets.enc.json",Fc="secrets.pass.json",Lc="secrets.dpapi.json",Mc="DLINK_SECRETS_BACKEND",$c="DLINK_PASSPHRASE";function Uc(n={}){let e=n.platform??process.platform,t=n.env??process.env,r=n.configDir??Z(),o=n.runner??new ur,i=n.machineId,s=new pr(t.DEVICELINK_ENV),a=m=>Si.join(r,m),c=new Map([[N.MacosKeychain,new Sr({runner:o,namespace:s})],[N.LinuxSecretService,new hr({runner:o,namespace:s,env:t})],[N.WindowsDpapi,new fr({filePath:a(Lc),runner:o,platform:e})],[N.Passphrase,new Er({filePath:a(Fc),platform:e,passphrase:t[$c]})],[N.MachineId,new br({filePath:a(Pc),platform:e,machineId:i})]]),l=t[Mc]?.trim(),d=l?c.get(l):void 0;if(d)return[d];let f=[],p=m=>{let g=c.get(m);g&&f.push(g)};return p(N.Passphrase),p(e==="darwin"?N.MacosKeychain:e==="win32"?N.WindowsDpapi:N.LinuxSecretService),p(N.MachineId),f}async function Ei(n={}){let e=n.platform??process.platform,t=n.configDir??Z(),r=n.candidates??Uc(n),o=await new Tr().resolve(r),i=new cr(t,e),s=await i.read(),a={backend:o.provider.id,label:o.provider.label,weak:o.provider.id===N.MachineId,attempts:o.attempts,expectedBackend:s,degraded:s!==void 0&&s!==o.provider.id},c=r.find(l=>l.id===N.MachineId);if(c&&c.id!==o.provider.id){let l=await new dr().migrate(c,o.provider);l.migrated&&(a.migratedFrom=l.from)}return await i.write(o.provider.id),{store:o.provider,report:a}}var wr=class{},Ln=class{ok;config;constructor(e,t){this.ok=e,this.config=t}},Mn=class extends Y{constructor(){super(new z({name:"load-config",lane:"main",priority:1e3,locks:["GLOBAL"],maxAttempts:3,cancellable:!0}))}async run(e,t){t.notifier.info("Loading configuration...",{scope:"system"});let r=t.engine.configurationContext.loader,o=await t.engine.secrets.get("devicePrivateKey");r.setPrivateKeyCache(o.ok&&o.value?o.value:void 0),r.withDefaultConfig(),r.withArgv(t.engine.argv),t.engine.argv.enviromentFile&&r.withEnviromentFile(t.engine.argv.enviromentFile),r.withConfigFile("config.json"),r.withProcessEnv(),r.withDiscoveryCache();let i=r.build(),s=r.getPrivateKeyToStore();return s&&await t.engine.secrets.set("devicePrivateKey",s),this.updateUi(i,t),t.notifier.success("Configuration loaded"),t.engine.applyConfiguration(i),t.bus.emit("config:loaded",i),new Ln(!0,i)}updateUi(e,t){let r={scope:"system"};t.notifier.info(`Control base URL: ${e.controlBaseUrl}`,r),t.notifier.info(`Bridge WebSocket URL: ${e.bridgeWsUrl}`,r),t.notifier.info(`Bridge endpoint source: ${t.engine.configurationContext.loader.getBridgeEndpointSource()??"none"}`,r);let o=e.discovery;o&&t.notifier.info(`Discovery cache: issued_at=${o.issuedAt??"-"} expires_at=${o.expiresAt} control=${o.controlUrl??"-"} bridge=${(o.bridgeUrls??[]).join(",")||"-"}`,r),t.notifier.info(`Directories: ${e.directories.map(i=>i.path).join(", ")}`,r),t.notifier.info(`Device: ${e.device?.id}`,r),t.notifier.info(`Device name: ${e.device?.name}`,r),t.notifier.info(`Device tag: ${e.device?.tag}`,r),t.notifier.info(`Device keys public: ${e.device?.keys?.public?"***":"(none)"}`,r)}},$n=new Mn;function _i(n){return new pe($n,n)}var Un=class{ok;constructor(e){this.ok=e}},Bn=class extends Y{constructor(){super(new z({name:"console-command",lane:"console",priority:1e3,locks:[],maxAttempts:1,cancellable:!1}))}async run(e,t){return t.notifier.info(`Executing console command: ${e.kind}`),await new Promise(r=>setTimeout(r,2e3)),t.notifier.info(`Console command executed: ${e.kind}`),t.notifier.success(`Console command executed: ${e.kind}`),new Un(!0)}},ki=new Bn;var Kn=class{ok;constructor(e){this.ok=e}},jn=class extends Y{constructor(){super(new z({name:"contact-server",lane:"main",priority:900,locks:["GLOBAL"],maxAttempts:8,cancellable:!0}))}async run(e,t){return t.notifier.info(`contact server mode=${e.mode}`,{scope:"system"}),await new Promise(r=>setTimeout(r,200)),new Kn(!0)}},Ti=new jn;var Vn=class{ok;constructor(e){this.ok=e}},qn=class extends Y{constructor(){super(new z({name:"send-server-result",lane:"io",priority:200,locks:[],maxAttempts:10,cancellable:!0}))}async run(e,t){return t.notifier.info(`send result requestId=${e.requestId}`,{scope:"system"}),await new Promise(r=>setTimeout(r,10)),new Vn(!0)}},wi=new qn;import Kc from"node:crypto";import te from"lodash/get.js";import Et from"lodash/isPlainObject.js";import tt from"lodash/isString.js";var ee=class{constructor(e,t){this.context=e;this.handler=t}execute(e){return this.handler(this.context,e)}};async function Ee(n,e,t){let r=`${n.configuration.controlBaseUrl}${e}`,o=await fetch(r,t);if(!o.ok){let i=await o.text().catch(a=>{let c=a instanceof Error?a.message:String(a);return n.notifier.error(`Failed to read HTTP error response body: ${c}`),""}),s=new Error(`HTTP ${o.status}: ${i}`);s.status=o.status;try{s.body=i?JSON.parse(i):void 0}catch{s.body=void 0}if(o.status===429){let a=o.headers.get("Retry-After");if(a!==null){let c=parseInt(a,10);Number.isFinite(c)&&c>=0&&(s.retryAfterSec=c)}}throw s}return o.json()}function Ri(n){return new ee(n,async(e,t)=>Ee(e,"/api/device/authorize/start",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}))}function Ci(n){return new ee(n,async(e,t)=>Ee(e,"/api/device/authorize/prove",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}))}import{z as me}from"zod";var Bc=me.union([me.object({status:me.literal("pending"),needs_proof:me.boolean()}),me.object({status:me.literal("approved"),needs_proof:me.boolean()}),me.object({error:me.literal("access_denied")}),me.object({error:me.literal("expired_token")})]);function xi(n){return new ee(n,async(e,t)=>{let r=new URL("/api/device/authorize/stream",e.configuration.controlBaseUrl);r.searchParams.set("device_code",t.deviceCode);let o=e.notifier,i=new AbortController,s=setTimeout(()=>{o.error("[deviceAuthStream] Timeout reached, aborting"),i.abort()},Math.max(1e3,t.timeoutMs));if(t.signal){let a=t.signal;a.addEventListener("abort",()=>{let c="reason"in a&&a.reason!=null?String(a.reason):"";o.warn(`[deviceAuthStream] External signal aborted: ${c}`),i.abort()})}try{let a=await fetch(r.toString(),{method:"GET",headers:{Accept:"text/event-stream"},signal:i.signal});if(!a.ok||!a.body){let f=await a.text().catch(p=>{let m=p instanceof Error?p.message:String(p);return o.error(`[deviceAuthStream] Failed to read response body (${a.status}): ${m}`),""});throw o.error(`[deviceAuthStream] Response error: ${a.status} - ${f}`),new Error(`device/authorize/stream failed (${a.status}): ${f}`)}let c=a.body.getReader(),l=new TextDecoder("utf-8"),d="";for(;;){let{value:f,done:p}=await c.read();if(p){o.error("[deviceAuthStream] Stream ended unexpectedly");break}for(d+=l.decode(f,{stream:!0});;){let m=d.indexOf(`
2
+ import Pc from"node:crypto";var Ae=class{debug;headless;headlessReason;constructor(e,t=!1,r=""){this.debug=e,this.headless=t,this.headlessReason=r}};var Te=class{name;concurrency;constructor(e,t){this.name=e,this.concurrency=t}};var De=class n{status;output;error;constructor(e,t,r){this.status=e,this.output=t,this.error=r}static success(e){return new n("success",e,null)}static failure(e){return new n("failure",null,e)}static cancelled(e){return new n("cancelled",null,e)}},Kt=class{promise;resolveFn;rejectFn;constructor(){this.promise=new Promise((e,t)=>{this.resolveFn=e,this.rejectFn=t})}resolve(e){this.resolveFn(e)}reject(e){this.rejectFn(e)}};var z=class{name;lane;priority;locks;maxAttempts;cancellable;constructor(e){this.name=e.name,this.lane=e.lane,this.priority=e.priority,this.locks=e.locks,this.maxAttempts=e.maxAttempts,this.cancellable=e.cancellable}},Y=class{options;constructor(e){this.options=e}},pe=class{type;input;constructor(e,t){this.type=e,this.input=t}},jt=class{bus;logger;notifier;flags;signal;engine;get headless(){return this.flags.headless}dispatchFn;constructor(e){this.bus=e.bus,this.engine=e.engine,this.logger=e.logger,this.notifier=e.notifier,this.flags=e.flags,this.signal=e.signal,this.dispatchFn=e.dispatch}dispatch(e,t){let r=t||new ft(null,null,null,null);return this.dispatchFn(e,r)}};var Vt=class{ts;message;constructor(e,t){this.ts=t?.ts??Date.now(),this.message=e}},ye=class{id;ts;groupKey;kind;scope;message;category;constructor(e,t){this.id=crypto.randomUUID(),this.ts=t?.ts??Date.now(),this.kind=t?.kind??"info",this.scope=t?.scope??"default",this.message=e,this.groupKey=t?.groupKey,this.category=t?.category??[]}},qt=class{ts;jobId;jobType;state;attempt;maxAttempts;lane;priority;error;nextRunAt;constructor(e){this.ts=e.ts,this.jobId=e.jobId,this.jobType=e.jobType,this.state=e.state,this.attempt=e.attempt,this.maxAttempts=e.maxAttempts,this.lane=e.lane,this.priority=e.priority,this.error=e.error,this.nextRunAt=e.nextRunAt}};var Le=class{jobs;constructor(e){this.jobs=e}},ht=class{id;jobType;inputJson;state;lane;priority;locks;attempts;maxAttempts;nextRunAt;cancellable;parentId;dedupeKey;lastError;createdAt;updatedAt;constructor(e){this.id=e.id,this.jobType=e.jobType,this.inputJson=e.inputJson,this.state=e.state,this.lane=e.lane,this.priority=e.priority,this.locks=e.locks,this.attempts=e.attempts,this.maxAttempts=e.maxAttempts,this.nextRunAt=e.nextRunAt,this.cancellable=e.cancellable,this.parentId=e.parentId,this.dedupeKey=e.dedupeKey,this.lastError=e.lastError,this.createdAt=e.createdAt,this.updatedAt=e.updatedAt}};var Wt=class{state;constructor(e){this.state=e??new Le({})}async load(){return new Le(structuredClone(this.state.jobs))}async save(e){this.state=new Le(structuredClone(e.jobs))}};var Ge=class{engine;bus;logger;notifier;flags;signal;get headless(){return this.flags.headless}constructor(e){this.engine=e.engine,this.bus=e.bus,this.logger=e.logger,this.notifier=e.notifier,this.flags=e.flags,this.signal=e.signal}on(e,t){return this.bus.on(e,t)}};var Ht=class{version=1;controlBaseUrl;bridgeWsUrl;directories;device;tokens;discovery;constructor(){this.directories=[]}},Gt=class{_configuration;loader;get configuration(){return this._configuration}constructor(e,t){this._configuration=e,this.loader=t}apply(e){this._configuration=e}};import Be from"node:path";import _i from"node:os";import cr from"node:fs";import ca from"node:path";import la from"env-paths";var ua="DeviceLink",da=la(ua,{suffix:""});function pa(){if(process.env.DEVICELINK_DATA_DIR)return process.env.DEVICELINK_DATA_DIR;let n=process.env.DEVICELINK_ENV,e=da.config;return!n||n==="production"?e:ca.join(e,n)}function Z(){return pa()}import Vn from"dotenv";import we from"lodash/get.js";import lr from"lodash/isArray.js";import qn from"lodash/isObject.js";import ki from"lodash/isString.js";import Ce from"lodash/isEmpty.js";import Nc from"lodash/defaultTo.js";import{createRequire as fa}from"node:module";var ma=fa(import.meta.url),ha=ma("node-machine-id");function Jt(n=!0){try{let e=ha.machineIdSync(n);if(e&&typeof e=="string"&&e.trim().length>0)return e.trim()}catch{}}import Vo from"node:path";import ln from"node:fs";import un from"node:crypto";import dn from"lodash/get.js";import Ie from"lodash/isEmpty.js";var zt=class{_notifier;argv;envFile;processEnv;configFileContent;getPrivateKey;_lastGeneratedPrivateKey;constructor(e){this._notifier=e.notifier,this.argv=e.argv,this.envFile=e.envFile,this.processEnv=e.processEnv,this.configFileContent=e.configFileContent,this.getPrivateKey=e.getPrivateKey}getLastGeneratedPrivateKey(){let e=this._lastGeneratedPrivateKey;return this._lastGeneratedPrivateKey=void 0,e}ensureDeviceKeys(){let e=this.getDevicePrivateKey(),t=this.getDevicePublicKey();if(e&&t)return{publicKey:t,privateKey:e};if(e&&!t)try{let a=un.createPrivateKey(e);return t=un.createPublicKey(a).export({format:"pem",type:"spki"}).toString("utf8"),this._notifier.info("Derived public key from private key",{scope:"system"}),{publicKey:t,privateKey:e}}catch{this._notifier.warn("Failed to derive public key from private key, generating new keypair",{scope:"system"})}t&&!e&&this._notifier.warn("Public key found but no private key, generating new keypair",{scope:"system"}),this._notifier.info("Generating new Ed25519 keypair...",{scope:"system"});let{publicKey:r,privateKey:o}=un.generateKeyPairSync("ed25519"),i=r.export({format:"pem",type:"spki"}).toString("utf8"),s=o.export({format:"pem",type:"pkcs8"}).toString("utf8");return this._lastGeneratedPrivateKey=s,this._notifier.info("Generated new Ed25519 keypair",{scope:"system"}),{publicKey:i,privateKey:s}}getDevicePrivateKey(){if(this.getPrivateKey){let r=this.getPrivateKey();if(r&&!Ie(r))return this._notifier.info("Using private key from secret storage cache",{scope:"system"}),r}if(this.argv?.privateKeyFile){let r=this.loadKeyFromFile(this.argv.privateKeyFile);if(r)return this._notifier.info(`Found private key from --private-key-file: ${this.argv.privateKeyFile}`,{scope:"system"}),r;this._notifier.warn(`Failed to load private key from file: ${this.argv.privateKeyFile}`,{scope:"system"})}let e=this.safeGetEnvValue("DLINK_DEVICE_PRIVATE_KEY");if(e&&!Ie(e))return this._notifier.info("Found private key in env file",{scope:"system"}),e;let t=this.processEnv.DLINK_DEVICE_PRIVATE_KEY;if(t&&!Ie(t))return this._notifier.info("Found private key in process env",{scope:"system"}),t}getDevicePublicKey(){if(this.argv?.publicKeyFile){let o=this.loadKeyFromFile(this.argv.publicKeyFile);if(o)return this._notifier.info(`Found public key from --public-key-file: ${this.argv.publicKeyFile}`,{scope:"system"}),o;this._notifier.warn(`Failed to load public key from file: ${this.argv.publicKeyFile}`,{scope:"system"})}let e=dn(this.safeGetConfigValue("device"),"keys.public");if(e&&!Ie(String(e)))return this._notifier.info("Found public key in config file",{scope:"system"}),String(e);let t=this.safeGetEnvValue("DLINK_DEVICE_PUBLIC_KEY");if(t&&!Ie(t))return this._notifier.info("Found public key in env file",{scope:"system"}),t;let r=this.processEnv.DLINK_DEVICE_PUBLIC_KEY;if(r&&!Ie(r))return this._notifier.info("Found public key in process env",{scope:"system"}),r}loadKeyFromFile(e){if(!e||Ie(e))return;let t=this.getApplicationConfigFolder(),r=[e,Vo.join(t,e)];for(let o of r)try{let i=Vo.resolve(o);if(ln.existsSync(i))if(ln.statSync(i).isFile()){let a=ln.readFileSync(i,"utf8").trim();if(Ie(a))this._notifier.warn(`Key file is empty: ${i}`,{scope:"system"});else return this._notifier.info(`Loaded key from file: ${i}`,{scope:"system"}),a}else this._notifier.warn(`Path is not a file: ${i}`,{scope:"system"})}catch(i){let s=i instanceof Error?i.message:String(i);this._notifier.warn(`Failed to read key file ${o}: ${s}`,{scope:"system"})}this._notifier.warn(`Key file not found: ${e} (tried: ${r.join(", ")})`,{scope:"system"})}safeGetEnvValue(e){try{return dn(this.envFile,`parsed.${e}`)}catch{return}}safeGetConfigValue(e){try{return dn(this.configFileContent,e)}catch{return}}getApplicationConfigFolder(){return Z()}};import qo from"node:crypto";function Wo(n){let e=n.trim();e=e.replace(/\\/g,"/"),e=e.replace(/(^\/\/+)|\/{2,}/g,(u,d)=>d?"//":"/"),e.length>1&&e.endsWith("/")&&(e=e.replace(/\/+$/g,"")),e===""&&(e="/"),e=e.replace(/^([a-zA-Z]):(?=\/|$)/,(u,d)=>`${String(d).toUpperCase()}:`);let t=e.startsWith("/")||e.startsWith("//")||/^[A-Z]:\//.test(e),r=e.startsWith("//")?"//":e.startsWith("/")?"/":"",o="",i=e.match(/^([A-Z]:)(\/|$)/);i?(o=i[1],e=e.slice(o.length),e.startsWith("/")&&(e=e.slice(1))):e=e.replace(/^\/+/,"");let s=e.split("/").filter(Boolean),a=[];for(let u of s)if(u!=="."){if(u===".."){a.length>0&&a[a.length-1]!==".."?a.pop():t||a.push("..");continue}a.push(u)}let c=a.join("/");return o?c=`${o}/${c}`.replace(/\/+$/g,""):t&&(c=`${r}${c}`.replace(/\/+$/g,"")),c=c.toLowerCase(),c}function gt(n,e=[3,3,3,3]){let t=Wo(n),o=qo.createHash("sha256").update(t,"utf8").digest("base64url").replace(/[^a-zA-Z0-9]/g,"").toLowerCase(),i=e.reduce((c,u)=>c+u,0),s=o.length>=i?o:o.padEnd(i,o),a=0;return e.map(c=>s.slice(a,a+=c)).join("-")}function yt(n){let e=Wo(n),r=qo.createHash("sha256").update(e,"utf8").digest("hex").slice(0,32),o=r.slice(0,8),i=r.slice(8,12),s=r.slice(12,16),a=r.slice(16,20),c=r.slice(20,32);return`${o}-${i}-${s}-${a}-${c}`}import*as ae from"node:crypto";function pn(n){return`${n.deviceId}|${n.ts}|${n.nonce}`}function fn(n){return`${n.deviceId}|${n.ts}|${n.nonce}|${n.refreshTokenSha256Hex}`}function mn(n){let e=ae.createPublicKey(n);if(e.asymmetricKeyType!=="ed25519")throw new Error(`Unexpected key type: ${e.asymmetricKeyType}`);let t=e.export({format:"der",type:"spki"});return ae.createHash("sha256").update(t).digest("base64url").slice(0,16).toUpperCase()}function hn(n){let e=Buffer.from(pn(n),"utf8"),t=ae.createPrivateKey(n.privateKeyPem);return ae.sign(null,e,t).toString("base64")}function gn(n){let e=ae.createHash("sha256").update(n.refreshToken,"utf8").digest("hex"),t=Buffer.from(fn({...n,refreshTokenSha256Hex:e}),"utf8"),r=ae.createPrivateKey(n.privateKeyPem);return ae.sign(null,t,r).toString("base64")}function bt(n){return new Promise(e=>setTimeout(e,n))}import*as Ho from"node:path";var Go=process.platform==="win32";function yn(n){let e=Ho.resolve(n);return Go?e.toLowerCase():e}import*as be from"node:path";import*as Jo from"node:os";function Me(n){return n.replace(/\\/g,"/")}function zo(n){return/^[A-Za-z]:[\\/]/.test(n)||/^[A-Za-z]:$/.test(n.trim())}function ba(n){return zo(n)?n.replace(/\//g,"\\"):n}function bn(n){if(n==null)return;let e=String(n).trim();if(e==="")return;if(e.startsWith("~"))return Me(e);if(!zo(e))try{let u=be.resolve(e),d=be.resolve(Jo.homedir()),f=be.relative(d,u);if(!f.startsWith("..")&&!be.isAbsolute(f))return f===""?"~":"~/"+Me(f)}catch{}let r=ba(e).match(/^([A-Za-z]:)\\(?:[Uu][Ss][Ee][Rr][Ss])\\([^\\]+)(\\.*)?$/);if(r){let u=(r[3]??"").replace(/\\/g,"/");return u?"~"+u:"~"}let o=e.match(/^\/mnt\/[a-z]\/(?:[Uu][Ss][Ee][Rr][Ss])\/[^/]+(\/.*)?$/i);if(o){let u=o[1]??"";return u?"~"+Me(u):"~"}let i=e.match(/^\/Users\/[^/]+(\/.*)?$/);if(i){let u=i[1]??"";return u?"~"+Me(u):"~"}let s=e.match(/^\/home\/[^/]+(\/.*)?$/);if(s){let u=s[1]??"";return u?"~"+Me(u):"~"}let a=e.match(/^\/usr\/home\/[^/]+(\/.*)?$/);if(a){let u=a[1]??"";return u?"~"+Me(u):"~"}let c=e.match(/^\/export\/home\/[^/]+(\/.*)?$/);if(c){let u=c[1]??"";return u?"~"+Me(u):"~"}try{return be.basename(be.resolve(e))}catch{return e.split(/[/\\]/).pop()??e}}var Yo="<path>",va=/(['"`])((?:[A-Za-z]:[\\/]|\\\\|~?\/)[^'"`\n]*)\1/g,Sa=/(^|[\s'"`([{=,;])(?:\\\\[^\s'"`<>|?*\n]+|[A-Za-z]:[\\/][^\s'"`<>|?*\n]*|~?\/[^\s'"`<>|?*\n:]*\/[^\s'"`<>|?*\n:]*)/g;function vn(n){return typeof n!="string"||n.length===0?n:n.replace(va,(e,t)=>`${t}${Yo}${t}`).replace(Sa,(e,t)=>`${t}${Yo}`)}import Ea from"lodash/get.js";function fe(n){return Ea(n,["context","file_policies"])}var Qt=[{pattern:"node_modules",type:"exact"},{pattern:".git",type:"exact"},{pattern:"dist",type:"exact"},{pattern:"build",type:"exact"},{pattern:".next",type:"exact"},{pattern:".cache",type:"exact"},{pattern:".DS_Store",type:"exact"},{pattern:"Thumbs.db",type:"exact"},{pattern:"*.tmp",type:"glob"},{pattern:"*.log",type:"glob"},{pattern:".env*",type:"glob"}];function Qo(n){let e=n.lastIndexOf("."),t=Math.max(n.lastIndexOf("/"),n.lastIndexOf("\\"));return e>t+1?n.slice(e).toLowerCase():""}function Yt(n,e){let t="^",r=0;for(;r<e.length;){let o=e[r];o==="*"?r+1<e.length&&e[r+1]==="*"?(t+=".*",r+=2):(t+="[^/]*",r+=1):o==="?"?(t+="[^/]",r+=1):"\\^$|.+(){}[]".includes(o)?(t+=`\\${o}`,r+=1):(t+=o,r+=1)}t+="$";try{return new RegExp(t,"i").test(n)}catch{return n.toLowerCase().includes(e.toLowerCase())}}function Xo(n){let e=n.replace(/\\/g,"/").toLowerCase();return e.includes("/secrets/")||e.startsWith("secrets/")?{shouldIgnore:!0,reason:"denylist:secrets",matchedRule:"secrets/"}:e.includes("/.env")||e.startsWith(".env")?{shouldIgnore:!0,reason:"denylist:env",matchedRule:".env"}:e.includes("/id_rsa")||e.startsWith("id_rsa")?{shouldIgnore:!0,reason:"denylist:ssh",matchedRule:"id_rsa"}:e.includes("/id_ed25519")||e.startsWith("id_ed25519")?{shouldIgnore:!0,reason:"denylist:ssh",matchedRule:"id_ed25519"}:e.endsWith(".pem")?{shouldIgnore:!0,reason:"denylist:pem",matchedRule:"*.pem"}:e.endsWith(".key")?{shouldIgnore:!0,reason:"denylist:key",matchedRule:"*.key"}:e.endsWith(".p12")?{shouldIgnore:!0,reason:"denylist:p12",matchedRule:"*.p12"}:e.endsWith(".pfx")?{shouldIgnore:!0,reason:"denylist:pfx",matchedRule:"*.pfx"}:null}function _a(n,e){let t=Qo(n);if(t&&e.blocked_extensions?.includes(t))return{shouldIgnore:!0,reason:"policy:blocked_extension",matchedRule:t};if(e.allowed_extensions&&e.allowed_extensions.length>0&&t&&!e.allowed_extensions.includes(t))return{shouldIgnore:!0,reason:"policy:not_in_allowlist",matchedRule:t};for(let r of e.blocked_patterns??[])if(Yt(n,r))return{shouldIgnore:!0,reason:"policy:blocked_pattern",matchedRule:r};return null}function ka(n,e){let t=n.replace(/\\/g,"/"),r=t.split("/").filter(Boolean);for(let o of e){let i=!1;if(o.type==="exact"?i=r.some(s=>s===o.pattern):o.type==="prefix"?i=t.startsWith(o.pattern):o.type==="glob"&&(!o.pattern.includes("/")&&!o.pattern.includes("*")&&!o.pattern.includes("?")?i=r.some(s=>s.toLowerCase()===o.pattern.toLowerCase()):o.pattern.includes("/")?i=Yt(t,o.pattern):i=r.some(s=>Yt(s,o.pattern))),i)return{shouldIgnore:!0,matchedRule:o.pattern}}return null}function Sn(n,e,t,r){let o=Xo(n);if(o)return o;if(r&&!e){let i=_a(n,r);if(i)return i}return ka(n,t)??{shouldIgnore:!1}}function En(n){return n.split(`
3
+ `).map(e=>e.trim()).filter(e=>e&&!e.startsWith("#")).map(e=>e.includes("*")||e.includes("?")?{pattern:e,type:"glob"}:e.startsWith("/")?{pattern:e.slice(1),type:"prefix"}:{pattern:e,type:"exact"})}var Ra='Use relative paths like "src/file.ts" or "." for the root directory. Paths must be relative to the configured root.',Ta='Use relative paths like "src/file.ts" or "." for the root directory. Do not use drive letters (C:) or UNC paths (\\\\server).',wa='Paths cannot use URL schemes (like "http://" or "file://"). Use simple relative paths like "src/file.ts".',Ca='Paths cannot use ".." to escape the configured root directory. Use paths relative to the root, like "src/file.ts" or "subdir/file.ts".';function vt(n,e){let t=(n??"").trim();if(!t)return".";t.includes("\0")&&e("INVALID_INPUT","Path contains null byte."),t.startsWith("/")&&e("PATH_ESCAPE","Absolute paths are not allowed. Use a path relative to the root.",Ra),(/^[a-zA-Z]:[\\/]/.test(t)||t.startsWith("\\\\")||t.startsWith("//"))&&e("PATH_ESCAPE","Absolute/drive/UNC paths are not allowed. Use a path relative to the root.",Ta);let r=t.replace(/\\/g,"/");/^[a-zA-Z]+:\/\//.test(r)&&e("INVALID_INPUT","URL-style paths are not allowed.",wa);let o=[];for(let i of r.split("/"))if(!(!i||i===".")){if(i===".."){o.length===0&&e("PATH_ESCAPE","Path escapes the root.",Ca),o.pop();continue}o.push(i)}return o.length===0?".":o.join("/")}function _n(n,e){return{workspace_id:n.workspace_id,device_id:n.device_id,directory_id:n.directory_id,path:vt(n.path,e)}}var xa=["","utf-8","utf8"],Aa=["utf-16le","utf16le","ucs-2","ucs2"];function Da(n){return n&128?(n&224)===192?2:(n&240)===224?3:(n&248)===240?4:0:1}function Ia(n){let e=n.length,t=e-1,r=0;for(;t>=0&&(n[t]&192)===128&&r<3;)r+=1,t-=1;if(t<0)return e;let o=Da(n[t]);return o===0||e-t>=o?e:t}function Oa(n){let e=n.length-n.length%2;if(e<2)return e;let t=n[e-2]|n[e-1]<<8;return t>=55296&&t<=56319?e-2:e}function kn(n,e){let t=e.trim().toLowerCase();if(xa.includes(t)){let r=Ia(n);return r===0?n.length:r}if(Aa.includes(t)){let r=Oa(n);return r===0?n.length:r}return n.length}function $e(n){let e=Date.now()-n;return{execution_ms:e,execution_sec:parseFloat((e/1e3).toFixed(2))}}function Rn(n){let{retryAfterSec:e}=n;if(typeof e=="number"&&Number.isFinite(e)&&e>=0)return{delayMs:Math.min(n.retryAfterMaxSec*1e3,Math.max(n.retryAfterMinSec*1e3,e*1e3)),honoredRetryAfter:!0};let r=Math.max(1,n.attempt),o=Math.min(r-1,n.maxDoublings),i=n.baseSec*Math.pow(2,o);return{delayMs:Math.min(n.ceilingSec*1e3,(i+n.jitterSec)*1e3),honoredRetryAfter:!1}}var Na=/^v?(\d+)\.(\d+)\.(\d+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/;function ve(n){if(typeof n!="string")return null;let e=n.trim().match(Na);return e?{major:Number(e[1]),minor:Number(e[2]),patch:Number(e[3]),prerelease:e[4]??null}:null}function Pa(n,e){if(n===e)return 0;if(n===null)return 1;if(e===null)return-1;let t=n.split("."),r=e.split("."),o=Math.max(t.length,r.length);for(let i=0;i<o;i+=1){let s=t[i],a=r[i];if(s===void 0)return-1;if(a===void 0)return 1;let c=/^\d+$/.test(s),u=/^\d+$/.test(a);if(c&&u){let d=Number(s)-Number(a);if(d!==0)return d<0?-1:1;continue}if(c!==u)return c?-1:1;if(s!==a)return s<a?-1:1}return 0}function Xt(n,e){let t=ve(n),r=ve(e);if(!t)throw new Error(`not a version: ${n}`);if(!r)throw new Error(`not a version: ${e}`);for(let i of["major","minor","patch"]){let s=t[i]-r[i];if(s!==0)return s<0?-1:1}let o=Pa(t.prerelease,r.prerelease);return o===0?0:o<0?-1:1}function Tn(n,e){let t=ve(n),r=ve(e);return!t||!r?!1:Xt(n,e)<0}function wn(n,e){let t=ve(n),r=ve(e);return!t||!r?!1:t.major===r.major}import Cn from"lodash/get.js";import Fa from"lodash/isObject.js";import Zt from"lodash/isString.js";function K(n){if(n instanceof Error)return n.message;let e=Cn(n,"message");return Zt(e)?e:String(n)}function me(n){if(!Fa(n))return;let e=Cn(n,"code");return Zt(e)?e:void 0}function ne(n){return Zt(me(n))&&Zt(Cn(n,"message"))}function j(n,e={}){return{code:me(n)??e.code??"INTERNAL",message:K(n)||e.message||"An unexpected error occurred."}}import La from"lodash/isBoolean.js";import Zo from"lodash/isFinite.js";import Ma from"lodash/isInteger.js";import ri from"lodash/isPlainObject.js";import ei from"lodash/isString.js";import xn from"lodash/isUndefined.js";import $a from"lodash/omit.js";import Ua from"lodash/omitBy.js";import Ba from"lodash/toNumber.js";var Ka=/^[+-]?(\d+\.?\d*|\.\d+)([eE][+-]?\d+)?$/;function ti(n){return ri(n)?n:{}}var er=class{_found;constructor(e){this._found=e}exists(){return!xn(this._found)}unknown(){return this._found}string(){return ei(this._found)?this._found:null}number(){if(Zo(this._found))return this._found;if(!ei(this._found)||!Ka.test(this._found.trim()))return null;let e=Ba(this._found);return Zo(e)?e:null}integer(){let e=this.number();return e!==null&&Ma(e)?e:null}boolean(){return La(this._found)?this._found:this._found==="true"?!0:this._found==="false"?!1:null}object(){return ri(this._found)?this._found:null}list(){return Array.isArray(this._found)?this._found:null}},tr=class n{_value;constructor(e){this._value=ti(e)}set(e,t){return xn(t)?this:new n({...this._value,[e]:t})}merge(e){return new n({...this._value,...Ua(ti(e),xn)})}drop(e){return new n($a(this._value,e))}has(e){return e in this._value}property(e){return new er(this._value[e])}string(e){return this.property(e).string()}value(){return this._value}toJSON(){return this._value}};function An(n){return new tr(n)}import ja from"lodash/isUndefined.js";import Va from"lodash/omitBy.js";function Dn(n){return Va(n,ja)}import Dc from"lodash/isPlainObject.js";import Ye from"lodash/isString.js";import le from"lodash/trim.js";var Rf=Math.ceil(300),ni=[4011,4013,4014,4016,4017,4018];var U={FILE_POLICIES:"file_policies",CONTEXT_V2:"context_v2",QUIESCE_V2:"quiesce.v2",TELEMETRY_RELAY_V1:"telemetry.relay.v1",ENDPOINT_DISCOVERY_V1:"endpoint.discovery.v1",RESULT_REDELIVERY_V1:"result.redelivery.v1"},oi=[U.FILE_POLICIES,U.CONTEXT_V2,U.QUIESCE_V2,U.TELEMETRY_RELAY_V1,U.ENDPOINT_DISCOVERY_V1,U.RESULT_REDELIVERY_V1],wf=[U.FILE_POLICIES,U.CONTEXT_V2,U.QUIESCE_V2],Cf=[U.FILE_POLICIES,U.CONTEXT_V2,U.QUIESCE_V2,U.TELEMETRY_RELAY_V1,U.ENDPOINT_DISCOVERY_V1,U.RESULT_REDELIVERY_V1];function Je(n,e){return!!n&&n.includes(e)}var qa=["Chrome","Edge","Brave","Opera"],Af=qa.join(", ");import{z as l}from"zod";var Wa=l.object({name:l.string().min(1),description:l.string().optional(),inputSchema:l.any().optional(),outputSchema:l.any().optional(),defaults:l.record(l.string(),l.unknown()).optional(),version:l.string().optional(),errorCodes:l.array(l.string()).optional()}),Ha=l.object({id:l.string().min(1),name:l.string().min(1),path:l.string().optional(),path_hint:l.string().optional(),policy:l.any().optional()});var Ga=["USE_NEW","KEEP_OLD"];var ii=["SESSION_REPLACED","SERVER_DRAINING","REBALANCE","ENDPOINT_MOVED"],ze=l.object({code:l.string().min(1),message:l.string().min(1)}).passthrough(),Ja=l.object({type:l.literal("connect"),device_id:l.string().min(1),agent_version:l.string().min(1),protocol_version:l.number().int().min(1).default(2),capabilities:l.array(l.string()).default([]),platform:l.string().optional(),hostname:l.string().optional(),device_tag:l.string().optional(),ts:l.number(),nonce:l.string().min(8),sig:l.string().min(16),access_token:l.string().optional(),refresh_token:l.string().min(20).optional(),public_key_pem:l.string().optional()}).passthrough(),za=l.object({type:l.literal("connect_ack"),ok:l.literal(!0),session_id:l.string().min(1),device_id:l.string().min(1),server_time:l.number(),auth:l.object({device_proof:l.string().min(1),access_token:l.string().min(1)}).passthrough(),next:l.array(l.string().min(1)).min(1),workspace_id:l.string().optional()}).passthrough(),Ya=l.object({type:l.literal("connect_ack"),ok:l.literal(!1),session_id:l.string().optional(),server_time:l.number(),error:ze}).passthrough(),Qa=l.union([za,Ya]),Xa=l.object({type:l.literal("refresh_access_token"),device_id:l.string().min(1),ts:l.number(),nonce:l.string().min(8),refresh_token:l.string().min(20),sig:l.string().min(16),session_id:l.string().min(1).optional()}).strict(),Za=l.object({type:l.literal("refresh_access_token_ack"),ok:l.literal(!0),access_token:l.string().min(1),refresh_token:l.string().min(20),expires_in_sec:l.number().int().positive().optional(),next:l.array(l.string().min(1)).default(["session_init"])}).passthrough(),ec=l.object({type:l.literal("refresh_access_token_ack"),ok:l.literal(!1),error:ze}).passthrough(),tc=l.union([Za,ec]),rc=l.object({type:l.literal("session_init"),device_id:l.string().min(1),session_id:l.string().min(1)}).strict(),nc=l.object({type:l.literal("session_init_ack"),ok:l.literal(!0),device_id:l.string().min(1),session_id:l.string().min(1),mode:l.string().min(1),reason:l.string().optional(),server_time:l.number(),next:l.array(l.string().min(1)).optional(),analytics_session_id:l.string().uuid().optional(),capabilities:l.array(l.string()).optional(),server_protocol_version:l.number().default(2),min_agent_version:l.string().optional(),target_agent_version:l.string().optional(),update_policy:l.string().min(1).optional(),upgrade_message:l.string().optional(),upgrade_url:l.string().optional()}).passthrough(),oc=l.object({type:l.literal("session_init_ack"),ok:l.literal(!1),device_id:l.string().min(1),server_time:l.number(),error:ze,min_agent_version:l.string().optional(),target_agent_version:l.string().optional(),update_policy:l.string().min(1).optional(),upgrade_message:l.string().optional(),upgrade_url:l.string().optional()}).passthrough(),ic=l.union([nc,oc]),sc=l.object({type:l.literal("session_conflict"),device_id:l.string().min(1),new_session_id:l.string().min(1),max_sessions:l.number().int().positive(),active_count:l.number().int().nonnegative(),deadline_ms:l.number().int().positive(),message:l.string().min(1),choices:l.array(l.object({id:l.string().min(1),default:l.boolean().optional(),prompt:l.string().optional()}).passthrough()).min(1)}).passthrough(),ac=l.object({type:l.literal("session_conflict_resolve"),device_id:l.string().min(1),new_session_id:l.string().min(1),choice:l.enum(Ga)}).strict(),cc=l.object({type:l.literal("session_conflict_resolve_ack"),ok:l.literal(!0),device_id:l.string().min(1),choice:l.string().min(1),next:l.array(l.string().min(1)).optional()}).passthrough(),lc=l.object({type:l.literal("session_conflict_resolve_ack"),ok:l.literal(!1),device_id:l.string().min(1),error:ze}).passthrough(),uc=l.union([cc,lc]),dc=l.object({after_ms:l.number().optional(),url:l.string().optional(),discover:l.boolean().optional()}).passthrough(),pc=l.object({type:l.literal("quiesce"),session_id:l.string().min(1),reason:l.string().min(1),deadline_ms:l.number().int().positive(),reconnect:dc.optional()}).passthrough(),fc=l.object({type:l.literal("quiesce_ack"),session_id:l.string().min(1),status:l.enum(["IDLE","BUSY"])}).strict(),In=1,On=20;var mc=l.object({kind:l.string().min(1),severity:l.string().min(1).optional(),at:l.number().optional(),props:l.record(l.string(),l.unknown()).optional()}).strict(),hc=l.object({type:l.literal("agent_event"),schema_version:l.number().int().optional(),events:l.array(mc)}).strict(),gc=l.object({type:l.literal("tools_publish"),device_id:l.string().min(1),workspace_id:l.string().optional(),tools:l.array(Wa).default([]),tools_version:l.string().optional()}).strict(),yc=l.object({type:l.literal("tools_publish_ack"),ok:l.boolean(),device_id:l.string().min(1),tools_version:l.string().optional(),error:ze.optional()}).passthrough(),bc=l.object({type:l.literal("directories_publish"),device_id:l.string().min(1),workspace_id:l.string().optional(),directories:l.array(Ha).default([])}).strict(),vc=l.object({type:l.literal("directories_publish_ack"),ok:l.boolean(),device_id:l.string().min(1),error:ze.optional()}).passthrough(),Sc=l.object({blocked_extensions:l.array(l.string()).default([]),allowed_extensions:l.array(l.string()).default([]),blocked_patterns:l.array(l.string()).default([]),max_file_size_bytes:l.number().default(10485760)}).passthrough(),Nn=l.object({workspace_id:l.string(),organization_id:l.string(),workspace_name:l.string().optional(),user_id:l.string(),user_email:l.string().optional(),connector:l.string().optional(),connector_policies:l.object({max_response_chars:l.number(),timeout_ms:l.number()}).passthrough().optional(),file_policies:Sc.optional()}).passthrough(),rr=l.object({type:l.literal("tool_call"),job_id:l.string().min(1),device_id:l.string().min(1).optional(),workspace_id:l.string().optional(),tool:l.string().min(1),args:l.record(l.string(),l.unknown()).default({}),context:Nn.optional()}).passthrough(),Ec=l.object({type:l.enum(["error","warning","info"]),description:l.string().min(1)}),nr=l.object({type:l.literal("tool_result"),job_id:l.string().min(1),tool:l.string().min(1),ok:l.boolean(),result:l.unknown().optional(),error:l.unknown().optional(),messages:l.array(Ec).optional(),timing:l.object({execution_ms:l.number(),execution_sec:l.number()}).optional()}).strict().superRefine((n,e)=>{n.ok&&n.result===void 0&&e.addIssue({code:l.ZodIssueCode.custom,message:"tool_result ok=true should include result",path:["result"]}),!n.ok&&n.error===void 0&&e.addIssue({code:l.ZodIssueCode.custom,message:"tool_result ok=false should include error",path:["error"]})}),si=l.object({type:l.literal("disconnect_notice"),code:l.number().int(),reason:l.string(),at:l.number()}).passthrough(),ai=l.object({type:l.literal("promoted_active"),workspaceId:l.string().min(1)}).passthrough(),ci=l.object({type:l.literal("demoted_standby"),workspaceId:l.string().min(1)}).passthrough(),Of=l.union([Ja,Xa,rc,ac,gc,bc,rr,nr,fc,hc,si,ai,ci]),li=l.union([Qa,tc,ic,sc,uc,yc,vc,rr,pc,si,ai,ci]),_c=["connect_ack","refresh_access_token_ack","session_init_ack","session_conflict","session_conflict_resolve_ack","tools_publish_ack","directories_publish_ack","tool_call","quiesce","disconnect_notice","promoted_active","demoted_standby"];function or(n){if(typeof n!="object"||n===null)return;let e=n.type;return typeof e=="string"?e:void 0}function ui(n){return n===void 0?!1:_c.includes(n)}import{z as y}from"zod";import{z as ce}from"zod";var kc=ce.object({url:ce.string().optional()}).passthrough(),Rc=ce.object({urls:ce.array(ce.string()).optional()}).passthrough(),ir=ce.object({schema:ce.number().int().optional(),issued_at:ce.number().int().optional(),control:kc.optional(),bridge:Rc.optional(),ttl_seconds:ce.number().optional(),capabilities:ce.array(ce.string()).optional(),notice:ce.string().nullable().optional()}).passthrough(),fi="/.well-known/devicelink-endpoints",di=300,pi=86400;function mi(n){if(typeof n!="number"||!Number.isFinite(n))return 3600;let t=Math.floor(n);return t<di?di:t>pi?pi:t}var sr=["agent","browser"];var Tc=y.object({device_id:y.string().optional(),device_name:y.string().optional(),kind:y.enum(sr).default("agent"),platform:y.string().optional(),agent_version:y.string().optional(),public_key_pem:y.string().min(1)}),Bf=y.object({device_code:y.string(),user_code:y.string(),verification_uri:y.string(),verification_uri_complete:y.string(),expires_in:y.number(),interval:y.number(),challenge_id:y.string(),challenge:y.string()}),Kf=Tc.extend({enrollment_jws:y.string().min(1)}),jf=y.union([y.object({status:y.literal("pending"),needs_proof:y.boolean()}),y.object({status:y.literal("approved"),needs_proof:y.boolean()}),y.object({error:y.literal("access_denied")}),y.object({error:y.literal("expired_token")})]),Vf=y.object({device_code:y.string(),challenge_id:y.string(),challenge:y.string(),signature_b64:y.string()}),qf=y.object({ok:y.literal(!0)}),Wf=y.object({device_code:y.string(),install_id:y.string().min(8).max(64).optional()}),Hf=y.object({access_token:y.string(),refresh_token:y.string(),token_type:y.literal("Bearer"),expires_in:y.number(),device_id:y.string(),endpoints:ir.optional()}),Gf=y.object({device_id:y.string().min(1),refresh_token:y.string().min(1),ts:y.number().int(),nonce:y.string().min(8),sig:y.string().min(16)}),wc=y.object({ok:y.literal(!0),access_token:y.string().min(10),refresh_token:y.string().min(10),expires_in_sec:y.number().int().positive(),device_id:y.string().min(1)}),Cc=y.object({ok:y.literal(!1),error:y.object({code:y.string(),message:y.string(),drift_ms:y.number().optional()})}),Jf=y.union([wc,Cc]),zf=y.object({device_id:y.string().min(1),refresh_token:y.string().min(1),ts:y.number().int(),nonce:y.string().min(8),sig:y.string().min(16)}),Yf=y.union([y.object({ok:y.literal(!0),device_id:y.string().min(1),state:y.string()}),y.object({ok:y.literal(!1),error:y.object({code:y.string(),message:y.string(),drift_ms:y.number().optional()})})]);import{z as w}from"zod";var xc=w.object({code:w.string().min(1),message:w.string(),hint:w.string().optional()}),Ac=w.object({execution_ms:w.number().optional(),execution_sec:w.number().optional()}),nm=w.object({v:w.literal(1),dispatch_id:w.string().min(1),request_id:w.string().min(1),device_id:w.string().min(1),workspace_id:w.string().min(1),user_id:w.string().min(1),tool:w.string().min(1),args:w.record(w.string(),w.unknown()).default({}),context:Nn.optional()}).passthrough(),om=w.object({v:w.literal(1),dispatch_id:w.string().min(1),request_id:w.string().min(1),device_id:w.string().min(1),workspace_id:w.string().min(1),instance_id:w.string().optional(),ok:w.boolean(),result:w.unknown().optional(),error:xc.optional(),timing:Ac.optional()}).passthrough().superRefine((n,e)=>{n.ok===!1&&!n.error&&e.addIssue({code:w.ZodIssueCode.custom,path:["error"],message:"A failed dispatch reply must name an error"})});var im=w.object({v:w.literal(1),session_id:w.string().min(1),user_id:w.string().min(1),workspace_id:w.string().min(1),reason:w.string().min(1),deadline_ms:w.number().int().positive(),replaced_by_session_id:w.string().min(1).optional(),requested_by_instance:w.string().min(1).optional()}).passthrough();import{z as Fn}from"zod";var lm=Fn.object({enabledKinds:Fn.array(Fn.enum(sr))});function hi(n){return{ok:!0,data:n}}function Ue(n){return{ok:!1,error:n}}var Ln={PENDING:"PENDING",APPLIED:"APPLIED",FAILED:"FAILED",VOID:"VOID"};var Am=[Ln.APPLIED,Ln.FAILED,Ln.VOID];var Mn=[{name:"dl_ping",version:"1.0",description:"Liveness probe. Answers with the agent version, platform and a timestamp without reading any file. Needs no shared folder and charges no credit.",inputSchema:{type:"object",properties:{echo:{type:"string",maxLength:64}},required:[]},errorCodes:["INTERNAL"]},{name:"fs_list",version:"1.0",description:"List files and folders at a relative path inside a shared folder.",inputSchema:{type:"object",properties:{directory_id:{type:"string",minLength:1},path:{type:"string",default:"."},limit:{type:"integer",minimum:1,maximum:1e3,default:200},offset:{type:"integer",minimum:0,default:0},include_hidden:{type:"boolean",default:!1},only:{type:"string",enum:["all","files","dirs"],default:"all"},sort:{type:"string",enum:["name","mtime","size"],default:"name"},order:{type:"string",enum:["asc","desc"],default:"asc"},detail:{type:"string",enum:["basic","stat","digest"],default:"stat"}},required:["path"]},errorCodes:["PATH_ESCAPE","NOT_FOUND","NOT_A_DIRECTORY","INVALID_INPUT","INTERNAL","UNKNOWN_DIRECTORY"]},{name:"fs_read",version:"1.0",description:"Read the contents of a SINGLE text file inside a shared folder. For reading many files at once, prefer fs_read_many instead of multiple fs_read calls.",inputSchema:{type:"object",properties:{directory_id:{type:"string",minLength:1},path:{type:"string",minLength:1},offset:{type:"integer",minimum:0,default:0},limit:{type:"integer",minimum:1,maximum:2e5,default:4e4},encoding:{type:"string",default:"utf-8"}},required:["path"]},errorCodes:["PATH_ESCAPE","NOT_FOUND","NOT_A_FILE","PERMISSION_DENIED","INVALID_INPUT","INTERNAL","UNKNOWN_DIRECTORY"]},{name:"fs_info",version:"1.0",description:"Get metadata about a file or directory (type, size, timestamps, symlink).",inputSchema:{type:"object",properties:{directory_id:{type:"string",minLength:1},path:{type:"string",minLength:1}},required:["path"]},errorCodes:["PATH_ESCAPE","NOT_FOUND","PERMISSION_DENIED","INVALID_INPUT","INTERNAL","UNKNOWN_DIRECTORY"]},{name:"fs_tree",version:"1.0",description:"Return a directory tree from a relative path up to max_depth.",inputSchema:{type:"object",properties:{directory_id:{type:"string",minLength:1},path:{type:"string",default:"."},max_depth:{type:"integer",minimum:1,maximum:20,default:3},max_entries:{type:"integer",minimum:1,maximum:2e4,default:5e3},include_hidden:{type:"boolean",default:!1},only:{type:"string",enum:["all","files","dirs"],default:"all"},detail:{type:"string",enum:["basic","stat","digest"],default:"stat"},include_display:{type:"boolean",default:!1},max_display_rows:{type:"integer",minimum:1,maximum:2e4,default:2e3}},required:["path"]},errorCodes:["PATH_ESCAPE","NOT_FOUND","NOT_A_DIRECTORY","INVALID_INPUT","INTERNAL","UNKNOWN_DIRECTORY"]},{name:"fs_search",version:"1.0",description:"Search for files/folders by name inside a root, optionally recursively.",inputSchema:{type:"object",properties:{directory_id:{type:"string",minLength:1},path:{type:"string",default:"."},query:{type:"string",minLength:1},mode:{type:"string",enum:["substring","glob"],default:"substring"},recursive:{type:"boolean",default:!0},include_hidden:{type:"boolean",default:!1},only:{type:"string",enum:["all","files","dirs"],default:"all"},max_results:{type:"integer",minimum:1,maximum:2e4,default:200}},required:["query"]},errorCodes:["PATH_ESCAPE","NOT_FOUND","INVALID_INPUT","INTERNAL","UNKNOWN_DIRECTORY"]},{name:"fs_grep",version:"1.0",description:"Search for text content inside files (like grep/ripgrep).",inputSchema:{type:"object",properties:{directory_id:{type:"string",minLength:1},path:{type:"string",default:"."},query:{type:"string",minLength:1},mode:{type:"string",enum:["substring","regex"],default:"substring"},file_glob:{type:"string"},max_files:{type:"integer",minimum:1,maximum:1e4,default:2e3},max_matches:{type:"integer",minimum:1,maximum:1e3,default:200},context_lines:{type:"integer",minimum:0,maximum:10,default:2},case_sensitive:{type:"boolean",default:!1}},required:["query"]},errorCodes:["PATH_ESCAPE","NOT_FOUND","NOT_A_DIRECTORY","INVALID_INPUT","INTERNAL"]},{name:"fs_read_many",version:"1.0",description:"Read multiple files in a single call (batch read). Prefer this over multiple fs_read calls when you need to read several files\u2014fewer round-trips and better performance (up to 50 items per call).",inputSchema:{type:"object",properties:{directory_id:{type:"string",minLength:1},items:{type:"array",minItems:1,maxItems:50,items:{type:"object",properties:{path:{type:"string",minLength:1},offset:{type:"integer",minimum:0,default:0},limit:{type:"integer",minimum:1,maximum:2e5},encoding:{type:"string"}},required:["path"]}},default_limit:{type:"integer",minimum:1,maximum:2e5,default:12e3},default_encoding:{type:"string",default:"utf-8"}},required:["items"]},errorCodes:["PATH_ESCAPE","NOT_FOUND","NOT_A_FILE","INVALID_INPUT","INTERNAL"]}];var Ic=2e3,$n=2;function Un(){return Math.floor(Date.now()/1e3)}function gi(n=process.env){let e=le(n.DEVICELINK_ENV??"");return e!=="production"&&e!=="staging"}function ar(n,e=process.env){if(!Ye(n))return!1;let t=le(n);return t===""?!1:/^wss:\/\/.+/.test(t)?!0:gi(e)&&/^ws:\/\/.+/.test(t)}function yi(n){if(!Ye(n))return!1;let e=le(n);return/^https:\/\/.+/.test(e)?!0:gi()&&/^http:\/\/.+/.test(e)}function Bn(n){let e=ir.safeParse(n);return e.success?e.data:null}function Kn(n,e,t=Un(),r=process.env){if(!n)return null;let o=(n.bridge?.urls??[]).filter(c=>ar(c,r)).map(c=>le(c)),i=yi(n.control?.url)?le(String(n.control?.url)):void 0,s=mi(n.ttl_seconds),a={expiresAt:t+s,source:e};return typeof n.schema=="number"&&(a.schema=n.schema),typeof n.issued_at=="number"&&(a.issuedAt=n.issued_at),o.length>0&&(a.bridgeUrls=o),i&&(a.controlUrl=i),n.capabilities&&n.capabilities.length>0&&(a.capabilities=n.capabilities.filter(Ye)),Ye(n.notice)&&le(n.notice)!==""&&(a.notice=le(n.notice)),!a.bridgeUrls&&!a.controlUrl&&!a.notice?null:a}function bi(n){if(!Dc(n))return null;let e=n,t=e.expiresAt;if(typeof t!="number"||!Number.isFinite(t))return null;let r={expiresAt:t};typeof e.schema=="number"&&(r.schema=e.schema),typeof e.issuedAt=="number"&&(r.issuedAt=e.issuedAt);let o=e.bridgeUrls;if(Array.isArray(o)){let a=o.filter(c=>ar(c)).map(c=>le(String(c)));a.length>0&&(r.bridgeUrls=a)}yi(e.controlUrl)&&(r.controlUrl=le(String(e.controlUrl)));let i=e.capabilities;Array.isArray(i)&&(r.capabilities=i.filter(Ye)),Ye(e.notice)&&le(e.notice)!==""&&(r.notice=le(e.notice));let s=e.source;return(s==="well_known"||s==="token")&&(r.source=s),!r.bridgeUrls&&!r.controlUrl&&!r.notice?null:r}function jn(n,e=Un()){return!!n&&n.expiresAt>e}function vi(n,e){if(!n)return e??null;if(!e)return n;let t=n.issuedAt??-1;return(e.issuedAt??-1)>t?e:n}function Si(n,e=Un()){if(jn(n,e))return n?.bridgeUrls?.[0]}function Oc(n){return`${n.replace(/\/+$/,"")}${fi}`}async function Ei(n,e=Ic){if(!n||le(n)==="")return null;let t=new AbortController,r=setTimeout(()=>t.abort(),e);r.unref?.();try{let o=await fetch(Oc(n),{method:"GET",headers:{accept:"application/json"},signal:t.signal});return o.ok?Bn(await o.json()):null}catch{return null}finally{clearTimeout(r)}}var Qe={version:1,controlBaseUrl:"",bridgeWsUrl:"",directories:[],device:void 0},ur=class{_notifier;argv;config=Qe;envFile=Vn.config({quiet:!0});processEnv={};productionEnv={};configFileContent={};_privateKeyCache=void 0;_privateKeyToStore=void 0;_discovery=null;_bridgeEndpointSource=void 0;constructor(e){this._notifier=e,this.loadProductionEnv()}loadProductionEnv(){let e=[Be.resolve(Be.dirname(process.argv[1]??"."),".env.production"),Be.resolve(process.cwd(),".env.production")];for(let t of e)try{if(cr.existsSync(t)){this.productionEnv=Vn.parse(cr.readFileSync(t));return}}catch{}}setPrivateKeyCache(e){this._privateKeyCache=e}getPrivateKeyToStore(){return this._privateKeyToStore}withDiscoveryCache(e){return this._discovery=e??bi(this.safeGetConfigValue("discovery")),this}getDiscoveryCache(){return this._discovery}getBridgeEndpointSource(){return this._bridgeEndpointSource}getBundledBridgeWsUrl(){return this.firstSet(this.productionEnv.DLINK_BRIDGE_URL)}withDefaultConfig(){return this.config.version=Qe.version,this.config.controlBaseUrl=Qe.controlBaseUrl,this.config.bridgeWsUrl=Qe.bridgeWsUrl,this.config.directories=Qe.directories,this.config.device=Qe.device,this}withProcessEnv(){return this.processEnv={NODE_ENV:process.env.NODE_ENV,APPDATA:process.env.APPDATA,npm_package_version:process.env.npm_package_version,DLINK_DEVICE_ID:process.env.DLINK_DEVICE_ID,DLINK_DEVICE_NAME:process.env.DLINK_DEVICE_NAME,DLINK_DEVICE_TAG:process.env.DLINK_DEVICE_TAG,DLINK_CONTROL_URL:process.env.DLINK_CONTROL_URL,DLINK_BRIDGE_URL:process.env.DLINK_BRIDGE_URL,DLINK_DIRECTORIES:process.env.DLINK_DIRECTORIES},this}withArgv(e){return this.argv=e,this}withEnviromentFile(e){return this.envFile=Vn.config({path:e,quiet:!0}),this}withConfigFile(e){try{let t=this.getApplicationConfigFolder(),r=Be.join(t,e);if(cr.existsSync(r)){let o=cr.readFileSync(r,"utf8"),i=JSON.parse(o);qn(i)&&!lr(i)?this.configFileContent=i:this._notifier.warn(`Config file ${e} does not contain a valid object`,{scope:"system"})}}catch(t){let r=t instanceof Error?t.message:String(t);this._notifier.warn(`Failed to load config file ${e}: ${r}`,{scope:"system"})}return this}build(){return this.config.controlBaseUrl=this.getControlBaseUrl(),this.config.bridgeWsUrl=this.getBridgeWsUrl(),this.config.discovery=this._discovery??void 0,this.config.directories=this.getDirectories(),this.config.device=this.getDevice(),this.config.tokens=this.getTokens(),this.config}getConfigValue(e,t){let r=this.safeGetConfigValue(e);return r===void 0?t?.defaultValue:r}firstSet(...e){return e.find(t=>t!=null&&String(t).trim()!=="")}getControlBaseUrl(){return this.firstSet(this.argv?.controlUrl,this.safeGetEnvValue("DLINK_CONTROL_URL"),this.safeGetConfigValue("controlBaseUrl"),this.processEnv.DLINK_CONTROL_URL,this.productionEnv.DLINK_CONTROL_URL)}resolveBridgeWsUrl(e=this._discovery){let t=[["argv",this.argv?.bridgeWsUrl],["env-file",this.safeGetEnvValue("DLINK_BRIDGE_URL")],["process-env",this.processEnv.DLINK_BRIDGE_URL],["discovered",Si(e)],["config-file",this.safeGetConfigValue("bridgeWsUrl")],["bundled",this.productionEnv.DLINK_BRIDGE_URL]];for(let[r,o]of t){let i=this.firstSet(o);if(i)return{url:i,source:r}}return{url:void 0,source:void 0}}getBridgeWsUrl(){let{url:e,source:t}=this.resolveBridgeWsUrl(this._discovery);return this._bridgeEndpointSource=t,e}getDirectories(){let e=[];if(e.push(this.createDirectoryFromPath(process.cwd())),this.argv?.rootPath)try{e.push(...this.parseDirectoriesFromString(this.argv.rootPath))}catch{e.push(this.createDirectoryFromPath(this.argv.rootPath))}let t=this.safeGetEnvValue("DLINK_DIRECTORIES")??this.safeGetEnvValue("DLINK_ROOTS");if(t)try{e.push(...this.parseDirectoriesFromString(t))}catch{}let r=this.safeGetConfigValue("directories")??this.safeGetConfigValue("roots");if(r)try{e.push(...this.parseDirectoriesFromValue(r))}catch{}let o=this.processEnv.DLINK_DIRECTORIES??this.processEnv.DLINK_ROOTS;if(o)try{e.push(...this.parseDirectoriesFromString(o))}catch{}return this.deduplicateDirectories(e)}deduplicateDirectories(e){let t=new Set,r=[];for(let o of e){let i=yn(o.path);t.has(i)||(t.add(i),r.push(o))}return r}getDevice(){let e=this.getDeviceId();if(!e){this._notifier.warn("No device ID found from any source (argv, env, config, process env, or machine ID)",{scope:"system"});return}let t=this.getDeviceName();t||(t=_i.hostname()||"Unknown Device");let r=this.getDeviceTag(),o=new zt({notifier:this._notifier,argv:this.argv,envFile:this.envFile,processEnv:this.processEnv,configFileContent:this.configFileContent,getPrivateKey:()=>this._privateKeyCache}),{publicKey:i}=o.ensureDeviceKeys();this._privateKeyToStore=o.getLastGeneratedPrivateKey();let s={id:e,name:t,tag:r||"",keys:{public:i}};return this._notifier.info(`Created device: id=${s.id?.substring(0,8)}..., name=${s.name}, tag=${s.tag||"(empty)"}`,{scope:"system"}),s}getDeviceId(){this._notifier.info("Checking env file for DLINK_DEVICE_ID...",{scope:"system"});let e=this.safeGetEnvValue("DLINK_DEVICE_ID");if(e&&!Ce(e))return this._notifier.info(`Found device ID in env file: ${e.substring(0,8)}...`,{scope:"system"}),e;this._notifier.info("Checking config file for deviceId...",{scope:"system"});let t=this.safeGetConfigValue("deviceId")??we(this.safeGetConfigValue("device"),"id");if(t&&!Ce(String(t)))return this._notifier.info(`Found device ID in config file: ${String(t).substring(0,8)}...`,{scope:"system"}),String(t);this._notifier.info("Checking process env for DLINK_DEVICE_ID...",{scope:"system"});let r=this.processEnv.DLINK_DEVICE_ID;if(r&&!Ce(r))return this._notifier.info(`Found device ID in process env: ${r.substring(0,8)}...`,{scope:"system"}),r;this._notifier.info("Trying machine ID as fallback...",{scope:"system"});let o=Jt(!0);if(o)return this._notifier.info(`Using machine ID: ${o.substring(0,8)}...`,{scope:"system"}),o;this._notifier.error("Failed to get machine ID in getDeviceId()",{scope:"system"}),this._notifier.warn("No device ID found in any source",{scope:"system"})}getDeviceName(){let e=this.safeGetEnvValue("DLINK_DEVICE_NAME");if(e&&!Ce(e))return e;let t=we(this.safeGetConfigValue("device"),"name");if(t&&!Ce(String(t)))return String(t);let r=this.processEnv.DLINK_DEVICE_NAME;if(r&&!Ce(r))return r;let o=_i.hostname();if(o&&!Ce(o))return o}getDeviceTag(){let e=this.safeGetEnvValue("DLINK_DEVICE_TAG");if(e)return e;let t=we(this.safeGetConfigValue("device"),"tag");if(t)return String(t);let r=this.processEnv.DLINK_DEVICE_TAG;if(r)return r}getTokens(){let e=this.safeGetConfigValue("tokens");if(!e||!qn(e)||lr(e))return;let t=e,r={},o=we(t,"accessTokenExpSec");if(typeof o=="number"&&(r.accessTokenExpSec=o),r.accessTokenExpSec!==void 0)return r}safeGetEnvValue(e){try{return we(this.envFile,`parsed.${e}`)}catch{return}}safeGetConfigValue(e){try{return we(this.configFileContent,e)}catch{return}}parseDirectoriesFromString(e){try{let t=JSON.parse(e);return this.parseDirectoriesFromValue(t)}catch{return[this.createDirectoryFromPath(e)]}}parseDirectoriesFromValue(e){if(lr(e))return e.map(r=>this.parseDirectoryFromValue(r)).filter(r=>r!==null);if(ki(e))return[this.createDirectoryFromPath(e)];let t=this.parseDirectoryFromValue(e);return t?[t]:[]}parseDirectoryFromValue(e){if(ki(e))return this.createDirectoryFromPath(e);if(qn(e)&&!lr(e)){let t=e,r=yt(we(t,"path")),o=we(t,"path"),i=Nc(we(t,"name"),o?Be.basename(o):"");if(!Ce(r)&&!Ce(o)){let s=gt(o);return{id:String(r),name:String(i),path:String(o),tag:s}}}return null}createDirectoryFromPath(e){let t=Be.resolve(e),r=yt(t),o=Be.basename(t),i=gt(t);return{id:r,name:o,path:t,tag:i}}getApplicationConfigFolder(){return Z()}};var ft=class{dedupeKey;parentId;overridePriority;overrideLane;constructor(e,t,r,o){this.dedupeKey=e,this.parentId=t,this.overridePriority=r,this.overrideLane=o}},Wn=class{phase;flags;constructor(e){this.phase="idle",this.flags=e??new Ae(!1)}},dr=class{argv;configurationContext;bus;notifier;logger;storage;secrets;secretsReport;runtime;lanes;laneActive;registry;orchestrators;orchestratorSubscriptions=new Map;orchestratorAbort;jobs;queue;locksHeldBy;completions;dedupeIndex;engineAbort;jobAbort;stopping;running;wakeFn;wakePromise;constructor(e){this.argv=e.argv,this.bus=e.bus,this.logger=e.logger,this.notifier=e.notifier,this.storage=e.storage,this.secrets=e.secrets,this.secretsReport=e.secretsReport,this.runtime=new Wn(e.flags),this.lanes=new Map;for(let o of e.lanes)this.lanes.set(o.name,o);this.laneActive=new Map;for(let o of e.lanes)this.laneActive.set(o.name,0);this.registry=new Map,this.orchestrators=[],this.orchestratorAbort=new AbortController,this.jobs=new Map,this.queue=[],this.locksHeldBy=new Map,this.completions=new Map,this.dedupeIndex=new Map,this.engineAbort=new AbortController,this.jobAbort=new Map,this.stopping=!1,this.running=!1,this.wakeFn=null,this.wakePromise=this.resetWake();let t=new Ht,r=new ur(this.notifier);this.configurationContext=new Gt(t,r)}applyConfiguration(e){this.configurationContext.apply(e)}setPhase(e){this.runtime.phase=e}getBus(){return this.bus}hasRunningJobs(){for(let[,e]of this.laneActive)if(e>0)return!0;return!1}register(e){let t=e.options.name;if(this.registry.has(t))throw new Error(`JobType already registered: ${t}`);this.registry.set(t,e)}registerOrchestrator(e){if(this.orchestrators.some(o=>o.name===e.name))throw new Error(`Orchestrator already registered: ${e.name}`);let r=new Ge({engine:this,bus:this.bus,logger:this.logger,notifier:this.notifier,flags:this.runtime.flags,signal:this.orchestratorAbort.signal});e.onRegister?.(r),this.setupOrchestratorSubscriptions(e,r),this.orchestrators.push(e)}setupOrchestratorSubscriptions(e,t){let r=e.handlers?.();if(r){let o=[];Object.keys(r).forEach(i=>{let s=r[i];s&&o.push(this.bus.on(i,a=>{Promise.resolve(s(a,t)).catch(c=>{let u=c instanceof Error?c.message:String(c);this.logger.error(`handler error (${e.name}/${String(i)}): ${u}`),this.notifier.error(`handler error (${e.name}/${String(i)}): ${u}`,{scope:"system"})})}))}),this.orchestratorSubscriptions.set(e.name,o)}}async init(){let e=await this.storage.load();for(let[t,r]of Object.entries(e.jobs))this.jobs.set(t,new ht(r));for(let t of this.jobs.values())t.state==="running"&&(t.state="queued",t.nextRunAt=Date.now(),t.updatedAt=Date.now()),t.dedupeKey&&this.dedupeIndex.set(t.dedupeKey,t.id),t.state==="queued"&&this.queue.push(t.id)}async start(){if(!this.running){this.running=!0,this.runtime.phase="running",process.on("uncaughtException",e=>{this.notifier.error(`uncaughtException: ${e.stack?e.stack:String(e)}`,{scope:"system"}),this.bus.emit("engine:crashed",{reason:"uncaughtException",detail:e instanceof Error?`${e.name}: ${e.message}`:String(e)}),this.requestStop("uncaughtException")}),process.on("unhandledRejection",e=>{this.notifier.error(`unhandledRejection: ${String(e)}`,{scope:"system"}),this.bus.emit("engine:crashed",{reason:"unhandledRejection",detail:String(e)})}),this.bus.emit("engine:started",Date.now());try{await this.startOrchestratorsSafe(),await this.loopGuarded()}finally{await this.stopOrchestratorsSafe(),await this.persist(),this.bus.emit("engine:stopped",Date.now())}}}requestStop(e){if(!this.stopping){this.stopping=!0,this.runtime.phase="stopping",this.bus.emit("engine:stopping",e),this.engineAbort.abort(new Error(`Stopping: ${e}`)),this.orchestratorAbort.abort(new Error(`Stopping: ${e}`));for(let[t,r]of this.jobAbort.entries())this.jobs.get(t)?.cancellable&&r.abort(new Error("Cancelled by user"));this.wake()}}async dispatch(e,t){let r=t||new ft(null,null,null,null),o=e.type.options.name;if(!this.registry.has(o)){let f=new Error(`JobType not registered: ${o}`);return De.failure(f)}if(r.dedupeKey){let f=this.dedupeIndex.get(r.dedupeKey);if(f){let p=this.jobs.get(f);if(p&&(p.state==="queued"||p.state==="running")){let m=this.completions.get(f);if(m)return await m.promise}}}let i=this.newId(),s=new Kt;this.completions.set(i,s);let a=r.overrideLane?r.overrideLane:e.type.options.lane,c=r.overridePriority!==null?r.overridePriority:e.type.options.priority,u=new ht({id:i,jobType:o,inputJson:e.input===void 0?"null":JSON.stringify(e.input),state:"queued",lane:a,priority:c,locks:e.type.options.locks,attempts:0,maxAttempts:e.type.options.maxAttempts,nextRunAt:Date.now(),cancellable:e.type.options.cancellable,parentId:r.parentId,dedupeKey:r.dedupeKey,lastError:null,createdAt:Date.now(),updatedAt:Date.now()});return this.jobs.set(i,u),this.queue.push(i),r.dedupeKey&&this.dedupeIndex.set(r.dedupeKey,i),this.emitJobEvent(u,"queued",null,null),await this.persist(),this.wake(),await s.promise}async loopGuarded(){for(;!this.stopping;)try{await this.loopOnce()}catch(e){this.notifier.error(`Engine loop error: ${String(e)}`,{scope:"system"}),await new Promise(t=>setTimeout(t,250))}}async loopOnce(){let e=0;for(;;){let t=this.pickNextRunnable();if(!t)break;e+=1,this.runJobSafe(t)}e===0&&(await this.wakePromise,this.wakePromise=this.resetWake())}async runJobSafe(e){try{await this.runJobInternal(e)}catch(t){this.notifier.error(`runJobInternal crashed: ${String(t)}`,{scope:"system"});let r=this.completions.get(e);r&&r.resolve(De.failure(new Error(String(t))))}finally{this.wake()}}pickNextRunnable(){let e=Date.now(),t=null,r=Number.NEGATIVE_INFINITY,o=Number.POSITIVE_INFINITY;for(let s of this.queue){let a=this.jobs.get(s);a&&a.state==="queued"&&(this.stopping&&a.lane!=="console"||a.nextRunAt>e||this.canRunInLane(a.lane)&&this.canAcquireLocks(a)&&(a.priority>r||a.priority===r&&a.nextRunAt<o)&&(r=a.priority,o=a.nextRunAt,t=s))}if(!t)return null;let i=this.queue.indexOf(t);return i>=0&&this.queue.splice(i,1),t}canRunInLane(e){let t=this.lanes.get(e);if(!t)return!1;let r=this.laneActive.get(e);return r===void 0?!1:r<t.concurrency}canAcquireLocks(e){for(let t of e.locks){let r=this.locksHeldBy.get(t);if(r&&r!==e.id&&!(e.parentId&&r===e.parentId))return!1}return!0}acquireLocks(e){for(let t of e.locks)this.locksHeldBy.get(t)||this.locksHeldBy.set(t,e.id)}releaseLocks(e){for(let t of e.locks)this.locksHeldBy.get(t)===e.id&&this.locksHeldBy.delete(t)}async runJobInternal(e){let t=this.jobs.get(e);if(!t)return;let r=this.registry.get(t.jobType);if(!r){this.completeFailure(e,new Error(`No registered JobType: ${t.jobType}`));return}let o=this.laneActive.get(t.lane);if(o===void 0){this.completeFailure(e,new Error(`Unknown lane: ${t.lane}`));return}let i=new AbortController;if(this.jobAbort.set(e,i),t.cancellable){let a=this.engineAbort.signal;a.aborted?i.abort(a.reason instanceof Error?a.reason:new Error("Stopped")):a.addEventListener("abort",()=>i.abort(a.reason instanceof Error?a.reason:new Error("Stopped")),{once:!0})}this.laneActive.set(t.lane,o+1),this.acquireLocks(t),t.state="running",t.updatedAt=Date.now(),await this.persist(),this.emitJobEvent(t,"running",null,null);let s=new jt({engine:this,bus:this.bus,logger:this.logger,notifier:this.notifier,flags:this.runtime.flags,signal:i.signal,dispatch:async(a,c)=>this.dispatch(a,c)});try{let a=JSON.parse(t.inputJson),c=a===null?void 0:a,u=await r.run(c,s);t.state="succeeded",t.updatedAt=Date.now(),t.lastError=null,await this.persist(),this.emitJobEvent(t,"succeeded",null,null),this.completeSuccess(e,u)}catch(a){let c=a instanceof Error?a:new Error("Unknown error");if(t.attempts+=1,t.updatedAt=Date.now(),t.lastError=c.message,i.signal.aborted)t.state="failed",await this.persist(),this.emitJobEvent(t,"failed",c.message,null),this.notifier.error(`Job ${t.jobType} (${e.substring(0,8)}) cancelled: ${c.message}`),this.completeCancelled(e,c);else if(t.attempts<t.maxAttempts&&!this.stopping){let f=Fc(t.attempts);t.state="queued",t.nextRunAt=Date.now()+f,await this.persist(),this.queue.push(t.id),this.emitJobEvent(t,"queued",c.message,t.nextRunAt),this.notifier.warn(`Job ${t.jobType} (${e.substring(0,8)}) failed, retrying in ${f}ms (attempt ${t.attempts}/${t.maxAttempts}): ${c.message}`)}else t.state="failed",await this.persist(),this.emitJobEvent(t,"failed",c.message,null),this.notifier.error(`Job ${t.jobType} (${e.substring(0,8)}) failed after ${t.attempts} attempt(s): ${c.message}`),this.completeFailure(e,c)}finally{this.releaseLocks(t);let a=this.laneActive.get(t.lane);a!==void 0&&this.laneActive.set(t.lane,Math.max(0,a-1)),this.jobAbort.delete(e),this.wake()}}async startOrchestratorsSafe(){let e=new Ge({engine:this,bus:this.bus,logger:this.logger,notifier:this.notifier,flags:this.runtime.flags,signal:this.orchestratorAbort.signal});for(let t of this.orchestrators)Promise.resolve().then(()=>t.onStart?.(e)).then(()=>t.onStarted?.(e)).catch(r=>this.notifier.error(`Orchestrator start failed (${t.name}): ${String(r)}`,{scope:"system"}))}async stopOrchestratorsSafe(){let e=new Ge({engine:this,bus:this.bus,logger:this.logger,notifier:this.notifier,flags:this.runtime.flags,signal:this.orchestratorAbort.signal});for(let t=this.orchestrators.length-1;t>=0;t--){let r=this.orchestrators[t];try{await r.onStop?.(e),r.onStopped?.(e)}catch(i){this.notifier.error(`Orchestrator stop failed (${r.name}): ${String(i)}`,{scope:"system"})}let o=this.orchestratorSubscriptions.get(r.name);if(o){for(let i of o)i.unsubscribe();this.orchestratorSubscriptions.delete(r.name)}}}emitJobEvent(e,t,r,o){this.bus.emit("job:event",new qt({ts:Date.now(),jobId:e.id,jobType:e.jobType,state:t,attempt:e.attempts,maxAttempts:e.maxAttempts,lane:e.lane,priority:e.priority,error:r,nextRunAt:o}))}completeSuccess(e,t){let r=this.completions.get(e);r&&r.resolve(De.success(t))}completeFailure(e,t){let r=this.completions.get(e);r&&r.resolve(De.failure(t))}completeCancelled(e,t){let r=this.completions.get(e);r&&r.resolve(De.cancelled(t))}async persist(){let e={};for(let[t,r]of this.jobs.entries())e[t]=r;await this.storage.save(new Le(e))}wake(){this.wakeFn&&this.wakeFn()}resetWake(){return new Promise(e=>{this.wakeFn=e})}newId(){return Pc.randomBytes(8).toString("hex")}};function Fc(n){let r=Math.min(3e4,300*2**(n-1)),o=Math.floor(Math.random()*200);return r+o}var pr=class{handlers;constructor(){this.handlers=new Map}on(e,t){let r=this.handlers.get(e),o=r||[];return o.push(t),this.handlers.set(e,o),{unsubscribe:()=>{let i=this.handlers.get(e);if(!i)return;let s=i.filter(a=>a!==t);this.handlers.set(e,s)}}}emit(e,t){let r=this.handlers.get(e);if(r)for(let o of r)o(t)}};import*as Pi from"node:path";import*as Oe from"node:fs/promises";import*as mr from"node:path";var Ri={DevicePrivateKey:"devicePrivateKey",RefreshToken:"refreshToken"},Ti=[Ri.DevicePrivateKey,Ri.RefreshToken],O={MacosKeychain:"macos-keychain",LinuxSecretService:"linux-secret-service",WindowsDpapi:"windows-dpapi",Passphrase:"passphrase",MachineId:"machine-id-file"},F={WrongPlatform:"wrong_platform",ToolMissing:"tool_missing",NoSessionBus:"no_session_bus",Locked:"locked",Timeout:"timeout",NotConfigured:"not_configured",RoundTripFailed:"round_trip_failed"},N=class extends Error{backend;constructor(e,t){super(t),this.name="SecretsUnreadableError",this.backend=e}};var Lc="secrets.backend",Mc=Object.values(O),fr=class{filePath;platform;constructor(e,t=process.platform){this.filePath=mr.join(e,Lc),this.platform=t}async read(){try{let e=(await Oe.readFile(this.filePath,"utf8")).trim();return Mc.includes(e)?e:void 0}catch{return}}async write(e){try{await Oe.mkdir(mr.dirname(this.filePath),{recursive:!0,mode:448}),await Oe.writeFile(this.filePath,`${e}
4
+ `,{encoding:"utf8",mode:384}),this.platform!=="win32"&&await Oe.chmod(this.filePath,384).catch(()=>{})}catch{return}}};import{spawn as $c}from"node:child_process";var St=5e3,hr=class{run(e,t={}){let r=t.timeoutMs??St;return new Promise(o=>{let i="",s="",a=!1,c=!1,u=$c(e.command,[...e.args],{stdio:["pipe","pipe","pipe"],windowsHide:!0,env:t.env?{...process.env,...t.env}:void 0}),d=setTimeout(()=>{a=!0,u.kill("SIGKILL")},r);d.unref();let f=p=>{c||(c=!0,clearTimeout(d),o(p))};u.stdout?.setEncoding("utf8"),u.stdout?.on("data",p=>{i+=p}),u.stderr?.setEncoding("utf8"),u.stderr?.on("data",p=>{s+=p}),u.on("error",()=>{f({code:null,stdout:i,stderr:s,timedOut:a,spawnFailed:!0})}),u.on("close",p=>{f({code:p,stdout:i,stderr:s,timedOut:a,spawnFailed:!1})}),u.stdin?.on("error",()=>{}),u.stdin?.end(t.stdin??"","utf8")})}};var gr=class{async migrate(e,t,r=Ti){if(e.id===t.id)return{migrated:!1,reason:"same_backend"};if(await this.hasAny(t,r))return{migrated:!1,reason:"target_populated"};let o;try{o=await this.read(e,r)}catch{return{migrated:!1,reason:"source_unreadable"}}if(o.length===0)return{migrated:!1,reason:"source_empty"};try{for(let i of o)await t.set(i.key,i.value)}catch{return{migrated:!1,reason:"target_write_failed"}}if(!await this.verify(t,o))return{migrated:!1,reason:"verify_failed"};for(let i of o)await e.delete(i.key).catch(()=>{});return{migrated:!0,from:e.id,keys:o.map(i=>i.key)}}async hasAny(e,t){for(let r of t)if((await e.get(r).catch(()=>({ok:!1}))).ok)return!0;return!1}async read(e,t){let r=[];for(let o of t){let i=await e.get(o);i.ok&&r.push({key:o,value:i.value})}return r}async verify(e,t){for(let r of t){let o=await e.get(r.key).catch(()=>({ok:!1}));if(!o.ok||o.value!==r.value)return!1}return!0}};var wi="DeviceLink",yr=class{service;constructor(e){let t=(e??"").trim().toLowerCase();this.service=t===""||t==="production"?wi:`${wi}-${t}`}account(e){return e}label(e){return`${this.service} ${e}`}attributes(e){return["service",this.service,"key",this.account(e)]}};import*as Se from"node:fs/promises";import*as Ai from"node:path";var Ci=448,xi=384,Ne=class{filePath;platform;cache=null;constructor(e){this.filePath=e.filePath,this.platform=e.platform??process.platform}async get(e){let r=(await this.load())[e];return r===void 0?{ok:!1}:{ok:!0,value:r}}async set(e,t){let r=await this.load();r[e]=t,await this.save(r)}async delete(e){let t=await this.load();t[e]!==void 0&&(delete t[e],await this.save(t))}async load(){if(this.cache!==null)return this.cache;let e;try{e=await Se.readFile(this.filePath,"utf8")}catch(t){if(Uc(t))return this.cache={},this.cache;throw new N(this.id,`${this.label} could not read its secret store`)}try{this.cache=JSON.parse(await this.unprotect(e))}catch(t){throw t instanceof N?t:new N(this.id,`${this.label} could not decrypt its secret store. The store exists but is unreadable with the current key, so it has been left untouched.`)}return this.cache}async save(e){let t=Ai.dirname(this.filePath);await Se.mkdir(t,{recursive:!0,mode:Ci}),await this.hardenPath(t,Ci);let r=await this.protect(JSON.stringify(e)),o=`${this.filePath}.tmp`;await Se.writeFile(o,r,{encoding:"utf8",mode:xi}),await Se.rename(o,this.filePath),await this.hardenPath(this.filePath,xi)}async hardenPath(e,t){this.platform!=="win32"&&await Se.chmod(e,t).catch(()=>{})}};function Uc(n){return typeof n=="object"&&n!==null&&n.code==="ENOENT"}var Bc=["powershell.exe","pwsh"],Di=['$ErrorActionPreference = "Stop"',"Add-Type -AssemblyName System.Security","$in = [Console]::In.ReadToEnd()","$bytes = [Text.Encoding]::UTF8.GetBytes($in)",'$out = [Security.Cryptography.ProtectedData]::Protect($bytes, $null, "CurrentUser")',"[Console]::Out.Write([Convert]::ToBase64String($out))"].join("; "),Ii=['$ErrorActionPreference = "Stop"',"Add-Type -AssemblyName System.Security","$in = [Console]::In.ReadToEnd()","$bytes = [Convert]::FromBase64String($in.Trim())",'$out = [Security.Cryptography.ProtectedData]::Unprotect($bytes, $null, "CurrentUser")',"[Console]::Out.Write([Text.Encoding]::UTF8.GetString($out))"].join("; "),br=class extends Ne{id=O.WindowsDpapi;label="Windows DPAPI";runner;shell;timeoutMs;constructor(e){super(e),this.runner=e.runner,this.shell=e.shell??Bc[0],this.timeoutMs=e.timeoutMs??St}async probe(){if(this.platform!=="win32")return{available:!1,reason:F.WrongPlatform};let e="dlink-dpapi-probe",t=await this.invoke(Di,e);if(t.timedOut)return{available:!1,reason:F.Timeout};if(t.spawnFailed)return{available:!1,reason:F.ToolMissing,detail:`${this.shell} is not available`};if(t.code!==0)return{available:!1,reason:F.RoundTripFailed,detail:"DPAPI could not protect a value"};let r=await this.invoke(Ii,t.stdout);return r.code!==0||r.stdout!==e?{available:!1,reason:F.RoundTripFailed,detail:"DPAPI could not read back a value"}:{available:!0}}async protect(e){let t=await this.invoke(Di,e);if(t.code!==0||t.timedOut||t.spawnFailed)throw new N(this.id,"DPAPI could not protect the secret store.");return t.stdout.trim()}async unprotect(e){let t=await this.invoke(Ii,e);if(t.timedOut||t.spawnFailed)throw new N(this.id,"DPAPI did not respond while reading the secret store.");if(t.code!==0)throw new N(this.id,"DPAPI could not decrypt the secret store. A DPAPI store is bound to one user on one machine, so a copied or roamed profile cannot be read; nothing has been changed.");return t.stdout}invoke(e,t){let r={command:this.shell,args:["-NoProfile","-NonInteractive","-Command",e],secretVia:"stdin"};return this.runner.run(r,{stdin:t,timeoutMs:this.timeoutMs})}};var Gn="__DLINK_SECRET__",Xe=class{runner;namespace;timeoutMs;constructor(e){this.runner=e.runner,this.namespace=e.namespace,this.timeoutMs=e.timeoutMs??St}normaliseValue(e){return e.replace(/\r?\n$/,"")}encodeValue(e){return Buffer.from(e,"utf8").toString("base64url")}decodeValue(e){let t=Buffer.from(e,"base64url").toString("utf8");if(Buffer.from(t,"utf8").toString("base64url")!==e)throw new N(this.id,`${this.label} holds an item this agent did not write, so it cannot be read safely.`);return t}runEnv(){}runOptions(e={}){return{...e,timeoutMs:this.timeoutMs,env:this.runEnv()}}async probe(){let e=await this.runner.run(this.probeCommand(),this.runOptions());return this.interpretProbe(e)}async get(e){let t=await this.runner.run(this.readCommand(e),this.runOptions());return this.isMissing(t)?{ok:!1}:(this.assertUsable(t,`read ${e}`),{ok:!0,value:this.decodeValue(this.normaliseValue(t.stdout))})}async set(e,t){let r=this.writeCommand(e),o=r.secretVia!=="argv",i=this.encodeValue(t),s=await this.runner.run(o?r:{...r,args:Kc(r.args,i)},o?this.runOptions({stdin:i}):this.runOptions());this.assertUsable(s,`write ${e}`);let a=await this.get(e);if(!a.ok||a.value!==t)throw new N(this.id,`${this.label} accepted ${e} but did not store it correctly, so it has not been trusted.`)}async delete(e){let t=await this.runner.run(this.deleteCommand(e),this.runOptions());this.isMissing(t)||this.assertUsable(t,`delete ${e}`)}assertUsable(e,t){if(e.timedOut)throw new N(this.id,`${this.label} timed out trying to ${t}`);if(e.spawnFailed)throw new N(this.id,`${this.label} is no longer available (could not ${t})`);if(e.code!==0)throw new N(this.id,`${this.label} failed to ${t} (exit ${String(e.code)})`)}};function Kc(n,e){return n.map(t=>t===Gn?e:t)}var vr="secret-tool",jc="__dlink_probe__",Vc="DBUS_SESSION_BUS_ADDRESS",qc=1,Wc=/could not connect|cannot autolaunch|not provided by any \.service/i,Sr=class extends Xe{id=O.LinuxSecretService;label="Linux Secret Service";env;constructor(e){super(e),this.env=e.env??process.env}async probe(){let e=this.env[Vc];return e===void 0||e.trim()===""?{available:!1,reason:F.NoSessionBus}:super.probe()}runEnv(){return this.env}readCommand(e){return{command:vr,args:["lookup",...this.namespace.attributes(e)]}}writeCommand(e){return{command:vr,args:["store",`--label=${this.namespace.label(e)}`,...this.namespace.attributes(e)],secretVia:"stdin"}}deleteCommand(e){return{command:vr,args:["clear",...this.namespace.attributes(e)]}}probeCommand(){return{command:vr,args:["lookup","service",this.namespace.service,"key",jc]}}isMissing(e){return e.timedOut||e.spawnFailed?!1:e.code===qc&&e.stdout.trim()===""&&e.stderr.trim()===""}interpretProbe(e){return e.timedOut?{available:!1,reason:F.Timeout,detail:"the keyring did not respond"}:e.spawnFailed?{available:!1,reason:F.ToolMissing,detail:"secret-tool is not installed"}:Wc.test(e.stderr)?{available:!1,reason:F.NoSessionBus,detail:"the Secret Service could not be reached"}:e.code===0||this.isMissing(e)?{available:!0}:{available:!1,reason:F.Locked,detail:`secret-tool exited ${String(e.code)}`}}};import*as Oi from"node:crypto";import*as et from"node:crypto";var Et=12,Er=16,_r=32,Ze=class{key;constructor(e){this.key=e}encrypt(e){let t=et.randomBytes(Et),r=et.createCipheriv("aes-256-gcm",this.key,t,{authTagLength:Er}),o=Buffer.concat([r.update(e,"utf8"),r.final()]),i=r.getAuthTag();return Buffer.concat([t,i,o]).toString("base64url")}decrypt(e){let t=Buffer.from(e,"base64url"),r=t.subarray(0,Et),o=t.subarray(Et,Et+Er),i=t.subarray(Et+Er),s=et.createDecipheriv("aes-256-gcm",this.key,r,{authTagLength:Er});return s.setAuthTag(o),Buffer.concat([s.update(i),s.final()]).toString("utf8")}};var Hc="DeviceLink-SecretStorage-v1",Gc=1e5;function Jc(n){return Oi.pbkdf2Sync(n,Hc,Gc,_r,"sha256")}var kr=class extends Ne{id=O.MachineId;label="encrypted file (machine-derived key)";codec;constructor(e){super(e);let t=e.machineId?.trim();this.codec=t?new Ze(Jc(t)):null}probe(){return this.codec===null?Promise.resolve({available:!1,reason:F.NotConfigured}):Promise.resolve({available:!0})}protect(e){return Promise.resolve(this.requireCodec().encrypt(e))}unprotect(e){return Promise.resolve(this.requireCodec().decrypt(e))}requireCodec(){if(this.codec===null)throw new N(this.id,"Secret storage requires a machine ID");return this.codec}};var Rr="/usr/bin/security",zc=44,Yc="__dlink_probe__",Qc=/could not be found/i,Xc=/interaction is not allowed/i,Tr=class extends Xe{id=O.MacosKeychain;label="macOS Keychain";readCommand(e){return{command:Rr,args:["find-generic-password","-s",this.namespace.service,"-a",this.namespace.account(e),"-w"]}}writeCommand(e){return{command:Rr,args:["add-generic-password","-s",this.namespace.service,"-a",this.namespace.account(e),"-U","-w",Gn],secretVia:"argv"}}deleteCommand(e){return{command:Rr,args:["delete-generic-password","-s",this.namespace.service,"-a",this.namespace.account(e)]}}probeCommand(){return{command:Rr,args:["find-generic-password","-s",this.namespace.service,"-a",Yc,"-w"]}}isMissing(e){return e.timedOut||e.spawnFailed?!1:e.code===zc||Qc.test(e.stderr)}interpretProbe(e){return e.timedOut?{available:!1,reason:F.Timeout}:e.spawnFailed?{available:!1,reason:F.ToolMissing}:Xc.test(e.stderr)?{available:!1,reason:F.Locked,detail:"the login keychain is locked"}:e.code===0||this.isMissing(e)?{available:!0}:{available:!1,reason:F.Locked,detail:`security exited ${String(e.code)}`}}};import*as Cr from"node:crypto";var _t={N:32768,r:8,p:1,maxmem:64*1024*1024},Zc=16,el=1,Ni="scrypt";function tl(n,e,t){return new Promise((r,o)=>{Cr.scrypt(n,e,_r,{N:t.N,r:t.r,p:t.p,maxmem:_t.maxmem},(i,s)=>{if(i){o(i);return}r(s)})})}var wr=class extends Ne{id=O.Passphrase;label="encrypted file (operator passphrase)";passphrase;salt=null;codec=null;codecSalt=null;codecParams=null;constructor(e){super(e);let t=e.passphrase??"";this.passphrase=t.trim().length>0?t:null}probe(){return this.passphrase===null?Promise.resolve({available:!1,reason:F.NotConfigured}):Promise.resolve({available:!0})}async protect(e){let t=this.requirePassphrase();this.salt===null&&(this.salt=Cr.randomBytes(Zc));let r=await this.codecFor(t,this.salt,_t),o={v:el,kdf:Ni,salt:this.salt.toString("base64url"),N:_t.N,r:_t.r,p:_t.p,blob:r.encrypt(e)};return JSON.stringify(o)}async unprotect(e){let t=this.requirePassphrase(),r=this.parseEnvelope(e),o=Buffer.from(r.salt,"base64url"),i=await this.codecFor(t,o,r);this.salt=o;try{return i.decrypt(r.blob)}catch{throw new N(this.id,"The stored secrets could not be decrypted with DLINK_PASSPHRASE. The passphrase is wrong or the store belongs to another passphrase; nothing has been changed.")}}parseEnvelope(e){let t;try{t=JSON.parse(e)}catch{throw new N(this.id,"The secret store is not a passphrase-protected store.")}let r=t;if(r.kdf!==Ni||typeof r.salt!="string"||typeof r.blob!="string")throw new N(this.id,"The secret store is not a passphrase-protected store.");if(typeof r.N!="number"||typeof r.r!="number"||typeof r.p!="number")throw new N(this.id,"The passphrase store does not record its key derivation parameters.");return r}async codecFor(e,t,r){return this.codec!==null&&this.codecSalt!==null&&this.codecSalt.equals(t)&&this.codecParams!==null&&this.codecParams.N===r.N&&this.codecParams.r===r.r&&this.codecParams.p===r.p?this.codec:(this.codec=new Ze(await tl(e,t,r)),this.codecSalt=t,this.codecParams={N:r.N,r:r.r,p:r.p},this.codec)}requirePassphrase(){if(this.passphrase===null)throw new N(this.id,"DLINK_PASSPHRASE is not set, so the secret store cannot be opened.");return this.passphrase}};var xr=class extends Error{attempts;constructor(e){super("No secret backend is available, so the agent cannot store its device key."),this.name="NoSecretBackendError",this.attempts=e}},Ar=class{async resolve(e){let t=[];for(let r of e){let o=await this.safeProbe(r);if(t.push(rl(r,o)),o.available)return{provider:r,attempts:t}}throw new xr(t)}async safeProbe(e){try{return await e.probe()}catch{return{available:!1,reason:F.RoundTripFailed}}}};function rl(n,e){return e.available?{id:n.id,available:!0}:{id:n.id,available:!1,reason:e.reason}}var nl="secrets.enc.json",ol="secrets.pass.json",il="secrets.dpapi.json",sl="DLINK_SECRETS_BACKEND",al="DLINK_PASSPHRASE";function cl(n={}){let e=n.platform??process.platform,t=n.env??process.env,r=n.configDir??Z(),o=n.runner??new hr,i=n.machineId,s=new yr(t.DEVICELINK_ENV),a=m=>Pi.join(r,m),c=new Map([[O.MacosKeychain,new Tr({runner:o,namespace:s})],[O.LinuxSecretService,new Sr({runner:o,namespace:s,env:t})],[O.WindowsDpapi,new br({filePath:a(il),runner:o,platform:e})],[O.Passphrase,new wr({filePath:a(ol),platform:e,passphrase:t[al]})],[O.MachineId,new kr({filePath:a(nl),platform:e,machineId:i})]]),u=t[sl]?.trim(),d=u?c.get(u):void 0;if(d)return[d];let f=[],p=m=>{let g=c.get(m);g&&f.push(g)};return p(O.Passphrase),p(e==="darwin"?O.MacosKeychain:e==="win32"?O.WindowsDpapi:O.LinuxSecretService),p(O.MachineId),f}async function Fi(n={}){let e=n.platform??process.platform,t=n.configDir??Z(),r=n.candidates??cl(n),o=await new Ar().resolve(r),i=new fr(t,e),s=await i.read(),a={backend:o.provider.id,label:o.provider.label,weak:o.provider.id===O.MachineId,attempts:o.attempts,expectedBackend:s,degraded:s!==void 0&&s!==o.provider.id},c=r.find(u=>u.id===O.MachineId);if(c&&c.id!==o.provider.id){let u=await new gr().migrate(c,o.provider);u.migrated&&(a.migratedFrom=u.from)}return await i.write(o.provider.id),{store:o.provider,report:a}}var Dr=class{},Jn=class{ok;config;constructor(e,t){this.ok=e,this.config=t}},zn=class extends Y{constructor(){super(new z({name:"load-config",lane:"main",priority:1e3,locks:["GLOBAL"],maxAttempts:3,cancellable:!0}))}async run(e,t){t.notifier.info("Loading configuration...",{scope:"system"});let r=t.engine.configurationContext.loader,o=await t.engine.secrets.get("devicePrivateKey");r.setPrivateKeyCache(o.ok&&o.value?o.value:void 0),r.withDefaultConfig(),r.withArgv(t.engine.argv),t.engine.argv.enviromentFile&&r.withEnviromentFile(t.engine.argv.enviromentFile),r.withConfigFile("config.json"),r.withProcessEnv(),r.withDiscoveryCache();let i=r.build(),s=r.getPrivateKeyToStore();return s&&await t.engine.secrets.set("devicePrivateKey",s),this.updateUi(i,t),t.notifier.success("Configuration loaded"),t.engine.applyConfiguration(i),t.bus.emit("config:loaded",i),new Jn(!0,i)}updateUi(e,t){let r={scope:"system"};t.notifier.info(`Control base URL: ${e.controlBaseUrl}`,r),t.notifier.info(`Bridge WebSocket URL: ${e.bridgeWsUrl}`,r),t.notifier.info(`Bridge endpoint source: ${t.engine.configurationContext.loader.getBridgeEndpointSource()??"none"}`,r);let o=e.discovery;o&&t.notifier.info(`Discovery cache: issued_at=${o.issuedAt??"-"} expires_at=${o.expiresAt} control=${o.controlUrl??"-"} bridge=${(o.bridgeUrls??[]).join(",")||"-"}`,r),t.notifier.info(`Directories: ${e.directories.map(i=>i.path).join(", ")}`,r),t.notifier.info(`Device: ${e.device?.id}`,r),t.notifier.info(`Device name: ${e.device?.name}`,r),t.notifier.info(`Device tag: ${e.device?.tag}`,r),t.notifier.info(`Device keys public: ${e.device?.keys?.public?"***":"(none)"}`,r)}},Yn=new zn;function Li(n){return new pe(Yn,n)}var Qn=class{ok;constructor(e){this.ok=e}},Xn=class extends Y{constructor(){super(new z({name:"console-command",lane:"console",priority:1e3,locks:[],maxAttempts:1,cancellable:!1}))}async run(e,t){return t.notifier.info(`Executing console command: ${e.kind}`),await new Promise(r=>setTimeout(r,2e3)),t.notifier.info(`Console command executed: ${e.kind}`),t.notifier.success(`Console command executed: ${e.kind}`),new Qn(!0)}},Mi=new Xn;var Zn=class{ok;constructor(e){this.ok=e}},eo=class extends Y{constructor(){super(new z({name:"contact-server",lane:"main",priority:900,locks:["GLOBAL"],maxAttempts:8,cancellable:!0}))}async run(e,t){return t.notifier.info(`contact server mode=${e.mode}`,{scope:"system"}),await new Promise(r=>setTimeout(r,200)),new Zn(!0)}},$i=new eo;var to=class{ok;constructor(e){this.ok=e}},ro=class extends Y{constructor(){super(new z({name:"send-server-result",lane:"io",priority:200,locks:[],maxAttempts:10,cancellable:!0}))}async run(e,t){return t.notifier.info(`send result requestId=${e.requestId}`,{scope:"system"}),await new Promise(r=>setTimeout(r,10)),new to(!0)}},Ui=new ro;import ul from"node:crypto";import te from"lodash/get.js";import kt from"lodash/isPlainObject.js";import rt from"lodash/isString.js";var ee=class{constructor(e,t){this.context=e;this.handler=t}execute(e){return this.handler(this.context,e)}};async function Ee(n,e,t){let r=`${n.configuration.controlBaseUrl}${e}`,o=await fetch(r,t);if(!o.ok){let i=await o.text().catch(a=>{let c=a instanceof Error?a.message:String(a);return n.notifier.error(`Failed to read HTTP error response body: ${c}`),""}),s=new Error(`HTTP ${o.status}: ${i}`);s.status=o.status;try{s.body=i?JSON.parse(i):void 0}catch{s.body=void 0}if(o.status===429){let a=o.headers.get("Retry-After");if(a!==null){let c=parseInt(a,10);Number.isFinite(c)&&c>=0&&(s.retryAfterSec=c)}}throw s}return o.json()}function Bi(n){return new ee(n,async(e,t)=>Ee(e,"/api/device/authorize/start",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}))}function Ki(n){return new ee(n,async(e,t)=>Ee(e,"/api/device/authorize/prove",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}))}import{z as he}from"zod";var ll=he.union([he.object({status:he.literal("pending"),needs_proof:he.boolean()}),he.object({status:he.literal("approved"),needs_proof:he.boolean()}),he.object({error:he.literal("access_denied")}),he.object({error:he.literal("expired_token")})]);function ji(n){return new ee(n,async(e,t)=>{let r=new URL("/api/device/authorize/stream",e.configuration.controlBaseUrl);r.searchParams.set("device_code",t.deviceCode);let o=e.notifier,i=new AbortController,s=setTimeout(()=>{o.error("[deviceAuthStream] Timeout reached, aborting"),i.abort()},Math.max(1e3,t.timeoutMs));if(t.signal){let a=t.signal;a.addEventListener("abort",()=>{let c="reason"in a&&a.reason!=null?String(a.reason):"";o.warn(`[deviceAuthStream] External signal aborted: ${c}`),i.abort()})}try{let a=await fetch(r.toString(),{method:"GET",headers:{Accept:"text/event-stream"},signal:i.signal});if(!a.ok||!a.body){let f=await a.text().catch(p=>{let m=p instanceof Error?p.message:String(p);return o.error(`[deviceAuthStream] Failed to read response body (${a.status}): ${m}`),""});throw o.error(`[deviceAuthStream] Response error: ${a.status} - ${f}`),new Error(`device/authorize/stream failed (${a.status}): ${f}`)}let c=a.body.getReader(),u=new TextDecoder("utf-8"),d="";for(;;){let{value:f,done:p}=await c.read();if(p){o.error("[deviceAuthStream] Stream ended unexpectedly");break}for(d+=u.decode(f,{stream:!0});;){let m=d.indexOf(`
4
5
 
5
- `);if(m===-1)break;let g=d.slice(0,m);d=d.slice(m+2);let h=null,y=null;for(let k of g.split(`
6
- `))k.startsWith("event:")&&(h=k.slice(6).trim()),k.startsWith("data:")&&(y=k.slice(5).trim());if(!h||!y)continue;let _;try{_=JSON.parse(y)}catch(k){o.error(`[deviceAuthStream] Failed to parse event data as JSON: ${String(k)}`);continue}let b=Bc.safeParse(_);if(!b.success){o.error(`[deviceAuthStream] Event validation failed (${h}): ${String(b.error)}`);continue}let E=b.data;if(h==="approved"||h==="denied"||h==="expired")return E;if(h==="pending"){"status"in E&&E.status==="pending"&&E.needs_proof===!0&&o.warn("[deviceAuthStream] pending: needs_proof=true (unexpected before approval)");continue}o.warn(`[deviceAuthStream] Unknown event type: ${h}`)}}throw o.error("[deviceAuthStream] Stream ended unexpectedly without completion"),new Error("Device authorization stream ended without completion")}catch(a){if(a instanceof Error&&a.name==="AbortError")o.warn(`[deviceAuthStream] Aborted: ${a.message??""}`);else{let c=a instanceof Error?a.message:String(a);o.error(`[deviceAuthStream] Error: ${c}`)}throw a}finally{clearTimeout(s)}})}function Ai(n){return new ee(n,async(e,t)=>Ee(e,"/api/device/authorize/token",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}))}function Di(n){return new ee(n,async(e,t)=>{let r=new AbortController,o=3e4,i=setTimeout(()=>{r.abort()},o);try{let s=await Ee(e,"/api/device/authorize/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),signal:r.signal});return clearTimeout(i),s}catch(s){throw clearTimeout(i),s instanceof Error&&s.name==="AbortError"?new Error(`Refresh token request timed out after ${o}ms`):s}})}function Ii(n){return new ee(n,async(e,t)=>Ee(e,"/api/device/enrollment/start",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}))}var et=class{deviceAuthStartCall;deviceAuthProveCall;deviceAuthStreamCall;deviceAuthTokenCall;deviceAuthRefreshCall;deviceEnrollmentStartCall;constructor(e,t){let r={configuration:e,notifier:t};this.deviceAuthStartCall=Ri(r),this.deviceAuthProveCall=Ci(r),this.deviceAuthStreamCall=xi(r),this.deviceAuthTokenCall=Ai(r),this.deviceAuthRefreshCall=Di(r),this.deviceEnrollmentStartCall=Ii(r)}deviceAuthStart(e){return this.deviceAuthStartCall.execute(e)}deviceEnrollmentStart(e){return this.deviceEnrollmentStartCall.execute(e)}deviceAuthProve(e){return this.deviceAuthProveCall.execute(e)}deviceAuthStream(e){return this.deviceAuthStreamCall.execute(e)}deviceAuthToken(e){return this.deviceAuthTokenCall.execute(e)}deviceAuthRefresh(e){return this.deviceAuthRefreshCall.execute(e)}};function jc(n){if(!Et(n)||te(n,"ok")!==!0)return!1;let e=te(n,"data");return Et(e)?te(e,"ok")===!0&&tt(te(e,"access_token"))&&tt(te(e,"refresh_token"))&&typeof te(e,"expires_in_sec")=="number"&&tt(te(e,"device_id")):!1}function Vc(n){return n.ok===!0&&typeof n.access_token=="string"}var Rr=class{constructor(e){this.reason=e}},Gn=["REFRESH_EXPIRED","REFRESH_REVOKED","REFRESH_NOT_FOUND","DEVICE_NOT_FOUND"],_e=class{constructor(e,t,r,o,i,s,a,c){this.ok=e;this.accessToken=t;this.refreshToken=r;this.expiresInSec=o;this.error=i;this.retryAfterSec=s;this.errorCode=a;this.driftMs=c}},Wn=class extends Y{constructor(){super(new z({name:"refresh-tokens",lane:"io",priority:900,locks:["AUTH_REFRESH"],maxAttempts:5,cancellable:!0}))}async run(e,t){let r=t.engine.configurationContext.configuration;if(!r.controlBaseUrl)return new _e(!1,void 0,void 0,void 0,"controlBaseUrl missing");if(!r.device?.id)return new _e(!1,void 0,void 0,void 0,"device.id missing");let o=await t.engine.secrets.get("devicePrivateKey");if(!o.ok||!o.value)return new _e(!1,void 0,void 0,void 0,"device private key missing");let i=o.value,s=await t.engine.secrets.get("refreshToken");if(!s.ok||!s.value)return new _e(!1,void 0,void 0,void 0,"refresh token missing");let a=s.value;t.notifier.info(`Refreshing tokens (job) reason=${e.reason}`,{scope:"system",category:["token-refresh"]});let c=Date.now(),l=Kc.randomBytes(16).toString("base64url"),d=un({deviceId:r.device.id,ts:c,nonce:l,refreshToken:a,privateKeyPem:i}),f=new et(r,t.notifier),p;try{p=await f.deviceAuthRefresh({device_id:r.device.id,refresh_token:a,ts:c,nonce:l,sig:d})}catch(g){let h=g instanceof Error?g.message:String(g),y=g,_=y.retryAfterSec,b=y.body,E=b?.error,k=E!=null&&typeof E=="object"?E.code:void 0,D=tt(k)?k:void 0,S=E!=null&&typeof E=="object"?E.drift_ms:void 0,T=typeof S=="number"?S:void 0;return D==="REFRESH_NOT_FOUND"?(t.notifier.warn("Refresh token not found; clearing stored refresh token and stopping automatic refresh. Please run signin.",{category:["token-refresh"]}),await t.engine.secrets.delete("refreshToken").catch(x=>{let A=x instanceof Error?x.message:String(x);t.logger.warn(`Could not clear stored refresh token: ${A}`,{category:["token-refresh"]}),t.notifier.warn(`Could not clear stored refresh token: ${A}`,{category:["token-refresh"]})}),new _e(!1,void 0,void 0,void 0,"Refresh token not found",void 0,"REFRESH_NOT_FOUND")):(t.notifier.error(`Refresh tokens failed: ${h}`,{category:["token-refresh"]}),new _e(!1,void 0,void 0,void 0,h,_,D,T))}let m=this.normalizeRefreshResponse(p);if(!m){let g=this.extractErrorMessage(p),h=this.extractErrorCode(p),y=this.extractErrorDrift(p);return t.notifier.error(`Refresh tokens failed: ${g}`,{category:["token-refresh"]}),new _e(!1,void 0,void 0,void 0,g,void 0,h,y)}return m.refresh_token&&await t.engine.secrets.set("refreshToken",m.refresh_token),new _e(!0,m.access_token,m.refresh_token,m.expires_in_sec)}normalizeRefreshResponse(e){if(jc(e))return e.data;if(this.looksLikeDomainRefresh(e)){let t=e;return Vc(t)?t:null}return null}looksLikeDomainRefresh(e){if(typeof e!="object"||e===null)return!1;let t=e;return t.ok===!0||t.ok===!1}extractErrorMessage(e){if(!Et(e))return"Unknown error";if(te(e,"ok")===!1){let t=te(e,"error.message");if(tt(t)&&t.length>0)return t}return te(e,"ok")===!0&&"data"in e?"Bad refresh response: missing token fields":"Unknown error"}extractErrorDrift(e){if(!Et(e)||te(e,"ok")!==!1)return;let t=te(e,"error.drift_ms");return typeof t=="number"?t:void 0}extractErrorCode(e){if(!Et(e)||te(e,"ok")!==!1)return;let t=te(e,"error.code");return tt(t)?t:void 0}},Hn=new Wn;function Oi(n){return new pe(Hn,n)}function Ni(n,e){return e.headless?n.on("notify:event",t=>{qc(t,e.debug)}):null}function qc(n,e){if(!e&&!Wc(n))return;let t=`[agent] ${n.message}`;switch(n.kind){case"error":console.error(t);break;case"warning":console.warn(t);break;default:console.log(t);break}}function Wc(n){return n.kind==="error"||n.kind==="warning"||n.kind==="success"||n.scope==="system"}var Cr=class{constructor(e){this.argv=e;let t=e.map(f=>f.trim()?.toLowerCase()),r=e.map(f=>f.trim()),o=this.parseKeyValue(t,r,["--env"]);o.match&&(this.enviromentFile=o.value);let i=this.parseKeyValue(t,r,["--root"]);i.match&&(this.rootPath=i.value);let s=this.parseKeyValue(t,r,["--control-url"]);s.match&&(this.controlUrl=s.value);let a=this.parseKeyValue(t,r,["--bridge-ws-url"]);a.match&&(this.bridgeWsUrl=a.value);let c=this.parseKeyValue(t,r,["--private-key-file"]);c.match&&c.value&&(this.privateKeyFile=c.value);let l=this.parseKeyValue(t,r,["--public-key-file"]);l.match&&l.value&&(this.publicKeyFile=l.value);let d=this.parseKeyValue(t,r,["--enrollment-file"]);d.match&&d.value&&(this.enrollmentFile=d.value)}enviromentFile;rootPath;controlUrl;bridgeWsUrl;privateKeyFile;publicKeyFile;enrollmentFile;parseKeyValue(e,t,r){let o=r.map(i=>i.toLowerCase()?.trim()).filter(i=>i!==void 0);if(o.length===0)return{match:!1,value:void 0};for(let i of o){let s=e.findIndex(a=>{let c=a.toLowerCase();return c===i||c.startsWith(i+"=")});if(s!==-1){let a=t[s],c=a.toLowerCase().indexOf("=");if(c!==-1)return{match:!0,value:a.substring(c+1)||void 0};let l=t[s+1];return l===void 0||l.startsWith("--")?{match:!0,value:void 0}:{match:!0,value:l}}}return{match:!1,value:void 0}}};var xr=class{bus;flags;constructor(e,t){this.bus=e,this.flags=t??new Ae(!1)}info(e,t){return this.push(e,t)}warn(e,t){let r=Object.assign({},t,{kind:"warning"});return this.push(e,r)}error(e,t){let r=Object.assign({},t,{kind:"error"});return this.push(e,r)}success(e,t){let r=Object.assign({},t,{kind:"success"});return this.push(e,r)}push(e,t){if((t?.scope??"default")==="system"&&!this.flags.debug&&!this.flags.headless)return null;let o=new ye(e,t);return this.bus.emit("notify:event",o),o}};var Ar=class{bus;constructor(e){this.bus=e}info(e,t){this.push(e,Object.assign({},t,{level:"info"}))}warn(e,t){this.push(e,Object.assign({},t,{level:"warn"}))}error(e,t){this.push(e,Object.assign({},t,{level:"error"}))}debug(e,t){this.push(e,Object.assign({},t,{level:"debug"}))}success(e,t){this.push(e,Object.assign({},t,{level:"success"}))}push(e,t){let r=new jt(e,t);this.bus.emit("log",r)}};import zn from"node:fs";import zc from"node:os";import Yn from"node:tty";import Gc from"lodash/toLower.js";import Hc from"lodash/trim.js";var Jc=new Set(["1","true","yes","on"]),Jn=new Set(["0","false","no","off"]);function Dr(n){let e=Gc(Hc(n));if(Jc.has(e))return!0;if(Jn.has(e))return!1}function _t(n,e,t=process.env){return Dr(t[n]??"")??e}function Yc(n){let e=n.setRawMode;return typeof e!="function"||(n.setRawMode=t=>{try{return e.call(n,t)}catch(r){let o=typeof r=="object"&&r!==null&&"code"in r?r.code:void 0;if(o==="EPERM"||o==="EINVAL")return n;throw r}}),n}var kt;function Qn(){if(kt!==void 0)return kt;let n;if(process.stdin.isTTY)n=process.stdin;else try{if(zc.platform()==="win32")try{let e=zn.openSync("CONIN$","rs");n=new Yn.ReadStream(e)}catch{let e=zn.openSync("\\\\.\\CONIN$","rs");n=new Yn.ReadStream(e)}else{let e=zn.openSync("/dev/tty","rs");n=new Yn.ReadStream(e)}}catch{return kt=null,null}return kt=Yc(n),kt}function Qc(){return Qn()===null}function Xc(n){for(let e of n){let t=e.trim(),r=t.toLowerCase();if(r==="--headless")return"on";if(r.startsWith("--headless=")){let o=t.slice(t.indexOf("=")+1).trim().toLowerCase();return Jn.has(o)?"off":"on"}}return"unset"}function Pi(n){let e=Xc(n);if(e==="on")return{headless:!0,reason:"CLI: --headless"};if(e==="off")return{headless:!1,reason:"CLI: --headless=false"};let t=process.env.HEADLESS;if(t!==void 0&&t.trim()!==""){let i=Dr(t);if(i!==void 0)return{headless:i,reason:i?"env: HEADLESS":"env: HEADLESS=false"}}let r=process.env.DLINK_HEADLESS;if(r!==void 0&&r.trim()!==""){let i=Dr(r);if(i!==void 0)return{headless:i,reason:i?"env: DLINK_HEADLESS":"env: DLINK_HEADLESS=false"}}return Qc()?{headless:!0,reason:"no TTY stdin (Docker/CI/background)"}:{headless:!1,reason:"TTY available (interactive)"}}import Ir from"dotenv";import{existsSync as Fi}from"node:fs";import{join as Zc,resolve as el,dirname as tl}from"node:path";function Li(n){Ir.config({quiet:!0});let e=Zc(process.cwd(),"apps","agent",".env");Fi(e)&&Ir.config({path:e,override:!0,quiet:!0}),n.enviromentFile&&Ir.config({path:n.enviromentFile,override:!0,quiet:!0});let t=el(tl(process.argv[1]??"."),".env.production");Fi(t)&&Ir.config({path:t,override:!1,quiet:!0})}import{access as Mi,readFile as rl}from"node:fs/promises";import{constants as $i}from"node:fs";function nl(n){return(n.trim().split(".")[0]??"").startsWith("eyJ")}function Xn(){let n=process.env.ENROLMENT_KEY?.trim()??process.env.DLINK_ENROLMENT_KEY?.trim();return n?nl(n)?{kind:"inline",jws:n}:{kind:"path",path:n}:{kind:"none"}}function Bi(n){let e=n?.trim();if(e)return`file:${e}`;let t=Xn();return t.kind==="none"?"none":t.kind==="inline"?"ENROLMENT_KEY(inline JWS)":`file:${t.path}`}async function Ui(n){try{let t=(await rl(n,"utf8")).trim();return t?{ok:!0,jws:t}:{ok:!1,error:"empty_file"}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}}async function Ki(n){let e=n?.trim();if(e)try{return await Mi(e,$i.R_OK),!0}catch{return!1}let t=Xn();if(t.kind==="inline")return t.jws.trim().length>0;if(t.kind==="path")try{return await Mi(t.path,$i.R_OK),!0}catch{return!1}return!1}async function ji(n){let e=n?.trim();if(e)return Ui(e);let t=Xn();if(t.kind==="none")return{ok:!1,error:"not_configured"};if(t.kind==="inline"){let r=t.jws.trim();return r?{ok:!0,jws:r}:{ok:!1,error:"empty_file"}}return Ui(t.path)}import Zn from"lodash/trim.js";var Vi=[{name:"help",aliases:["?"],summary:"Show this command list"},{name:"start",aliases:["run"],summary:"Connect the bridge"},{name:"stop",summary:"Disconnect the bridge"},{name:"status",summary:"Show device, bridge and session state"},{name:"doctor",summary:"Run local environment checks"},{name:"signin",summary:"Sign in to DeviceLink"},{name:"signout",summary:"Sign out and disconnect the bridge"},{name:"roots list",summary:"List the directories shared with the bridge"},{name:"roots add",args:"<path>",summary:"Share an additional directory"},{name:"debug on",summary:"Show internal system messages",hidden:!0},{name:"debug off",summary:"Hide internal system messages",hidden:!0},{name:"replace",aliases:["yes","y"],summary:"Take over an existing session on conflict"}],qi=[{flag:"-h, --help",summary:"Show this help and exit"},{flag:"-v, --version",summary:"Print the agent version and exit"},{flag:"--headless",args:"[=true|false]",summary:"Run without the interactive UI"},{flag:"--env",args:"<file>",summary:"Load environment from a specific file"},{flag:"--root",args:"<path>",summary:"Share this directory with the bridge"},{flag:"--control-url",args:"<url>",summary:"Override the control plane base URL"},{flag:"--bridge-ws-url",args:"<url>",summary:"Override the bridge WebSocket URL"},{flag:"--enrollment-file",args:"<file>",summary:"Path to a .devicelink enrollment key"},{flag:"--private-key-file",args:"<file>",summary:"Path to the device private key"},{flag:"--public-key-file",args:"<file>",summary:"Path to the device public key"}];function Wi(){let n=new Set;for(let e of Vi){let t=e.name.split(" ")[0];t&&n.add(t);for(let r of e.aliases??[])n.add(r)}return Array.from(n)}function Gi(n){let e=new Set,t=new Set;for(let i of qi){let s=!!i.args&&!i.args?.startsWith("[");for(let a of i.flag.split(",")){let c=Zn(a).toLowerCase();c.startsWith("-")&&(e.add(c),s&&t.add(c))}}let r=[],o=n.slice(2);for(let i=0;i<o.length;i++){let s=Zn(o[i]??"");if(s==="--"||!s.startsWith("-"))continue;let a=s.split("=")[0]??s;if(!e.has(a.toLowerCase())){r.push(a);continue}t.has(a.toLowerCase())&&!s.includes("=")&&i++}return r}function Hi(n){for(let e of n.slice(2)){let t=Zn(e).toLowerCase();if(t==="--version"||t==="-v")return"version";if(t==="--help"||t==="-h")return"help"}return null}function Ji(n){let e=n.args?`${n.name} ${n.args}`:n.name;return!n.aliases||n.aliases.length===0?e:`${e} (${n.aliases.join(", ")})`}function eo(n){let e=n.reduce((t,r)=>Math.max(t,r.left.length),0);return n.map(t=>` ${t.left.padEnd(e)} ${t.right}`)}function zi(){return Vi.filter(n=>!n.hidden)}function Yi(){let n=zi().map(e=>({left:Ji(e),right:e.summary}));return["Commands:",...eo(n)]}function Qi(n){let e=zi().map(r=>({left:Ji(r),right:r.summary})),t=qi.map(r=>({left:r.args?`${r.flag} ${r.args}`:r.flag,right:r.summary}));return[`DeviceLink Agent ${n}`,"","Usage: dlink [options]","","Options:",...eo(t),"","Interactive commands (type these once the agent is running):",...eo(e),""].join(`
7
- `)}import ol from"lodash/compact.js";import il from"lodash/isString.js";import sl from"lodash/trim.js";import{existsSync as al,readFileSync as cl}from"node:fs";import Xi from"node:path";import{fileURLToPath as ll}from"node:url";var to;function ul(){try{let n=Xi.dirname(ll(import.meta.url)),e=Xi.join(n,"package.json");if(!al(e))return;let t=JSON.parse(cl(e,"utf8"));if(t.name==="@devicelink/dlink"&&il(t.version))return t.version}catch{return}}function ue(){if(to===void 0){let n=[process.env.DLINK_AGENT_VERSION,process.env.npm_package_version,ul()].map(e=>sl(e));to=ol(n)[0]??"unknown"}return to}async function Zi(n){let e=Hi(process.argv);if(e==="version"){console.log(ue());return}if(e==="help"){console.log(Qi(ue()));return}let t=Gi(process.argv);t.length>0&&(console.warn(`[agent] Ignoring unrecognised ${t.length===1?"option":"options"}: ${t.join(", ")}`),console.warn('[agent] Run "dlink --help" to see the supported options.'));let r=new ar,o=new qt,{store:i,report:s}=await Ei({machineId:Ht(!0)}),a=new Cr(process.argv);Li(a);let c=Pi(process.argv);if(c.headless){let g=Bi(a.enrollmentFile);console.log(`[agent] Headless boot (${c.reason})`),console.log(`[agent] Enrollment: ${g}`),g==="none"&&console.log("[agent] No enrollment key (set ENROLMENT_KEY or DLINK_ENROLMENT_KEY, or use --enrollment-file)")}let l=new Ae(!1,c.headless,c.reason),d=new Ar(r),f=new xr(r,l);Ni(r,l);let p=new sr({bus:r,argv:a,logger:d,notifier:f,storage:o,secrets:i,secretsReport:s,flags:l,lanes:[new we("console",1),new we("supervisor",1),new we("main",1),new we("ws",1),new we("worker",8),new we("io",4)]});p.register($n),p.register(Hn),p.register(ki),p.register(Ti),p.register(wi);let m=n({headless:c.headless,headlessReason:c.reason});for(let g of m)p.registerOrchestrator(g);await p.init(),await p.start()}import Vl from"react";import{render as ql}from"ink";import{useEffect as $l,useCallback as no}from"react";import{Box as oo,useApp as Ul,useInput as Bl}from"ink";import{useEffect as dl,useState as pl}from"react";function es(){let[n,e]=pl(()=>{let t=process.stdout.columns||80,r=process.stdout.rows||24;return[t,r]});return dl(()=>{let t=()=>{let r=process.stdout.columns||80,o=process.stdout.rows||24;e([r,o])};return process.stdout.on("resize",t),t(),()=>{process.stdout.off("resize",t)}},[]),n}import is,{useEffect as Or,useState as ss}from"react";import{Box as nt,Text as L}from"ink";import{createContext as fl,useContext as ml,useReducer as hl,useMemo as rt,useEffect as ts,useState as gl}from"react";import{jsx as Sl}from"react/jsx-runtime";var rs=fl(null);function yl(n,e){let t=n.messages,r=t.findIndex(o=>o.id===e.id);if(r!==-1){let o=t[r],i=[...t];return i[r]={...e,id:o.id,ts:o.ts},{...n,messages:i}}if(e.groupKey)for(let o=t.length-1;o>=0;o--){let i=t[o];if(i.groupKey===e.groupKey){let s=[...t];return s[o]={...e,id:i.id,ts:i.ts,groupKey:i.groupKey},{...n,messages:s}}}return{...n,messages:[...t.slice(-380),e]}}function bl(n,e){switch(e.type){case"SET_INPUT":return{...n,input:e.payload};case"ADD_MESSAGE":return yl(n,e.payload);case"SET_MESSAGES":return{...n,messages:e.payload};case"SET_ENGINE_STATE":return{...n,engineState:e.payload};case"ADD_COMMAND_TO_HISTORY":{if(!e.payload)return n;let t=n.commandHistory.length===0||n.commandHistory[n.commandHistory.length-1]!==e.payload?[...n.commandHistory,e.payload]:n.commandHistory;return{...n,commandHistory:t}}case"SET_HISTORY_INDEX":return{...n,historyIndex:e.payload};case"SET_IS_PROCESSING":return{...n,isProcessing:e.payload};case"SET_DEBUG_ENABLED":return{...n,debugEnabled:e.payload};case"SET_CONNECTION_STATUS":return{...n,connectionStatus:e.payload};case"SET_CONNECTION_RETRY":return{...n,connectionRetryInSec:e.payload};case"SET_REFRESH_COUNTDOWN":return{...n,refreshCountdownSec:e.payload};case"SET_DEVICE_ID":return{...n,deviceId:e.payload};case"RESET_INPUT":return{...n,input:""};case"RESET_HISTORY_INDEX":return{...n,historyIndex:-1};case"RESET_HISTORY_INDEX_IF_TYPING":if(n.historyIndex!==-1){let t=n.commandHistory[n.historyIndex];if(t!==void 0&&n.input!==t)return{...n,historyIndex:-1}}return n;default:return n}}var vl={input:"",messages:[],engineState:"IDLE",commandHistory:[],historyIndex:-1,isProcessing:!1,debugEnabled:!1,connectionStatus:"disconnected",connectionRetryInSec:null,refreshCountdownSec:null,deviceId:null};function ns({engine:n,bus:e,children:t}){let[r,o]=hl(bl,vl),[i,s]=gl(()=>Object.freeze({phase:n.runtime.phase,flags:Object.freeze({debug:n.runtime.flags.debug})}));ts(()=>{e.emit("ui:initialized",Date.now())},[e]),ts(()=>{let c=S=>S==="running"?"RUNNING":S==="stopping"?"STOPPING":S==="booting"?"IDLE":"STOPPED",l=e.on("notify:event",S=>{if(o({type:"ADD_MESSAGE",payload:S}),S.groupKey?.startsWith("auth:refresh"))if(S.kind==="info"){let T=S.message.match(/refresh scheduled in (\d+)s/);if(T){let x=parseInt(T[1],10);isNaN(x)||o({type:"SET_REFRESH_COUNTDOWN",payload:x})}}else S.kind==="success"&&S.message.includes("refresh completed")&&o({type:"SET_REFRESH_COUNTDOWN",payload:null})}),d=()=>{let S=n.runtime;o({type:"SET_ENGINE_STATE",payload:c(S.phase)}),o({type:"SET_DEBUG_ENABLED",payload:S.flags.debug});let T=n.configurationContext.configuration.device?.id??null;o({type:"SET_DEVICE_ID",payload:T}),s(Object.freeze({phase:S.phase,flags:Object.freeze({debug:S.flags.debug})}))};d();let f=e.on("engine:started",()=>{o({type:"SET_ENGINE_STATE",payload:"RUNNING"}),d()}),p=e.on("engine:stopping",()=>{o({type:"SET_ENGINE_STATE",payload:"STOPPING"}),d()}),m=e.on("engine:stopped",()=>{o({type:"SET_ENGINE_STATE",payload:"STOPPED"}),d()}),g=e.on("ws:connecting",()=>{o({type:"SET_CONNECTION_STATUS",payload:"connecting"}),o({type:"SET_CONNECTION_RETRY",payload:null})}),h=e.on("ws:connected",()=>{o({type:"SET_CONNECTION_STATUS",payload:"connected"}),o({type:"SET_CONNECTION_RETRY",payload:null})}),y=e.on("ws:disconnected",()=>{o({type:"SET_CONNECTION_STATUS",payload:"disconnected"}),o({type:"SET_CONNECTION_RETRY",payload:null})}),_=e.on("ws:retrying",S=>{o({type:"SET_CONNECTION_STATUS",payload:"connecting"}),o({type:"SET_CONNECTION_RETRY",payload:S.retryInSec})}),b=e.on("runtime:debug:changed",({enabled:S})=>{o({type:"SET_DEBUG_ENABLED",payload:S});let T=n.runtime;s(Object.freeze({phase:T.phase,flags:Object.freeze({debug:S})}))}),E=e.on("config:loaded",S=>{let T=S.device?.id??null;o({type:"SET_DEVICE_ID",payload:T})}),k=new ye("Welcome to DeviceLink Agent UI",{ts:Date.now(),kind:"status"}),D=new ye('Type "help" for commands. Start bridge with: start or run',{ts:Date.now(),kind:"status"});return o({type:"SET_MESSAGES",payload:[k,D]}),()=>{l.unsubscribe(),f.unsubscribe(),p.unsubscribe(),m.unsubscribe(),g.unsubscribe(),h.unsubscribe(),y.unsubscribe(),_.unsubscribe(),b.unsubscribe(),E.unsubscribe()}},[e,n,o]);let a=rt(()=>({state:r,dispatch:o,engine:n,bus:e,runtime:i}),[r,n,e,i]);return Sl(rs.Provider,{value:a,children:t})}function Be(){let n=ml(rs);if(!n)throw new Error("useAppContext must be used within AppContextProvider");return n}function os(n){let{state:e}=Be(),t=c=>!(c.category?.includes("token-refresh")||c.groupKey?.startsWith("auth:refresh")&&c.kind==="info"&&c.message.includes("refresh scheduled in")),r=n?.displayFilter??t,o=rt(()=>e.messages.filter(r),[e.messages,r]),i=rt(()=>c=>e.messages.filter(c),[e.messages]),s=rt(()=>c=>e.messages.filter(l=>l.kind===c),[e.messages]),a=rt(()=>c=>e.messages.filter(l=>l.scope===c),[e.messages]);return rt(()=>({rawMessages:e.messages,messagesToDisplay:o,getFilteredMessages:i,getMessagesByKind:s,getMessagesByScope:a}),[e.messages,o,i,s,a])}import{Fragment as ot,jsx as U,jsxs as Q}from"react/jsx-runtime";function El(n){return n==="RUNNING"?"green":n==="STOPPING"?"yellow":n==="STOPPED"?"red":"gray"}function _l(n){return n==="connected"?"green":n==="connecting"?"yellow":"red"}function kl(n){return n==="connected"?"connected":n==="connecting"?"trying":"disconnected"}function as(n,e){return n.length<=e?n:n.slice(0,Math.max(0,e-3))+"..."}function Tl(n){let{state:e}=Be(),t="DeviceLink Agent",r=e.debugEnabled,o=e.deviceId??"not signed in",i=e.engineState,s=El(i),a=e.isProcessing,c=e.connectionStatus,l=e.connectionRetryInSec,d=e.refreshCountdownSec,[f,p]=ss(d),[m,g]=ss(l);Or(()=>{p(d)},[d]),Or(()=>{g(l)},[l]),Or(()=>{if(d===null||d<=0){p(null);return}p(d);let S=setInterval(()=>{p(T=>T===null||T<=1?null:T-1)},1e3);return()=>clearInterval(S)},[d]),Or(()=>{if(l===null||l<=0){g(null);return}g(l);let S=setInterval(()=>{g(T=>T===null||T<=1?null:T-1)},1e3);return()=>clearInterval(S)},[l]);let h=kl(c),y=_l(c),_=t.length,b=30,E=n.width-_-2,k=[];if(k.push(U(L,{color:y,children:h},"conn")),m!==null&&m>0&&k.push(Q(L,{color:y,children:["retry in ",m,"s"]},"retry")),f!==null&&f>0&&f<=5&&k.push(Q(L,{color:"cyan",children:["refresh in ",f,"s"]},"refresh")),E>=b){let S=as(o,Math.max(5,E-50));return Q(nt,{justifyContent:"space-between",width:n.width,children:[Q(nt,{children:[U(L,{bold:!0,children:t}),r&&Q(ot,{children:[U(L,{children:" "}),U(L,{color:"yellow",bold:!0,children:"[DEBUG]"})]})]}),Q(nt,{children:[a&&U(ot,{children:U(L,{dimColor:!0,children:"\u23F3 "})}),U(L,{dimColor:!0,children:"device "}),Q(L,{children:[S," "]}),U(L,{children:"\xB7 "}),U(L,{color:s,children:i}),k.length>0&&Q(ot,{children:[U(L,{children:" \xB7 "}),k.map((T,x)=>Q(is.Fragment,{children:[x>0&&U(L,{children:" \xB7 "}),T]},x))]})]})]})}let D=as(o,n.width-8);return Q(nt,{flexDirection:"column",width:n.width,children:[Q(nt,{children:[U(L,{bold:!0,children:t}),r&&Q(ot,{children:[U(L,{children:" "}),U(L,{color:"yellow",bold:!0,children:"[DEBUG]"})]})]}),Q(nt,{children:[a&&U(ot,{children:U(L,{dimColor:!0,children:"\u23F3 "})}),U(L,{dimColor:!0,children:"device "}),Q(L,{children:[D," "]}),U(L,{children:"\xB7 "}),U(L,{color:s,children:i}),k.length>0&&Q(ot,{children:[U(L,{children:" \xB7 "}),k.map((S,T)=>Q(is.Fragment,{children:[T>0&&U(L,{children:" \xB7 "}),S]},T))]})]})]})}var cs=Tl;import ds,{useMemo as ls}from"react";import{Box as wl,Text as Ke}from"ink";import{jsx as je,jsxs as us}from"react/jsx-runtime";function Rl(n){return n==="error"?"red":n==="warning"?"yellow":n==="success"?"green":n==="info"?"cyan":"white"}function Cl(n){return n==="error"?"ERROR":n==="warning"?"WARN":n==="success"?"SUCCESS":n==="info"?"INFO":n==="status"?"STATUS":"INFO"}function xl(n){let e=new Date(n),t=String(e.getHours()).padStart(2,"0"),r=String(e.getMinutes()).padStart(2,"0"),o=String(e.getSeconds()).padStart(2,"0");return`${t}:${r}:${o}`}function Al(n,e){if(typeof n!="string"&&(n=String(n??"")),n.length<=e)return[n];let t=[],r="",o=n.split(/(\s+)/);for(let i of o)if((r+i).length<=e)r+=i;else{r&&t.push(r),r="";let s=i;for(;s.length>e;)t.push(s.slice(0,e)),s=s.slice(e);r=s}return r&&t.push(r),t.length>0?t:[n]}var Dl=ds.memo(function(e){let{messagesToDisplay:t}=os(),r=e.height??14,c=Math.max(20,e.width-9-8-2-2),l=ls(()=>t.slice(-r),[t,r]),f=ls(()=>l.flatMap(p=>{let m=xl(p.ts),g=Cl(p.kind);return Al(p.message,c).map((y,_)=>({msg:p,lineIndex:_,time:_===0?m:"",kind:_===0?g:"",message:y,isContinuation:_>0}))}),[l,c]).slice(-r);return je(wl,{flexDirection:"column",borderStyle:"round",borderColor:"gray",paddingX:1,height:r+2,width:e.width,children:f.length===0?je(Ke,{dimColor:!0,children:"(no messages)"}):f.map(p=>je(Il,{item:p},`${p.msg.id}:${p.lineIndex}`))})},(n,e)=>n.height===e.height&&n.width===e.width),Il=ds.memo(function({item:e}){return us(Ke,{children:[e.time&&us(Ke,{dimColor:!0,children:[e.time," "]}),e.kind&&je(Ke,{color:Rl(e.msg.kind),children:e.kind}),e.kind&&je(Ke,{children:" "}),e.isContinuation&&je(Ke,{dimColor:!0,children:" "}),je(Ke,{dimColor:e.msg.scope==="system",children:e.message})]})}),ps=Dl;import Ol from"react";import{Box as Nr,Text as ro,useFocus as Nl}from"ink";import Pl from"ink-text-input";import{jsx as it,jsxs as fs}from"react/jsx-runtime";var Fl=Ol.memo(function(e){let{state:t,dispatch:r}=Be(),{isFocused:o}=Nl({autoFocus:!0,isActive:!t.isProcessing}),i=e.isPassphraseMode?"passphrase> ":"dlink> ",s=Math.max(10,e.width-i.length-2);return fs(Nr,{flexDirection:"column",width:e.width,children:[fs(Nr,{width:e.width,children:[it(ro,{color:e.isPassphraseMode?"cyan":"green",children:i}),it(Nr,{width:s,children:t.isProcessing?it(ro,{dimColor:!0,italic:!0,children:"Processing..."}):it(Pl,{value:t.input,onChange:a=>r({type:"SET_INPUT",payload:a}),onSubmit:e.onSubmit,placeholder:o?void 0:e.isPassphraseMode?"Enter passphrase...":'Type a command or "help"',mask:e.isPassphraseMode?"*":void 0},`input-${t.historyIndex}-${e.isPassphraseMode?"passphrase":"normal"}`)})]}),e.passphraseError&&it(Nr,{marginTop:1,children:it(ro,{color:"red",children:e.passphraseError})})]})}),ms=Fl;import{Component as Ll}from"react";import{Box as st,Text as Pr}from"ink";import{Fragment as Ml,jsx as xe,jsxs as hs}from"react/jsx-runtime";var Tt=class extends Ll{constructor(e){super(e),this.state={hasError:!1,error:null}}static getDerivedStateFromError(e){return{hasError:!0,error:e}}componentDidCatch(e,t){this.props.onError&&this.props.onError(e,t)}render(){return this.state.hasError&&this.state.error?xe(st,{flexDirection:"column",padding:1,children:xe(st,{borderStyle:"round",borderColor:"red",paddingX:1,children:hs(st,{flexDirection:"column",children:[xe(Pr,{color:"red",bold:!0,children:"\u26A0\uFE0F Application Error"}),xe(st,{height:1}),xe(Pr,{color:"red",children:this.state.error.message}),this.state.error.stack&&hs(Ml,{children:[xe(st,{height:1}),xe(Pr,{dimColor:!0,children:this.state.error.stack})]}),xe(st,{height:1}),xe(Pr,{dimColor:!0,children:"Press Ctrl+C to exit"})]})})}):this.props.children}};import{jsx as Pe,jsxs as jl}from"react/jsx-runtime";function Kl(){let{exit:n}=Ul(),{state:e,dispatch:t,engine:r,bus:o}=Be(),[i,s]=es(),a=i,c=s,l=no(g=>o.emit("console:command",g),[o]),d=Math.max(5,c-5),f=Math.min(d-3,Math.max(5,Math.floor(d*.7)));Bl((g,h)=>{if(h.ctrl&&g==="c"){r.requestStop("user exit");return}if(!e.isProcessing&&(h.upArrow||h.downArrow)){if(e.commandHistory.length===0)return;if(h.upArrow){let y=e.historyIndex===-1?e.commandHistory.length-1:Math.max(0,e.historyIndex-1);t({type:"SET_HISTORY_INDEX",payload:y}),t({type:"SET_INPUT",payload:e.commandHistory[y]})}else if(h.downArrow){if(e.historyIndex===-1)return;let y=e.historyIndex+1;y>=e.commandHistory.length?(t({type:"SET_HISTORY_INDEX",payload:-1}),t({type:"SET_INPUT",payload:""})):(t({type:"SET_HISTORY_INDEX",payload:y}),t({type:"SET_INPUT",payload:e.commandHistory[y]}))}}}),$l(()=>{t({type:"RESET_HISTORY_INDEX_IF_TYPING"})},[e.input,t]);let p=no(async g=>{let h=g.trim();t({type:"RESET_INPUT"}),t({type:"RESET_HISTORY_INDEX"}),h&&t({type:"ADD_COMMAND_TO_HISTORY",payload:h}),t({type:"SET_IS_PROCESSING",payload:!0});try{await l(h)}catch(y){let _=B(y),b=new ye(`Command failed: ${_}`,{ts:Date.now(),kind:"error"});t({type:"ADD_MESSAGE",payload:b})}finally{t({type:"SET_IS_PROCESSING",payload:!1})}},[t,n,l,r]),m=no((g,h)=>{let y=new ye(`UI Error: ${g.message}`,{ts:Date.now(),kind:"error"});t({type:"ADD_MESSAGE",payload:y})},[t]);return Pe(Tt,{onError:m,children:jl(oo,{flexDirection:"column",padding:1,width:a,children:[Pe(cs,{width:a-2}),Pe(oo,{height:1}),Pe(ps,{height:f,width:a-2}),Pe(oo,{height:1}),Pe(ms,{width:a-2,onSubmit:p})]})})}function io({engine:n,bus:e}){return Pe(ns,{engine:n,bus:e,children:Pe(Kl,{})})}function gs(n,e){let t=n.runtime.flags;t.headless?console.log(`[agent] Headless UI (${t.headlessReason})`):console.warn(`[agent] No TTY stdin; non-interactive boot (${t.headlessReason})`),e.emit("ui:initialized",Date.now());let r=setInterval(()=>{},6e4);return new Promise(o=>{process.on("SIGTERM",()=>{clearInterval(r),o()}),process.on("SIGINT",()=>{clearInterval(r),o()})})}function ys(n,e){let t=n.runtime.flags.headless?null:Qn();if(!t)return gs(n,e);let{waitUntilExit:r}=ql(Vl.createElement(io,{engine:n,bus:e}),{stdin:t});return r()}var Fr=class{name="ui-orchestrator";async onStarted(e){ys(e.engine,e.bus)}async onStop(e){e.notifier.info("UI exited, stopping engine",{scope:"system"}),e.engine&&e.engine.requestStop("UI exited")}};import cu from"lodash/truncate.js";import so from"lodash/isEmpty.js";import eu from"lodash/isString.js";import at from"lodash/trim.js";import tu from"lodash/trimEnd.js";import Wl from"lodash/isEmpty.js";import Gl from"lodash/isString.js";import{randomUUID as Hl}from"node:crypto";import{existsSync as Jl,mkdirSync as zl,readFileSync as Yl,writeFileSync as Ql}from"node:fs";import bs from"node:path";var Xl="telemetry.json";function Zl(){return bs.join(Z(),Xl)}function Lr(){let n=Zl();try{if(Jl(n)){let t=JSON.parse(Yl(n,"utf8"));if(Gl(t.anonymous_id)&&!Wl(t.anonymous_id))return t.anonymous_id}}catch{}let e=Hl().replace(/-/g,"");try{zl(bs.dirname(n),{recursive:!0});let t={anonymous_id:e,created_at:new Date().toISOString()};Ql(n,JSON.stringify(t,null,2),"utf8")}catch{}return e}var ru=1e4,nu=En,ou=200,iu=4e3,su="/api/telemetry/agent";function ao(n=process.env){return!(!_t("DLINK_TELEMETRY",!0,n)||_t("DO_NOT_TRACK",!1,n))}var Mr=class{enabled;transport;queue;timer;inFlight;constructor(e,t=ao()){this.transport=e,this.enabled=t,this.queue=[],this.timer=null,this.inFlight=new Set}get isEnabled(){return this.enabled}get anonymousId(){return this.enabled?Lr():"disabled"}capture(e,t,r){if(this.enabled&&!(!eu(e)||so(at(e)))&&!(this.queue.length>=ou)){if(this.queue.push({kind:at(e),severity:r,at:Date.now(),props:t&&Object.keys(t).length>0?t:void 0}),this.queue.length>=nu){this.flush();return}this.timer||(this.timer=setTimeout(()=>void this.flush(),ru),this.timer.unref?.())}}async flush(){if(this.timer&&(clearTimeout(this.timer),this.timer=null),!this.enabled||this.queue.length===0)return;let e=this.queue.splice(0,En);if(this.transport.socketReady()){this.sendOverSocket(e),this.queue.length>0&&this.flush();return}let t=this.post(e).finally(()=>this.inFlight.delete(t));this.inFlight.add(t),await t,this.queue.length>0&&await this.flush()}async shutdown(){await this.flush(),await Promise.allSettled([...this.inFlight])}sendOverSocket(e){try{this.transport.socketSend(JSON.stringify({type:"agent_event",schema_version:Sn,events:e.map(t=>this.wire(t))}))}catch{return}}async post(e){let t=this.transport.controlBaseUrl();if(!t||so(at(t)))return;let r=new AbortController,o=setTimeout(()=>r.abort(),iu);o.unref?.();let i=this.transport.accessToken(),s={"content-type":"application/json"};i&&!so(at(i))&&(s.authorization=`Bearer ${at(i)}`);try{await fetch(`${tu(at(t),"/")}${su}`,{method:"POST",headers:s,body:JSON.stringify({schema_version:Sn,fingerprint:this.anonymousId,events:e.map(a=>this.wire(a))}),signal:r.signal})}catch{return}finally{clearTimeout(o)}}wire(e){let t={kind:e.kind};return e.severity&&(t.severity=e.severity),typeof e.at=="number"&&(t.at=e.at),e.props&&(t.props=e.props),t}};var X={SESSION_STARTED:"agent.session.started",SESSION_EXITED:"agent.session.exited",SESSION_CRASHED:"agent.session.crashed",CONFIG_LOADED:"agent.config.loaded",SECRETS_BACKEND_RESOLVED:"agent.secrets.backend_resolved",AUTH_SIGNIN_REQUESTED:"agent.auth.signin_requested",AUTH_SIGNIN_COMPLETED:"agent.auth.signin_completed",AUTH_SIGNOUT:"agent.auth.signout",AUTH_TOKENS_REFRESHED:"agent.auth.tokens_refreshed",SOCKET_CONNECTED:"agent.socket.connected",SOCKET_DISCONNECTED:"agent.socket.disconnected",SOCKET_RETRYING:"agent.socket.retrying",SOCKET_SESSION_READY:"agent.socket.session_ready",SOCKET_SESSION_CONFLICT:"agent.socket.session_conflict",TOOL_CALL_RECEIVED:"agent.tool.call_received"};var au="protects the store only if it leaves this machine; set DLINK_PASSPHRASE or unlock a keychain for local protection";function vs(n){let e=[n.label];n.migratedFrom!==void 0&&e.push(`migrated from ${n.migratedFrom}`),n.degraded&&n.expectedBackend!==void 0&&e.push(`secrets were stored by ${n.expectedBackend}, which is unavailable now`),n.weak&&e.push(au);let t=Es(n);return t.length>0&&e.push(`skipped ${t.join(", ")}`),{ok:!n.weak&&!n.degraded,detail:e.join("; ")}}function Ss(n){let e={backend:n.backend,weak:n.weak,degraded:n.degraded,skipped:Es(n)};return n.migratedFrom!==void 0&&(e.migrated_from=n.migratedFrom),e}function Es(n){return n.attempts.filter(e=>!e.available).map(e=>`${e.id}:${e.reason??"unknown"}`)}var $r=class{name="telemetry-orchestrator";relay;startedAt;reachedReady;toolCalls;context=null;accessToken;relayNegotiated=!1;socketConnected=!1;constructor(){this.startedAt=Date.now(),this.reachedReady=!1,this.toolCalls=0;let e={controlBaseUrl:()=>this.context?.engine.configurationContext.configuration.controlBaseUrl,accessToken:()=>this.accessToken,socketSend:t=>this.context?.bus.emit("ws:tx",{text:t}),socketReady:()=>this.socketConnected&&this.relayNegotiated};this.relay=new Mr(e)}handlers(){return{"config:loaded":()=>{this.relay.capture(X.CONFIG_LOADED)},"auth:signin:requested":()=>{this.relay.capture(X.AUTH_SIGNIN_REQUESTED)},"auth:signin:completed":()=>{this.relay.capture(X.AUTH_SIGNIN_COMPLETED,{seconds_since_start:this.elapsedSec()})},"auth:signout:requested":()=>{this.relay.capture(X.AUTH_SIGNOUT)},"auth:tokens:updated":e=>{this.accessToken=e.accessToken||void 0,this.relay.capture(X.AUTH_TOKENS_REFRESHED)},"ws:connected":()=>{this.socketConnected=!0,this.relay.capture(X.SOCKET_CONNECTED)},"ws:disconnected":e=>{this.socketConnected=!1,this.relayNegotiated=!1,this.relay.capture(X.SOCKET_DISCONNECTED,{code:e.code})},"ws:retrying":e=>{this.relay.capture(X.SOCKET_RETRYING,{attempt:e.attempt,retry_in_sec:e.retryInSec})},"auth:session_init_ack":e=>{this.reachedReady=!0,this.relayNegotiated=e.ok===!0&&He(e.capabilities,G.TELEMETRY_RELAY_V1),this.relay.capture(X.SOCKET_SESSION_READY,{mode:e.ok?e.mode??null:null,reason:e.ok?e.reason??null:null,seconds_since_start:this.elapsedSec()})},"auth:session_conflict":()=>{this.relay.capture(X.SOCKET_SESSION_CONFLICT)},"tool:call":e=>{this.toolCalls+=1,this.relay.capture(X.TOOL_CALL_RECEIVED,{tool:e.tool,call_index:this.toolCalls})},"engine:crashed":e=>{this.relay.capture(X.SESSION_CRASHED,{reason:e.reason,detail:cu(fn(e.detail),{length:200,omission:""})||null,uptime_sec:this.elapsedSec(),reached_session_ready:this.reachedReady,tool_calls:this.toolCalls},"error")}}}async onStart(e){this.context=e,this.relay.capture(X.SESSION_STARTED,{headless:e.headless}),this.relay.capture(X.SECRETS_BACKEND_RESOLVED,{...Ss(e.engine.secretsReport),platform:process.platform})}async onStop(e){this.relay.capture(X.SESSION_EXITED,{uptime_sec:this.elapsedSec(),reached_session_ready:this.reachedReady,tool_calls:this.toolCalls}),await this.relay.shutdown()}elapsedSec(){return Math.round((Date.now()-this.startedAt)/1e3)}};var Ur=class{name="os-signals-orchestrator";sigint;sigterm;async onStart(e){let t=r=>{e.notifier.warn(`received ${r}`,{scope:"system"}),e.engine.requestStop(r)};this.sigint=()=>t("SIGINT"),this.sigterm=()=>t("SIGTERM"),process.on("SIGINT",this.sigint),process.on("SIGTERM",this.sigterm)}async onStarted(e){return Promise.resolve()}async onStop(e){this.sigint&&process.off("SIGINT",this.sigint),this.sigterm&&process.off("SIGTERM",this.sigterm),this.sigint=void 0,this.sigterm=void 0,e.notifier.info("OS signal handlers removed",{scope:"system"})}async onStopped(e){return Promise.resolve()}};import Ve from"node:fs";import lo from"node:path";var Br=class{handlers=new Map;subcommandHandlers=new Map;command(e,t){if(this.handlers.has(e))throw new Error(`Command '${e}' is already registered`);return this.handlers.set(e,t),this}subcommand(e,t,r){this.subcommandHandlers.has(e)||this.subcommandHandlers.set(e,new Map);let o=this.subcommandHandlers.get(e);if(o.has(t))throw new Error(`Subcommand '${e} ${t}' is already registered`);return o.set(t,r),this}commandStringToArgv(e){let t=[],r="",o=!1,i="";for(let s=0;s<e.length;s++){let a=e[s];a==='"'||a==="'"?o&&a===i?(t.push(r),r="",o=!1,i=""):o?r+=a:(r&&(t.push(r),r=""),o=!0,i=a):a===" "&&!o?r&&(t.push(r),r=""):r+=a}return(o||r)&&t.push(r),["node","script",...t]}parseString(e){let t=this.commandStringToArgv(e);return this.parse(t)}parse(e){let t=e.slice(2);if(t.length===0)return null;let r={command:"",args:[],options:{}},o=0;for(;o<t.length&&t[o]?.startsWith("--");)o++;if(o>=t.length||!t[o])return null;for(r.command=t[o],o++;o<t.length&&t[o]?.startsWith("--");)o++;for(o<t.length&&t[o]&&!t[o].startsWith("--")&&(r.subcommand=t[o],o++);o<t.length;){let i=t[o];if(i.startsWith("--")){let s=i.slice(2);if(s.includes("=")){let[a,c]=s.split("=",2);r.options[a]=c||!0}else{let a=t[o+1];a&&!a.startsWith("--")?(r.options[s]=a,o++):r.options[s]=!0}}else r.args.push(i);o++}return r}async execute(e){let t=this.parse(e);if(!t)return!1;if(t.subcommand){let o=this.subcommandHandlers.get(t.command);if(o){let i=o.get(t.subcommand);if(i)return await i(t),!0}}let r=this.handlers.get(t.command);return r?(await r(t),!0):!1}hasCommand(e,t){return t?this.subcommandHandlers.get(e)?.has(t)??!1:this.handlers.has(e)}getCommands(){return Array.from(this.handlers.keys())}};var co=class{kind;payloadJson;constructor(e,t){this.kind=e,this.payloadJson=t}},Kr=class{matchers=[];register(e){return this.matchers.push(e),this}build(e){let t=[e.command.toLowerCase()];e.subcommand&&t.push(e.subcommand.toLowerCase());for(let r of this.matchers){let o=r(t,e);if(o.handled){let i;if(o.job)i=o.job;else if(o.kind)i=this.createCommandInput(o.kind,e);else return null;return i}}return null}createCommandInput(e,t){let r={command:t.command,subcommand:t.subcommand,args:t.args,options:t.options};return new co(e,JSON.stringify(r))}};var jr=class{name="console-orchestrator";commandParser;commandJobBuilder;bridgeConnected=!1;constructor(){this.commandParser=new Br,this.commandJobBuilder=new Kr,this.setupCommandMappings()}onRegister(e){}async onStart(e){e.notifier.info("Starting console orchestrator (UI)",{scope:"system"}),e.on("ws:connected",()=>{this.bridgeConnected=!0}),e.on("ws:disconnected",()=>{this.bridgeConnected=!1}),e.on("console:command",async t=>{try{let r=this.commandParser.parseString(t);if(!r){e.notifier.warn("Invalid command format");return}let o=this.commandJobBuilder.build(r);if(!o){this.reportUnknownCommand(r,e);return}switch(o.kind){case"help":for(let i of Yi())e.notifier.info(i);break;case"start":this.handleStart(e);break;case"stop":this.handleStop(e);break;case"status":this.handleStatus(e);break;case"doctor":this.handleDoctor(e);break;case"roots-list":this.handleRootsList(e);break;case"roots-add":this.handleRootsAdd(r,e);break;case"signin":e.bus.emit("auth:signin:requested",void 0),e.notifier.info("Sign-in requested");break;case"signout":e.bus.emit("auth:signout:requested",void 0),e.notifier.info("Sign-out requested");break;case"debug-on":e.flags.debug=!0,e.bus.emit("runtime:debug:changed",{enabled:!0}),e.notifier.success("Debug mode enabled");break;case"debug-off":e.flags.debug=!1,e.bus.emit("runtime:debug:changed",{enabled:!1}),e.notifier.success("Debug mode disabled");break;case"replace":e.bus.emit("auth:session_conflict:resolve",{choice:"USE_NEW"}),e.notifier.info("Taking over the existing session");break;default:e.notifier.warn(`Command not implemented: ${o.kind}`);break}}catch(r){let o=B(r);e.notifier.error(`Command failed: ${o}`)}})}async onStarted(e){e.notifier.info("Console orchestrator started",{scope:"system"})}async onStopped(e){}reportUnknownCommand(e,t){let r=`${e.command}${e.subcommand?" "+e.subcommand:""}`,o=this.suggestCommand(e.command),i=o?` Did you mean "${o}"?`:' Type "help" for commands.';t.notifier.warn(`Unknown command: ${r}.${i}`)}suggestCommand(e){let t=e.toLowerCase();if(!t)return null;let r=null;for(let i of Wi()){let s=this.editDistance(t,i);(r===null||s<r.distance)&&(r={name:i,distance:s})}if(!r)return null;let o=t.length<=4?1:2;return r.distance<=o?r.name:null}editDistance(e,t){let r=t.length+1,o=Array.from({length:r},(i,s)=>s);for(let i=1;i<=e.length;i++){let s=[i];for(let a=1;a<r;a++){let c=o[a-1]+(e[i-1]===t[a-1]?0:1),l=s[a-1]+1,d=o[a]+1;s[a]=Math.min(c,l,d)}o=s}return o[r-1]}isSignedIn(e){let t=e.tokens?.accessTokenExpSec;return typeof t!="number"?!1:t>Math.floor(Date.now()/1e3)}handleStart(e){let t=e.engine.configurationContext.configuration;if(!t.device?.id){e.notifier.warn("Bridge: no device identity yet. Wait for configuration to load.");return}if(!this.isSignedIn(t)){e.notifier.warn("Bridge: not signed in. Run signin first.");return}if(this.bridgeConnected){e.notifier.info("Bridge is already connected");return}e.bus.emit("auth:ws:reconnect",void 0),e.notifier.info("Bridge start requested")}handleStop(e){if(!this.bridgeConnected){e.notifier.info("Bridge is already disconnected");return}e.bus.emit("ws:disconnect",{reason:"console: stop"}),e.notifier.info("Bridge stop requested")}handleStatus(e){let t=e.engine.configurationContext.configuration,r=[["Agent",ue()],["Engine",String(e.engine.runtime.phase)],["Device",t.device?.id??"(none)"],["Device name",t.device?.name??"(none)"],["Signed in",this.isSignedIn(t)?"yes":"no"],["Bridge",this.bridgeConnected?"connected":"disconnected"],["Control URL",t.controlBaseUrl??"(unset)"],["Bridge URL",t.bridgeWsUrl??"(unset)"],["Directories",String(t.directories.length)],["Config dir",Z()]],o=r.reduce((i,[s])=>Math.max(i,s.length),0);e.notifier.info("Status:");for(let[i,s]of r)e.notifier.info(` ${i.padEnd(o)} ${s}`)}handleDoctor(e){let t=e.engine.configurationContext.configuration,r=[],o=Number.parseInt(process.versions.node.split(".")[0],10);r.push({label:"Node runtime",ok:Number.isFinite(o)&&o>=20,detail:`v${process.versions.node} (requires >= 20)`});let i=Z(),s=!1,a=i;try{Ve.mkdirSync(i,{recursive:!0}),Ve.accessSync(i,Ve.constants.W_OK),s=!0}catch(m){a=`${i} (${B(m)})`}r.push({label:"Config directory",ok:s,detail:a}),r.push({label:"Device identity",ok:!!t.device?.id&&!!t.device?.keys?.public,detail:t.device?.id?`id ${t.device.id}`:"no device id"});let c=this.isSignedIn(t);r.push({label:"Authentication",ok:c,detail:c?"access token valid":"not signed in (run signin)"}),r.push({label:"Control URL",ok:!!t.controlBaseUrl,detail:t.controlBaseUrl??"unset"}),r.push({label:"Bridge URL",ok:!!t.bridgeWsUrl,detail:t.bridgeWsUrl??"unset"});let l=vs(e.engine.secretsReport);r.push({label:"Secret storage",ok:l.ok,detail:l.detail}),r.push({label:"Bridge connection",ok:this.bridgeConnected,detail:this.bridgeConnected?"connected":"disconnected"});let d=t.directories.filter(m=>!Ve.existsSync(m.path));r.push({label:"Shared directories",ok:t.directories.length>0&&d.length===0,detail:t.directories.length===0?"none configured":d.length===0?`${t.directories.length} present`:`missing: ${d.map(m=>m.path).join(", ")}`});let f=r.reduce((m,g)=>Math.max(m,g.label.length),0);e.notifier.info("Doctor:");for(let m of r){let g=` ${m.ok?"PASS":"WARN"} ${m.label.padEnd(f)} ${m.detail}`;m.ok?e.notifier.success(g):e.notifier.warn(g)}let p=r.filter(m=>!m.ok).length;p===0?e.notifier.success("Doctor: all checks passed"):e.notifier.warn(`Doctor: ${p} check(s) need attention`)}handleRootsList(e){let t=e.engine.configurationContext.configuration.directories;if(t.length===0){e.notifier.info("No directories shared. Add one with: roots add <path>");return}e.notifier.info(`Shared directories (${t.length}):`);for(let r of t){let o=Ve.existsSync(r.path)?"":" (missing)";e.notifier.info(` ${r.name} ${r.path}${o}`)}}handleRootsAdd(e,t){let r=e.args[0];if(!r){t.notifier.warn("Usage: roots add <path>");return}let o=lo.resolve(r);if(!Ve.existsSync(o)){t.notifier.warn(`Directory does not exist: ${o}`);return}let i;try{i=Ve.statSync(o)}catch(l){t.notifier.warn(`Cannot read ${o}: ${B(l)}`);return}if(!i.isDirectory()){t.notifier.warn(`Not a directory: ${o}`);return}let s=t.engine.configurationContext.configuration;if(s.directories.some(l=>lo.resolve(l.path).toLowerCase()===o.toLowerCase())){t.notifier.info(`Already shared: ${o}`);return}let c={id:gt(o),name:lo.basename(o),path:o,tag:ht(o)};s.directories.push(c),t.bus.emit("config:save:requested",s),t.bus.emit("meta:data:requested:directories",void 0),t.notifier.success(`Added directory: ${o}`)}setupCommandMappings(){let e=this.commandJobBuilder;e.register(t=>{if(t.length===1){let r=t[0];if(r==="help"||r==="?")return{handled:!0,kind:"help"};if(r==="roots")return{handled:!0,kind:"roots-list"};if(r==="start"||r==="run")return{handled:!0,kind:"start"};if(r==="stop")return{handled:!0,kind:"stop"};if(r==="signin")return{handled:!0,kind:"signin"};if(r==="signout")return{handled:!0,kind:"signout"};if(r==="status")return{handled:!0,kind:"status"};if(r==="doctor")return{handled:!0,kind:"doctor"};if(r==="replace"||r==="yes"||r==="y")return{handled:!0,kind:"replace"}}return{handled:!1}}),e.register(t=>{if(t.length===2){let[r,o]=t;if(r==="roots"){if(o==="add")return{handled:!0,kind:"roots-add"};if(o==="list")return{handled:!0,kind:"roots-list"}}if(r==="debug"){if(o==="on")return{handled:!0,kind:"debug-on"};if(o==="off")return{handled:!0,kind:"debug-off"}}}return{handled:!1}}),e.register((t,r)=>{if(t.length===1&&t[0]==="debug"&&r.args.length>0){let o=r.args[0];if(o==="on")return{handled:!0,kind:"debug-on"};if(o==="off")return{handled:!0,kind:"debug-off"}}return{handled:!1}})}};import qe from"ws";var Vr=class{ws=null;state={kind:"DISCONNECTED"};stopped=!1;connecting=!1;connId=0;connectionTimeout=null;heartbeatInterval=null;heartbeatTimeout=null;awaitingPong=!1;sendQueue=[];url;abortSignal;connectionTimeoutMs;heartbeatIntervalMs;pongTimeoutMs;maxSendQueueSize;sendQueueItemTtlMs;onStateChangeCallback;onErrorCallback;onConnectedCallback;onDisconnectedCallback;onMessageCallback;constructor(e,t={}){this.url=e,this.abortSignal=t.abortSignal,this.connectionTimeoutMs=t.connectionTimeoutMs??1e4,this.heartbeatIntervalMs=t.heartbeatIntervalMs??2e4,this.pongTimeoutMs=t.pongTimeoutMs??1e4,this.maxSendQueueSize=t.maxSendQueueSize??1e3,this.sendQueueItemTtlMs=t.sendQueueItemTtlMs??6e4,this.abortSignal&&this.abortSignal.addEventListener("abort",()=>{this.stop()},{once:!0})}registerOnStateChangeCallback(e){this.onStateChangeCallback=e}registerOnErrorCallback(e){this.onErrorCallback=e}registerOnConnectedCallback(e){this.onConnectedCallback=e}registerOnDisconnectedCallback(e){this.onDisconnectedCallback=e}registerOnMessageCallback(e){this.onMessageCallback=e}getState(){return this.state}getSocket(){return this.ws}isConnected(){return this.ws?.readyState===qe.OPEN}async connect(){if(this.stopped)throw new Error("Socket is stopped");if(!(this.connecting||this.isConnected())){this.connecting=!0,this.updateState({kind:"CONNECTING"});try{await this.connectWebSocketOnce()}catch(e){let t=e instanceof Error?e:new Error(String(e));throw this.onErrorCallback?.(t),this.updateState({kind:"DISCONNECTED"}),t}finally{this.connecting=!1}}}stop(){this.stopped=!0,this.disconnect(!0)}reset(){this.stopped=!1}disconnect(e=!1){e&&(this.stopped=!0),this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.stopHeartbeat();let t=this.ws;this.ws=null,this.connecting=!1,t&&this.closeGracefullyThenTerminate(t,1e3,"client disconnect",2e3),this.updateState({kind:"DISCONNECTED"})}send(e,t){if(this.stopped){t?.(new Error("Socket is stopped"));return}let r=this.ws;if(r&&r.readyState===qe.OPEN){r.send(e,i=>t?.(i??void 0));return}let o=Date.now();if(this.pruneSendQueue(o),this.sendQueue.length>=this.maxSendQueueSize){t?.(new Error(`Send queue full (max ${this.maxSendQueueSize})`));return}this.sendQueue.push({data:e,cb:t,expiresAt:o+this.sendQueueItemTtlMs})}closeGracefullyThenTerminate(e,t,r,o){try{(e.readyState===qe.OPEN||e.readyState===qe.CONNECTING)&&e.close(t,r)}catch{}let i=setTimeout(()=>{try{e.terminate()}catch{}},o);e.once("close",()=>clearTimeout(i))}async connectWebSocketOnce(){let e=++this.connId;return new Promise((t,r)=>{if(this.stopped){r(new Error("Socket is stopped"));return}let o=!1,i=!1,s=()=>{this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null)},a=()=>{i||(i=!0,s(),t())},c=(d,f)=>{i||(i=!0,s(),f&&this.closeGracefullyThenTerminate(f,1e3,"connect failed",1500),r(d))},l;try{l=new qe(this.url),this.connectionTimeout=setTimeout(()=>{c(new Error(`Connection timeout: unable to connect to ${this.url} within ${this.connectionTimeoutMs}ms`),l)},this.connectionTimeoutMs),l.on("open",()=>{if(o=!0,e!==this.connId){this.closeGracefullyThenTerminate(l,1e3,"stale connection",500);return}this.ws=l,this.retryResetOnConnect(),this.updateState({kind:"CONNECTED"}),this.onConnectedCallback?.(l),this.startHeartbeat(e),this.flushSendQueue(),a()}),l.on("error",d=>{if(e!==this.connId)return;let f=d instanceof Error?d:new Error(String(d));if(!o&&!i){c(f,l);return}this.onErrorCallback?.(f)}),l.on("close",(d,f)=>{if(e!==this.connId)return;let p=f?.toString?.()||"";if(!o&&!i){this.ws=null,this.stopHeartbeat(),this.updateState({kind:"DISCONNECTED"}),c(new Error(`WebSocket closed before connection established: ${d} ${p}`),l);return}this.ws===l&&(this.ws=null),this.stopHeartbeat(),this.updateState({kind:"DISCONNECTED"}),this.onDisconnectedCallback?.(d,p||`code ${d}`)}),l.on("message",d=>{if(e!==this.connId){this.onErrorCallback?.(new Error("Message ignored - connection ID mismatch"));return}if(this.ws!==l){this.onErrorCallback?.(new Error("Message ignored - socket mismatch"));return}this.onMessageCallback?.(d)}),l.on("pong",()=>{e===this.connId&&(this.awaitingPong=!1,this.heartbeatTimeout&&(clearTimeout(this.heartbeatTimeout),this.heartbeatTimeout=null))}),this.abortSignal&&this.abortSignal.addEventListener("abort",()=>{e===this.connId&&(this.closeGracefullyThenTerminate(l,1e3,"aborted",1e3),i||c(new Error("Connection aborted"),l))},{once:!0})}catch(d){let f=d instanceof Error?d:new Error(String(d));r(f)}})}retryResetOnConnect(){}startHeartbeat(e){this.stopHeartbeat(),this.ws&&(this.awaitingPong=!1,this.heartbeatInterval=setInterval(()=>{if(this.stopped||e!==this.connId)return;let r=this.ws;if(!(!r||r.readyState!==qe.OPEN)){if(this.awaitingPong){this.closeGracefullyThenTerminate(r,4e3,"pong timeout",1e3);return}this.awaitingPong=!0;try{r.ping()}catch{this.closeGracefullyThenTerminate(r,1011,"ping failed",1e3);return}this.heartbeatTimeout&&clearTimeout(this.heartbeatTimeout),this.heartbeatTimeout=setTimeout(()=>{if(e!==this.connId)return;let o=this.ws;o&&this.closeGracefullyThenTerminate(o,4e3,"pong timeout",1e3)},this.pongTimeoutMs)}},this.heartbeatIntervalMs))}stopHeartbeat(){this.awaitingPong=!1,this.heartbeatInterval&&(clearInterval(this.heartbeatInterval),this.heartbeatInterval=null),this.heartbeatTimeout&&(clearTimeout(this.heartbeatTimeout),this.heartbeatTimeout=null)}flushSendQueue(){let e=this.ws;if(!e||e.readyState!==qe.OPEN)return;let t=Date.now();this.pruneSendQueue(t);let r=this.sendQueue;this.sendQueue=[];for(let o of r)e.send(o.data,i=>o.cb?.(i??void 0))}pruneSendQueue(e){if(this.sendQueue.length===0)return;let t=[];for(let r of this.sendQueue)r.expiresAt>=e?t.push(r):r.cb?.(new Error("Send dropped: queued item expired"));this.sendQueue=t}updateState(e){this.state=e,this.onStateChangeCallback?.(e)}};var qr=class{name="websocket-orchestrator";socket=null;stopped=!1;connectLoopInFlight=null;retryAttempt=0;countdownTimer=null;lastUrl=null;endpointSource=void 0;discoveredFailures=0;reconnectPolicy=null;endpointOverride=null;async onStart(e){e.notifier.info("WS: orchestrator started",{scope:"system"})}async onStarted(e){let t=e.engine.configurationContext.configuration;await this.isConnectableToBridge(t,e)&&this.ensureStarted(e,"onStarted")}async onStop(e){this.stopped=!0,this.clearCountdown(),this.socket&&(e.notifier.info("WS: stopping socket (onStop)",{scope:"system"}),this.socket.stop(),this.socket=null),e.notifier.info("WS: orchestrator stopped",{scope:"system"})}handlers(){let e=async(t,r)=>{if(this.stopped)return;let o=r.engine.configurationContext.configuration;await this.isConnectableToBridge(o,r)&&this.ensureStarted(r,t)};return{"config:cache:validated":async(t,r)=>e("config:cache:validated",r),"auth:signout:requested":async(t,r)=>{r.notifier.info("WS: sign-out requested -> disconnecting"),this.stopped=!0,this.clearCountdown(),this.socket?.stop(),this.socket=null},"ws:disconnect":async(t,r)=>{r.notifier.info("WS: disconnect requested",{scope:"system"}),this.stopped=!0,this.clearCountdown(),this.socket?.stop(),this.socket=null},"auth:ws:reconnect":async(t,r)=>{r.notifier.info("WS: reconnect requested by auth",{scope:"system"}),this.retryAttempt=0,this.clearCountdown(),this.stopped=!0,this.socket?.stop(),this.connectLoopInFlight&&await this.connectLoopInFlight.catch(()=>{}),this.socket=null,this.stopped=!1,this.ensureStarted(r,"auth:ws:reconnect")},"ws:reconnect:policy":async(t,r)=>{this.reconnectPolicy=t,r.notifier.info(`WS: reconnect policy reconnect=${t.reconnect} delay_ms=${t.delayMs??"-"} url=${t.url??"-"} rediscover=${t.rediscover===!0}`,{scope:"system"})},"ws:tx":async(t,r)=>{let o=this.socket?.getSocket();if(!o||o.readyState!==1){r.notifier.info("WS: TX dropped (not connected)",{scope:"system"});return}o.send(t.text)}}}ensureStarted(e,t){if(this.connectLoopInFlight){e.notifier.info(`WS: connect loop already running (reason=${t})`,{scope:"system"});return}let r=this.socket?.getSocket();if(r&&r.readyState<=1){e.notifier.info(`WS: already connected/connecting, skipping (reason=${t})`,{scope:"system"});return}this.connectLoopInFlight=this.startOrJoinConnectLoop(e,t).finally(()=>{this.connectLoopInFlight=null})}resolveEndpoint(e){let t=e.engine.configurationContext.loader,r=e.engine.configurationContext.configuration,o=t.resolveBridgeWsUrl(r.discovery);return this.endpointOverride&&(o.source==="discovered"||o.source==="bundled"||o.source===void 0)?{url:this.endpointOverride,source:"discovered"}:o}applyEndpointOverride(e,t){e&&(this.endpointOverride=e,t.notifier.info(`WS: server directed the next connection to ${e}`,{scope:"system"}))}async reconnectAfter(e,t){this.retryAttempt=0,this.clearCountdown(),e>0&&await yt(e),!this.stopped&&this.ensureStarted(t,"socket:disconnected")}noteConnectFailure(e){return this.endpointSource!=="discovered"?(this.discoveredFailures=0,!1):(this.discoveredFailures+=1,this.discoveredFailures<wn?!1:(this.discoveredFailures=0,this.endpointOverride=null,e.notifier.info(`WS: discovered endpoint failed ${wn}x -> falling back to the bundled endpoint`,{scope:"system"}),e.bus.emit("discovery:cache:discarded",{reason:"connect-failed-twice"}),!0))}async startOrJoinConnectLoop(e,t){this.stopped=!1;let r=e.engine.configurationContext.configuration;if(!await this.isConnectableToBridge(r,e))return;let i=this.resolveEndpoint(e),s=String(i.url??r.bridgeWsUrl),a=this.lastUrl;if(this.endpointSource=i.source,this.lastUrl=s,e.notifier.info(`WS: ensure connection (reason=${t}) url=${s} source=${this.endpointSource??"config"}`,{scope:"system"}),this.socket&&a!==null&&a!==s&&(e.notifier.info(`WS: endpoint changed ${a} -> ${s}; rebuilding the socket`,{scope:"system"}),this.socket.stop(),this.socket=null),!this.socket){let c=new Vr(s,{abortSignal:e.signal,connectionTimeoutMs:1e4,heartbeatIntervalMs:2e4,pongTimeoutMs:1e4});this.socket=c,c.registerOnStateChangeCallback(l=>this.handleStateChange(l,e)),c.registerOnErrorCallback(l=>{e.notifier.error(`WS: transport error: ${l.message}`)}),c.registerOnConnectedCallback(l=>{this.socket===c&&(this.retryAttempt=0,this.clearCountdown(),e.notifier.success(e.flags.debug?`WS: connected (${s})`:"WS: connected"),e.bus.emit("ws:connected",{url:s,attempt:0}))}),c.registerOnDisconnectedCallback((l,d)=>{if(this.socket!==c){e.notifier.info(`WS: ignoring stale disconnect (code=${l})`,{scope:"system"});return}if(e.notifier.warn(`WS: disconnected code=${l} reason=${d||"-"}`),e.bus.emit("ws:disconnected",{code:l,reason:d}),this.stopped){e.notifier.info(`WS: stopped flag set, skipping auto-reconnect (code=${l})`,{scope:"system"});return}if(l===4001){e.notifier.info("WS: auth disconnect (4001) -> waiting for auth",{scope:"system"});return}if(l===4011){this.stopped=!0,this.socket?.stop(),this.socket=null;return}if(l===4013||l===4014){e.notifier.error(`This agent is not accepted by the server (code=${l} ${d||"-"}). Upgrade with: npm i -g @devicelink/dlink`),this.stopped=!0,this.socket?.stop(),this.socket=null;return}let f=this.reconnectPolicy;if(this.reconnectPolicy=null,f&&!f.reconnect){e.notifier.info("WS: server asked us not to reconnect",{scope:"system"}),this.stopped=!0,this.socket?.stop(),this.socket=null;return}if(f){this.applyEndpointOverride(f.url,e),this.reconnectAfter(f.delayMs??0,e);return}this.ensureStarted(e,"socket:disconnected")}),c.registerOnMessageCallback(l=>{if(this.socket!==c)return;let d=typeof l=="string"?l:l.toString("utf8");e.bus.emit("ws:rx",{text:d})})}for(;!this.stopped;)try{let c=this.retryAttempt+1;e.notifier.info(`WS: connecting attempt #${c} to ${s}`,{scope:"system",groupKey:"ws:connecting"}),e.bus.emit("ws:connecting",{url:s,attempt:c}),await this.socket.connect();return}catch(c){if(this.stopped)return;if(this.retryAttempt+=1,this.noteConnectFailure(e)){this.socket?.stop(),this.socket=null,this.retryAttempt=0,this.clearCountdown(),e.bus.emit("ws:retrying",{retryInSec:1,attempt:0}),this.ensureStartedSoon(e);return}let l=this.computeBackoffMs(this.retryAttempt),d=Math.max(1,Math.ceil(l/1e3)),f=B(c);e.notifier.warn(`WS: connect failed (attempt=${this.retryAttempt}) -> retry in ${d}s (${f})`,{scope:"system",category:["websocket-connect"],groupKey:"ws:connect-retry"});let p={retryInSec:d,attempt:this.retryAttempt};e.bus.emit("ws:retrying",p),this.startCountdown(d,e),await this.interruptibleSleep(l)}}async isConnectableToBridge(e,t){if(!e.device?.id)return t.notifier.error("WS: cannot connect: device.id missing"),!1;if(!e.bridgeWsUrl)return t.notifier.error("WS: cannot connect: bridgeWsUrl missing"),!1;if(!e.device?.keys?.public)return t.notifier.error("WS: cannot connect: device public key missing"),!1;let r=await t.engine.secrets.get("refreshToken");return!!r.ok&&!!r.value?!0:(t.notifier.warn("WS: not connecting (no tokens). Run signin."),!1)}handleStateChange(e,t){e.kind==="CONNECTING"&&t.notifier.info(`WS: state CONNECTING (url=${this.lastUrl})`,{scope:"system"}),e.kind==="CONNECTED"&&t.notifier.info(`WS: state CONNECTED (url=${this.lastUrl})`,{scope:"system"}),e.kind==="DISCONNECTED"&&t.notifier.info(`WS: state DISCONNECTED (url=${this.lastUrl})`,{scope:"system"})}computeBackoffMs(e){let t=Math.min(3e4,1e3*Math.pow(2,Math.min(e-1,5))),r=t*(.2*(Math.random()*2-1));return Math.max(250,Math.floor(t+r))}startCountdown(e,t){this.clearCountdown();let r=e;this.countdownTimer=setInterval(()=>{if(r-=1,r<=0){this.clearCountdown();return}let o={retryInSec:r,attempt:this.retryAttempt};t.bus.emit("ws:retrying",o)},1e3)}clearCountdown(){this.countdownTimer&&(clearInterval(this.countdownTimer),this.countdownTimer=null)}async ensureStartedSoon(e){await yt(250),!this.stopped&&this.ensureStarted(e,"socket:disconnected")}async interruptibleSleep(e){let r=Date.now();for(;Date.now()-r<e;){if(this.stopped)return;await yt(100)}}};import _s from"node:fs";import du from"node:path";var Wr=class{static save(e){let t=this.getApplicationConfigFolder(),r=du.join(t,"config.json"),o=this.stripSecrets(e);return _s.mkdirSync(t,{recursive:!0}),_s.writeFileSync(r,JSON.stringify(o,null,2),"utf8"),r}static stripSecrets(e){let t=e.device?{id:e.device.id,name:e.device.name,tag:e.device.tag,keys:{public:e.device.keys.public}}:void 0,r=e.tokens?{accessTokenExpSec:e.tokens.accessTokenExpSec}:void 0;return{...e,device:t,tokens:r}}static getApplicationConfigFolder(){return Z()}};var Gr=class{name="main-orchestrator";bootStarted=!1;saveTimer=null;saveInFlight=null;latestConfigToSave=null;saveDebounceMs=500;async onStop(e){await this.flushSaveOnStop()}handlers(){return{"ui:initialized":async(e,t)=>{this.bootStarted||(this.bootStarted=!0,t.engine.setPhase("booting"),t.notifier.info("Booting..."),t.engine.dispatch(_i(new wr)))},"config:save:requested":async(e,t)=>{this.latestConfigToSave=e,this.saveTimer&&clearTimeout(this.saveTimer),this.saveTimer=setTimeout(()=>{this.performSave(t)},this.saveDebounceMs)}}}async performSave(e){this.saveInFlight||(this.saveInFlight=(async()=>{for(;this.latestConfigToSave;){let t=this.latestConfigToSave;this.latestConfigToSave=null;try{let r=Wr.save(t);e.notifier.info(`Config saved to: ${r}`,{scope:"system"}),e.bus.emit("config:saved",void 0)}catch(r){let o=B(r);e.notifier.error(`Failed to save configuration: ${o}`)}}})().finally(()=>{this.saveInFlight=null}),await this.saveInFlight)}async flushSaveOnStop(){this.saveTimer&&(clearTimeout(this.saveTimer),this.saveTimer=null)}};import{decodeJwt as Cu}from"jose";import uo from"node:crypto";var ks={invalid_enrollment_token:"Enrollment key is invalid or could not be verified (wrong controller URL, bad signature, or server signing keys do not match the key issuer).",invalid_enrollment_scope:"Enrollment key does not match this device account or organization membership.",enrollment_jwt_expired:"This enrollment key file has expired (JWT). Issue a new key under Organization \u2192 Devices and update ENROLMENT_KEY / your .devicelink file.",enrollment_ticket_invalid:"Enrollment key could not be accepted (already used, expired, or out of sync). Issue a new key under Organization \u2192 Devices.",enrollment_ticket_already_used:"This enrollment key was already used (single-use). Issue a new key under Organization \u2192 Devices.",enrollment_ticket_expired:"This enrollment key has expired. Issue a new key under Organization \u2192 Devices.",server_misconfigured:"Server cannot verify enrollment keys (OAuth keys missing on controller).",enrollment_start_failed:"Device enrollment failed. See controller logs."};function pu(n){if(typeof n!="object"||n===null)return;let e=n;if(e.body&&typeof e.body=="object"&&e.body!==null&&"error"in e.body){let t=e.body.error;if(typeof t=="string")return t}if(n instanceof Error){let t=n.message.match(/"error"\s*:\s*"([^"]+)"/);if(t?.[1])return t[1]}}function Ts(n){let e=pu(n);return e&&ks[e]?ks[e]:e?`Enrollment failed (${e}). ${B(n)}`:B(n)}var wt=class{timeout=null;interval=null;totalSec=0;remainingSec=0;stepSec=1;task=null;stepCb=null;setStep(e){return this.stepSec=Math.max(1,e),this}schedule(e,t){return this.task=e,this.totalSec=t,this.remainingSec=t,this}onStep(e){return this.stepCb=e,this}start(){return this.clear(),this.remainingSec<=0?(this.runTask(),this):(this.stepCb?.(this.stepSec,this.remainingSec),this.interval=setInterval(()=>{this.remainingSec-=this.stepSec,this.remainingSec<=0?this.runTask():this.stepCb?.(this.stepSec,this.remainingSec)},this.stepSec*1e3),this)}stop(){return this.clear(),this}restart(){return this.remainingSec=this.totalSec,this.start()}runTask(){if(this.clear(),this.task)try{this.task()}catch(e){throw new Error(`Scheduler task failed: ${e}`)}}clear(){this.timeout&&(clearTimeout(this.timeout),this.timeout=null),this.interval&&(clearInterval(this.interval),this.interval=null)}};function ws(n){let{retryAfterSec:e}=n;if(typeof e=="number"&&Number.isFinite(e)&&e>=0)return{delayMs:Math.min(n.retryAfterMaxSec*1e3,Math.max(n.retryAfterMinSec*1e3,e*1e3)),honoredRetryAfter:!0};let r=Math.max(1,n.attempt),o=Math.min(r-1,n.maxDoublings),i=n.baseSec*Math.pow(2,o);return{delayMs:Math.min(n.ceilingSec*1e3,(i+n.jitterSec)*1e3),honoredRetryAfter:!1}}var fu=["off","notify","stage","apply_when_idle","required"];function mu(n){return n===void 0?"off":fu.find(t=>t===n)??"notify"}var hu={action:"none",target:null,belowFloor:!1,message:null,url:null};function Rt(n){return{...hu,reason:n}}function gu(n){let{currentVersion:e,guidance:t,autoUpdateEnabled:r}=n;if(!t)return Rt("no guidance from server");let o=mu(t.update_policy);if(o==="off")return Rt("policy off");if(!ve(e))return Rt("current version unreadable");let s=t.min_agent_version??null,a=t.target_agent_version??null,c=t.upgrade_message??null,l=t.upgrade_url??null,d=s!==null&&mn(e,s),f=a??s;if(!f||!ve(f))return Rt("no usable target version");if(zt(e,f)>=0)return Rt("already at or above the target");let p={target:f,belowFloor:d,message:c,url:l};return d?{...p,action:"required",reason:"below the minimum version"}:r?hn(e,f)?o==="notify"?{...p,action:"notify",reason:"policy notify"}:o==="stage"?{...p,action:"stage",reason:"policy stage"}:o==="apply_when_idle"?{...p,action:"apply_when_idle",reason:"policy apply_when_idle"}:{...p,action:"required",reason:"policy required"}:{...p,action:"notify",reason:"major version change is not applied automatically"}:{...p,action:"notify",reason:"automatic updates disabled locally"}}function Rs(n,e){let t=gu(e);if(t.action==="none")return t;let r=yu(t,String(e.currentVersion));return t.belowFloor?n.error(r):n.warn(r),t}function yu(n,e){if(n.action==="none")return"";let t=n.target??"a newer version",r=n.belowFloor?`This agent (${e}) is below the minimum version the server accepts (${t}).`:`A newer agent is available (${e} -> ${t}).`,o=n.message?` ${n.message}`:"",i=n.url?` See ${n.url}`:"";return`${r}${o}${i}`}var bu=15e3,vu=2e3,Su=12e3,Eu=0,Cs=6e4,_u=250,xs="This device is being replaced by another connection. Finishing in-flight operations...",As="Device replaced by new connection. Disconnecting.",ku="Reconnecting to DeviceLink\u2026";function Tu(n){return typeof n!="string"?"SERVER_DRAINING":Wo.find(t=>t===n)??"SERVER_DRAINING"}function wu(n){let e=typeof n=="number"&&Number.isFinite(n)?n:0,t=Math.min(e,bu);return Math.max(0,Math.min(t-vu,Su))}function Ru(n,e=Math.random){let t=typeof n=="number"&&Number.isFinite(n)?n:0,r=Math.min(Cs,Math.max(Eu,Math.floor(t))),o=Math.max(_u,Math.floor(r*.25)),i=r+Math.floor(e()*o);return Math.min(Cs,i)}function Ds(n,e){let t=Tu(n.reason),r=typeof n.reason=="string"?n.reason:"",o=wu(n.deadline_ms);if(!e.quiesceV2)return{reason:t,reasonAsSent:r,drainWindowMs:o,reconnect:!0,rediscover:!1,startMessage:xs,endMessage:As};let i=n.reconnect,a=typeof i?.after_ms=="number"?Ru(i?.after_ms,e.random):void 0,c=i?.url,l=nr(c,e.env)?String(c):void 0,d={reason:t,reasonAsSent:r,drainWindowMs:o,reconnect:!0,rediscover:i?.discover===!0,reconnectDelayMs:a,reconnectUrl:l};return t==="SESSION_REPLACED"?{...d,reconnect:!1,reconnectDelayMs:void 0,reconnectUrl:void 0,rediscover:!1,startMessage:xs,endMessage:As}:t==="SERVER_DRAINING"?{...d,startMessage:r==="SERVER_DRAINING"?ku:void 0}:t==="ENDPOINT_MOVED"?{...d,rediscover:!0}:d}var Is="BAD_TS",xu=10,Hr=class{name="auth-orchestrator";phase="IDLE";connectionId=null;sessionId=null;accessToken;rejectedByConflict=!1;negotiatedCapabilities=[];refreshGroupKey="auth:refresh";refreshCycle=0;refreshScheduler=null;refreshRetryScheduler=null;refreshRetryAttempt=0;lastRefreshPlan;refreshInFlight;conflictTimer=null;pendingConflictRequest=null;signinStarted=!1;async onStart(e){e.notifier.info("Auth orchestrator started",{scope:"system"})}async onStop(e){this.clearTimers(),this.resetConnectionState(),e.notifier.info("Auth orchestrator stopped",{scope:"system"})}handlers(){return{"config:loaded":this.onEventConfigLoaded.bind(this),"config:cache:validated":this.onEventConfigCacheValidated.bind(this),"auth:signin:requested":this.onEventAuthSigninRequested.bind(this),"auth:signin:completed":async(e,t)=>{t.notifier.info("Auth: signin completed; requesting ws reconnect",{scope:"system"}),this.rejectedByConflict=!1,this.refreshRetryScheduler&&(this.refreshRetryScheduler.stop(),this.refreshRetryScheduler=null),this.ensureAccessExpPersisted(t,"signin"),await this.ensureRefreshScheduling(t,"signin"),t.bus.emit("auth:ws:reconnect",void 0)},"auth:signout:requested":async(e,t)=>{t.notifier.info("Signing out\u2026"),this.clearTimers(),this.accessToken=void 0;try{await t.engine.secrets.delete("refreshToken")}catch{}let o={...t.engine.configurationContext.configuration,tokens:void 0};t.engine.applyConfiguration(o),t.bus.emit("config:save:requested",o),this.resetConnectionState(),t.engine.setPhase("idle"),t.bus.emit("auth:tokens:updated",{accessToken:"",refreshToken:"",expSec:void 0}),t.bus.emit("ws:disconnect",{reason:"signout"}),t.notifier.success("Signed out successfully")},"auth:session_conflict:resolve":async(e,t)=>{this.sendSessionConflictResolve(t,e.choice)},"ws:connected":async(e,t)=>{this.resetConnectionState();let r=await t.engine.secrets.get("refreshToken"),o=!!r.ok&&!!r.value,i=!!this.accessToken;if(t.notifier.info(`Auth: ws connected; tokens access=${i} refresh=${o}`,{scope:"system"}),!i&&!o){t.notifier.warn("Auth: no tokens; run signin");return}await this.sendConnect(t)},"ws:rx":async(e,t)=>{this.onInbound(e.text,t)},"ws:disconnected":async(e,t)=>{if(t.notifier.warn(`Auth: ws disconnected code=${e.code} reason=${e.reason??"-"}`,{scope:"system"}),this.resetConnectionState(),e.code===4011){t.notifier.warn('Connection rejected - another device is active on this workspace. Run "signin" to try again.'),this.rejectedByConflict=!0,t.bus.emit("ws:disconnect",{reason:"REPLACEMENT_REJECTED"});return}if(e.code===4001){let r=await t.engine.secrets.get("refreshToken");if(!r.ok||!r.value){t.notifier.warn("Auth: token invalid and no refresh; please sign in"),await this.teardownTokens(t,"AUTH_REQUIRED");return}await this.requestRefresh(t,{force:!0,reason:"ws_4001"})&&t.bus.emit("auth:ws:reconnect",void 0)}}}}async onEventConfigLoaded(e,t){if(t.notifier.info("Initializing with cached configuration",{scope:"system"}),!e.device?.id){t.notifier.error("Device ID is not available");return}if(!e.device.keys?.public){t.notifier.error("Device public key is not available");return}t.bus.emit("config:cache:validated",void 0)}async onEventConfigCacheValidated(e,t){this.ensureAccessExpPersisted(t,"boot"),await this.ensureRefreshScheduling(t,"boot");let r=await t.engine.secrets.get("refreshToken"),o=!!r.ok&&!!r.value,i=!!this.accessToken,s=this.isAccessLikelyUsable(t);if(t.notifier.info(`Auth: cache validated; access=${i} refresh=${o} accessOk=${s}`,{scope:"system"}),!i&&!o){if(t.headless&&await Ki(t.engine.argv.enrollmentFile)){t.notifier.info("Headless: enrollment certificate present; starting device authorization (approve the pending request under Organization \u2192 Devices).",{scope:"system"}),t.bus.emit("auth:signin:requested",void 0);return}t.notifier.warn("Auth: not signed in; run signin");return}}isAccessLikelyUsable(e){let t=this.accessToken;if(!t)return!1;let o=e.engine.configurationContext.configuration?.tokens?.accessTokenExpSec??this.tryDecodeExp(t);if(!o)return!0;let i=Math.floor(Date.now()/1e3);return o>i}async waitForApproval(e,t,r){let o=Date.now()+t.expires_in*1e3;r.notifier.info("Waiting for approval... (streaming)",{scope:"system"});try{return await e.deviceAuthStream({deviceCode:t.device_code,timeoutMs:Math.max(1e3,o-Date.now()),signal:r.signal})}catch(i){let s=i instanceof Error?i.message:String(i);return r.notifier.error(`Failed to wait for approval: ${s}`),null}}async onEventAuthSigninRequested(e,t){if(this.signinStarted){t.notifier.warn("Sign-in already in progress",{scope:"system"});return}this.signinStarted=!0;try{let r=t.engine.configurationContext.configuration;if(!r.controlBaseUrl){t.notifier.error("Control base URL is not set");return}if(!r.device?.id){t.notifier.error("Device ID is not available");return}if(!r.device.keys?.public){t.notifier.error("Device public key is not available");return}let o=await t.engine.secrets.get("devicePrivateKey");if(!o.ok||!o.value){t.notifier.error("Device private key is not available (secret storage)");return}let i=o.value,s=r.device.name,a=process.platform,c=r.device.keys.public,l=cn(c),d=new et(r,t.notifier);t.notifier.info("Starting device authentication...");let f=await ji(t.engine.argv.enrollmentFile),p;if(f.ok){t.notifier.info(t.engine.argv.enrollmentFile?"Using enrollment key from --enrollment-file":"Using ENROLMENT_KEY / DLINK_ENROLMENT_KEY from environment",{scope:"system"});try{p=await d.deviceEnrollmentStart({device_id:r.device.id,device_name:s,platform:a,agent_version:ue(),public_key_pem:c,enrollment_jws:f.jws})}catch(E){t.notifier.error(Ts(E),{scope:"system"});return}t.notifier.info("Approve this device in the dashboard: Organization \u2192 Devices (pending), or use the verification link below.",{scope:"system"})}else{if(f.error!=="not_configured"){t.notifier.error(f.error==="empty_file"?"Enrollment key is empty":`Could not load enrollment key: ${f.error}`);return}p=await d.deviceAuthStart({device_id:r.device.id,device_name:s,platform:a,agent_version:ue(),public_key_pem:c})}t.notifier.info("DeviceLink sign-in"),t.notifier.info(`User code: ${p.user_code}`),t.notifier.info(`Device fingerprint: ${l}`),t.notifier.info(`Verification URL: ${p.verification_uri_complete}`);let m=await this.waitForApproval(d,p,t);if(!m)return;if("error"in m){if(m.error==="access_denied"){t.notifier.error("Sign-in denied in browser.");return}if(m.error==="expired_token"){t.notifier.error("Sign-in expired. Run `signin` again.");return}t.notifier.error(`Unexpected error: ${m.error}`);return}if(m.status!=="approved"){t.notifier.error(`Unexpected status: ${m.status}`);return}if(m.needs_proof){t.notifier.info("Sending proof-of-possession signature...",{scope:"system"});let E=uo.createPrivateKey(i),k=Buffer.from(p.challenge,"base64url"),S=uo.sign(null,k,E).toString("base64");await d.deviceAuthProve({device_code:p.device_code,challenge_id:p.challenge_id,challenge:p.challenge,signature_b64:S}),t.notifier.info("Proof-of-possession verified",{scope:"system"})}t.notifier.info("Fetching tokens...",{scope:"system"});let g=await d.deviceAuthToken({device_code:p.device_code,install_id:ao()?Lr():void 0}),h=Cn(g.endpoints);h&&t.bus.emit("discovery:document:received",{document:h,source:"token"});let y="tag";await t.engine.secrets.set("refreshToken",g.refresh_token),this.accessToken=g.access_token;let _=this.tryDecodeExp(g.access_token),b={...r,controlBaseUrl:r.controlBaseUrl,device:{...r.device,id:g.device_id,name:s,tag:y,keys:{public:c}},tokens:{...r.tokens??{},accessTokenExpSec:_??void 0}};t.engine.applyConfiguration(b),t.bus.emit("config:save:requested",b),t.bus.emit("auth:signin:completed",void 0),t.notifier.success("Signed in successfully \u2705")}catch(r){let o=fe(r);if(o&&["ECONNREFUSED","ENOTFOUND","ETIMEDOUT"].includes(o)){t.notifier.error(`Network error: ${B(r)}`);return}t.notifier.error(`Sign-in failed: ${B(r)}`)}finally{this.signinStarted=!1}}async sendConnect(e){let r=e.engine.configurationContext.configuration.device,o=await e.engine.secrets.get("devicePrivateKey");if(!r?.id||!o.ok||!o.value){e.notifier.warn("Cannot connect: device not configured");return}let i=o.value,s=await e.engine.secrets.get("refreshToken"),a=s.ok?s.value:void 0,c=Date.now(),l=uo.randomBytes(16).toString("base64url"),d=ln({deviceId:r.id,ts:c,nonce:l,privateKeyPem:i}),f={type:"connect",device_id:r.id,agent_version:ue(),protocol_version:2,capabilities:[...qo],ts:c,nonce:l,sig:d,platform:process.platform,hostname:r.name,device_tag:r.tag,access_token:this.accessToken,refresh_token:a,public_key_pem:r.keys.public};this.phase="CONNECT_SENT",e.notifier.info("Auth: sending connect",{scope:"system"}),this.send(e,f)}async sendSessionInit(e,t){let o=e.engine.configurationContext.configuration.device;if(!o?.id||!this.sessionId){e.notifier.error("Cannot send session_init: device ID or session ID not available");return}let i={type:"session_init",device_id:o.id,session_id:this.sessionId};this.phase="WAIT_SESSION_INIT_ACK",e.notifier.info("Auth: sending session_init",{scope:"system"}),this.send(e,i)}onInbound(e,t){let r;try{r=JSON.parse(e)}catch{t.notifier.error("Unexpected message format");return}let o=tr(r);if(!Yo(o)){t.notifier.info(`Auth: ignoring unknown message type ${o??"(none)"}`,{scope:"system"});return}let i=zo.safeParse(r);if(!i.success){let a=i.error.message;t.notifier.error(`Unexpected message format: ${a}`);return}let s=i.data;switch(s.type){case"connect_ack":t.bus.emit("auth:connect_ack",s),this.onConnectAck(t,s);return;case"session_init_ack":t.bus.emit("auth:session_init_ack",s),this.onSessionInitAck(t,s);return;case"disconnect_notice":this.onDisconnectNotice(t,s);return;case"session_conflict":t.bus.emit("auth:session_conflict",s),this.handleSessionConflict(t,s);return;case"quiesce":this.handleQuiesce(t,s);return;default:return}}async handleSessionConflict(e,t){this.conflictTimer&&(clearTimeout(this.conflictTimer),this.conflictTimer=null),this.pendingConflictRequest=t,e.notifier.warn(`Another device is already connected to this workspace. Type "replace" to disconnect it, or this connection will be rejected in ${Math.round(t.deadline_ms/1e3)}s.`);let r=Math.min(t.deadline_ms,15e3);this.conflictTimer=setTimeout(()=>{this.conflictTimer=null,this.pendingConflictRequest?.new_session_id===t.new_session_id&&(e.notifier.info("No response - keeping existing device connected."),this.sendSessionConflictResolve(e,"KEEP_OLD"))},r)}async handleQuiesce(e,t){let r=Ds(t,{quiesceV2:this.sessionHas(G.QUIESCE_V2)});if(e.notifier.info(`Auth: quiesce reason=${r.reasonAsSent||"(none)"} handled_as=${r.reason} reconnect=${r.reconnect} drain_ms=${r.drainWindowMs}`,{scope:"system"}),r.startMessage&&e.notifier.warn(r.startMessage),e.engine.hasRunningJobs?.()??!1){let i=Date.now();for(;Date.now()-i<r.drainWindowMs&&(e.engine.hasRunningJobs?.()??!1);)await new Promise(s=>setTimeout(s,500))}e.bus.emit("ws:reconnect:policy",{reconnect:r.reconnect,delayMs:r.reconnectDelayMs,url:r.reconnectUrl,rediscover:r.rediscover}),r.rediscover&&e.bus.emit("discovery:refresh:requested",{reason:`quiesce:${r.reason}`});let o=e.engine.hasRunningJobs?.()??!1?"BUSY":"IDLE";this.send(e,{type:"quiesce_ack",session_id:t.session_id,status:o}),r.endMessage&&e.notifier.info(r.endMessage)}sendSessionConflictResolve(e,t){let r=this.pendingConflictRequest;r&&(this.conflictTimer&&(clearTimeout(this.conflictTimer),this.conflictTimer=null),this.pendingConflictRequest=null,this.send(e,{type:"session_conflict_resolve",device_id:r.device_id,new_session_id:r.new_session_id,choice:t}))}async onConnectAck(e,t){if(!t.ok){e.notifier.error(`Connect rejected: ${t.error.code} ${t.error.message}`),this.phase="IDLE";return}this.sessionId=t.session_id;let r=t.auth.access_token;if(e.notifier.info(`Auth: connect_ack ok auth.access=${r} next=[${t.next.join(",")}]`,{scope:"system"}),t.next.includes("refresh_access_token")){let o=await e.engine.secrets.get("refreshToken");if(!o.ok||!o.value){e.notifier.warn("Auth: server requested refresh but no refresh token; please sign in"),await this.teardownTokens(e,"NO_REFRESH_TOKEN");return}await this.requestRefresh(e,{force:!0,reason:"connect_ack_next"})?e.bus.emit("auth:ws:reconnect",void 0):e.notifier.warn("Auth: refresh failed; please sign in");return}if(t.next.includes("session_init")){await this.sendSessionInit(e,t);return}if(r==="invalid"||r==="missing"){e.notifier.warn("Auth: access token invalid; please sign in again"),await this.teardownTokens(e,"INVALID_ACCESS");return}e.notifier.warn("Auth: connect_ack had no next; staying idle",{scope:"system"})}onSessionInitAck(e,t){if(!t.ok){e.notifier.error(`Session init failed: ${t.error.code} ${t.error.message}`),t.error.code==="AGENT_BELOW_MINIMUM"&&this.surfaceUpdateGuidance(e,t),this.phase="IDLE";return}this.sessionId=t.session_id,this.phase="READY",this.negotiatedCapabilities=Array.isArray(t.capabilities)?[...t.capabilities]:[],e.notifier.success(`Session ready (${t.mode})`),e.notifier.info(`Auth: session capabilities=[${this.negotiatedCapabilities.join(",")}]`,{scope:"system"}),this.surfaceUpdateGuidance(e,t),this.ensureRefreshScheduling(e,"manual").catch(r=>{e.notifier.error(`Auth: refresh scheduling failed after session_init_ack: ${r instanceof Error?r.message:String(r)}`,{scope:"system",category:["token-refresh"]})}),t.next&&(t.next.includes("tools_publish")&&e.bus.emit("meta:data:requested:tools",void 0),t.next.includes("directories_publish")&&e.bus.emit("meta:data:requested:directories",void 0))}surfaceUpdateGuidance(e,t){return Rs({warn:o=>e.notifier.warn(o),error:o=>e.notifier.error(o)},{currentVersion:ue(),guidance:t,autoUpdateEnabled:_t("DLINK_AUTO_UPDATE",!0)})}onDisconnectNotice(e,t){e.notifier.warn(`Server disconnect_notice: ${t.reason} (code=${t.code})`)}async requestRefresh(e,t){return this.refreshInFlight?this.refreshInFlight:(this.refreshInFlight=(async()=>{try{return await this.withTimeout(this.dispatchRefreshJob(e,t),6e4,"Refresh operation")}catch(r){throw r instanceof Error&&r.message.includes("timed out")&&e.notifier.error(`Auth: refresh timed out: ${r.message}`,{category:["token-refresh"],groupKey:"auth:refresh-failure"}),r}finally{this.refreshInFlight=void 0}})(),this.refreshInFlight)}async withTimeout(e,t,r){return Promise.race([e,new Promise((o,i)=>{setTimeout(()=>{i(new Error(`${r} timed out after ${t}ms`))},t)})])}async dispatchRefreshJob(e,t){let r=await e.engine.secrets.get("refreshToken");if(!r.ok||!r.value)return!1;if(!t.force){let a=await this.shouldRefreshNow(e);if(!a.ok)return e.notifier.info(`Auth: skip refresh (${a.reason})`,{scope:"system",category:["token-refresh"]}),!1}e.notifier.info(`Auth: dispatch refresh job (${t.reason})`,{scope:"system",category:["token-refresh"]});let o=Oi(new Rr(t.reason)),i=await e.engine.dispatch(o);if(e.notifier.info(`Auth: refresh job dispatch completed (status=${i.status})`,{scope:"system",category:["token-refresh"]}),i.status!=="success"){let a=i.error?.message??"Unknown error";e.notifier.error(`Auth: refresh job failed: ${a}`,{category:["token-refresh"],groupKey:"auth:refresh-failure"});let c=i.output;return c?.errorCode&&Gn.includes(c.errorCode)?(await this.teardownTokens(e,c.errorCode),!1):(this.scheduleRefreshRetry(e,t.reason,c?.retryAfterSec,c?.errorCode,c?.driftMs),!1)}let s=i.output;if(!s.ok||!s.accessToken){let a=s.error??"Unknown refresh failure";return e.notifier.error(`Auth: refresh failed: ${a}`,{category:["token-refresh"],groupKey:"auth:refresh-failure"}),s.errorCode&&Gn.includes(s.errorCode)?(await this.teardownTokens(e,s.errorCode),!1):(this.scheduleRefreshRetry(e,t.reason,s.retryAfterSec,s.errorCode,s.driftMs),!1)}return this.refreshRetryAttempt=0,this.accessToken=s.accessToken,this.persistTokens(e,s.accessToken,s.expiresInSec),await this.ensureRefreshScheduling(e,"manual"),e.bus.emit("auth:tokens:updated",{accessToken:s.accessToken,refreshToken:s.refreshToken??"",expSec:e.engine.configurationContext.configuration.tokens?.accessTokenExpSec}),!0}scheduleRefreshRetry(e,t,r,o,i){this.refreshRetryScheduler&&this.refreshRetryScheduler.stop(),this.refreshRetryAttempt+=1,o===Is&&this.warnAboutClockSkew(e,i);let s=this.computeRefreshRetryMs(e,t,r,o),a=Math.max(1,Math.ceil(s/1e3));this.refreshRetryScheduler=new wt().schedule(()=>{this.requestRefresh(e,{force:!0,reason:"retry"}).then(c=>{c&&e.bus.emit("auth:ws:reconnect",void 0)})},a).start()}warnAboutClockSkew(e,t){let r=typeof t=="number"&&Number.isFinite(t)?`about ${Math.round(Math.abs(t)/1e3)}s`:"more than a minute";e.notifier.error(`Auth: this device\u2019s clock is ${r} away from the server, so sign-in cannot be renewed. Correct the system time, then run signin.`,{category:["token-refresh"],groupKey:"auth:clock-skew"})}computeRefreshRetryMs(e,t,r,o){let i=e.engine.configurationContext.loader,s=i.getConfigValue("DL_ACCESS_REFRESH_RETRY_AFTER_MIN_SEC",{defaultValue:1}),a=i.getConfigValue("DL_ACCESS_REFRESH_RETRY_AFTER_MAX_SEC",{defaultValue:300}),c=i.getConfigValue("DL_ACCESS_REFRESH_RETRY_BASE_SEC",{defaultValue:2}),l=i.getConfigValue("DL_ACCESS_REFRESH_RETRY_JITTER_SEC",{defaultValue:1}),d=i.getConfigValue("DL_ACCESS_REFRESH_RETRY_MAX_SEC",{defaultValue:30}),f=i.getConfigValue("DL_ACCESS_REFRESH_CLOCK_SKEW_MIN_SEC",{defaultValue:300}),p=Math.max(1,this.refreshRetryAttempt),m=o===Is?Math.max(d,f):d,{delayMs:g,honoredRetryAfter:h}=ws({attempt:p,baseSec:c,jitterSec:Math.floor(Math.random()*(l+1)),ceilingSec:m,maxDoublings:xu,retryAfterSec:r,retryAfterMinSec:s,retryAfterMaxSec:a}),y=Math.max(1,Math.ceil(g/1e3));return e.notifier.warn(h?`Auth: refresh retry scheduled in ${y}s (honoring Retry-After, ${t})`:`Auth: refresh retry scheduled in ${y}s (${t}, attempt ${p})`,{scope:"system",category:["token-refresh"],groupKey:"auth:refresh-retry"}),g}async ensureRefreshScheduling(e,t){let r=await e.engine.secrets.get("refreshToken");!r.ok||!r.value||(this.accessToken&&!e.engine.configurationContext.configuration.tokens?.accessTokenExpSec&&this.ensureAccessExpPersisted(e,t),this.refreshRetryScheduler&&(this.refreshRetryScheduler.stop(),this.refreshRetryScheduler=null),this.scheduleSilentRefresh(e,t))}async scheduleSilentRefresh(e,t){let r=await e.engine.secrets.get("refreshToken");if(!r.ok||!r.value)return;this.refreshScheduler&&this.refreshScheduler.stop();let o=e.engine.configurationContext.loader,i=o.getConfigValue("DL_ACCESS_REFRESH_MIN_DELAY_SEC",{defaultValue:2}),s=e.engine.configurationContext.configuration,a=this.accessToken,c=s.tokens?.accessTokenExpSec??(a?this.tryDecodeExp(a):null),l=c??null,d=this.getRefreshGroupKey(e);if(this.lastRefreshPlan&&this.lastRefreshPlan.exp===l&&this.lastRefreshPlan.groupKey===d)return;this.lastRefreshPlan={exp:l,groupKey:d};let f=b=>{let E=new wt().schedule(()=>{this.requestRefresh(e,{force:b.force,reason:"timer"}).then(k=>{k&&e.notifier.success("Auth: refresh completed",{scope:"system",groupKey:d,category:["token-refresh"]})})},b.delaySec);b.log&&(E=E.onStep((k,D)=>b.log(D))),this.refreshScheduler=E.start()};if(!c){e.headless||e.notifier.info(`Auth: no exp; scheduling refresh in ${i}s [${t}]`,{scope:"system",groupKey:d,category:["token-refresh"]}),f({delaySec:i,force:!0});return}let p=Math.floor(Date.now()/1e3),m=o.getConfigValue("DL_ACCESS_REFRESH_MARGIN_SEC",{defaultValue:5}),g=o.getConfigValue("DL_ACCESS_REFRESH_JITTER_SEC",{defaultValue:2}),h=g>0?Math.floor(Math.random()*(g+1)):0,y=c-m-h,_=Math.max(i,y-p);e.headless||e.notifier.info(`Auth: refresh scheduled in ${_}s (exp=${c} now=${p} margin=${m} jitter=${h}) [${t}]`,{scope:"system",groupKey:d,category:["token-refresh"]}),f({delaySec:_,force:!1,log:b=>{e.headless||e.notifier.info(`Auth: refresh scheduled in ${b}s (exp=${c} now=${p} margin=${m} jitter=${h}) [${t}]`,{scope:"system",groupKey:d,category:["token-refresh"]})}})}getRefreshGroupKey(e){return this.refreshCycle++,`${this.refreshGroupKey}:${this.refreshCycle}`}async shouldRefreshNow(e){let t=await e.engine.secrets.get("refreshToken");if(!t.ok||!t.value)return{ok:!1,reason:"no_refresh_token"};let r=e.engine.configurationContext.configuration,o=this.accessToken,i=r.tokens?.accessTokenExpSec??(o?this.tryDecodeExp(o):null);if(!i)return{ok:!0,reason:"no_exp_assume_refresh"};let s=Math.floor(Date.now()/1e3),c=e.engine.configurationContext.loader.getConfigValue("DL_ACCESS_REFRESH_MARGIN_SEC",{defaultValue:300}),l=i-s;return l<=c?{ok:!0,reason:`within_margin remaining=${l}s margin=${c}s`}:{ok:!1,reason:`too_early remaining=${l}s margin=${c}s`}}ensureAccessExpPersisted(e,t){let r=e.engine.configurationContext.configuration,o=this.accessToken,i=r.tokens?.accessTokenExpSec;if(!o||typeof i=="number"&&Number.isFinite(i))return;let s=this.tryDecodeExp(o);if(!s)return;let a={...r,tokens:{...r.tokens??{},accessTokenExpSec:s}};e.engine.applyConfiguration(a),e.bus.emit("config:save:requested",a),e.notifier.info(`Auth: derived accessTokenExpSec=${s} (${t})`,{scope:"system"})}persistTokens(e,t,r){let o=e.engine.configurationContext.configuration,i=this.tryDecodeExp(t),s=typeof r=="number"&&Number.isFinite(r)?Math.floor(Date.now()/1e3)+r:void 0,a={...o,tokens:{...o.tokens??{},accessTokenExpSec:i??s}};e.engine.applyConfiguration(a),e.bus.emit("config:save:requested",a),e.notifier.info(`Auth: tokens updated exp=${a.tokens?.accessTokenExpSec??"-"}`,{scope:"system"})}async teardownTokens(e,t){this.accessToken=void 0;let o={...e.engine.configurationContext.configuration,tokens:void 0};e.engine.applyConfiguration(o),e.bus.emit("config:save:requested",o),this.clearTimers(),this.resetConnectionState(),e.bus.emit("auth:signout:requested",void 0),e.notifier.warn(`Auth: signed out (${t}). Please run signin.`)}tryDecodeExp(e){try{let t=Cu(e);return typeof t.exp=="number"?t.exp:null}catch{return null}}send(e,t){e.bus.emit("ws:tx",{text:JSON.stringify(t)})}resetConnectionState(){this.connectionId=null,this.sessionId=null,this.phase="IDLE",this.negotiatedCapabilities=[]}sessionHas(e){return He(this.negotiatedCapabilities,e)}clearTimers(){this.refreshScheduler&&(this.refreshScheduler.stop(),this.refreshScheduler=null),this.refreshRetryScheduler&&(this.refreshRetryScheduler.stop(),this.refreshRetryScheduler=null),this.conflictTimer&&clearTimeout(this.conflictTimer),this.conflictTimer=null,this.pendingConflictRequest=null}};import mo from"node:fs/promises";import ho from"node:path";var H=class{config;constructor(e){this.config=e}async execute(e){try{let t=await this.executeTool(e);return ti(t)}catch(t){return ne(t)?$e(t):$e(K(t,{message:"An unexpected error occurred"}))}}};import Ps from"node:path";import Os from"node:fs";import Au from"lodash/get.js";function ke(n){return Au(n,["context","file_policies"])}function Du(n){let e=n.replace(/\\/g,"/").toLowerCase();return e.includes("/secrets/")||e.startsWith("secrets/")?{shouldIgnore:!0,reason:"denylist:secrets",matchedRule:"secrets/"}:e.includes("/.env")||e.startsWith(".env")?{shouldIgnore:!0,reason:"denylist:env",matchedRule:".env"}:e.includes("/id_rsa")||e.startsWith("id_rsa")?{shouldIgnore:!0,reason:"denylist:ssh",matchedRule:"id_rsa"}:e.includes("/id_ed25519")||e.startsWith("id_ed25519")?{shouldIgnore:!0,reason:"denylist:ssh",matchedRule:"id_ed25519"}:e.endsWith(".pem")?{shouldIgnore:!0,reason:"denylist:pem",matchedRule:"*.pem"}:e.endsWith(".key")?{shouldIgnore:!0,reason:"denylist:key",matchedRule:"*.key"}:e.endsWith(".p12")?{shouldIgnore:!0,reason:"denylist:p12",matchedRule:"*.p12"}:e.endsWith(".pfx")?{shouldIgnore:!0,reason:"denylist:pfx",matchedRule:"*.pfx"}:null}var Ns=[{pattern:"node_modules",type:"exact"},{pattern:".git",type:"exact"},{pattern:"dist",type:"exact"},{pattern:"build",type:"exact"},{pattern:".next",type:"exact"},{pattern:".cache",type:"exact"},{pattern:".DS_Store",type:"exact"},{pattern:"Thumbs.db",type:"exact"},{pattern:"*.tmp",type:"glob"},{pattern:"*.log",type:"glob"},{pattern:".env*",type:"glob"}];function Iu(n,e,t){let r=n.directories.find(s=>s.id===e);if(!r)return Ns;let o=[],i=Ps.join(r.path,".devicelinkignore");if(Os.existsSync(i))try{let a=Os.readFileSync(i,"utf-8").split(`
8
- `).map(c=>c.trim()).filter(c=>c&&!c.startsWith("#"));for(let c of a)c.includes("*")||c.includes("?")?o.push({pattern:c,type:"glob"}):c.startsWith("/")?o.push({pattern:c.slice(1),type:"prefix"}):o.push({pattern:c,type:"exact"})}catch(s){console.warn(`[ignore] Failed to read .devicelinkignore: ${s}`)}return o.push(...Ns),o}function oe(n,e,t,r,o){let i=Du(n);if(i)return i;if(o&&!e){let l=Ps.extname(n).toLowerCase();if(l&&o.blocked_extensions?.includes(l))return{shouldIgnore:!0,reason:"policy:blocked_extension",matchedRule:l};if(o.allowed_extensions&&o.allowed_extensions.length>0&&l&&!o.allowed_extensions.includes(l))return{shouldIgnore:!0,reason:"policy:not_in_allowlist",matchedRule:l};if(o.blocked_patterns){for(let d of o.blocked_patterns)if(po(n,d,!1))return{shouldIgnore:!0,reason:"policy:blocked_pattern",matchedRule:d}}}let s=Iu(r,t.directory_id,t.workspace_id),a=n.replace(/\\/g,"/"),c=a.split("/").filter(Boolean);for(let l of s){let d=!1;if(l.type==="exact"?d=c.some(f=>f===l.pattern):l.type==="prefix"?d=a.startsWith(l.pattern):l.type==="glob"&&(!l.pattern.includes("/")&&!l.pattern.includes("*")&&!l.pattern.includes("?")?d=c.some(f=>f.toLowerCase()===l.pattern.toLowerCase()):l.pattern.includes("/")?d=po(a,l.pattern,e):d=c.some(f=>po(f,l.pattern,e))),d)return{shouldIgnore:!0,matchedRule:l.pattern}}return{shouldIgnore:!1}}function po(n,e,t){let r="^",o=0;for(;o<e.length;){let i=e[o];i==="*"?o+1<e.length&&e[o+1]==="*"?(r+=".*",o+=2):(r+="[^/]*",o++):i==="?"?(r+="[^/]",o++):"\\^$|.+(){}[]".includes(i)?(r+="\\"+i,o++):(r+=i,o++)}r+="$";try{return new RegExp(r,"i").test(n)}catch{return n.toLowerCase().includes(e.toLowerCase())}}import fo from"node:fs/promises";import he from"node:path";function Fs(n){let e=(n??"").trim();if(!e)return".";if(e.includes("\0"))throw O("INVALID_INPUT","Path contains null byte.");if(e.startsWith("/"))throw O("PATH_ESCAPE","Absolute paths are not allowed. Use a path relative to the root.",{hint:'Use relative paths like "src/file.ts" or "." for the root directory. Paths must be relative to the configured root.'});if(/^[a-zA-Z]:[\\/]/.test(e)||e.startsWith("\\\\")||e.startsWith("//"))throw O("PATH_ESCAPE","Absolute/drive/UNC paths are not allowed. Use a path relative to the root.",{hint:'Use relative paths like "src/file.ts" or "." for the root directory. Do not use drive letters (C:) or UNC paths (\\\\server).'});let t=e.replace(/\\/g,"/");if(/^[a-zA-Z]+:\/\//.test(t))throw O("INVALID_INPUT","URL-style paths are not allowed.",{hint:'Paths cannot use URL schemes (like "http://" or "file://"). Use simple relative paths like "src/file.ts".'});let r=he.posix.normalize(t);if(r===".."||r.startsWith("../"))throw O("PATH_ESCAPE","Path escapes the root.",{hint:'Paths cannot use ".." to escape the configured root directory. Use paths relative to the root, like "src/file.ts" or "subdir/file.ts".'});return r===""?".":r}async function de(n,e){let t=Fs(e),r=he.resolve(n),o=await fo.realpath(r),i=he.resolve(o,t==="."?"":t),s=he.relative(o,i);if(s.startsWith("..")||he.isAbsolute(s))throw O("PATH_ESCAPE","Path escapes the root.",{hint:"The resolved path escapes the configured root directory. Ensure the path stays within the root boundaries."});try{let a=await fo.realpath(i),c=he.relative(o,a);if(c.startsWith("..")||he.isAbsolute(c))throw O("PATH_ESCAPE","Symlink/junction escape detected.",{hint:"A symlink or junction in the path resolves outside the configured root directory. Ensure all symlinks stay within the root boundaries."});return{absTarget:a,rel:t}}catch(a){if(fe(a)!=="ENOENT")throw a;let c=t.split("/").filter(Boolean);for(let l=c.length;l>0;l--){let d=c.slice(0,l).join("/"),f=c.slice(l).join("/"),p=he.resolve(o,d);try{let m=await fo.realpath(p),g=he.relative(o,m);if(g.startsWith("..")||he.isAbsolute(g))throw O("PATH_ESCAPE","Symlink/junction escape detected.",{hint:"A symlink or junction in the path resolves outside the configured root directory. Ensure all symlinks stay within the root boundaries."});return{absTarget:f?he.join(m,f):m,rel:t}}catch(m){if(fe(m)==="ENOENT")continue;throw m}}throw O("NOT_FOUND","Path not found.",{hint:"The specified path does not exist. Verify the path is correct and that the file or directory exists within the configured root."})}}function M(n){return{workspace_id:n.workspace_id,device_id:n.device_id,directory_id:n.directory_id,path:Fs(n.path)}}function J(n,e){let t=String(fe(n)??"");return t==="ENOENT"?ct("NOT_FOUND","Path not found.",{fs_code:t}):t==="ENOTDIR"?ct("NOT_A_DIRECTORY","Path is not a directory.",{fs_code:t}):t==="EISDIR"?ct("NOT_A_FILE","Path is a directory, not a file.",{fs_code:t}):t==="EACCES"||t==="EPERM"?ct("PERMISSION_DENIED","Permission denied.",{fs_code:t}):ct("INTERNAL",e,{fs_code:t})}function O(n,e,t){return ct(n,e,t)}function ct(n,e,t){return{code:n,message:e,details:t}}function re(n,e){if(Array.isArray(n.directories)&&n.directories.length===0)throw O("UNKNOWN_DIRECTORY","No directories configured.",{hint:"No directories configured. This may happen if the agent was restarted with different directory configuration. If you have only one directory configured, it will be used automatically.",requested_directory_id:e,available_directory_ids:n.directories.map(r=>r.id),available_paths:n.directories.map(r=>r.path),directory_count:n.directories.length});let t=n.directories.find(r=>r.id===e);if(!t&&n.directories.length===1&&(t=n.directories[0]),!t){let r=n.directories.map(s=>s.id).join(", ")||"none",o=n.directories.map(s=>s.path).join(", ")||"none",i=e===void 0?"undefined (missing)":String(e);throw O("UNKNOWN_DIRECTORY",`Unknown directory_id: ${i}`,{hint:`The directory_id "${i}" does not match any configured directory. Available directory IDs: ${r}. Available paths: ${o}. This may happen if the agent was restarted with different directory configuration. If you have only one directory configured, it will be used automatically.`,requested_directory_id:e,available_directory_ids:n.directories.map(s=>s.id),available_paths:n.directories.map(s=>s.path),directory_count:n.directories.length})}return t}function $(n,e,t,r,o){let i={operation:n,path:e.path||".",directory_id:e.directory_id,workspace_id:e.workspace_id,device_id:e.device_id,success:t,error:r?r.substring(0,200):void 0,metadata:o,timestamp:Date.now()},s=`[FS_AUDIT] ${n} ${t?"SUCCESS":"FAILED"} directory=${i.directory_id} path=${i.path}${i.workspace_id?` workspace=${i.workspace_id}`:""}${i.device_id?` device=${i.device_id}`:""}${i.error?` error=${i.error}`:""}${o?` ${JSON.stringify(o)}`:""}`}import Ls from"lodash/orderBy.js";import Ou from"lodash/clamp.js";import Nu from"lodash/take.js";import Pu from"lodash/map.js";function Fu(n,e,t){return Ls(n,[e==="name"?"name":e==="mtime"?o=>o.mtime??0:o=>o.size??0],[t])}function Lu(n,e){return e==="all"?n:e==="files"?n.filter(t=>t.type==="file"||t.type==="symlink"):e==="dirs"?n.filter(t=>t.type==="dir"):n}var Jr=class extends H{async executeTool(e){let t=e.directory_id,r=re(this.config,t),{absTarget:o,rel:i}=await de(r.path,e.path),s=Ou(e.limit??200,1,1e3),a=Math.max(e.offset??0,0),c=e.include_hidden??!1,l=e.only??"all",d=e.sort??"name",f=e.order??"asc",p=e.detail??"stat";try{if(!(await mo.stat(o)).isDirectory()){let I=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i});throw $("list",I,!1,"Path is not a directory."),O("NOT_A_DIRECTORY","Path is not a directory.",{path:i,hint:"The path must point to a directory, not a file. Use fs_read to read files, or provide a directory path for listing."})}}catch(w){if(ne(w)){let I=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i});throw $("list",I,!1,K(w).message),w}throw J(w,"Failed to list directory.")}let m;try{m=await mo.readdir(o,{withFileTypes:!0})}catch(w){throw J(w,"Failed to read directory.")}let g=c?m:m.filter(w=>!w.name.startsWith(".")),h=[],y=0,_={total_entries:0,files:0,dirs:0,symlinks:0,hidden:0,ignored:0,total_file_bytes:0},b=new Map,E=ke(e),k={directory_id:t,workspace_id:e.workspace_id,directory_path:r.path};for(let w of g){let I=ho.join(o,w.name),Fe=(i==="."?w.name:ho.posix.join(i,w.name)).replace(/\\/g,"/"),ge="other";w.isDirectory()?ge="dir":w.isFile()?ge="file":w.isSymbolicLink()&&(ge="symlink");let Mt=w.name.startsWith(".");if(oe(Fe,w.isDirectory(),k,this.config,E).shouldIgnore){y++,_.ignored++;continue}_.total_entries++,ge==="file"?_.files++:ge==="dir"?_.dirs++:ge==="symlink"&&_.symlinks++,Mt&&_.hidden++;let Do,Io;if(p==="stat"||p==="digest")try{let Ut=await mo.stat(I);Ut.isFile()&&(Do=Ut.size,_.total_file_bytes=(_.total_file_bytes??0)+Ut.size),Io=Math.floor(Ut.mtimeMs/1e3)}catch{}let $t=ge==="file"?ho.extname(w.name).slice(1):void 0;$t&&(p==="stat"||p==="digest")&&b.set($t,(b.get($t)??0)+1),h.push({name:w.name,path:Fe,type:ge,size:Do,mtime:Io,ext:$t,hidden:Mt,ignored:!1})}p==="digest"&&b.size>0&&(_.by_ext=Nu(Ls(Pu([...b.entries()],([w,I])=>({ext:w,count:I})),["count"],["desc"]),10));let D=Lu(h,l),S=Fu(D,d,f),T=S.slice(a,a+s),x=a+T.length,A=x<S.length,ie={count:T.length,limit:s,offset:a,has_more:A,next_offset:A?x:void 0},V=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i}),q={items:T,meta:ie,context:V,filtered:{ignored_count:y}};return p==="digest"&&(q.summary=_),$("list",V,!0,void 0,{file_count:T.length}),q}};import Ms from"node:fs/promises";var lt=class extends H{async executeTool(e){let t=e.directory_id,r=re(this.config,t),{absTarget:o,rel:i}=await de(r.path,e.path),s=ke(e),a={directory_id:t,workspace_id:e.workspace_id,directory_path:r.path},c=oe(i,!1,a,this.config,s);if(c.shouldIgnore){let h=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i});throw $("read",h,!1,`Access denied: ${c.reason||c.matchedRule||"blocked"}`),O("PERMISSION_DENIED",`Access denied: ${c.reason||c.matchedRule||"blocked"}`,{path:i,reason:c.reason})}let l=Math.max(e.offset??0,0),d=Math.min(Math.max(e.limit??4e4,1),2e5),f=e.encoding??"utf-8",p;try{p=await Ms.stat(o)}catch(h){let y=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i});throw $("read",y,!1,J(h,"Failed to stat file.").message),J(h,"Failed to stat file.")}if(!p.isFile()){let h=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i});throw $("read",h,!1,"Path is not a file."),O("NOT_A_FILE","Path is not a file.",{path:i,hint:"The path must point to a file, not a directory. Use fs_list or fs_tree to explore directories, or provide a file path to read."})}let m=s?.max_file_size_bytes;if(typeof m=="number"&&m>0&&p.size>m){let h=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i});throw $("read",h,!1,`File exceeds the policy size limit (${p.size} > ${m}).`),O("PERMISSION_DENIED",`File exceeds the maximum size allowed by policy (${p.size} > ${m} bytes).`,{path:i,reason:"policy:max_file_size_bytes"})}let g;try{g=await Ms.open(o,"r")}catch(h){let y=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i});throw $("read",y,!1,J(h,"Failed to open file.").message),J(h,"Failed to open file.")}try{let h=Buffer.alloc(d),{bytesRead:y}=await g.read(h,0,d,l),b=h.subarray(0,y).toString(f),E=l+y,k=y<d,D=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i});return $("read",D,!0,void 0,{bytes_read:y}),{content:b,bytes_read:y,next_offset:E,eof:k,context:D}}catch(h){let y=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i});throw $("read",y,!1,K(h).message),h}finally{await g.close()}}};import go from"node:fs/promises";var zr=class extends H{async executeTool(e){let t=e.directory_id,r=re(this.config,t),{absTarget:o,rel:i}=await de(r.path,e.path),s=!1,a;try{a=await go.readlink(o),s=!0}catch(f){if(fe(f)==="ENOENT")throw J(f,"Path not found.")}let c;try{c=s?await go.stat(o):await go.lstat(o)}catch(f){throw J(f,"Failed to stat path.")}let l="other";c.isDirectory()?l="dir":c.isFile()?l="file":s&&(l="symlink");let d=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i});return $("info",d,!0),{type:l,size:c.isFile()?c.size:void 0,mtime:Math.floor(c.mtimeMs/1e3),ctime:Math.floor(c.ctimeMs/1e3),atime:Math.floor(c.atimeMs/1e3),is_symlink:s,target:s?a:void 0,context:d}}};import vo from"node:fs/promises";import Te from"node:path";import bo from"node:fs/promises";import $s from"node:path";import yo from"lodash/clamp.js";function Mu(n,e){let t="^",r=0;for(;r<e.length;){let o=e[r];if(o==="*")r+1<e.length&&e[r+1]==="*"?(t+=".*",r+=2):(t+="[^/]*",r++);else if(o==="?")t+="[^/]",r++;else if(o==="{"){let i=e.indexOf("}",r);if(i===-1)t+="\\{",r++;else{let s=e.substring(r+1,i).split(",");t+="("+s.map(a=>a.trim().replace(/[.*+?^${}()|[\]\\]/g,"\\$&")).join("|")+")",r=i+1}}else"\\^$|.+()[]".includes(o)?(t+="\\"+o,r++):(t+=o,r++)}t+="$";try{return new RegExp(t,"i").test(n)}catch{return!1}}async function $u(n,e,t,r,o,i,s,a){let c;try{c=await bo.readFile(n,"utf-8")}catch{return 0}let l=c.split(/\r?\n/),d=0,f;if(r==="regex")try{f=new RegExp(t,o?"g":"gi")}catch{let p=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");f=new RegExp(p,o?"g":"gi")}else{let p=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");f=new RegExp(p,o?"g":"gi")}for(let p=0;p<l.length&&d<s;p++){let m=l[p];if(f.test(m)){f.lastIndex=0;let g=Math.max(0,p-i),h=Math.min(l.length-1,p+i),y=l.slice(g,h+1);a.push({path:e,line:p+1,preview:m.trim(),snippet:y}),d++}}return d}async function Us(n,e,t,r,o,i,s,a,c,l,d,f,p,m,g){if(d.value>=c||f.length>=l)return;let h;try{h=await bo.readdir(n,{withFileTypes:!0})}catch{return}for(let y of h){if(d.value>=c||f.length>=l)break;let _=$s.join(n,y.name),b=e==="."?y.name:$s.posix.join(e,y.name);if(oe(b,y.isDirectory(),m,g).shouldIgnore){p.value++;continue}if(y.isFile()){if(i&&!Mu(b,i))continue;d.value++,await $u(_,b,r,o,s,a,l-f.length,f)}else y.isDirectory()&&await Us(_,b,t,r,o,i,s,a,c,l,d,f,p,m,g)}}var ut=class extends H{async executeTool(e){let t=e.directory_id,r=re(this.config,t),o=e.query;if(!o||o.length===0)throw O("INVALID_INPUT","Query is required.",{hint:'Query should be a search pattern to find in file contents. Use a substring (default) or regex pattern (with mode="regex"). Examples: "function", "import.*from", "TODO"'});let i=e.mode??"substring",s=e.file_glob,a=yo(e.max_files??2e3,1,1e4),c=yo(e.max_matches??200,1,1e3),l=yo(e.context_lines??2,0,10),d=e.case_sensitive??!1,{absTarget:f,rel:p}=await de(r.path,e.path??".");if(p!==".")try{if(!(await bo.stat(f)).isDirectory())throw O("NOT_A_DIRECTORY","Grep path is not a directory.",{path:p,hint:'The grep path must be a directory. Grep searches within directories recursively. Use "." to search from the root, or provide a directory path.'})}catch(b){throw ne(b)?b:J(b,"Failed to stat grep path.")}let m={directory_id:t,workspace_id:e.workspace_id,directory_path:r.path},g=[],h={value:0},y={value:0};await Us(f,p,r.path,o,i,s,d,l,a,c,h,g,y,m,this.config);let _=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:p});return $("grep",_,!0,void 0,{file_count:h.value,match_count:g.length}),{matches:g,meta:{files_scanned:h.value,matches:g.length,truncated:h.value>=a||g.length>=c},context:_,filtered:{ignored_count:y.value}}}};import Uu from"lodash/isEmpty.js";var dt=class extends H{async executeTool(e){let t=e.directory_id,r=re(this.config,t),o=e.default_limit??12e3,i=e.default_encoding??"utf-8",s=[];if(e.items&&Array.isArray(e.items)&&(s=e.items),Uu(s))throw O("INVALID_INPUT","fs_read_many expects { items: [{path,...}] }",{receivedKeys:Object.keys(e),hint:'Provide an "items" array with at least one object containing a "path" property. Each item can optionally include "offset", "limit", and "encoding". Example: { items: [{ path: "file1.ts" }, { path: "file2.ts", limit: 5000 }] }'});let a=ke(e),c=[],l={directory_id:t,workspace_id:e.workspace_id,directory_path:r.path},d=new lt(this.config);for(let p of s)try{let m=oe(p.path,!1,l,this.config,a);if(m.shouldIgnore){c.push({path:p.path,content:"",bytes_read:0,truncated:!1,error:{code:"PERMISSION_DENIED",message:`Access denied: ${m.reason||m.matchedRule||"blocked"}`}});continue}let g={directory_id:t,path:p.path,workspace_id:e.workspace_id,device_id:e.device_id,offset:p.offset??0,limit:p.limit??o,encoding:p.encoding??i},h=await d.execute(g);if(!h.ok){c.push({path:p.path,content:"",bytes_read:0,truncated:!1,error:{code:h.error.code,message:h.error.message}});continue}c.push({path:p.path,content:h.data.content,bytes_read:h.data.bytes_read,truncated:!h.data.eof})}catch(m){let{code:g,message:h}=K(m);c.push({path:p.path,content:"",bytes_read:0,truncated:!1,error:{code:g,message:h}})}let f=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:"."});return $("read_many",f,!0,void 0,{file_count:c.length}),{files:c,context:f}}};import Ct from"lodash/clamp.js";import Bu from"lodash/compact.js";import Ks from"lodash/orderBy.js";import Ku from"lodash/uniq.js";import Bs from"lodash/take.js";function js(n,e,t){if(!(e.length>=t)){if(n.type==="file"){e.push(n.path);return}if(n.children)for(let r of n.children){if(e.length>=t)break;js(r,e,t)}}}function ju(n){let e=t=>{let r=t.toLowerCase(),o=r.split("/");return r==="readme.md"||r.endsWith("/readme.md")||r.includes("/readme.md")?0:r.endsWith(".md")?1:r.endsWith("package.json")||r.endsWith("pyproject.toml")||r.endsWith("go.mod")||r.endsWith("cargo.toml")||r.endsWith("pom.xml")||r.endsWith("build.gradle")?2:r.includes("dockerfile")||r.includes("compose")||r.endsWith(".env.example")?3:o.includes("config")||o.includes("conf")||o.includes("settings")?4:o.includes("ci")||o.includes(".github")||o.includes(".gitlab")||o.includes("jenkins")||r.includes("workflow")?5:r.endsWith(".ts")||r.endsWith(".tsx")||r.endsWith(".js")||r.endsWith(".jsx")||r.endsWith(".py")||r.endsWith(".go")||r.endsWith(".rs")||r.endsWith(".java")?6:7};return[...n].sort((t,r)=>{let o=e(t),i=e(r);return o!==i?o-i:t.localeCompare(r)})}function Vs(n,e,t,r){let o={path:n.path,name:n.name,type:n.type,depth:e,size:n.size,mtime:n.mtime,ext:n.ext,hidden:n.hidden,ignored:n.ignored};if(r?.has(n.path)?o.error=r.get(n.path):n.type==="other"&&n.name==="<readdir_error>"&&(o.error={code:"INTERNAL",message:"Failed to read directory"}),t.push(o),n.children)for(let i of n.children)Vs(i,e+1,t,r)}async function qs(n,e,t,r,o,i,s,a,c,l,d,f,p,m,g,h,y){if(a.value>=s)return g.reason="MAX_ENTRIES",null;if(t>r)return g.reason="MAX_DEPTH",null;let _=e==="."?".":e.replace(/\\/g,"/"),b;try{b=await vo.lstat(n)}catch(x){let{code:A,message:ie}=K(x);l.total_entries++;let V={name:Te.basename(e)||e,type:"other",path:_,hidden:Te.basename(e)?.startsWith("."),ignored:!1};return h&&h.set(_,{code:A,message:`Failed to stat: ${ie}`}),o==="files"||o==="dirs"?null:(a.value++,V)}let E="other";if(b.isDirectory()?E="dir":b.isFile()?E="file":b.isSymbolicLink()&&(E="symlink"),oe(_,b.isDirectory(),p,m,y).shouldIgnore)return c.value++,l.ignored++,null;l.total_entries++,E==="file"?l.files++:E==="dir"?l.dirs++:E==="symlink"&&l.symlinks++;let D=Te.basename(e)?.startsWith(".");D&&l.hidden++;let S=E==="file"?Te.extname(Te.basename(e)||e).slice(1):void 0;S&&(f==="stat"||f==="digest")&&d.set(S,(d.get(S)??0)+1),E==="file"&&(f==="stat"||f==="digest")&&(l.total_file_bytes=(l.total_file_bytes??0)+(b.size??0));let T={name:Te.basename(e)||e,type:E,path:_,size:(f==="stat"||f==="digest")&&b.isFile()?b.size:void 0,mtime:f==="stat"||f==="digest"?Math.floor(b.mtimeMs/1e3):void 0,ext:S,hidden:D,ignored:!1};if(o==="files"&&E!=="file"&&E!=="symlink"||o==="dirs"&&E!=="dir")return null;if(a.value++,E==="dir"&&t<r){let x,A;try{x=await vo.readdir(n,{withFileTypes:!0})}catch(C){A=K(C),x=[]}let ie=Ks(i?x:x.filter(C=>!C.name.startsWith(".")),[C=>C.isDirectory()?0:1,"name"],["asc","asc"]),V=[];A&&h&&h.set(_,{code:A.code,message:`Failed to read directory: ${A.message}`});for(let C of ie){if(a.value>=s)break;let q=Te.join(n,C.name),w=e==="."?C.name:Te.posix.join(e,C.name),I=w.replace(/\\/g,"/");if(oe(I,C.isDirectory(),p,m,y).shouldIgnore){c.value++,l.ignored++;continue}try{let Fe=await qs(q,w,t+1,r,o,i,s,a,c,l,d,f,p,m,g,h,y);Fe&&V.push(Fe)}catch(Fe){let{code:ge,message:Mt}=K(Fe);h&&h.set(I,{code:ge,message:`Failed to build subtree: ${Mt}`}),l.total_entries++;let Ao={name:Te.basename(w)||w,type:"other",path:I,hidden:Te.basename(w)?.startsWith("."),ignored:!1};if(o==="files"||o==="dirs")continue;a.value++,V.push(Ao)}}V.length>0&&(T.children=V)}return T}var Yr=class extends H{async executeTool(e){let t=e.directory_id,r=re(this.config,t),{absTarget:o,rel:i}=await de(r.path,e.path),s=Ct(e.max_depth??3,1,20),a=e.only??"all",c=e.include_hidden??!1,l=Ct(e.max_entries??5e3,1,2e4),d=e.detail??"stat",f=e.include_display??!1,p=Ct(e.max_display_rows??2e3,1,2e4);try{if(!(await vo.stat(o)).isDirectory())throw O("NOT_A_DIRECTORY","Path is not a directory.",{path:i,hint:"The path must point to a directory to build a tree. Provide a directory path, not a file."})}catch(C){throw ne(C)?C:J(C,"Failed to build tree.")}let m=ke(e),g={directory_id:t,workspace_id:e.workspace_id,directory_path:r.path},h={reason:void 0},y={value:0},_={value:0},b={total_entries:0,files:0,dirs:0,symlinks:0,hidden:0,ignored:0,total_file_bytes:0},E=new Map,k=new Map,D=await qs(o,i,0,s,a,c,l,y,_,b,E,d,g,this.config,h,k,m);if(!D)throw O("INTERNAL","Failed to build tree (empty result).");let S=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i});d==="digest"&&E.size>0&&(b.by_ext=Bs(Ks([...E.entries()].map(([C,q])=>({ext:C,count:q})),["count"],["desc"]),10));let T={tree:D,context:S,filtered:{ignored_count:_.value}};if(f){let C=[];Vs(D,0,C,k),C.length>p&&(C.length=p,T.truncated=T.truncated??{reason:"MAX_ENTRIES",continuation:"Display rows truncated; reduce max_entries/max_depth or lower max_display_rows"}),T.display={rows:C}}h.reason&&(T.truncated={reason:h.reason,continuation:h.reason==="MAX_ENTRIES"?"Reduce max_entries or list this folder with fs_list instead":"Reduce max_depth or list this folder with fs_list instead"}),(d==="digest"||e.include_summary)&&(T.summary=b);let x={};if(e.grep?.query)try{let C=new ut(this.config),q={directory_id:t,workspace_id:e.workspace_id,device_id:e.device_id,path:e.path??".",query:e.grep.query,mode:e.grep.mode??"substring",file_glob:e.grep.file_glob,max_files:e.grep.max_files??2e3,max_matches:e.grep.max_matches??200,context_lines:e.grep.context_lines??2,case_sensitive:e.grep.case_sensitive??!1},w=await C.execute(q);w.ok&&(x.grep={matches:w.data.matches,meta:w.data.meta,context:w.data.context})}catch{}let A=Bu(e.read?.paths),ie=[];if(e.read?.auto){let C=Ct(e.read.auto.max_files??10,1,50),q=[];js(D,q,3e3),ie=ju(q).slice(0,C)}let V=Bs(Ku([...A,...ie]),50);if(V.length>0)try{let C=Ct(e.read?.auto?.max_bytes_each??2e4,1,2e5),q=new dt(this.config),w={directory_id:t,workspace_id:e.workspace_id,device_id:e.device_id,default_limit:C,default_encoding:"utf-8",items:V.map(se=>({path:se}))},I=await q.execute(w);I.ok&&(x.read_many={files:I.data.files.map(se=>({path:se.path,content:se.content,bytes_read:se.bytes_read,truncated:se.truncated,error:se.error})),context:I.data.context})}catch{}return Object.keys(x).length>0&&(T.extras=x),$("tree",S,!0,void 0,{file_count:y.value}),T}};import So from"node:fs/promises";import xt from"node:path";import Vu from"lodash/clamp.js";import qu from"lodash/orderBy.js";function Wu(n,e){let t="^",r=0;for(;r<e.length;){let o=e[r];if(o==="*")r+1<e.length&&e[r+1]==="*"?(t+=".*",r+=2):(t+="[^/\\\\]*",r++);else if(o==="?")t+="[^/\\\\]",r++;else if(o==="["){let i=e.indexOf("]",r);if(i===-1)t+="\\[",r++;else{let s=e.substring(r+1,i);s.startsWith("!")?t+="[^"+s.substring(1)+"]":t+="["+s+"]",r=i+1}}else"\\^$|.+(){}[]".includes(o)?(t+="\\"+o,r++):(t+=o,r++)}t+="$";try{return new RegExp(t,"i").test(n)}catch{return n.toLowerCase().includes(e.toLowerCase())}}function Gu(n,e,t){return t==="glob"?Wu(n,e):n.toLowerCase().includes(e.toLowerCase())}function Hu(n,e,t){let r=100;if(e){for(let o of e)if(n.path.startsWith(o)){r+=50;break}}if(t){for(let o of t)if(n.path.startsWith(o)){r-=30;break}}return n.name===n.path.split("/").pop()&&(r+=20),r}function Ju(n,e){let t="^",r=0;for(;r<e.length;){let o=e[r];o==="*"?r+1<e.length&&e[r+1]==="*"?(t+=".*",r+=2):(t+="[^/]*",r++):o==="?"?(t+="[^/]",r++):"\\^$|.+(){}[]".includes(o)?(t+="\\"+o,r++):(t+=o,r++)}t+="$";try{return new RegExp(t,"i").test(n)}catch{return!1}}async function Eo(n,e,t,r,o,i,s,a,c,l,d,f,p,m,g,h,y,_){if(l.length>=c)return;let b;try{b=await So.readdir(n,{withFileTypes:!0})}catch{return}let E=a?b:b.filter(k=>!k.name.startsWith("."));for(let k of E){if(l.length>=c)break;let D=xt.join(n,k.name),S=e==="."?k.name:xt.posix.join(e,k.name);if(oe(S,k.isDirectory(),f,p,_).shouldIgnore){d.value++;continue}if(m&&!Ju(S,m)){i&&k.isDirectory()&&await Eo(D,S,t,r,o,i,s,a,c,l,d,f,p,m,g,h,y,_);continue}let x=Gu(k.name,r,o),A="other";if(k.isDirectory()?A="dir":k.isFile()?A="file":k.isSymbolicLink()&&(A="symlink"),x&&(s==="all"||s==="files"&&(A==="file"||A==="symlink")||s==="dirs"&&A==="dir")){let V,C;if(y!==!1)try{let I=await So.stat(D);V=I.isFile()?I.size:void 0,C=Math.floor(I.mtimeMs/1e3)}catch{}let q=A==="file"?xt.extname(k.name).slice(1):void 0,w=Hu({name:k.name,path:S},g,h);l.push({name:k.name,path:S,type:A,size:V,mtime:C,ext:q,hidden:k.name.startsWith("."),ignored:!1,score:w,matched:"name"})}i&&A==="dir"&&await Eo(D,S,t,r,o,i,s,a,c,l,d,f,p,m,g,h,y)}}var Qr=class extends H{async executeTool(e){let t=e.directory_id,r=re(this.config,t),o=e.query;if(!o||o.length===0)throw O("INVALID_INPUT","Query is required.",{hint:'Query should be a pattern to match file or directory names. Use a substring (default) or glob pattern (with mode="glob"). Examples: "config", "*.ts", "test/**"'});let i=e.mode??"substring",s=e.recursive??!0,a=e.only??"all",c=e.include_hidden??!1,l=Vu(e.max_results??200,1,2e4),d=Math.max(e.offset??0,0),f=e.file_glob,p=e.prefer_paths,m=e.avoid_paths,g=e.include_stats!==!1,{absTarget:h,rel:y}=await de(r.path,e.path??"."),_=h,b=y,E=[];if(y!==".")try{let I=await So.stat(h);if(!I.isDirectory())if(I.isFile()){_=xt.dirname(h);let se=xt.posix.dirname(y);b=se==="."?".":se,E.push({type:"warning",description:`Search path "${y}" is not a directory (it's a file). Searching the directory containing it instead: "${b}"`})}else throw O("NOT_A_DIRECTORY","Search path is not a directory.",{path:y,hint:'The search path must be a directory. Search looks for files/directories matching the query within directories. Use "." to search from the root, or provide a directory path.'})}catch(I){throw ne(I)?I:J(I,"Failed to stat search path.")}let k=ke(e),D={directory_id:t,workspace_id:e.workspace_id,directory_path:r.path},S=[],T={value:0};await Eo(_,b,r.path,o,i,s,a,c,l+d,S,T,D,this.config,f,p,m,g,k);let x=qu(S,[I=>I.score??0,"name"],["desc","asc"]),A=x.slice(d,d+l),ie=d+A.length,V=ie<x.length,C={count:A.length,limit:l,offset:d,has_more:V,next_offset:V?ie:void 0},q=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:b});$("search",q,!0,void 0,{file_count:A.length});let w={results:A,meta:C,context:q,filtered:{ignored_count:T.value}};return E.length>0&&(w.messages=E),w}};var Xr=class extends H{async executeTool(e){let t={agent_version:ue(),platform:process.platform,answered_at:Date.now()};return e.echo!==void 0&&(t.echo=e.echo),t}};var Zr=class{config;executers=new Map;constructor(e){this.config=e,this.initializeExecuters()}initializeExecuters(){this.executers.set("fs_list",new Jr(this.config)),this.executers.set("fs_read",new lt(this.config)),this.executers.set("fs_info",new zr(this.config)),this.executers.set("fs_tree",new Yr(this.config)),this.executers.set("fs_search",new Qr(this.config)),this.executers.set("fs_grep",new ut(this.config)),this.executers.set("fs_read_many",new dt(this.config)),this.executers.set("dl_ping",new Xr(this.config))}async executeTool(e,t){let r=this.executers.get(e);if(!r)return $e({code:"UNKNOWN_TOOL",message:`Unknown tool: ${e}`,details:{toolName:e}});try{return await r.execute(t)}catch(o){return ne(o)?$e(o):$e({...K(o),details:{raw:String(o)}})}}getExecuter(e){return this.executers.get(e)}hasTool(e){return this.executers.has(e)}getRegisteredTools(){return Array.from(this.executers.keys())}};import Ws from"lodash/isObject.js";import We from"lodash/get.js";function At(n){let e=Date.now()-n,t=parseFloat((e/1e3).toFixed(2));return{execution_ms:e,execution_sec:t}}function zu(n){return Ws(n)&&typeof We(n,"ok")=="boolean"}function Yu(n){let e=zu(n),t=e?!!We(n,"ok"):!0,r,o,i;if(t){if(e?r=We(n,"data")??We(n,"result")??n:r=n,Ws(r)&&Array.isArray(We(r,"messages"))){i=We(r,"messages");let s={...r};delete s.messages,r=s}}else e?o=We(n,"error")??n:o=n;return{ok:t,result:r,error:o,messages:i}}function Gs(n,e,t,r){let o=At(r),{ok:i,result:s,error:a,messages:c}=Yu(t);return vn({type:"tool_result",job_id:n,tool:e,ok:i,timing:o,...i?{result:s??null}:{error:a??{code:"UNKNOWN",message:"Unknown error"}},messages:c})}function Hs(n,e,t,r){let o=At(r);return{type:"tool_result",job_id:n,tool:e,ok:!1,error:K(t),timing:o}}var j=class{toolName;jobId;ok;elapsedSec;raw;constructor(e,t,r,o){this.toolName=e,this.jobId=t,this.ok=r.ok,this.elapsedSec=o,this.raw=r}getErrorDescription(){return`error: ${B(this.raw.error)}`}getStatusIcon(){return this.ok?"\u2713":"\u2717"}getStatusText(){return this.ok?"SUCCESS":"FAILED"}toString(){let e=this.getStatusIcon(),t=this.getDescription();return`${e} ${this.toolName} (${t}, elapsed=${this.elapsedSec}s)`}};var Dt=class extends j{output;constructor(e,t,r,o){super(e,t,r,o),this.output=r.ok?r.data:void 0}getDescription(){if(!this.ok)return this.getErrorDescription();if(!this.output)return"no result";let{items:e,meta:t,filtered:r,context:o}=this.output,i=e?.length??0,s=r?.ignored_count??0,a=o?.path??"unknown",c=[];i>0&&c.push(`${i} item${i!==1?"s":""}`),s>0&&c.push(`${s} ignored`),t?.has_more&&c.push("has_more");let l=c.length>0?c.join(", "):"empty";return`path=${a}, ${l}`}};var It=class extends j{output;constructor(e,t,r,o){super(e,t,r,o),this.output=r.ok?r.data:void 0}getDescription(){if(!this.ok)return this.getErrorDescription();if(!this.output)return"no result";let{bytes_read:e,eof:t,context:r}=this.output,o=r?.path??"unknown",i=e??0,s=!t,a=[`path=${o}`,`${i} bytes`];return s&&a.push("truncated"),a.join(", ")}};var Ot=class extends j{output;constructor(e,t,r,o){super(e,t,r,o),this.output=r.ok?r.data:void 0}getDescription(){if(!this.ok)return this.getErrorDescription();if(!this.output)return"no result";let{type:e,size:t,context:r}=this.output,o=r?.path??"unknown",i=t!==void 0?`${t} bytes`:"no size";return`path=${o}, type=${e}, ${i}`}};var Nt=class extends j{output;constructor(e,t,r,o){super(e,t,r,o),this.output=r.ok?r.data:void 0}getDescription(){if(!this.ok)return this.getErrorDescription();if(!this.output)return"no result";let{tree:e,filtered:t,summary:r,context:o}=this.output,i=o?.path??"unknown",s=t?.ignored_count??0,a=[`path=${i}`];if(r){let{total_entries:c,files:l,dirs:d}=r;c!==void 0&&a.push(`${c} entries`),l!==void 0&&a.push(`${l} files`),d!==void 0&&a.push(`${d} dirs`)}else if(e){let c=d=>{let f=1;if(d.children)for(let p of d.children)f+=c(p);return f},l=c(e);a.push(`${l} nodes`)}return s>0&&a.push(`${s} ignored`),this.output.truncated&&a.push("truncated"),a.join(", ")}};var Pt=class extends j{output;constructor(e,t,r,o){super(e,t,r,o),this.output=r.ok?r.data:void 0}getDescription(){if(!this.ok)return this.getErrorDescription();if(!this.output)return"no result";let{results:e,meta:t,filtered:r,context:o}=this.output,i=o?.path??"unknown",s=e?.length??0,a=r?.ignored_count??0,c=[`path=${i}`,`${s} result${s!==1?"s":""}`];return a>0&&c.push(`${a} ignored`),t?.has_more&&c.push("has_more"),c.join(", ")}};var Ft=class extends j{output;constructor(e,t,r,o){super(e,t,r,o),this.output=r.ok?r.data:void 0}getDescription(){if(!this.ok)return this.getErrorDescription();if(!this.output)return"no result";let{matches:e,meta:t,filtered:r,context:o}=this.output,i=o?.path??"unknown",s=e?.length??0,a=t?.files_scanned??0,c=r?.ignored_count??0,l=[`path=${i}`,`${s} match${s!==1?"es":""}`,`${a} file${a!==1?"s":""} scanned`];return c>0&&l.push(`${c} ignored`),t?.truncated&&l.push("truncated"),l.join(", ")}};var Lt=class extends j{output;constructor(e,t,r,o){super(e,t,r,o),this.output=r.ok?r.data:void 0}getDescription(){if(!this.ok)return this.getErrorDescription();if(!this.output)return"no result";let{files:e}=this.output,t=e?.length??0,r=e?.filter(a=>!a.error).length??0,o=t-r,i=e?.reduce((a,c)=>a+(c.bytes_read??0),0)??0,s=[`${t} file${t!==1?"s":""}`,`${r} success`];return o>0&&s.push(`${o} error${o!==1?"s":""}`),i>0&&s.push(`${i} bytes`),s.join(", ")}};function _o(n,e,t,r){switch(n){case"fs_list":return new Dt(n,e,t,r);case"fs_read":return new It(n,e,t,r);case"fs_info":return new Ot(n,e,t,r);case"fs_tree":return new Nt(n,e,t,r);case"fs_search":return new Pt(n,e,t,r);case"fs_grep":return new Ft(n,e,t,r);case"fs_read_many":return new Lt(n,e,t,r);default:{class o extends j{getDescription(){return this.ok?"completed":"failed"}}return new o(n,e,t,r)}}}var Qu=64,Xu=5*6e4,ko=class{entries=new Map;max;ttlMs;now;constructor(e={}){this.max=Math.max(1,e.max??Qu),this.ttlMs=Math.max(1,e.ttlMs??Xu),this.now=e.now??(()=>Date.now())}get size(){return this.prune(),this.entries.size}get(e){return this.prune(),this.entries.get(e)}has(e){return this.get(e)!==void 0}remember(e,t,r){this.prune(),this.entries.delete(e),this.entries.set(e,{jobId:e,text:t,at:this.now(),delivered:r}),this.evictOverflow()}markDelivered(e){let t=this.entries.get(e);t&&(t.delivered=!0)}undelivered(){return this.prune(),[...this.entries.values()].filter(e=>!e.delivered)}prune(){let e=this.now()-this.ttlMs;for(let[t,r]of this.entries)r.at<=e&&this.entries.delete(t)}evictOverflow(){for(;this.entries.size>this.max;){let e=this.entries.keys().next();if(e.done)return;this.entries.delete(e.value)}}},en=class{cache;inFlight=new Set;connected=!1;negotiated=!1;constructor(e={}){this.cache=new ko(e)}get isConnected(){return this.connected}get redeliveryNegotiated(){return this.negotiated}onConnected(){this.connected=!0}onDisconnected(){this.connected=!1,this.negotiated=!1}onSessionAck(e){this.negotiated=e.ok===!0&&He(e.capabilities,G.RESULT_REDELIVERY_V1)}decide(e){if(this.inFlight.has(e))return{action:"ignore",reason:"in_flight"};let t=this.cache.get(e);return t?{action:"resend",text:t.text}:{action:"execute"}}beginExecution(e){this.inFlight.add(e)}endExecution(e){this.inFlight.delete(e)}recordResult(e,t){return this.cache.remember(e,t,this.connected),{heldForRedelivery:!this.connected}}pendingRedeliveries(){return this.negotiated?this.cache.undelivered():[]}markDelivered(e){this.cache.markDelivered(e)}get cachedCount(){return this.cache.size}};var tn=class{name="tools-orchestrator";delivery=new en;handlers(){return{"ws:connected":async(e,t)=>{this.delivery.onConnected(),t.notifier.info(`WS connected: ${e.url}`,{scope:"system"})},"ws:disconnected":async()=>{this.delivery.onDisconnected()},"auth:session_init_ack":async(e,t)=>{this.delivery.onSessionAck(e),this.redeliverPendingResults(t)},"ws:rx":async(e,t)=>{let r;try{r=JSON.parse(e.text)}catch{return}if(tr(r)!=="tool_call")return;let o=Zt.safeParse(r);if(!o.success){t.notifier.error("Unexpected message format",{scope:"system"});return}let i=o.data,s=this.delivery.decide(i.job_id);if(s.action==="ignore"){t.notifier.info(`Tool call ${i.job_id} is already running; ignoring the repeat`,{scope:"system"});return}if(s.action==="resend"){t.notifier.info(`Tool call ${i.job_id} already ran; re-sending the stored result`,{scope:"system"}),this.sendResult(t,i.job_id,s.text);return}t.bus.emit("tool:call",i),await this.handleToolCall(i,t)}}}sendResult(e,t,r){let{heldForRedelivery:o}=this.delivery.recordResult(t,r);e.bus.emit("ws:tx",{text:r}),o&&e.notifier.info(`Tool result for ${t} produced while disconnected; holding it for redelivery`,{scope:"system"})}redeliverPendingResults(e){let t=this.delivery.pendingRedeliveries();if(t.length!==0){e.notifier.info(`Re-sending ${t.length} tool result${t.length===1?"":"s"} produced while disconnected`,{scope:"system"});for(let r of t)e.bus.emit("ws:tx",{text:r.text}),this.delivery.markDelivered(r.jobId)}}async handleToolCall(e,t){let r=e.tool,o=e.job_id,i=bn(e.args).set("workspace_id",e.workspace_id).set("device_id",e.device_id).set("context",e.context).value(),s=i.directory_id,a=t.engine.configurationContext.configuration,c=a.directories.map(f=>f.id).join(", ")||"none",l=a.directories.map(f=>f.path).join(", ")||"none";t.notifier.info(`Tool call: ${r} (job=${o}, directory_id=${s||"MISSING"}, available_ids=[${c}], available_paths=[${l}], directory_count=${a.directories.length})`,{scope:"system"}),t.notifier.info(`Executing: ${r}`);let d=Date.now();this.delivery.beginExecution(o);try{let p=await new Zr(a).executeTool(r,i),m=Gs(o,r,p,d);er.parse(m),this.sendResult(t,o,JSON.stringify(m));let g=At(d),h=_o(r,o,p,g.execution_sec);h.ok?t.notifier.success(h.toString()):t.notifier.error(h.toString())}catch(f){let p=Hs(o,r,f,d);er.parse(p),this.sendResult(t,o,JSON.stringify(p));let m=At(d),g={ok:!1,error:K(f)},h=_o(r,o,g,m.execution_sec);t.notifier.error(h.toString())}finally{this.delivery.endExecution(o)}}};var To=[{name:"dl_ping",version:"1.0",description:"Liveness probe. Answers with the agent version, platform and a timestamp without reading any file. Needs no shared folder and charges no credit.",inputSchema:{type:"object",properties:{echo:{type:"string",maxLength:64}},required:[]},errorCodes:["INTERNAL"]},{name:"fs_list",version:"1.0",description:"List files and folders at a relative path inside a shared folder.",inputSchema:{type:"object",properties:{directory_id:{type:"string",minLength:1},path:{type:"string",default:"."},limit:{type:"integer",minimum:1,maximum:1e3,default:200},offset:{type:"integer",minimum:0,default:0},include_hidden:{type:"boolean",default:!1},only:{type:"string",enum:["all","files","dirs"],default:"all"},sort:{type:"string",enum:["name","mtime","size"],default:"name"},order:{type:"string",enum:["asc","desc"],default:"asc"},detail:{type:"string",enum:["basic","stat","digest"],default:"stat"}},required:["path"]},errorCodes:["PATH_ESCAPE","NOT_FOUND","NOT_A_DIRECTORY","INVALID_INPUT","INTERNAL","UNKNOWN_ROOT"]},{name:"fs_read",version:"1.0",description:"Read the contents of a SINGLE text file inside a shared folder. For reading many files at once, prefer fs_read_many instead of multiple fs_read calls.",inputSchema:{type:"object",properties:{directory_id:{type:"string",minLength:1},path:{type:"string",minLength:1},offset:{type:"integer",minimum:0,default:0},limit:{type:"integer",minimum:1,maximum:2e5,default:4e4},encoding:{type:"string",default:"utf-8"}},required:["path"]},errorCodes:["PATH_ESCAPE","NOT_FOUND","NOT_A_FILE","PERMISSION_DENIED","INVALID_INPUT","INTERNAL","UNKNOWN_ROOT"]},{name:"fs_info",version:"1.0",description:"Get metadata about a file or directory (type, size, timestamps, symlink).",inputSchema:{type:"object",properties:{directory_id:{type:"string",minLength:1},path:{type:"string",minLength:1}},required:["path"]},errorCodes:["PATH_ESCAPE","NOT_FOUND","PERMISSION_DENIED","INVALID_INPUT","INTERNAL","UNKNOWN_ROOT"]},{name:"fs_tree",version:"1.0",description:"Return a directory tree from a relative path up to max_depth.",inputSchema:{type:"object",properties:{directory_id:{type:"string",minLength:1},path:{type:"string",default:"."},max_depth:{type:"integer",minimum:1,maximum:20,default:3},max_entries:{type:"integer",minimum:1,maximum:2e4,default:5e3},include_hidden:{type:"boolean",default:!1},only:{type:"string",enum:["all","files","dirs"],default:"all"},detail:{type:"string",enum:["basic","stat","digest"],default:"stat"},include_display:{type:"boolean",default:!1},max_display_rows:{type:"integer",minimum:1,maximum:2e4,default:2e3}},required:["path"]},errorCodes:["PATH_ESCAPE","NOT_FOUND","NOT_A_DIRECTORY","INVALID_INPUT","INTERNAL","UNKNOWN_ROOT"]},{name:"fs_search",version:"1.0",description:"Search for files/folders by name inside a root, optionally recursively.",inputSchema:{type:"object",properties:{directory_id:{type:"string",minLength:1},path:{type:"string",default:"."},query:{type:"string",minLength:1},mode:{type:"string",enum:["substring","glob"],default:"substring"},recursive:{type:"boolean",default:!0},include_hidden:{type:"boolean",default:!1},only:{type:"string",enum:["all","files","dirs"],default:"all"},max_results:{type:"integer",minimum:1,maximum:2e4,default:200}},required:["query"]},errorCodes:["PATH_ESCAPE","NOT_FOUND","INVALID_INPUT","INTERNAL","UNKNOWN_ROOT"]},{name:"fs_grep",version:"1.0",description:"Search for text content inside files (like grep/ripgrep).",inputSchema:{type:"object",properties:{directory_id:{type:"string",minLength:1},path:{type:"string",default:"."},query:{type:"string",minLength:1},mode:{type:"string",enum:["substring","regex"],default:"substring"},file_glob:{type:"string"},max_files:{type:"integer",minimum:1,maximum:1e4,default:2e3},max_matches:{type:"integer",minimum:1,maximum:1e3,default:200},context_lines:{type:"integer",minimum:0,maximum:10,default:2},case_sensitive:{type:"boolean",default:!1}},required:["query"]},errorCodes:["PATH_ESCAPE","NOT_FOUND","NOT_A_DIRECTORY","INVALID_INPUT","INTERNAL"]},{name:"fs_read_many",version:"1.0",description:"Read multiple files in a single call (batch read). Prefer this over multiple fs_read calls when you need to read several files\u2014fewer round-trips and better performance (up to 50 items per call).",inputSchema:{type:"object",properties:{directory_id:{type:"string",minLength:1},items:{type:"array",minItems:1,maxItems:50,items:{type:"object",properties:{path:{type:"string",minLength:1},offset:{type:"integer",minimum:0,default:0},limit:{type:"integer",minimum:1,maximum:2e5},encoding:{type:"string"}},required:["path"]}},default_limit:{type:"integer",minimum:1,maximum:2e5,default:12e3},default_encoding:{type:"string",default:"utf-8"}},required:["items"]},errorCodes:["PATH_ESCAPE","NOT_FOUND","NOT_A_FILE","INVALID_INPUT","INTERNAL"]}];var wo=class extends Y{constructor(){super(new z({name:"tools-job",lane:"worker",priority:1e3,locks:[],maxAttempts:1,cancellable:!1}))}async run(e,t){t.notifier.info("Executing supported tools job");let o=t.engine.configurationContext.configuration.device?.id;if(!o){t.notifier.error("Cannot publish tools: device ID not available");return}let i={type:"tools_publish",device_id:o,tools:To};t.bus.emit("ws:tx",{text:JSON.stringify(i)}),t.notifier.success(`\u2192 tools_publish (count=${To.length})`)}},Ro=new wo;function Js(){return new pe(Ro,void 0)}var Co=class extends Y{constructor(){super(new z({name:"directories-job",lane:"worker",priority:1e3,locks:[],maxAttempts:1,cancellable:!1}))}async run(e,t){t.notifier.info("Executing directories job");let r=t.engine.configurationContext.configuration,o=r.device?.id;if(!o){t.notifier.error("Cannot publish directories: device ID not available");return}let i=r.directories.map(a=>({id:a.id,name:a.name,path:pn(a.path)??a.name,path_hint:a.tag||void 0})),s={type:"directories_publish",device_id:o,directories:i};t.bus.emit("ws:tx",{text:JSON.stringify(s)}),t.notifier.success(`\u2192 directories_publish (dirs=${s.directories.length})`)}},xo=new Co;function zs(){return new pe(xo,void 0)}var rn=class{name="meta-data-orchestrator";onRegister(e){e.engine.register(Ro),e.engine.register(xo)}handlers(){return{"meta:data:requested:tools":async(e,t)=>{t.notifier.info("MetaData: tools requested -> dispatching supported tools job"),t.engine.dispatch(Js())},"meta:data:requested:directories":async(e,t)=>{t.notifier.info("MetaData: directories requested -> dispatching directories job"),t.engine.dispatch(zs())}}}};var nn=class{name="discovery-orchestrator";refreshInFlight=!1;noticeShown=null;handlers(){return{"config:loaded":async(e,t)=>{this.surfaceNotice(e.discovery,t),!An(e.discovery)&&this.refresh(t,"cache-missing-or-expired")},"discovery:refresh:requested":async(e,t)=>{await this.refresh(t,e.reason)},"discovery:document:received":async(e,t)=>{this.adopt(xn(e.document,e.source),t,e.source)},"discovery:cache:discarded":async(e,t)=>{let r=t.engine.configurationContext.configuration;if(!r.discovery)return;t.notifier.info(`Discovery: dropping cached endpoint (${e.reason})`,{scope:"system"});let o={...r,discovery:void 0};t.engine.configurationContext.loader.withDiscoveryCache(null),t.engine.applyConfiguration(o),t.bus.emit("config:save:requested",o)}}}async refresh(e,t){if(!this.refreshInFlight){this.refreshInFlight=!0;try{let r=e.engine.configurationContext.configuration,o=await ai(r.controlBaseUrl);if(!o){e.notifier.info(`Discovery: no document available (${t})`,{scope:"system"});return}this.adopt(xn(o,"well_known"),e,"well_known")}catch{return}finally{this.refreshInFlight=!1}}}adopt(e,t,r){if(!e)return;let o=t.engine.configurationContext.configuration,i=ii(o.discovery,e);if(!i||i===o.discovery){t.notifier.info(`Discovery: keeping the cached document (${r} was not newer)`,{scope:"system"});return}let s={...o,discovery:i};t.engine.configurationContext.loader.withDiscoveryCache(i),t.engine.applyConfiguration(s),t.bus.emit("config:save:requested",s),t.notifier.info(`Discovery: cached ${r} document issued_at=${i.issuedAt??"-"} bridge=${(i.bridgeUrls??[]).join(",")||"-"}`,{scope:"system"}),this.surfaceNotice(i,t)}surfaceNotice(e,t){let r=e?.notice;!r||this.noticeShown===r||(this.noticeShown=r,t.notifier.warn(r))}};Zi(()=>[new Fr,new jr,new $r,new Ur,new Gr,new Hr,new nn,new qr,new tn,new rn]);
6
+ `);if(m===-1)break;let g=d.slice(0,m);d=d.slice(m+2);let h=null,b=null;for(let k of g.split(`
7
+ `))k.startsWith("event:")&&(h=k.slice(6).trim()),k.startsWith("data:")&&(b=k.slice(5).trim());if(!h||!b)continue;let E;try{E=JSON.parse(b)}catch(k){o.error(`[deviceAuthStream] Failed to parse event data as JSON: ${String(k)}`);continue}let v=ll.safeParse(E);if(!v.success){o.error(`[deviceAuthStream] Event validation failed (${h}): ${String(v.error)}`);continue}let _=v.data;if(h==="approved"||h==="denied"||h==="expired")return _;if(h==="pending"){"status"in _&&_.status==="pending"&&_.needs_proof===!0&&o.warn("[deviceAuthStream] pending: needs_proof=true (unexpected before approval)");continue}o.warn(`[deviceAuthStream] Unknown event type: ${h}`)}}throw o.error("[deviceAuthStream] Stream ended unexpectedly without completion"),new Error("Device authorization stream ended without completion")}catch(a){if(a instanceof Error&&a.name==="AbortError")o.warn(`[deviceAuthStream] Aborted: ${a.message??""}`);else{let c=a instanceof Error?a.message:String(a);o.error(`[deviceAuthStream] Error: ${c}`)}throw a}finally{clearTimeout(s)}})}function Vi(n){return new ee(n,async(e,t)=>Ee(e,"/api/device/authorize/token",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}))}function qi(n){return new ee(n,async(e,t)=>{let r=new AbortController,o=3e4,i=setTimeout(()=>{r.abort()},o);try{let s=await Ee(e,"/api/device/authorize/refresh",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t),signal:r.signal});return clearTimeout(i),s}catch(s){throw clearTimeout(i),s instanceof Error&&s.name==="AbortError"?new Error(`Refresh token request timed out after ${o}ms`):s}})}function Wi(n){return new ee(n,async(e,t)=>Ee(e,"/api/device/enrollment/start",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(t)}))}var tt=class{deviceAuthStartCall;deviceAuthProveCall;deviceAuthStreamCall;deviceAuthTokenCall;deviceAuthRefreshCall;deviceEnrollmentStartCall;constructor(e,t){let r={configuration:e,notifier:t};this.deviceAuthStartCall=Bi(r),this.deviceAuthProveCall=Ki(r),this.deviceAuthStreamCall=ji(r),this.deviceAuthTokenCall=Vi(r),this.deviceAuthRefreshCall=qi(r),this.deviceEnrollmentStartCall=Wi(r)}deviceAuthStart(e){return this.deviceAuthStartCall.execute(e)}deviceEnrollmentStart(e){return this.deviceEnrollmentStartCall.execute(e)}deviceAuthProve(e){return this.deviceAuthProveCall.execute(e)}deviceAuthStream(e){return this.deviceAuthStreamCall.execute(e)}deviceAuthToken(e){return this.deviceAuthTokenCall.execute(e)}deviceAuthRefresh(e){return this.deviceAuthRefreshCall.execute(e)}};function dl(n){if(!kt(n)||te(n,"ok")!==!0)return!1;let e=te(n,"data");return kt(e)?te(e,"ok")===!0&&rt(te(e,"access_token"))&&rt(te(e,"refresh_token"))&&typeof te(e,"expires_in_sec")=="number"&&rt(te(e,"device_id")):!1}function pl(n){return n.ok===!0&&typeof n.access_token=="string"}var Ir=class{constructor(e){this.reason=e}},oo=["REFRESH_EXPIRED","REFRESH_REVOKED","REFRESH_NOT_FOUND","DEVICE_NOT_FOUND"],_e=class{constructor(e,t,r,o,i,s,a,c){this.ok=e;this.accessToken=t;this.refreshToken=r;this.expiresInSec=o;this.error=i;this.retryAfterSec=s;this.errorCode=a;this.driftMs=c}},no=class extends Y{constructor(){super(new z({name:"refresh-tokens",lane:"io",priority:900,locks:["AUTH_REFRESH"],maxAttempts:5,cancellable:!0}))}async run(e,t){let r=t.engine.configurationContext.configuration;if(!r.controlBaseUrl)return new _e(!1,void 0,void 0,void 0,"controlBaseUrl missing");if(!r.device?.id)return new _e(!1,void 0,void 0,void 0,"device.id missing");let o=await t.engine.secrets.get("devicePrivateKey");if(!o.ok||!o.value)return new _e(!1,void 0,void 0,void 0,"device private key missing");let i=o.value,s=await t.engine.secrets.get("refreshToken");if(!s.ok||!s.value)return new _e(!1,void 0,void 0,void 0,"refresh token missing");let a=s.value;t.notifier.info(`Refreshing tokens (job) reason=${e.reason}`,{scope:"system",category:["token-refresh"]});let c=Date.now(),u=ul.randomBytes(16).toString("base64url"),d=gn({deviceId:r.device.id,ts:c,nonce:u,refreshToken:a,privateKeyPem:i}),f=new tt(r,t.notifier),p;try{p=await f.deviceAuthRefresh({device_id:r.device.id,refresh_token:a,ts:c,nonce:u,sig:d})}catch(g){let h=g instanceof Error?g.message:String(g),b=g,E=b.retryAfterSec,v=b.body,_=v?.error,k=_!=null&&typeof _=="object"?_.code:void 0,I=rt(k)?k:void 0,S=_!=null&&typeof _=="object"?_.drift_ms:void 0,R=typeof S=="number"?S:void 0;return I==="REFRESH_NOT_FOUND"?(t.notifier.warn("Refresh token not found; clearing stored refresh token and stopping automatic refresh. Please run signin.",{category:["token-refresh"]}),await t.engine.secrets.delete("refreshToken").catch(x=>{let A=x instanceof Error?x.message:String(x);t.logger.warn(`Could not clear stored refresh token: ${A}`,{category:["token-refresh"]}),t.notifier.warn(`Could not clear stored refresh token: ${A}`,{category:["token-refresh"]})}),new _e(!1,void 0,void 0,void 0,"Refresh token not found",void 0,"REFRESH_NOT_FOUND")):(t.notifier.error(`Refresh tokens failed: ${h}`,{category:["token-refresh"]}),new _e(!1,void 0,void 0,void 0,h,E,I,R))}let m=this.normalizeRefreshResponse(p);if(!m){let g=this.extractErrorMessage(p),h=this.extractErrorCode(p),b=this.extractErrorDrift(p);return t.notifier.error(`Refresh tokens failed: ${g}`,{category:["token-refresh"]}),new _e(!1,void 0,void 0,void 0,g,void 0,h,b)}return m.refresh_token&&await t.engine.secrets.set("refreshToken",m.refresh_token),new _e(!0,m.access_token,m.refresh_token,m.expires_in_sec)}normalizeRefreshResponse(e){if(dl(e))return e.data;if(this.looksLikeDomainRefresh(e)){let t=e;return pl(t)?t:null}return null}looksLikeDomainRefresh(e){if(typeof e!="object"||e===null)return!1;let t=e;return t.ok===!0||t.ok===!1}extractErrorMessage(e){if(!kt(e))return"Unknown error";if(te(e,"ok")===!1){let t=te(e,"error.message");if(rt(t)&&t.length>0)return t}return te(e,"ok")===!0&&"data"in e?"Bad refresh response: missing token fields":"Unknown error"}extractErrorDrift(e){if(!kt(e)||te(e,"ok")!==!1)return;let t=te(e,"error.drift_ms");return typeof t=="number"?t:void 0}extractErrorCode(e){if(!kt(e)||te(e,"ok")!==!1)return;let t=te(e,"error.code");return rt(t)?t:void 0}},io=new no;function Hi(n){return new pe(io,n)}function Gi(n,e){return e.headless?n.on("notify:event",t=>{fl(t,e.debug)}):null}function fl(n,e){if(!e&&!ml(n))return;let t=`[agent] ${n.message}`;switch(n.kind){case"error":console.error(t);break;case"warning":console.warn(t);break;default:console.log(t);break}}function ml(n){return n.kind==="error"||n.kind==="warning"||n.kind==="success"||n.scope==="system"}var Or=class{constructor(e){this.argv=e;let t=e.map(f=>f.trim()?.toLowerCase()),r=e.map(f=>f.trim()),o=this.parseKeyValue(t,r,["--env"]);o.match&&(this.enviromentFile=o.value);let i=this.parseKeyValue(t,r,["--root"]);i.match&&(this.rootPath=i.value);let s=this.parseKeyValue(t,r,["--control-url"]);s.match&&(this.controlUrl=s.value);let a=this.parseKeyValue(t,r,["--bridge-ws-url"]);a.match&&(this.bridgeWsUrl=a.value);let c=this.parseKeyValue(t,r,["--private-key-file"]);c.match&&c.value&&(this.privateKeyFile=c.value);let u=this.parseKeyValue(t,r,["--public-key-file"]);u.match&&u.value&&(this.publicKeyFile=u.value);let d=this.parseKeyValue(t,r,["--enrollment-file"]);d.match&&d.value&&(this.enrollmentFile=d.value)}enviromentFile;rootPath;controlUrl;bridgeWsUrl;privateKeyFile;publicKeyFile;enrollmentFile;parseKeyValue(e,t,r){let o=r.map(i=>i.toLowerCase()?.trim()).filter(i=>i!==void 0);if(o.length===0)return{match:!1,value:void 0};for(let i of o){let s=e.findIndex(a=>{let c=a.toLowerCase();return c===i||c.startsWith(i+"=")});if(s!==-1){let a=t[s],c=a.toLowerCase().indexOf("=");if(c!==-1)return{match:!0,value:a.substring(c+1)||void 0};let u=t[s+1];return u===void 0||u.startsWith("--")?{match:!0,value:void 0}:{match:!0,value:u}}}return{match:!1,value:void 0}}};var Nr=class{bus;flags;constructor(e,t){this.bus=e,this.flags=t??new Ae(!1)}info(e,t){return this.push(e,t)}warn(e,t){let r=Object.assign({},t,{kind:"warning"});return this.push(e,r)}error(e,t){let r=Object.assign({},t,{kind:"error"});return this.push(e,r)}success(e,t){let r=Object.assign({},t,{kind:"success"});return this.push(e,r)}push(e,t){if((t?.scope??"default")==="system"&&!this.flags.debug&&!this.flags.headless)return null;let o=new ye(e,t);return this.bus.emit("notify:event",o),o}};var Pr=class{bus;constructor(e){this.bus=e}info(e,t){this.push(e,Object.assign({},t,{level:"info"}))}warn(e,t){this.push(e,Object.assign({},t,{level:"warn"}))}error(e,t){this.push(e,Object.assign({},t,{level:"error"}))}debug(e,t){this.push(e,Object.assign({},t,{level:"debug"}))}success(e,t){this.push(e,Object.assign({},t,{level:"success"}))}push(e,t){let r=new Vt(e,t);this.bus.emit("log",r)}};import ao from"node:fs";import bl from"node:os";import co from"node:tty";import hl from"lodash/toLower.js";import gl from"lodash/trim.js";var yl=new Set(["1","true","yes","on"]),so=new Set(["0","false","no","off"]);function Fr(n){let e=hl(gl(n));if(yl.has(e))return!0;if(so.has(e))return!1}function Rt(n,e,t=process.env){return Fr(t[n]??"")??e}function vl(n){let e=n.setRawMode;return typeof e!="function"||(n.setRawMode=t=>{try{return e.call(n,t)}catch(r){let o=typeof r=="object"&&r!==null&&"code"in r?r.code:void 0;if(o==="EPERM"||o==="EINVAL")return n;throw r}}),n}var Tt;function lo(){if(Tt!==void 0)return Tt;let n;if(process.stdin.isTTY)n=process.stdin;else try{if(bl.platform()==="win32")try{let e=ao.openSync("CONIN$","rs");n=new co.ReadStream(e)}catch{let e=ao.openSync("\\\\.\\CONIN$","rs");n=new co.ReadStream(e)}else{let e=ao.openSync("/dev/tty","rs");n=new co.ReadStream(e)}}catch{return Tt=null,null}return Tt=vl(n),Tt}function Sl(){return lo()===null}function El(n){for(let e of n){let t=e.trim(),r=t.toLowerCase();if(r==="--headless")return"on";if(r.startsWith("--headless=")){let o=t.slice(t.indexOf("=")+1).trim().toLowerCase();return so.has(o)?"off":"on"}}return"unset"}function Ji(n){let e=El(n);if(e==="on")return{headless:!0,reason:"CLI: --headless"};if(e==="off")return{headless:!1,reason:"CLI: --headless=false"};let t=process.env.HEADLESS;if(t!==void 0&&t.trim()!==""){let i=Fr(t);if(i!==void 0)return{headless:i,reason:i?"env: HEADLESS":"env: HEADLESS=false"}}let r=process.env.DLINK_HEADLESS;if(r!==void 0&&r.trim()!==""){let i=Fr(r);if(i!==void 0)return{headless:i,reason:i?"env: DLINK_HEADLESS":"env: DLINK_HEADLESS=false"}}return Sl()?{headless:!0,reason:"no TTY stdin (Docker/CI/background)"}:{headless:!1,reason:"TTY available (interactive)"}}import uo from"dotenv";import{existsSync as zi}from"node:fs";import{join as _l,resolve as kl,dirname as Rl}from"node:path";function Yi(n){let e=kl(Rl(process.argv[1]??"."),".env.production"),t=zi(e);if(uo.config({quiet:!0}),!t){let r=_l(process.cwd(),"apps","agent",".env");zi(r)&&uo.config({path:r,override:!0,quiet:!0})}n.enviromentFile&&uo.config({path:n.enviromentFile,override:!0,quiet:!0})}import{access as Qi,readFile as Tl}from"node:fs/promises";import{constants as Xi}from"node:fs";function wl(n){return(n.trim().split(".")[0]??"").startsWith("eyJ")}function po(){let n=process.env.ENROLMENT_KEY?.trim()??process.env.DLINK_ENROLMENT_KEY?.trim();return n?wl(n)?{kind:"inline",jws:n}:{kind:"path",path:n}:{kind:"none"}}function es(n){let e=n?.trim();if(e)return`file:${e}`;let t=po();return t.kind==="none"?"none":t.kind==="inline"?"ENROLMENT_KEY(inline JWS)":`file:${t.path}`}async function Zi(n){try{let t=(await Tl(n,"utf8")).trim();return t?{ok:!0,jws:t}:{ok:!1,error:"empty_file"}}catch(e){return{ok:!1,error:e instanceof Error?e.message:String(e)}}}async function ts(n){let e=n?.trim();if(e)try{return await Qi(e,Xi.R_OK),!0}catch{return!1}let t=po();if(t.kind==="inline")return t.jws.trim().length>0;if(t.kind==="path")try{return await Qi(t.path,Xi.R_OK),!0}catch{return!1}return!1}async function rs(n){let e=n?.trim();if(e)return Zi(e);let t=po();if(t.kind==="none")return{ok:!1,error:"not_configured"};if(t.kind==="inline"){let r=t.jws.trim();return r?{ok:!0,jws:r}:{ok:!1,error:"empty_file"}}return Zi(t.path)}import fo from"lodash/trim.js";var ns=[{name:"help",aliases:["?"],summary:"Show this command list"},{name:"start",aliases:["run"],summary:"Connect the bridge"},{name:"stop",summary:"Disconnect the bridge"},{name:"status",summary:"Show device, bridge and session state"},{name:"doctor",summary:"Run local environment checks"},{name:"signin",summary:"Sign in to DeviceLink"},{name:"signout",summary:"Sign out and disconnect the bridge"},{name:"roots list",summary:"List the directories shared with the bridge"},{name:"roots add",args:"<path>",summary:"Share an additional directory"},{name:"debug on",summary:"Show internal system messages",hidden:!0},{name:"debug off",summary:"Hide internal system messages",hidden:!0},{name:"replace",aliases:["yes","y"],summary:"Take over an existing session on conflict"}],os=[{flag:"-h, --help",summary:"Show this help and exit"},{flag:"-v, --version",summary:"Print the agent version and exit"},{flag:"--headless",args:"[=true|false]",summary:"Run without the interactive UI"},{flag:"--env",args:"<file>",summary:"Load environment from a specific file"},{flag:"--root",args:"<path>",summary:"Share this directory with the bridge"},{flag:"--control-url",args:"<url>",summary:"Override the control plane base URL"},{flag:"--bridge-ws-url",args:"<url>",summary:"Override the bridge WebSocket URL"},{flag:"--enrollment-file",args:"<file>",summary:"Path to a .devicelink enrollment key"},{flag:"--private-key-file",args:"<file>",summary:"Path to the device private key"},{flag:"--public-key-file",args:"<file>",summary:"Path to the device public key"}];function is(){let n=new Set;for(let e of ns){let t=e.name.split(" ")[0];t&&n.add(t);for(let r of e.aliases??[])n.add(r)}return Array.from(n)}function ss(n){let e=new Set,t=new Set;for(let i of os){let s=!!i.args&&!i.args?.startsWith("[");for(let a of i.flag.split(",")){let c=fo(a).toLowerCase();c.startsWith("-")&&(e.add(c),s&&t.add(c))}}let r=[],o=n.slice(2);for(let i=0;i<o.length;i++){let s=fo(o[i]??"");if(s==="--"||!s.startsWith("-"))continue;let a=s.split("=")[0]??s;if(!e.has(a.toLowerCase())){r.push(a);continue}t.has(a.toLowerCase())&&!s.includes("=")&&i++}return r}function as(n){for(let e of n.slice(2)){let t=fo(e).toLowerCase();if(t==="--version"||t==="-v")return"version";if(t==="--help"||t==="-h")return"help"}return null}function cs(n){let e=n.args?`${n.name} ${n.args}`:n.name;return!n.aliases||n.aliases.length===0?e:`${e} (${n.aliases.join(", ")})`}function mo(n){let e=n.reduce((t,r)=>Math.max(t,r.left.length),0);return n.map(t=>` ${t.left.padEnd(e)} ${t.right}`)}function ls(){return ns.filter(n=>!n.hidden)}function us(){let n=ls().map(e=>({left:cs(e),right:e.summary}));return["Commands:",...mo(n)]}function ds(n){let e=ls().map(r=>({left:cs(r),right:r.summary})),t=os.map(r=>({left:r.args?`${r.flag} ${r.args}`:r.flag,right:r.summary}));return[`DeviceLink Agent ${n}`,"","Usage: dlink [options]","","Options:",...mo(t),"","Interactive commands (type these once the agent is running):",...mo(e),""].join(`
8
+ `)}import Cl from"lodash/compact.js";import xl from"lodash/isString.js";import Al from"lodash/trim.js";import{existsSync as Dl,readFileSync as Il}from"node:fs";import ps from"node:path";import{fileURLToPath as Ol}from"node:url";var ho;function Nl(){try{let n=ps.dirname(Ol(import.meta.url)),e=ps.join(n,"package.json");if(!Dl(e))return;let t=JSON.parse(Il(e,"utf8"));if(t.name==="@devicelink/dlink"&&xl(t.version))return t.version}catch{return}}function ue(){if(ho===void 0){let n=[process.env.DLINK_AGENT_VERSION,process.env.npm_package_version,Nl()].map(e=>Al(e));ho=Cl(n)[0]??"unknown"}return ho}async function fs(n){let e=as(process.argv);if(e==="version"){console.log(ue());return}if(e==="help"){console.log(ds(ue()));return}let t=ss(process.argv);t.length>0&&(console.warn(`[agent] Ignoring unrecognised ${t.length===1?"option":"options"}: ${t.join(", ")}`),console.warn('[agent] Run "dlink --help" to see the supported options.'));let r=new pr,o=new Wt,{store:i,report:s}=await Fi({machineId:Jt(!0)}),a=new Or(process.argv);Yi(a);let c=Ji(process.argv);if(c.headless){let g=es(a.enrollmentFile);console.log(`[agent] Headless boot (${c.reason})`),console.log(`[agent] Enrollment: ${g}`),g==="none"&&console.log("[agent] No enrollment key (set ENROLMENT_KEY or DLINK_ENROLMENT_KEY, or use --enrollment-file)")}let u=new Ae(!1,c.headless,c.reason),d=new Pr(r),f=new Nr(r,u);Gi(r,u);let p=new dr({bus:r,argv:a,logger:d,notifier:f,storage:o,secrets:i,secretsReport:s,flags:u,lanes:[new Te("console",1),new Te("supervisor",1),new Te("main",1),new Te("ws",1),new Te("worker",8),new Te("io",4)]});p.register(Yn),p.register(io),p.register(Mi),p.register($i),p.register(Ui);let m=n({headless:c.headless,headlessReason:c.reason});for(let g of m)p.registerOrchestrator(g);await p.init(),await p.start()}import pu from"react";import{render as fu}from"ink";import{useEffect as au,useCallback as yo}from"react";import{Box as bo,useApp as cu,useInput as lu}from"ink";import{useEffect as Pl,useState as Fl}from"react";function ms(){let[n,e]=Fl(()=>{let t=process.stdout.columns||80,r=process.stdout.rows||24;return[t,r]});return Pl(()=>{let t=()=>{let r=process.stdout.columns||80,o=process.stdout.rows||24;e([r,o])};return process.stdout.on("resize",t),t(),()=>{process.stdout.off("resize",t)}},[]),n}import vs,{useEffect as Lr,useState as Ss}from"react";import{Box as ot,Text as L}from"ink";import{createContext as Ll,useContext as Ml,useReducer as $l,useMemo as nt,useEffect as hs,useState as Ul}from"react";import{jsx as Vl}from"react/jsx-runtime";var gs=Ll(null);function Bl(n,e){let t=n.messages,r=t.findIndex(o=>o.id===e.id);if(r!==-1){let o=t[r],i=[...t];return i[r]={...e,id:o.id,ts:o.ts},{...n,messages:i}}if(e.groupKey)for(let o=t.length-1;o>=0;o--){let i=t[o];if(i.groupKey===e.groupKey){let s=[...t];return s[o]={...e,id:i.id,ts:i.ts,groupKey:i.groupKey},{...n,messages:s}}}return{...n,messages:[...t.slice(-380),e]}}function Kl(n,e){switch(e.type){case"SET_INPUT":return{...n,input:e.payload};case"ADD_MESSAGE":return Bl(n,e.payload);case"SET_MESSAGES":return{...n,messages:e.payload};case"SET_ENGINE_STATE":return{...n,engineState:e.payload};case"ADD_COMMAND_TO_HISTORY":{if(!e.payload)return n;let t=n.commandHistory.length===0||n.commandHistory[n.commandHistory.length-1]!==e.payload?[...n.commandHistory,e.payload]:n.commandHistory;return{...n,commandHistory:t}}case"SET_HISTORY_INDEX":return{...n,historyIndex:e.payload};case"SET_IS_PROCESSING":return{...n,isProcessing:e.payload};case"SET_DEBUG_ENABLED":return{...n,debugEnabled:e.payload};case"SET_CONNECTION_STATUS":return{...n,connectionStatus:e.payload};case"SET_CONNECTION_RETRY":return{...n,connectionRetryInSec:e.payload};case"SET_REFRESH_COUNTDOWN":return{...n,refreshCountdownSec:e.payload};case"SET_DEVICE_ID":return{...n,deviceId:e.payload};case"RESET_INPUT":return{...n,input:""};case"RESET_HISTORY_INDEX":return{...n,historyIndex:-1};case"RESET_HISTORY_INDEX_IF_TYPING":if(n.historyIndex!==-1){let t=n.commandHistory[n.historyIndex];if(t!==void 0&&n.input!==t)return{...n,historyIndex:-1}}return n;default:return n}}var jl={input:"",messages:[],engineState:"IDLE",commandHistory:[],historyIndex:-1,isProcessing:!1,debugEnabled:!1,connectionStatus:"disconnected",connectionRetryInSec:null,refreshCountdownSec:null,deviceId:null};function ys({engine:n,bus:e,children:t}){let[r,o]=$l(Kl,jl),[i,s]=Ul(()=>Object.freeze({phase:n.runtime.phase,flags:Object.freeze({debug:n.runtime.flags.debug})}));hs(()=>{e.emit("ui:initialized",Date.now())},[e]),hs(()=>{let c=S=>S==="running"?"RUNNING":S==="stopping"?"STOPPING":S==="booting"?"IDLE":"STOPPED",u=e.on("notify:event",S=>{if(o({type:"ADD_MESSAGE",payload:S}),S.groupKey?.startsWith("auth:refresh"))if(S.kind==="info"){let R=S.message.match(/refresh scheduled in (\d+)s/);if(R){let x=parseInt(R[1],10);isNaN(x)||o({type:"SET_REFRESH_COUNTDOWN",payload:x})}}else S.kind==="success"&&S.message.includes("refresh completed")&&o({type:"SET_REFRESH_COUNTDOWN",payload:null})}),d=()=>{let S=n.runtime;o({type:"SET_ENGINE_STATE",payload:c(S.phase)}),o({type:"SET_DEBUG_ENABLED",payload:S.flags.debug});let R=n.configurationContext.configuration.device?.id??null;o({type:"SET_DEVICE_ID",payload:R}),s(Object.freeze({phase:S.phase,flags:Object.freeze({debug:S.flags.debug})}))};d();let f=e.on("engine:started",()=>{o({type:"SET_ENGINE_STATE",payload:"RUNNING"}),d()}),p=e.on("engine:stopping",()=>{o({type:"SET_ENGINE_STATE",payload:"STOPPING"}),d()}),m=e.on("engine:stopped",()=>{o({type:"SET_ENGINE_STATE",payload:"STOPPED"}),d()}),g=e.on("ws:connecting",()=>{o({type:"SET_CONNECTION_STATUS",payload:"connecting"}),o({type:"SET_CONNECTION_RETRY",payload:null})}),h=e.on("ws:connected",()=>{o({type:"SET_CONNECTION_STATUS",payload:"connected"}),o({type:"SET_CONNECTION_RETRY",payload:null})}),b=e.on("ws:disconnected",()=>{o({type:"SET_CONNECTION_STATUS",payload:"disconnected"}),o({type:"SET_CONNECTION_RETRY",payload:null})}),E=e.on("ws:retrying",S=>{o({type:"SET_CONNECTION_STATUS",payload:"connecting"}),o({type:"SET_CONNECTION_RETRY",payload:S.retryInSec})}),v=e.on("runtime:debug:changed",({enabled:S})=>{o({type:"SET_DEBUG_ENABLED",payload:S});let R=n.runtime;s(Object.freeze({phase:R.phase,flags:Object.freeze({debug:S})}))}),_=e.on("config:loaded",S=>{let R=S.device?.id??null;o({type:"SET_DEVICE_ID",payload:R})}),k=new ye("Welcome to DeviceLink Agent UI",{ts:Date.now(),kind:"status"}),I=new ye('Type "help" for commands. Start bridge with: start or run',{ts:Date.now(),kind:"status"});return o({type:"SET_MESSAGES",payload:[k,I]}),()=>{u.unsubscribe(),f.unsubscribe(),p.unsubscribe(),m.unsubscribe(),g.unsubscribe(),h.unsubscribe(),b.unsubscribe(),E.unsubscribe(),v.unsubscribe(),_.unsubscribe()}},[e,n,o]);let a=nt(()=>({state:r,dispatch:o,engine:n,bus:e,runtime:i}),[r,n,e,i]);return Vl(gs.Provider,{value:a,children:t})}function Ke(){let n=Ml(gs);if(!n)throw new Error("useAppContext must be used within AppContextProvider");return n}function bs(n){let{state:e}=Ke(),t=c=>!(c.category?.includes("token-refresh")||c.groupKey?.startsWith("auth:refresh")&&c.kind==="info"&&c.message.includes("refresh scheduled in")),r=n?.displayFilter??t,o=nt(()=>e.messages.filter(r),[e.messages,r]),i=nt(()=>c=>e.messages.filter(c),[e.messages]),s=nt(()=>c=>e.messages.filter(u=>u.kind===c),[e.messages]),a=nt(()=>c=>e.messages.filter(u=>u.scope===c),[e.messages]);return nt(()=>({rawMessages:e.messages,messagesToDisplay:o,getFilteredMessages:i,getMessagesByKind:s,getMessagesByScope:a}),[e.messages,o,i,s,a])}import{Fragment as it,jsx as B,jsxs as Q}from"react/jsx-runtime";function ql(n){return n==="RUNNING"?"green":n==="STOPPING"?"yellow":n==="STOPPED"?"red":"gray"}function Wl(n){return n==="connected"?"green":n==="connecting"?"yellow":"red"}function Hl(n){return n==="connected"?"connected":n==="connecting"?"trying":"disconnected"}function Es(n,e){return n.length<=e?n:n.slice(0,Math.max(0,e-3))+"..."}function Gl(n){let{state:e}=Ke(),t="DeviceLink Agent",r=e.debugEnabled,o=e.deviceId??"not signed in",i=e.engineState,s=ql(i),a=e.isProcessing,c=e.connectionStatus,u=e.connectionRetryInSec,d=e.refreshCountdownSec,[f,p]=Ss(d),[m,g]=Ss(u);Lr(()=>{p(d)},[d]),Lr(()=>{g(u)},[u]),Lr(()=>{if(d===null||d<=0){p(null);return}p(d);let S=setInterval(()=>{p(R=>R===null||R<=1?null:R-1)},1e3);return()=>clearInterval(S)},[d]),Lr(()=>{if(u===null||u<=0){g(null);return}g(u);let S=setInterval(()=>{g(R=>R===null||R<=1?null:R-1)},1e3);return()=>clearInterval(S)},[u]);let h=Hl(c),b=Wl(c),E=t.length,v=30,_=n.width-E-2,k=[];if(k.push(B(L,{color:b,children:h},"conn")),m!==null&&m>0&&k.push(Q(L,{color:b,children:["retry in ",m,"s"]},"retry")),f!==null&&f>0&&f<=5&&k.push(Q(L,{color:"cyan",children:["refresh in ",f,"s"]},"refresh")),_>=v){let S=Es(o,Math.max(5,_-50));return Q(ot,{justifyContent:"space-between",width:n.width,children:[Q(ot,{children:[B(L,{bold:!0,children:t}),r&&Q(it,{children:[B(L,{children:" "}),B(L,{color:"yellow",bold:!0,children:"[DEBUG]"})]})]}),Q(ot,{children:[a&&B(it,{children:B(L,{dimColor:!0,children:"\u23F3 "})}),B(L,{dimColor:!0,children:"device "}),Q(L,{children:[S," "]}),B(L,{children:"\xB7 "}),B(L,{color:s,children:i}),k.length>0&&Q(it,{children:[B(L,{children:" \xB7 "}),k.map((R,x)=>Q(vs.Fragment,{children:[x>0&&B(L,{children:" \xB7 "}),R]},x))]})]})]})}let I=Es(o,n.width-8);return Q(ot,{flexDirection:"column",width:n.width,children:[Q(ot,{children:[B(L,{bold:!0,children:t}),r&&Q(it,{children:[B(L,{children:" "}),B(L,{color:"yellow",bold:!0,children:"[DEBUG]"})]})]}),Q(ot,{children:[a&&B(it,{children:B(L,{dimColor:!0,children:"\u23F3 "})}),B(L,{dimColor:!0,children:"device "}),Q(L,{children:[I," "]}),B(L,{children:"\xB7 "}),B(L,{color:s,children:i}),k.length>0&&Q(it,{children:[B(L,{children:" \xB7 "}),k.map((S,R)=>Q(vs.Fragment,{children:[R>0&&B(L,{children:" \xB7 "}),S]},R))]})]})]})}var _s=Gl;import Ts,{useMemo as ks}from"react";import{Box as Jl,Text as je}from"ink";import{jsx as Ve,jsxs as Rs}from"react/jsx-runtime";function zl(n){return n==="error"?"red":n==="warning"?"yellow":n==="success"?"green":n==="info"?"cyan":"white"}function Yl(n){return n==="error"?"ERROR":n==="warning"?"WARN":n==="success"?"SUCCESS":n==="info"?"INFO":n==="status"?"STATUS":"INFO"}function Ql(n){let e=new Date(n),t=String(e.getHours()).padStart(2,"0"),r=String(e.getMinutes()).padStart(2,"0"),o=String(e.getSeconds()).padStart(2,"0");return`${t}:${r}:${o}`}function Xl(n,e){if(typeof n!="string"&&(n=String(n??"")),n.length<=e)return[n];let t=[],r="",o=n.split(/(\s+)/);for(let i of o)if((r+i).length<=e)r+=i;else{r&&t.push(r),r="";let s=i;for(;s.length>e;)t.push(s.slice(0,e)),s=s.slice(e);r=s}return r&&t.push(r),t.length>0?t:[n]}var Zl=Ts.memo(function(e){let{messagesToDisplay:t}=bs(),r=e.height??14,c=Math.max(20,e.width-9-8-2-2),u=ks(()=>t.slice(-r),[t,r]),f=ks(()=>u.flatMap(p=>{let m=Ql(p.ts),g=Yl(p.kind);return Xl(p.message,c).map((b,E)=>({msg:p,lineIndex:E,time:E===0?m:"",kind:E===0?g:"",message:b,isContinuation:E>0}))}),[u,c]).slice(-r);return Ve(Jl,{flexDirection:"column",borderStyle:"round",borderColor:"gray",paddingX:1,height:r+2,width:e.width,children:f.length===0?Ve(je,{dimColor:!0,children:"(no messages)"}):f.map(p=>Ve(eu,{item:p},`${p.msg.id}:${p.lineIndex}`))})},(n,e)=>n.height===e.height&&n.width===e.width),eu=Ts.memo(function({item:e}){return Rs(je,{children:[e.time&&Rs(je,{dimColor:!0,children:[e.time," "]}),e.kind&&Ve(je,{color:zl(e.msg.kind),children:e.kind}),e.kind&&Ve(je,{children:" "}),e.isContinuation&&Ve(je,{dimColor:!0,children:" "}),Ve(je,{dimColor:e.msg.scope==="system",children:e.message})]})}),ws=Zl;import tu from"react";import{Box as Mr,Text as go,useFocus as ru}from"ink";import nu from"ink-text-input";import{jsx as st,jsxs as Cs}from"react/jsx-runtime";var ou=tu.memo(function(e){let{state:t,dispatch:r}=Ke(),{isFocused:o}=ru({autoFocus:!0,isActive:!t.isProcessing}),i=e.isPassphraseMode?"passphrase> ":"dlink> ",s=Math.max(10,e.width-i.length-2);return Cs(Mr,{flexDirection:"column",width:e.width,children:[Cs(Mr,{width:e.width,children:[st(go,{color:e.isPassphraseMode?"cyan":"green",children:i}),st(Mr,{width:s,children:t.isProcessing?st(go,{dimColor:!0,italic:!0,children:"Processing..."}):st(nu,{value:t.input,onChange:a=>r({type:"SET_INPUT",payload:a}),onSubmit:e.onSubmit,placeholder:o?void 0:e.isPassphraseMode?"Enter passphrase...":'Type a command or "help"',mask:e.isPassphraseMode?"*":void 0},`input-${t.historyIndex}-${e.isPassphraseMode?"passphrase":"normal"}`)})]}),e.passphraseError&&st(Mr,{marginTop:1,children:st(go,{color:"red",children:e.passphraseError})})]})}),xs=ou;import{Component as iu}from"react";import{Box as at,Text as $r}from"ink";import{Fragment as su,jsx as xe,jsxs as As}from"react/jsx-runtime";var wt=class extends iu{constructor(e){super(e),this.state={hasError:!1,error:null}}static getDerivedStateFromError(e){return{hasError:!0,error:e}}componentDidCatch(e,t){this.props.onError&&this.props.onError(e,t)}render(){return this.state.hasError&&this.state.error?xe(at,{flexDirection:"column",padding:1,children:xe(at,{borderStyle:"round",borderColor:"red",paddingX:1,children:As(at,{flexDirection:"column",children:[xe($r,{color:"red",bold:!0,children:"\u26A0\uFE0F Application Error"}),xe(at,{height:1}),xe($r,{color:"red",children:this.state.error.message}),this.state.error.stack&&As(su,{children:[xe(at,{height:1}),xe($r,{dimColor:!0,children:this.state.error.stack})]}),xe(at,{height:1}),xe($r,{dimColor:!0,children:"Press Ctrl+C to exit"})]})})}):this.props.children}};import{jsx as Pe,jsxs as du}from"react/jsx-runtime";function uu(){let{exit:n}=cu(),{state:e,dispatch:t,engine:r,bus:o}=Ke(),[i,s]=ms(),a=i,c=s,u=yo(g=>o.emit("console:command",g),[o]),d=Math.max(5,c-5),f=Math.min(d-3,Math.max(5,Math.floor(d*.7)));lu((g,h)=>{if(h.ctrl&&g==="c"){r.requestStop("user exit");return}if(!e.isProcessing&&(h.upArrow||h.downArrow)){if(e.commandHistory.length===0)return;if(h.upArrow){let b=e.historyIndex===-1?e.commandHistory.length-1:Math.max(0,e.historyIndex-1);t({type:"SET_HISTORY_INDEX",payload:b}),t({type:"SET_INPUT",payload:e.commandHistory[b]})}else if(h.downArrow){if(e.historyIndex===-1)return;let b=e.historyIndex+1;b>=e.commandHistory.length?(t({type:"SET_HISTORY_INDEX",payload:-1}),t({type:"SET_INPUT",payload:""})):(t({type:"SET_HISTORY_INDEX",payload:b}),t({type:"SET_INPUT",payload:e.commandHistory[b]}))}}}),au(()=>{t({type:"RESET_HISTORY_INDEX_IF_TYPING"})},[e.input,t]);let p=yo(async g=>{let h=g.trim();t({type:"RESET_INPUT"}),t({type:"RESET_HISTORY_INDEX"}),h&&t({type:"ADD_COMMAND_TO_HISTORY",payload:h}),t({type:"SET_IS_PROCESSING",payload:!0});try{await u(h)}catch(b){let E=K(b),v=new ye(`Command failed: ${E}`,{ts:Date.now(),kind:"error"});t({type:"ADD_MESSAGE",payload:v})}finally{t({type:"SET_IS_PROCESSING",payload:!1})}},[t,n,u,r]),m=yo((g,h)=>{let b=new ye(`UI Error: ${g.message}`,{ts:Date.now(),kind:"error"});t({type:"ADD_MESSAGE",payload:b})},[t]);return Pe(wt,{onError:m,children:du(bo,{flexDirection:"column",padding:1,width:a,children:[Pe(_s,{width:a-2}),Pe(bo,{height:1}),Pe(ws,{height:f,width:a-2}),Pe(bo,{height:1}),Pe(xs,{width:a-2,onSubmit:p})]})})}function vo({engine:n,bus:e}){return Pe(ys,{engine:n,bus:e,children:Pe(uu,{})})}function Ds(n,e){let t=n.runtime.flags;t.headless?console.log(`[agent] Headless UI (${t.headlessReason})`):console.warn(`[agent] No TTY stdin; non-interactive boot (${t.headlessReason})`),e.emit("ui:initialized",Date.now());let r=setInterval(()=>{},6e4);return new Promise(o=>{process.on("SIGTERM",()=>{clearInterval(r),o()}),process.on("SIGINT",()=>{clearInterval(r),o()})})}function Is(n,e){let t=n.runtime.flags.headless?null:lo();if(!t)return Ds(n,e);let{waitUntilExit:r}=fu(pu.createElement(vo,{engine:n,bus:e}),{stdin:t});return r()}var Ur=class{name="ui-orchestrator";async onStarted(e){Is(e.engine,e.bus)}async onStop(e){e.notifier.info("UI exited, stopping engine",{scope:"system"}),e.engine&&e.engine.requestStop("UI exited")}};import Iu from"lodash/truncate.js";import So from"lodash/isEmpty.js";import ku from"lodash/isString.js";import ct from"lodash/trim.js";import Ru from"lodash/trimEnd.js";import mu from"lodash/isEmpty.js";import hu from"lodash/isString.js";import{randomUUID as gu}from"node:crypto";import{existsSync as yu,mkdirSync as bu,readFileSync as vu,writeFileSync as Su}from"node:fs";import Os from"node:path";var Eu="telemetry.json";function _u(){return Os.join(Z(),Eu)}function Br(){let n=_u();try{if(yu(n)){let t=JSON.parse(vu(n,"utf8"));if(hu(t.anonymous_id)&&!mu(t.anonymous_id))return t.anonymous_id}}catch{}let e=gu().replace(/-/g,"");try{bu(Os.dirname(n),{recursive:!0});let t={anonymous_id:e,created_at:new Date().toISOString()};Su(n,JSON.stringify(t,null,2),"utf8")}catch{}return e}var Tu=1e4,wu=On,Cu=200,xu=4e3,Au="/api/telemetry/agent";function Eo(n=process.env){return!(!Rt("DLINK_TELEMETRY",!0,n)||Rt("DO_NOT_TRACK",!1,n))}var Kr=class{enabled;transport;queue;timer;inFlight;constructor(e,t=Eo()){this.transport=e,this.enabled=t,this.queue=[],this.timer=null,this.inFlight=new Set}get isEnabled(){return this.enabled}get anonymousId(){return this.enabled?Br():"disabled"}capture(e,t,r){if(this.enabled&&!(!ku(e)||So(ct(e)))&&!(this.queue.length>=Cu)){if(this.queue.push({kind:ct(e),severity:r,at:Date.now(),props:t&&Object.keys(t).length>0?t:void 0}),this.queue.length>=wu){this.flush();return}this.timer||(this.timer=setTimeout(()=>void this.flush(),Tu),this.timer.unref?.())}}async flush(){if(this.timer&&(clearTimeout(this.timer),this.timer=null),!this.enabled||this.queue.length===0)return;let e=this.queue.splice(0,On);if(this.transport.socketReady()){this.sendOverSocket(e),this.queue.length>0&&this.flush();return}let t=this.post(e).finally(()=>this.inFlight.delete(t));this.inFlight.add(t),await t,this.queue.length>0&&await this.flush()}async shutdown(){await this.flush(),await Promise.allSettled([...this.inFlight])}sendOverSocket(e){try{this.transport.socketSend(JSON.stringify({type:"agent_event",schema_version:In,events:e.map(t=>this.wire(t))}))}catch{return}}async post(e){let t=this.transport.controlBaseUrl();if(!t||So(ct(t)))return;let r=new AbortController,o=setTimeout(()=>r.abort(),xu);o.unref?.();let i=this.transport.accessToken(),s={"content-type":"application/json"};i&&!So(ct(i))&&(s.authorization=`Bearer ${ct(i)}`);try{await fetch(`${Ru(ct(t),"/")}${Au}`,{method:"POST",headers:s,body:JSON.stringify({schema_version:In,fingerprint:this.anonymousId,events:e.map(a=>this.wire(a))}),signal:r.signal})}catch{return}finally{clearTimeout(o)}}wire(e){let t={kind:e.kind};return e.severity&&(t.severity=e.severity),typeof e.at=="number"&&(t.at=e.at),e.props&&(t.props=e.props),t}};var X={SESSION_STARTED:"agent.session.started",SESSION_EXITED:"agent.session.exited",SESSION_CRASHED:"agent.session.crashed",CONFIG_LOADED:"agent.config.loaded",SECRETS_BACKEND_RESOLVED:"agent.secrets.backend_resolved",AUTH_SIGNIN_REQUESTED:"agent.auth.signin_requested",AUTH_SIGNIN_COMPLETED:"agent.auth.signin_completed",AUTH_SIGNOUT:"agent.auth.signout",AUTH_TOKENS_REFRESHED:"agent.auth.tokens_refreshed",SOCKET_CONNECTED:"agent.socket.connected",SOCKET_DISCONNECTED:"agent.socket.disconnected",SOCKET_RETRYING:"agent.socket.retrying",SOCKET_SESSION_READY:"agent.socket.session_ready",SOCKET_SESSION_CONFLICT:"agent.socket.session_conflict",TOOL_CALL_RECEIVED:"agent.tool.call_received"};var Du="protects the store only if it leaves this machine; set DLINK_PASSPHRASE or unlock a keychain for local protection";function Ns(n){let e=[n.label];n.migratedFrom!==void 0&&e.push(`migrated from ${n.migratedFrom}`),n.degraded&&n.expectedBackend!==void 0&&e.push(`secrets were stored by ${n.expectedBackend}, which is unavailable now`),n.weak&&e.push(Du);let t=Fs(n);return t.length>0&&e.push(`skipped ${t.join(", ")}`),{ok:!n.weak&&!n.degraded,detail:e.join("; ")}}function Ps(n){let e={backend:n.backend,weak:n.weak,degraded:n.degraded,skipped:Fs(n)};return n.migratedFrom!==void 0&&(e.migrated_from=n.migratedFrom),e}function Fs(n){return n.attempts.filter(e=>!e.available).map(e=>`${e.id}:${e.reason??"unknown"}`)}var jr=class{name="telemetry-orchestrator";relay;startedAt;reachedReady;toolCalls;context=null;accessToken;relayNegotiated=!1;socketConnected=!1;constructor(){this.startedAt=Date.now(),this.reachedReady=!1,this.toolCalls=0;let e={controlBaseUrl:()=>this.context?.engine.configurationContext.configuration.controlBaseUrl,accessToken:()=>this.accessToken,socketSend:t=>this.context?.bus.emit("ws:tx",{text:t}),socketReady:()=>this.socketConnected&&this.relayNegotiated};this.relay=new Kr(e)}handlers(){return{"config:loaded":()=>{this.relay.capture(X.CONFIG_LOADED)},"auth:signin:requested":()=>{this.relay.capture(X.AUTH_SIGNIN_REQUESTED)},"auth:signin:completed":()=>{this.relay.capture(X.AUTH_SIGNIN_COMPLETED,{seconds_since_start:this.elapsedSec()})},"auth:signout:requested":()=>{this.relay.capture(X.AUTH_SIGNOUT)},"auth:tokens:updated":e=>{this.accessToken=e.accessToken||void 0,this.relay.capture(X.AUTH_TOKENS_REFRESHED)},"ws:connected":()=>{this.socketConnected=!0,this.relay.capture(X.SOCKET_CONNECTED)},"ws:disconnected":e=>{this.socketConnected=!1,this.relayNegotiated=!1,this.relay.capture(X.SOCKET_DISCONNECTED,{code:e.code})},"ws:retrying":e=>{this.relay.capture(X.SOCKET_RETRYING,{attempt:e.attempt,retry_in_sec:e.retryInSec})},"auth:session_init_ack":e=>{this.reachedReady=!0,this.relayNegotiated=e.ok===!0&&Je(e.capabilities,U.TELEMETRY_RELAY_V1),this.relay.capture(X.SOCKET_SESSION_READY,{mode:e.ok?e.mode??null:null,reason:e.ok?e.reason??null:null,seconds_since_start:this.elapsedSec()})},"auth:session_conflict":()=>{this.relay.capture(X.SOCKET_SESSION_CONFLICT)},"tool:call":e=>{this.toolCalls+=1,this.relay.capture(X.TOOL_CALL_RECEIVED,{tool:e.tool,call_index:this.toolCalls})},"engine:crashed":e=>{this.relay.capture(X.SESSION_CRASHED,{reason:e.reason,detail:Iu(vn(e.detail),{length:200,omission:""})||null,uptime_sec:this.elapsedSec(),reached_session_ready:this.reachedReady,tool_calls:this.toolCalls},"error")}}}async onStart(e){this.context=e,this.relay.capture(X.SESSION_STARTED,{headless:e.headless}),this.relay.capture(X.SECRETS_BACKEND_RESOLVED,{...Ps(e.engine.secretsReport),platform:process.platform})}async onStop(e){this.relay.capture(X.SESSION_EXITED,{uptime_sec:this.elapsedSec(),reached_session_ready:this.reachedReady,tool_calls:this.toolCalls}),await this.relay.shutdown()}elapsedSec(){return Math.round((Date.now()-this.startedAt)/1e3)}};var Vr=class{name="os-signals-orchestrator";sigint;sigterm;async onStart(e){let t=r=>{e.notifier.warn(`received ${r}`,{scope:"system"}),e.engine.requestStop(r)};this.sigint=()=>t("SIGINT"),this.sigterm=()=>t("SIGTERM"),process.on("SIGINT",this.sigint),process.on("SIGTERM",this.sigterm)}async onStarted(e){return Promise.resolve()}async onStop(e){this.sigint&&process.off("SIGINT",this.sigint),this.sigterm&&process.off("SIGTERM",this.sigterm),this.sigint=void 0,this.sigterm=void 0,e.notifier.info("OS signal handlers removed",{scope:"system"})}async onStopped(e){return Promise.resolve()}};import qe from"node:fs";import ko from"node:path";var qr=class{handlers=new Map;subcommandHandlers=new Map;command(e,t){if(this.handlers.has(e))throw new Error(`Command '${e}' is already registered`);return this.handlers.set(e,t),this}subcommand(e,t,r){this.subcommandHandlers.has(e)||this.subcommandHandlers.set(e,new Map);let o=this.subcommandHandlers.get(e);if(o.has(t))throw new Error(`Subcommand '${e} ${t}' is already registered`);return o.set(t,r),this}commandStringToArgv(e){let t=[],r="",o=!1,i="";for(let s=0;s<e.length;s++){let a=e[s];a==='"'||a==="'"?o&&a===i?(t.push(r),r="",o=!1,i=""):o?r+=a:(r&&(t.push(r),r=""),o=!0,i=a):a===" "&&!o?r&&(t.push(r),r=""):r+=a}return(o||r)&&t.push(r),["node","script",...t]}parseString(e){let t=this.commandStringToArgv(e);return this.parse(t)}parse(e){let t=e.slice(2);if(t.length===0)return null;let r={command:"",args:[],options:{}},o=0;for(;o<t.length&&t[o]?.startsWith("--");)o++;if(o>=t.length||!t[o])return null;for(r.command=t[o],o++;o<t.length&&t[o]?.startsWith("--");)o++;for(o<t.length&&t[o]&&!t[o].startsWith("--")&&(r.subcommand=t[o],o++);o<t.length;){let i=t[o];if(i.startsWith("--")){let s=i.slice(2);if(s.includes("=")){let[a,c]=s.split("=",2);r.options[a]=c||!0}else{let a=t[o+1];a&&!a.startsWith("--")?(r.options[s]=a,o++):r.options[s]=!0}}else r.args.push(i);o++}return r}async execute(e){let t=this.parse(e);if(!t)return!1;if(t.subcommand){let o=this.subcommandHandlers.get(t.command);if(o){let i=o.get(t.subcommand);if(i)return await i(t),!0}}let r=this.handlers.get(t.command);return r?(await r(t),!0):!1}hasCommand(e,t){return t?this.subcommandHandlers.get(e)?.has(t)??!1:this.handlers.has(e)}getCommands(){return Array.from(this.handlers.keys())}};var _o=class{kind;payloadJson;constructor(e,t){this.kind=e,this.payloadJson=t}},Wr=class{matchers=[];register(e){return this.matchers.push(e),this}build(e){let t=[e.command.toLowerCase()];e.subcommand&&t.push(e.subcommand.toLowerCase());for(let r of this.matchers){let o=r(t,e);if(o.handled){let i;if(o.job)i=o.job;else if(o.kind)i=this.createCommandInput(o.kind,e);else return null;return i}}return null}createCommandInput(e,t){let r={command:t.command,subcommand:t.subcommand,args:t.args,options:t.options};return new _o(e,JSON.stringify(r))}};var Hr=class{name="console-orchestrator";commandParser;commandJobBuilder;bridgeConnected=!1;constructor(){this.commandParser=new qr,this.commandJobBuilder=new Wr,this.setupCommandMappings()}onRegister(e){}async onStart(e){e.notifier.info("Starting console orchestrator (UI)",{scope:"system"}),e.on("ws:connected",()=>{this.bridgeConnected=!0}),e.on("ws:disconnected",()=>{this.bridgeConnected=!1}),e.on("console:command",async t=>{try{let r=this.commandParser.parseString(t);if(!r){e.notifier.warn("Invalid command format");return}let o=this.commandJobBuilder.build(r);if(!o){this.reportUnknownCommand(r,e);return}switch(o.kind){case"help":for(let i of us())e.notifier.info(i);break;case"start":this.handleStart(e);break;case"stop":this.handleStop(e);break;case"status":this.handleStatus(e);break;case"doctor":this.handleDoctor(e);break;case"roots-list":this.handleRootsList(e);break;case"roots-add":this.handleRootsAdd(r,e);break;case"signin":e.bus.emit("auth:signin:requested",void 0),e.notifier.info("Sign-in requested");break;case"signout":e.bus.emit("auth:signout:requested",void 0),e.notifier.info("Sign-out requested");break;case"debug-on":e.flags.debug=!0,e.bus.emit("runtime:debug:changed",{enabled:!0}),e.notifier.success("Debug mode enabled");break;case"debug-off":e.flags.debug=!1,e.bus.emit("runtime:debug:changed",{enabled:!1}),e.notifier.success("Debug mode disabled");break;case"replace":e.bus.emit("auth:session_conflict:resolve",{choice:"USE_NEW"}),e.notifier.info("Taking over the existing session");break;default:e.notifier.warn(`Command not implemented: ${o.kind}`);break}}catch(r){let o=K(r);e.notifier.error(`Command failed: ${o}`)}})}async onStarted(e){e.notifier.info("Console orchestrator started",{scope:"system"})}async onStopped(e){}reportUnknownCommand(e,t){let r=`${e.command}${e.subcommand?" "+e.subcommand:""}`,o=this.suggestCommand(e.command),i=o?` Did you mean "${o}"?`:' Type "help" for commands.';t.notifier.warn(`Unknown command: ${r}.${i}`)}suggestCommand(e){let t=e.toLowerCase();if(!t)return null;let r=null;for(let i of is()){let s=this.editDistance(t,i);(r===null||s<r.distance)&&(r={name:i,distance:s})}if(!r)return null;let o=t.length<=4?1:2;return r.distance<=o?r.name:null}editDistance(e,t){let r=t.length+1,o=Array.from({length:r},(i,s)=>s);for(let i=1;i<=e.length;i++){let s=[i];for(let a=1;a<r;a++){let c=o[a-1]+(e[i-1]===t[a-1]?0:1),u=s[a-1]+1,d=o[a]+1;s[a]=Math.min(c,u,d)}o=s}return o[r-1]}isSignedIn(e){let t=e.tokens?.accessTokenExpSec;return typeof t!="number"?!1:t>Math.floor(Date.now()/1e3)}handleStart(e){let t=e.engine.configurationContext.configuration;if(!t.device?.id){e.notifier.warn("Bridge: no device identity yet. Wait for configuration to load.");return}if(!this.isSignedIn(t)){e.notifier.warn("Bridge: not signed in. Run signin first.");return}if(this.bridgeConnected){e.notifier.info("Bridge is already connected");return}e.bus.emit("auth:ws:reconnect",void 0),e.notifier.info("Bridge start requested")}handleStop(e){if(!this.bridgeConnected){e.notifier.info("Bridge is already disconnected");return}e.bus.emit("ws:disconnect",{reason:"console: stop"}),e.notifier.info("Bridge stop requested")}handleStatus(e){let t=e.engine.configurationContext.configuration,r=[["Agent",ue()],["Engine",String(e.engine.runtime.phase)],["Device",t.device?.id??"(none)"],["Device name",t.device?.name??"(none)"],["Signed in",this.isSignedIn(t)?"yes":"no"],["Bridge",this.bridgeConnected?"connected":"disconnected"],["Control URL",t.controlBaseUrl??"(unset)"],["Bridge URL",t.bridgeWsUrl??"(unset)"],["Directories",String(t.directories.length)],["Config dir",Z()]],o=r.reduce((i,[s])=>Math.max(i,s.length),0);e.notifier.info("Status:");for(let[i,s]of r)e.notifier.info(` ${i.padEnd(o)} ${s}`)}handleDoctor(e){let t=e.engine.configurationContext.configuration,r=[],o=Number.parseInt(process.versions.node.split(".")[0],10);r.push({label:"Node runtime",ok:Number.isFinite(o)&&o>=20,detail:`v${process.versions.node} (requires >= 20)`});let i=Z(),s=!1,a=i;try{qe.mkdirSync(i,{recursive:!0}),qe.accessSync(i,qe.constants.W_OK),s=!0}catch(m){a=`${i} (${K(m)})`}r.push({label:"Config directory",ok:s,detail:a}),r.push({label:"Device identity",ok:!!t.device?.id&&!!t.device?.keys?.public,detail:t.device?.id?`id ${t.device.id}`:"no device id"});let c=this.isSignedIn(t);r.push({label:"Authentication",ok:c,detail:c?"access token valid":"not signed in (run signin)"}),r.push({label:"Control URL",ok:!!t.controlBaseUrl,detail:t.controlBaseUrl??"unset"}),r.push({label:"Bridge URL",ok:!!t.bridgeWsUrl,detail:t.bridgeWsUrl??"unset"});let u=Ns(e.engine.secretsReport);r.push({label:"Secret storage",ok:u.ok,detail:u.detail}),r.push({label:"Bridge connection",ok:this.bridgeConnected,detail:this.bridgeConnected?"connected":"disconnected"});let d=t.directories.filter(m=>!qe.existsSync(m.path));r.push({label:"Shared directories",ok:t.directories.length>0&&d.length===0,detail:t.directories.length===0?"none configured":d.length===0?`${t.directories.length} present`:`missing: ${d.map(m=>m.path).join(", ")}`});let f=r.reduce((m,g)=>Math.max(m,g.label.length),0);e.notifier.info("Doctor:");for(let m of r){let g=` ${m.ok?"PASS":"WARN"} ${m.label.padEnd(f)} ${m.detail}`;m.ok?e.notifier.success(g):e.notifier.warn(g)}let p=r.filter(m=>!m.ok).length;p===0?e.notifier.success("Doctor: all checks passed"):e.notifier.warn(`Doctor: ${p} check(s) need attention`)}handleRootsList(e){let t=e.engine.configurationContext.configuration.directories;if(t.length===0){e.notifier.info("No directories shared. Add one with: roots add <path>");return}e.notifier.info(`Shared directories (${t.length}):`);for(let r of t){let o=qe.existsSync(r.path)?"":" (missing)";e.notifier.info(` ${r.name} ${r.path}${o}`)}}handleRootsAdd(e,t){let r=e.args[0];if(!r){t.notifier.warn("Usage: roots add <path>");return}let o=ko.resolve(r);if(!qe.existsSync(o)){t.notifier.warn(`Directory does not exist: ${o}`);return}let i;try{i=qe.statSync(o)}catch(u){t.notifier.warn(`Cannot read ${o}: ${K(u)}`);return}if(!i.isDirectory()){t.notifier.warn(`Not a directory: ${o}`);return}let s=t.engine.configurationContext.configuration;if(s.directories.some(u=>ko.resolve(u.path).toLowerCase()===o.toLowerCase())){t.notifier.info(`Already shared: ${o}`);return}let c={id:yt(o),name:ko.basename(o),path:o,tag:gt(o)};s.directories.push(c),t.bus.emit("config:save:requested",s),t.bus.emit("meta:data:requested:directories",void 0),t.notifier.success(`Added directory: ${o}`)}setupCommandMappings(){let e=this.commandJobBuilder;e.register(t=>{if(t.length===1){let r=t[0];if(r==="help"||r==="?")return{handled:!0,kind:"help"};if(r==="roots")return{handled:!0,kind:"roots-list"};if(r==="start"||r==="run")return{handled:!0,kind:"start"};if(r==="stop")return{handled:!0,kind:"stop"};if(r==="signin")return{handled:!0,kind:"signin"};if(r==="signout")return{handled:!0,kind:"signout"};if(r==="status")return{handled:!0,kind:"status"};if(r==="doctor")return{handled:!0,kind:"doctor"};if(r==="replace"||r==="yes"||r==="y")return{handled:!0,kind:"replace"}}return{handled:!1}}),e.register(t=>{if(t.length===2){let[r,o]=t;if(r==="roots"){if(o==="add")return{handled:!0,kind:"roots-add"};if(o==="list")return{handled:!0,kind:"roots-list"}}if(r==="debug"){if(o==="on")return{handled:!0,kind:"debug-on"};if(o==="off")return{handled:!0,kind:"debug-off"}}}return{handled:!1}}),e.register((t,r)=>{if(t.length===1&&t[0]==="debug"&&r.args.length>0){let o=r.args[0];if(o==="on")return{handled:!0,kind:"debug-on"};if(o==="off")return{handled:!0,kind:"debug-off"}}return{handled:!1}})}};import We from"ws";var Gr=class{ws=null;state={kind:"DISCONNECTED"};stopped=!1;connecting=!1;connId=0;connectionTimeout=null;heartbeatInterval=null;heartbeatTimeout=null;awaitingPong=!1;sendQueue=[];url;abortSignal;connectionTimeoutMs;heartbeatIntervalMs;pongTimeoutMs;maxSendQueueSize;sendQueueItemTtlMs;onStateChangeCallback;onErrorCallback;onConnectedCallback;onDisconnectedCallback;onMessageCallback;constructor(e,t={}){this.url=e,this.abortSignal=t.abortSignal,this.connectionTimeoutMs=t.connectionTimeoutMs??1e4,this.heartbeatIntervalMs=t.heartbeatIntervalMs??2e4,this.pongTimeoutMs=t.pongTimeoutMs??1e4,this.maxSendQueueSize=t.maxSendQueueSize??1e3,this.sendQueueItemTtlMs=t.sendQueueItemTtlMs??6e4,this.abortSignal&&this.abortSignal.addEventListener("abort",()=>{this.stop()},{once:!0})}registerOnStateChangeCallback(e){this.onStateChangeCallback=e}registerOnErrorCallback(e){this.onErrorCallback=e}registerOnConnectedCallback(e){this.onConnectedCallback=e}registerOnDisconnectedCallback(e){this.onDisconnectedCallback=e}registerOnMessageCallback(e){this.onMessageCallback=e}getState(){return this.state}getSocket(){return this.ws}isConnected(){return this.ws?.readyState===We.OPEN}async connect(){if(this.stopped)throw new Error("Socket is stopped");if(!(this.connecting||this.isConnected())){this.connecting=!0,this.updateState({kind:"CONNECTING"});try{await this.connectWebSocketOnce()}catch(e){let t=e instanceof Error?e:new Error(String(e));throw this.onErrorCallback?.(t),this.updateState({kind:"DISCONNECTED"}),t}finally{this.connecting=!1}}}stop(){this.stopped=!0,this.disconnect(!0)}reset(){this.stopped=!1}disconnect(e=!1){e&&(this.stopped=!0),this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null),this.stopHeartbeat();let t=this.ws;this.ws=null,this.connecting=!1,t&&this.closeGracefullyThenTerminate(t,1e3,"client disconnect",2e3),this.updateState({kind:"DISCONNECTED"})}send(e,t){if(this.stopped){t?.(new Error("Socket is stopped"));return}let r=this.ws;if(r&&r.readyState===We.OPEN){r.send(e,i=>t?.(i??void 0));return}let o=Date.now();if(this.pruneSendQueue(o),this.sendQueue.length>=this.maxSendQueueSize){t?.(new Error(`Send queue full (max ${this.maxSendQueueSize})`));return}this.sendQueue.push({data:e,cb:t,expiresAt:o+this.sendQueueItemTtlMs})}closeGracefullyThenTerminate(e,t,r,o){try{(e.readyState===We.OPEN||e.readyState===We.CONNECTING)&&e.close(t,r)}catch{}let i=setTimeout(()=>{try{e.terminate()}catch{}},o);e.once("close",()=>clearTimeout(i))}async connectWebSocketOnce(){let e=++this.connId;return new Promise((t,r)=>{if(this.stopped){r(new Error("Socket is stopped"));return}let o=!1,i=!1,s=()=>{this.connectionTimeout&&(clearTimeout(this.connectionTimeout),this.connectionTimeout=null)},a=()=>{i||(i=!0,s(),t())},c=(d,f)=>{i||(i=!0,s(),f&&this.closeGracefullyThenTerminate(f,1e3,"connect failed",1500),r(d))},u;try{u=new We(this.url),this.connectionTimeout=setTimeout(()=>{c(new Error(`Connection timeout: unable to connect to ${this.url} within ${this.connectionTimeoutMs}ms`),u)},this.connectionTimeoutMs),u.on("open",()=>{if(o=!0,e!==this.connId){this.closeGracefullyThenTerminate(u,1e3,"stale connection",500);return}this.ws=u,this.retryResetOnConnect(),this.updateState({kind:"CONNECTED"}),this.onConnectedCallback?.(u),this.startHeartbeat(e),this.flushSendQueue(),a()}),u.on("error",d=>{if(e!==this.connId)return;let f=d instanceof Error?d:new Error(String(d));if(!o&&!i){c(f,u);return}this.onErrorCallback?.(f)}),u.on("close",(d,f)=>{if(e!==this.connId)return;let p=f?.toString?.()||"";if(!o&&!i){this.ws=null,this.stopHeartbeat(),this.updateState({kind:"DISCONNECTED"}),c(new Error(`WebSocket closed before connection established: ${d} ${p}`),u);return}this.ws===u&&(this.ws=null),this.stopHeartbeat(),this.updateState({kind:"DISCONNECTED"}),this.onDisconnectedCallback?.(d,p||`code ${d}`)}),u.on("message",d=>{if(e!==this.connId){this.onErrorCallback?.(new Error("Message ignored - connection ID mismatch"));return}if(this.ws!==u){this.onErrorCallback?.(new Error("Message ignored - socket mismatch"));return}this.onMessageCallback?.(d)}),u.on("pong",()=>{e===this.connId&&(this.awaitingPong=!1,this.heartbeatTimeout&&(clearTimeout(this.heartbeatTimeout),this.heartbeatTimeout=null))}),this.abortSignal&&this.abortSignal.addEventListener("abort",()=>{e===this.connId&&(this.closeGracefullyThenTerminate(u,1e3,"aborted",1e3),i||c(new Error("Connection aborted"),u))},{once:!0})}catch(d){let f=d instanceof Error?d:new Error(String(d));r(f)}})}retryResetOnConnect(){}startHeartbeat(e){this.stopHeartbeat(),this.ws&&(this.awaitingPong=!1,this.heartbeatInterval=setInterval(()=>{if(this.stopped||e!==this.connId)return;let r=this.ws;if(!(!r||r.readyState!==We.OPEN)){if(this.awaitingPong){this.closeGracefullyThenTerminate(r,4e3,"pong timeout",1e3);return}this.awaitingPong=!0;try{r.ping()}catch{this.closeGracefullyThenTerminate(r,1011,"ping failed",1e3);return}this.heartbeatTimeout&&clearTimeout(this.heartbeatTimeout),this.heartbeatTimeout=setTimeout(()=>{if(e!==this.connId)return;let o=this.ws;o&&this.closeGracefullyThenTerminate(o,4e3,"pong timeout",1e3)},this.pongTimeoutMs)}},this.heartbeatIntervalMs))}stopHeartbeat(){this.awaitingPong=!1,this.heartbeatInterval&&(clearInterval(this.heartbeatInterval),this.heartbeatInterval=null),this.heartbeatTimeout&&(clearTimeout(this.heartbeatTimeout),this.heartbeatTimeout=null)}flushSendQueue(){let e=this.ws;if(!e||e.readyState!==We.OPEN)return;let t=Date.now();this.pruneSendQueue(t);let r=this.sendQueue;this.sendQueue=[];for(let o of r)e.send(o.data,i=>o.cb?.(i??void 0))}pruneSendQueue(e){if(this.sendQueue.length===0)return;let t=[];for(let r of this.sendQueue)r.expiresAt>=e?t.push(r):r.cb?.(new Error("Send dropped: queued item expired"));this.sendQueue=t}updateState(e){this.state=e,this.onStateChangeCallback?.(e)}};var Jr=class{name="websocket-orchestrator";socket=null;stopped=!1;connectLoopInFlight=null;retryAttempt=0;countdownTimer=null;lastUrl=null;endpointSource=void 0;discoveredFailures=0;reconnectPolicy=null;endpointOverride=null;async onStart(e){e.notifier.info("WS: orchestrator started",{scope:"system"})}async onStarted(e){let t=e.engine.configurationContext.configuration;await this.isConnectableToBridge(t,e)&&this.ensureStarted(e,"onStarted")}async onStop(e){this.stopped=!0,this.clearCountdown(),this.socket&&(e.notifier.info("WS: stopping socket (onStop)",{scope:"system"}),this.socket.stop(),this.socket=null),e.notifier.info("WS: orchestrator stopped",{scope:"system"})}handlers(){let e=async(t,r)=>{if(this.stopped)return;let o=r.engine.configurationContext.configuration;await this.isConnectableToBridge(o,r)&&this.ensureStarted(r,t)};return{"config:cache:validated":async(t,r)=>e("config:cache:validated",r),"auth:signout:requested":async(t,r)=>{r.notifier.info("WS: sign-out requested -> disconnecting"),this.stopped=!0,this.clearCountdown(),this.socket?.stop(),this.socket=null},"ws:disconnect":async(t,r)=>{r.notifier.info("WS: disconnect requested",{scope:"system"}),this.stopped=!0,this.clearCountdown(),this.socket?.stop(),this.socket=null},"auth:ws:reconnect":async(t,r)=>{r.notifier.info("WS: reconnect requested by auth",{scope:"system"}),this.retryAttempt=0,this.clearCountdown(),this.stopped=!0,this.socket?.stop(),this.connectLoopInFlight&&await this.connectLoopInFlight.catch(()=>{}),this.socket=null,this.stopped=!1,this.ensureStarted(r,"auth:ws:reconnect")},"ws:reconnect:policy":async(t,r)=>{this.reconnectPolicy=t,r.notifier.info(`WS: reconnect policy reconnect=${t.reconnect} delay_ms=${t.delayMs??"-"} url=${t.url??"-"} rediscover=${t.rediscover===!0}`,{scope:"system"})},"ws:tx":async(t,r)=>{let o=this.socket?.getSocket();if(!o||o.readyState!==1){r.notifier.info("WS: TX dropped (not connected)",{scope:"system"});return}o.send(t.text)}}}ensureStarted(e,t){if(this.connectLoopInFlight){e.notifier.info(`WS: connect loop already running (reason=${t})`,{scope:"system"});return}let r=this.socket?.getSocket();if(r&&r.readyState<=1){e.notifier.info(`WS: already connected/connecting, skipping (reason=${t})`,{scope:"system"});return}this.connectLoopInFlight=this.startOrJoinConnectLoop(e,t).finally(()=>{this.connectLoopInFlight=null})}resolveEndpoint(e){let t=e.engine.configurationContext.loader,r=e.engine.configurationContext.configuration,o=t.resolveBridgeWsUrl(r.discovery);return this.endpointOverride&&(o.source==="discovered"||o.source==="bundled"||o.source===void 0)?{url:this.endpointOverride,source:"discovered"}:o}applyEndpointOverride(e,t){e&&(this.endpointOverride=e,t.notifier.info(`WS: server directed the next connection to ${e}`,{scope:"system"}))}async reconnectAfter(e,t){this.retryAttempt=0,this.clearCountdown(),e>0&&await bt(e),!this.stopped&&this.ensureStarted(t,"socket:disconnected")}noteConnectFailure(e){return this.endpointSource!=="discovered"?(this.discoveredFailures=0,!1):(this.discoveredFailures+=1,this.discoveredFailures<$n?!1:(this.discoveredFailures=0,this.endpointOverride=null,e.notifier.info(`WS: discovered endpoint failed ${$n}x -> falling back to the bundled endpoint`,{scope:"system"}),e.bus.emit("discovery:cache:discarded",{reason:"connect-failed-twice"}),!0))}async startOrJoinConnectLoop(e,t){this.stopped=!1;let r=e.engine.configurationContext.configuration;if(!await this.isConnectableToBridge(r,e))return;let i=this.resolveEndpoint(e),s=String(i.url??r.bridgeWsUrl),a=this.lastUrl;if(this.endpointSource=i.source,this.lastUrl=s,e.notifier.info(`WS: ensure connection (reason=${t}) url=${s} source=${this.endpointSource??"config"}`,{scope:"system"}),this.socket&&a!==null&&a!==s&&(e.notifier.info(`WS: endpoint changed ${a} -> ${s}; rebuilding the socket`,{scope:"system"}),this.socket.stop(),this.socket=null),!this.socket){let c=new Gr(s,{abortSignal:e.signal,connectionTimeoutMs:1e4,heartbeatIntervalMs:2e4,pongTimeoutMs:1e4});this.socket=c,c.registerOnStateChangeCallback(u=>this.handleStateChange(u,e)),c.registerOnErrorCallback(u=>{e.notifier.error(`WS: transport error: ${u.message}`)}),c.registerOnConnectedCallback(u=>{this.socket===c&&(this.retryAttempt=0,this.clearCountdown(),e.notifier.success(e.flags.debug?`WS: connected (${s})`:"WS: connected"),e.bus.emit("ws:connected",{url:s,attempt:0}))}),c.registerOnDisconnectedCallback((u,d)=>{if(this.socket!==c){e.notifier.info(`WS: ignoring stale disconnect (code=${u})`,{scope:"system"});return}if(e.notifier.warn(`WS: disconnected code=${u} reason=${d||"-"}`),e.bus.emit("ws:disconnected",{code:u,reason:d}),this.stopped){e.notifier.info(`WS: stopped flag set, skipping auto-reconnect (code=${u})`,{scope:"system"});return}if(u===4001){e.notifier.info("WS: auth disconnect (4001) -> waiting for auth",{scope:"system"});return}if(ni.includes(u)){u===4013||u===4014?e.notifier.error(`This agent is not accepted by the server (code=${u} ${d||"-"}). Upgrade with: npm i -g @devicelink/dlink`):e.notifier.error(`The server refused this device permanently (code=${u} ${d||"-"}). Run dlink signin to connect it again.`),this.stopped=!0,this.socket?.stop(),this.socket=null;return}let f=this.reconnectPolicy;if(this.reconnectPolicy=null,f&&!f.reconnect){e.notifier.info("WS: server asked us not to reconnect",{scope:"system"}),this.stopped=!0,this.socket?.stop(),this.socket=null;return}if(f){this.applyEndpointOverride(f.url,e),this.reconnectAfter(f.delayMs??0,e);return}this.ensureStarted(e,"socket:disconnected")}),c.registerOnMessageCallback(u=>{if(this.socket!==c)return;let d=typeof u=="string"?u:u.toString("utf8");e.bus.emit("ws:rx",{text:d})})}for(;!this.stopped;)try{let c=this.retryAttempt+1;e.notifier.info(`WS: connecting attempt #${c} to ${s}`,{scope:"system",groupKey:"ws:connecting"}),e.bus.emit("ws:connecting",{url:s,attempt:c}),await this.socket.connect();return}catch(c){if(this.stopped)return;if(this.retryAttempt+=1,this.noteConnectFailure(e)){this.socket?.stop(),this.socket=null,this.retryAttempt=0,this.clearCountdown(),e.bus.emit("ws:retrying",{retryInSec:1,attempt:0}),this.ensureStartedSoon(e);return}let u=this.computeBackoffMs(this.retryAttempt),d=Math.max(1,Math.ceil(u/1e3)),f=K(c);e.notifier.warn(`WS: connect failed (attempt=${this.retryAttempt}) -> retry in ${d}s (${f})`,{scope:"system",category:["websocket-connect"],groupKey:"ws:connect-retry"});let p={retryInSec:d,attempt:this.retryAttempt};e.bus.emit("ws:retrying",p),this.startCountdown(d,e),await this.interruptibleSleep(u)}}async isConnectableToBridge(e,t){if(!e.device?.id)return t.notifier.error("WS: cannot connect: device.id missing"),!1;if(!e.bridgeWsUrl)return t.notifier.error("WS: cannot connect: bridgeWsUrl missing"),!1;if(!e.device?.keys?.public)return t.notifier.error("WS: cannot connect: device public key missing"),!1;let r=await t.engine.secrets.get("refreshToken");return!!r.ok&&!!r.value?!0:(t.notifier.warn("WS: not connecting (no tokens). Run signin."),!1)}handleStateChange(e,t){e.kind==="CONNECTING"&&t.notifier.info(`WS: state CONNECTING (url=${this.lastUrl})`,{scope:"system"}),e.kind==="CONNECTED"&&t.notifier.info(`WS: state CONNECTED (url=${this.lastUrl})`,{scope:"system"}),e.kind==="DISCONNECTED"&&t.notifier.info(`WS: state DISCONNECTED (url=${this.lastUrl})`,{scope:"system"})}computeBackoffMs(e){let t=Math.min(3e4,1e3*Math.pow(2,Math.min(e-1,5))),r=t*(.2*(Math.random()*2-1));return Math.max(250,Math.floor(t+r))}startCountdown(e,t){this.clearCountdown();let r=e;this.countdownTimer=setInterval(()=>{if(r-=1,r<=0){this.clearCountdown();return}let o={retryInSec:r,attempt:this.retryAttempt};t.bus.emit("ws:retrying",o)},1e3)}clearCountdown(){this.countdownTimer&&(clearInterval(this.countdownTimer),this.countdownTimer=null)}async ensureStartedSoon(e){await bt(250),!this.stopped&&this.ensureStarted(e,"socket:disconnected")}async interruptibleSleep(e){let r=Date.now();for(;Date.now()-r<e;){if(this.stopped)return;await bt(100)}}};import Ls from"node:fs";import Pu from"node:path";var zr=class{static save(e){let t=this.getApplicationConfigFolder(),r=Pu.join(t,"config.json"),o=this.stripSecrets(e);return Ls.mkdirSync(t,{recursive:!0}),Ls.writeFileSync(r,JSON.stringify(o,null,2),"utf8"),r}static stripSecrets(e){let t=e.device?{id:e.device.id,name:e.device.name,tag:e.device.tag,keys:{public:e.device.keys.public}}:void 0,r=e.tokens?{accessTokenExpSec:e.tokens.accessTokenExpSec}:void 0;return{...e,device:t,tokens:r}}static getApplicationConfigFolder(){return Z()}};var Yr=class{name="main-orchestrator";bootStarted=!1;saveTimer=null;saveInFlight=null;latestConfigToSave=null;saveDebounceMs=500;async onStop(e){await this.flushSaveOnStop()}handlers(){return{"ui:initialized":async(e,t)=>{this.bootStarted||(this.bootStarted=!0,t.engine.setPhase("booting"),t.notifier.info("Booting..."),t.engine.dispatch(Li(new Dr)))},"config:save:requested":async(e,t)=>{this.latestConfigToSave=e,this.saveTimer&&clearTimeout(this.saveTimer),this.saveTimer=setTimeout(()=>{this.performSave(t)},this.saveDebounceMs)}}}async performSave(e){this.saveInFlight||(this.saveInFlight=(async()=>{for(;this.latestConfigToSave;){let t=this.latestConfigToSave;this.latestConfigToSave=null;try{let r=zr.save(t);e.notifier.info(`Config saved to: ${r}`,{scope:"system"}),e.bus.emit("config:saved",void 0)}catch(r){let o=K(r);e.notifier.error(`Failed to save configuration: ${o}`)}}})().finally(()=>{this.saveInFlight=null}),await this.saveInFlight)}async flushSaveOnStop(){this.saveTimer&&(clearTimeout(this.saveTimer),this.saveTimer=null)}};import{decodeJwt as Qu}from"jose";import Ro from"node:crypto";var Ms={invalid_enrollment_token:"Enrollment key is invalid or could not be verified (wrong controller URL, bad signature, or server signing keys do not match the key issuer).",invalid_enrollment_scope:"Enrollment key does not match this device account or organization membership.",enrollment_jwt_expired:"This enrollment key file has expired (JWT). Issue a new key under Organization \u2192 Devices and update ENROLMENT_KEY / your .devicelink file.",enrollment_ticket_invalid:"Enrollment key could not be accepted (already used, expired, or out of sync). Issue a new key under Organization \u2192 Devices.",enrollment_ticket_already_used:"This enrollment key was already used (single-use). Issue a new key under Organization \u2192 Devices.",enrollment_ticket_expired:"This enrollment key has expired. Issue a new key under Organization \u2192 Devices.",server_misconfigured:"Server cannot verify enrollment keys (OAuth keys missing on controller).",enrollment_start_failed:"Device enrollment failed. See controller logs."};function Fu(n){if(typeof n!="object"||n===null)return;let e=n;if(e.body&&typeof e.body=="object"&&e.body!==null&&"error"in e.body){let t=e.body.error;if(typeof t=="string")return t}if(n instanceof Error){let t=n.message.match(/"error"\s*:\s*"([^"]+)"/);if(t?.[1])return t[1]}}function $s(n){let e=Fu(n);return e&&Ms[e]?Ms[e]:e?`Enrollment failed (${e}). ${K(n)}`:K(n)}var Ct=class{timeout=null;interval=null;totalSec=0;remainingSec=0;stepSec=1;task=null;stepCb=null;setStep(e){return this.stepSec=Math.max(1,e),this}schedule(e,t){return this.task=e,this.totalSec=t,this.remainingSec=t,this}onStep(e){return this.stepCb=e,this}start(){return this.clear(),this.remainingSec<=0?(this.runTask(),this):(this.stepCb?.(this.stepSec,this.remainingSec),this.interval=setInterval(()=>{this.remainingSec-=this.stepSec,this.remainingSec<=0?this.runTask():this.stepCb?.(this.stepSec,this.remainingSec)},this.stepSec*1e3),this)}stop(){return this.clear(),this}restart(){return this.remainingSec=this.totalSec,this.start()}runTask(){if(this.clear(),this.task)try{this.task()}catch(e){throw new Error(`Scheduler task failed: ${e}`)}}clear(){this.timeout&&(clearTimeout(this.timeout),this.timeout=null),this.interval&&(clearInterval(this.interval),this.interval=null)}};var Lu=["off","notify","stage","apply_when_idle","required"];function Mu(n){return n===void 0?"off":Lu.find(t=>t===n)??"notify"}var $u={action:"none",target:null,belowFloor:!1,message:null,url:null};function xt(n){return{...$u,reason:n}}function Uu(n){let{currentVersion:e,guidance:t,autoUpdateEnabled:r}=n;if(!t)return xt("no guidance from server");let o=Mu(t.update_policy);if(o==="off")return xt("policy off");if(!ve(e))return xt("current version unreadable");let s=t.min_agent_version??null,a=t.target_agent_version??null,c=t.upgrade_message??null,u=t.upgrade_url??null,d=s!==null&&Tn(e,s),f=a??s;if(!f||!ve(f))return xt("no usable target version");if(Xt(e,f)>=0)return xt("already at or above the target");let p={target:f,belowFloor:d,message:c,url:u};return d?{...p,action:"required",reason:"below the minimum version"}:r?wn(e,f)?o==="notify"?{...p,action:"notify",reason:"policy notify"}:o==="stage"?{...p,action:"stage",reason:"policy stage"}:o==="apply_when_idle"?{...p,action:"apply_when_idle",reason:"policy apply_when_idle"}:{...p,action:"required",reason:"policy required"}:{...p,action:"notify",reason:"major version change is not applied automatically"}:{...p,action:"notify",reason:"automatic updates disabled locally"}}function Us(n,e){let t=Uu(e);if(t.action==="none")return t;let r=Bu(t,String(e.currentVersion));return t.belowFloor?n.error(r):n.warn(r),t}function Bu(n,e){if(n.action==="none")return"";let t=n.target??"a newer version",r=n.belowFloor?`This agent (${e}) is below the minimum version the server accepts (${t}).`:`A newer agent is available (${e} -> ${t}).`,o=n.message?` ${n.message}`:"",i=n.url?` See ${n.url}`:"";return`${r}${o}${i}`}var Ku=15e3,ju=2e3,Vu=12e3,qu=0,Bs=6e4,Wu=250,Ks="This device is being replaced by another connection. Finishing in-flight operations...",js="Device replaced by new connection. Disconnecting.",Hu="Reconnecting to DeviceLink\u2026";function Gu(n){return typeof n!="string"?"SERVER_DRAINING":ii.find(t=>t===n)??"SERVER_DRAINING"}function Ju(n){let e=typeof n=="number"&&Number.isFinite(n)?n:0,t=Math.min(e,Ku);return Math.max(0,Math.min(t-ju,Vu))}function zu(n,e=Math.random){let t=typeof n=="number"&&Number.isFinite(n)?n:0,r=Math.min(Bs,Math.max(qu,Math.floor(t))),o=Math.max(Wu,Math.floor(r*.25)),i=r+Math.floor(e()*o);return Math.min(Bs,i)}function Vs(n,e){let t=Gu(n.reason),r=typeof n.reason=="string"?n.reason:"",o=Ju(n.deadline_ms);if(!e.quiesceV2)return{reason:t,reasonAsSent:r,drainWindowMs:o,reconnect:!0,rediscover:!1,startMessage:Ks,endMessage:js};let i=n.reconnect,a=typeof i?.after_ms=="number"?zu(i?.after_ms,e.random):void 0,c=i?.url,u=ar(c,e.env)?String(c):void 0,d={reason:t,reasonAsSent:r,drainWindowMs:o,reconnect:!0,rediscover:i?.discover===!0,reconnectDelayMs:a,reconnectUrl:u};return t==="SESSION_REPLACED"?{...d,reconnect:!1,reconnectDelayMs:void 0,reconnectUrl:void 0,rediscover:!1,startMessage:Ks,endMessage:js}:t==="SERVER_DRAINING"?{...d,startMessage:r==="SERVER_DRAINING"?Hu:void 0}:t==="ENDPOINT_MOVED"?{...d,rediscover:!0}:d}var qs="BAD_TS",Xu=10,Qr=class{name="auth-orchestrator";phase="IDLE";connectionId=null;sessionId=null;accessToken;rejectedByConflict=!1;negotiatedCapabilities=[];refreshGroupKey="auth:refresh";refreshCycle=0;refreshScheduler=null;refreshRetryScheduler=null;refreshRetryAttempt=0;lastRefreshPlan;refreshInFlight;conflictTimer=null;pendingConflictRequest=null;signinStarted=!1;async onStart(e){e.notifier.info("Auth orchestrator started",{scope:"system"})}async onStop(e){this.clearTimers(),this.resetConnectionState(),e.notifier.info("Auth orchestrator stopped",{scope:"system"})}handlers(){return{"config:loaded":this.onEventConfigLoaded.bind(this),"config:cache:validated":this.onEventConfigCacheValidated.bind(this),"auth:signin:requested":this.onEventAuthSigninRequested.bind(this),"auth:signin:completed":async(e,t)=>{t.notifier.info("Auth: signin completed; requesting ws reconnect",{scope:"system"}),this.rejectedByConflict=!1,this.refreshRetryScheduler&&(this.refreshRetryScheduler.stop(),this.refreshRetryScheduler=null),this.ensureAccessExpPersisted(t,"signin"),await this.ensureRefreshScheduling(t,"signin"),t.bus.emit("auth:ws:reconnect",void 0)},"auth:signout:requested":async(e,t)=>{t.notifier.info("Signing out\u2026"),this.clearTimers(),this.accessToken=void 0;try{await t.engine.secrets.delete("refreshToken")}catch{}let o={...t.engine.configurationContext.configuration,tokens:void 0};t.engine.applyConfiguration(o),t.bus.emit("config:save:requested",o),this.resetConnectionState(),t.engine.setPhase("idle"),t.bus.emit("auth:tokens:updated",{accessToken:"",refreshToken:"",expSec:void 0}),t.bus.emit("ws:disconnect",{reason:"signout"}),t.notifier.success("Signed out successfully")},"auth:session_conflict:resolve":async(e,t)=>{this.sendSessionConflictResolve(t,e.choice)},"ws:connected":async(e,t)=>{this.resetConnectionState();let r=await t.engine.secrets.get("refreshToken"),o=!!r.ok&&!!r.value,i=!!this.accessToken;if(t.notifier.info(`Auth: ws connected; tokens access=${i} refresh=${o}`,{scope:"system"}),!i&&!o){t.notifier.warn("Auth: no tokens; run signin");return}await this.sendConnect(t)},"ws:rx":async(e,t)=>{this.onInbound(e.text,t)},"ws:disconnected":async(e,t)=>{if(t.notifier.warn(`Auth: ws disconnected code=${e.code} reason=${e.reason??"-"}`,{scope:"system"}),this.resetConnectionState(),e.code===4011){t.notifier.warn('Connection rejected - another device is active on this workspace. Run "signin" to try again.'),this.rejectedByConflict=!0,t.bus.emit("ws:disconnect",{reason:"REPLACEMENT_REJECTED"});return}if(e.code===4001){let r=await t.engine.secrets.get("refreshToken");if(!r.ok||!r.value){t.notifier.warn("Auth: token invalid and no refresh; please sign in"),await this.teardownTokens(t,"AUTH_REQUIRED");return}await this.requestRefresh(t,{force:!0,reason:"ws_4001"})&&t.bus.emit("auth:ws:reconnect",void 0)}}}}async onEventConfigLoaded(e,t){if(t.notifier.info("Initializing with cached configuration",{scope:"system"}),!e.device?.id){t.notifier.error("Device ID is not available");return}if(!e.device.keys?.public){t.notifier.error("Device public key is not available");return}t.bus.emit("config:cache:validated",void 0)}async onEventConfigCacheValidated(e,t){this.ensureAccessExpPersisted(t,"boot"),await this.ensureRefreshScheduling(t,"boot");let r=await t.engine.secrets.get("refreshToken"),o=!!r.ok&&!!r.value,i=!!this.accessToken,s=this.isAccessLikelyUsable(t);if(t.notifier.info(`Auth: cache validated; access=${i} refresh=${o} accessOk=${s}`,{scope:"system"}),!i&&!o){if(t.headless&&await ts(t.engine.argv.enrollmentFile)){t.notifier.info("Headless: enrollment certificate present; starting device authorization (approve the pending request under Organization \u2192 Devices).",{scope:"system"}),t.bus.emit("auth:signin:requested",void 0);return}t.notifier.warn("Auth: not signed in; run signin");return}}isAccessLikelyUsable(e){let t=this.accessToken;if(!t)return!1;let o=e.engine.configurationContext.configuration?.tokens?.accessTokenExpSec??this.tryDecodeExp(t);if(!o)return!0;let i=Math.floor(Date.now()/1e3);return o>i}async waitForApproval(e,t,r){let o=Date.now()+t.expires_in*1e3;r.notifier.info("Waiting for approval... (streaming)",{scope:"system"});try{return await e.deviceAuthStream({deviceCode:t.device_code,timeoutMs:Math.max(1e3,o-Date.now()),signal:r.signal})}catch(i){let s=i instanceof Error?i.message:String(i);return r.notifier.error(`Failed to wait for approval: ${s}`),null}}async onEventAuthSigninRequested(e,t){if(this.signinStarted){t.notifier.warn("Sign-in already in progress",{scope:"system"});return}this.signinStarted=!0;try{let r=t.engine.configurationContext.configuration;if(!r.controlBaseUrl){t.notifier.error("Control base URL is not set");return}if(!r.device?.id){t.notifier.error("Device ID is not available");return}if(!r.device.keys?.public){t.notifier.error("Device public key is not available");return}let o=await t.engine.secrets.get("devicePrivateKey");if(!o.ok||!o.value){t.notifier.error("Device private key is not available (secret storage)");return}let i=o.value,s=r.device.name,a=process.platform,c=r.device.keys.public,u=mn(c),d=new tt(r,t.notifier);t.notifier.info("Starting device authentication...");let f=await rs(t.engine.argv.enrollmentFile),p;if(f.ok){t.notifier.info(t.engine.argv.enrollmentFile?"Using enrollment key from --enrollment-file":"Using ENROLMENT_KEY / DLINK_ENROLMENT_KEY from environment",{scope:"system"});try{p=await d.deviceEnrollmentStart({device_id:r.device.id,device_name:s,kind:"agent",platform:a,agent_version:ue(),public_key_pem:c,enrollment_jws:f.jws})}catch(_){t.notifier.error($s(_),{scope:"system"});return}t.notifier.info("Approve this device in the dashboard: Organization \u2192 Devices (pending), or use the verification link below.",{scope:"system"})}else{if(f.error!=="not_configured"){t.notifier.error(f.error==="empty_file"?"Enrollment key is empty":`Could not load enrollment key: ${f.error}`);return}p=await d.deviceAuthStart({device_id:r.device.id,device_name:s,kind:"agent",platform:a,agent_version:ue(),public_key_pem:c})}t.notifier.info("DeviceLink sign-in"),t.notifier.info(`User code: ${p.user_code}`),t.notifier.info(`Device fingerprint: ${u}`),t.notifier.info(`Verification URL: ${p.verification_uri_complete}`);let m=await this.waitForApproval(d,p,t);if(!m)return;if("error"in m){if(m.error==="access_denied"){t.notifier.error("Sign-in denied in browser.");return}if(m.error==="expired_token"){t.notifier.error("Sign-in expired. Run `signin` again.");return}t.notifier.error(`Unexpected error: ${m.error}`);return}if(m.status!=="approved"){t.notifier.error(`Unexpected status: ${m.status}`);return}if(m.needs_proof){t.notifier.info("Sending proof-of-possession signature...",{scope:"system"});let _=Ro.createPrivateKey(i),k=Buffer.from(p.challenge,"base64url"),S=Ro.sign(null,k,_).toString("base64");await d.deviceAuthProve({device_code:p.device_code,challenge_id:p.challenge_id,challenge:p.challenge,signature_b64:S}),t.notifier.info("Proof-of-possession verified",{scope:"system"})}t.notifier.info("Fetching tokens...",{scope:"system"});let g=await d.deviceAuthToken({device_code:p.device_code,install_id:Eo()?Br():void 0}),h=Bn(g.endpoints);h&&t.bus.emit("discovery:document:received",{document:h,source:"token"});let b="tag";await t.engine.secrets.set("refreshToken",g.refresh_token),this.accessToken=g.access_token;let E=this.tryDecodeExp(g.access_token),v={...r,controlBaseUrl:r.controlBaseUrl,device:{...r.device,id:g.device_id,name:s,tag:b,keys:{public:c}},tokens:{...r.tokens??{},accessTokenExpSec:E??void 0}};t.engine.applyConfiguration(v),t.bus.emit("config:save:requested",v),t.bus.emit("auth:signin:completed",void 0),t.notifier.success("Signed in successfully \u2705")}catch(r){let o=me(r);if(o&&["ECONNREFUSED","ENOTFOUND","ETIMEDOUT"].includes(o)){t.notifier.error(`Network error: ${K(r)}`);return}t.notifier.error(`Sign-in failed: ${K(r)}`)}finally{this.signinStarted=!1}}async sendConnect(e){let r=e.engine.configurationContext.configuration.device,o=await e.engine.secrets.get("devicePrivateKey");if(!r?.id||!o.ok||!o.value){e.notifier.warn("Cannot connect: device not configured");return}let i=o.value,s=await e.engine.secrets.get("refreshToken"),a=s.ok?s.value:void 0,c=Date.now(),u=Ro.randomBytes(16).toString("base64url"),d=hn({deviceId:r.id,ts:c,nonce:u,privateKeyPem:i}),f={type:"connect",device_id:r.id,agent_version:ue(),protocol_version:2,capabilities:[...oi],ts:c,nonce:u,sig:d,platform:process.platform,hostname:r.name,device_tag:r.tag,access_token:this.accessToken,refresh_token:a,public_key_pem:r.keys.public};this.phase="CONNECT_SENT",e.notifier.info("Auth: sending connect",{scope:"system"}),this.send(e,f)}async sendSessionInit(e,t){let o=e.engine.configurationContext.configuration.device;if(!o?.id||!this.sessionId){e.notifier.error("Cannot send session_init: device ID or session ID not available");return}let i={type:"session_init",device_id:o.id,session_id:this.sessionId};this.phase="WAIT_SESSION_INIT_ACK",e.notifier.info("Auth: sending session_init",{scope:"system"}),this.send(e,i)}onInbound(e,t){let r;try{r=JSON.parse(e)}catch{t.notifier.error("Unexpected message format");return}let o=or(r);if(!ui(o)){t.notifier.info(`Auth: ignoring unknown message type ${o??"(none)"}`,{scope:"system"});return}let i=li.safeParse(r);if(!i.success){let a=i.error.message;t.notifier.error(`Unexpected message format: ${a}`);return}let s=i.data;switch(s.type){case"connect_ack":t.bus.emit("auth:connect_ack",s),this.onConnectAck(t,s);return;case"session_init_ack":t.bus.emit("auth:session_init_ack",s),this.onSessionInitAck(t,s);return;case"disconnect_notice":this.onDisconnectNotice(t,s);return;case"session_conflict":t.bus.emit("auth:session_conflict",s),this.handleSessionConflict(t,s);return;case"quiesce":this.handleQuiesce(t,s);return;default:return}}async handleSessionConflict(e,t){this.conflictTimer&&(clearTimeout(this.conflictTimer),this.conflictTimer=null),this.pendingConflictRequest=t,e.notifier.warn(`Another device is already connected to this workspace. Type "replace" to disconnect it, or this connection will be rejected in ${Math.round(t.deadline_ms/1e3)}s.`);let r=Math.min(t.deadline_ms,15e3);this.conflictTimer=setTimeout(()=>{this.conflictTimer=null,this.pendingConflictRequest?.new_session_id===t.new_session_id&&(e.notifier.info("No response - keeping existing device connected."),this.sendSessionConflictResolve(e,"KEEP_OLD"))},r)}async handleQuiesce(e,t){let r=Vs(t,{quiesceV2:this.sessionHas(U.QUIESCE_V2)});if(e.notifier.info(`Auth: quiesce reason=${r.reasonAsSent||"(none)"} handled_as=${r.reason} reconnect=${r.reconnect} drain_ms=${r.drainWindowMs}`,{scope:"system"}),r.startMessage&&e.notifier.warn(r.startMessage),e.engine.hasRunningJobs?.()??!1){let i=Date.now();for(;Date.now()-i<r.drainWindowMs&&(e.engine.hasRunningJobs?.()??!1);)await new Promise(s=>setTimeout(s,500))}e.bus.emit("ws:reconnect:policy",{reconnect:r.reconnect,delayMs:r.reconnectDelayMs,url:r.reconnectUrl,rediscover:r.rediscover}),r.rediscover&&e.bus.emit("discovery:refresh:requested",{reason:`quiesce:${r.reason}`});let o=e.engine.hasRunningJobs?.()??!1?"BUSY":"IDLE";this.send(e,{type:"quiesce_ack",session_id:t.session_id,status:o}),r.endMessage&&e.notifier.info(r.endMessage)}sendSessionConflictResolve(e,t){let r=this.pendingConflictRequest;r&&(this.conflictTimer&&(clearTimeout(this.conflictTimer),this.conflictTimer=null),this.pendingConflictRequest=null,this.send(e,{type:"session_conflict_resolve",device_id:r.device_id,new_session_id:r.new_session_id,choice:t}))}async onConnectAck(e,t){if(!t.ok){e.notifier.error(`Connect rejected: ${t.error.code} ${t.error.message}`),this.phase="IDLE";return}this.sessionId=t.session_id;let r=t.auth.access_token;if(e.notifier.info(`Auth: connect_ack ok auth.access=${r} next=[${t.next.join(",")}]`,{scope:"system"}),t.next.includes("refresh_access_token")){let o=await e.engine.secrets.get("refreshToken");if(!o.ok||!o.value){e.notifier.warn("Auth: server requested refresh but no refresh token; please sign in"),await this.teardownTokens(e,"NO_REFRESH_TOKEN");return}await this.requestRefresh(e,{force:!0,reason:"connect_ack_next"})?e.bus.emit("auth:ws:reconnect",void 0):e.notifier.warn("Auth: refresh failed; please sign in");return}if(t.next.includes("session_init")){await this.sendSessionInit(e,t);return}if(r==="invalid"||r==="missing"){e.notifier.warn("Auth: access token invalid; please sign in again"),await this.teardownTokens(e,"INVALID_ACCESS");return}e.notifier.warn("Auth: connect_ack had no next; staying idle",{scope:"system"})}onSessionInitAck(e,t){if(!t.ok){e.notifier.error(`Session init failed: ${t.error.code} ${t.error.message}`),t.error.code==="AGENT_BELOW_MINIMUM"&&this.surfaceUpdateGuidance(e,t),this.phase="IDLE";return}this.sessionId=t.session_id,this.phase="READY",this.negotiatedCapabilities=Array.isArray(t.capabilities)?[...t.capabilities]:[],e.notifier.success(`Session ready (${t.mode})`),e.notifier.info(`Auth: session capabilities=[${this.negotiatedCapabilities.join(",")}]`,{scope:"system"}),this.surfaceUpdateGuidance(e,t),this.ensureRefreshScheduling(e,"manual").catch(r=>{e.notifier.error(`Auth: refresh scheduling failed after session_init_ack: ${r instanceof Error?r.message:String(r)}`,{scope:"system",category:["token-refresh"]})}),t.next&&(t.next.includes("tools_publish")&&e.bus.emit("meta:data:requested:tools",void 0),t.next.includes("directories_publish")&&e.bus.emit("meta:data:requested:directories",void 0))}surfaceUpdateGuidance(e,t){return Us({warn:o=>e.notifier.warn(o),error:o=>e.notifier.error(o)},{currentVersion:ue(),guidance:t,autoUpdateEnabled:Rt("DLINK_AUTO_UPDATE",!0)})}onDisconnectNotice(e,t){e.notifier.warn(`Server disconnect_notice: ${t.reason} (code=${t.code})`)}async requestRefresh(e,t){return this.refreshInFlight?this.refreshInFlight:(this.refreshInFlight=(async()=>{try{return await this.withTimeout(this.dispatchRefreshJob(e,t),6e4,"Refresh operation")}catch(r){throw r instanceof Error&&r.message.includes("timed out")&&e.notifier.error(`Auth: refresh timed out: ${r.message}`,{category:["token-refresh"],groupKey:"auth:refresh-failure"}),r}finally{this.refreshInFlight=void 0}})(),this.refreshInFlight)}async withTimeout(e,t,r){return Promise.race([e,new Promise((o,i)=>{setTimeout(()=>{i(new Error(`${r} timed out after ${t}ms`))},t)})])}async dispatchRefreshJob(e,t){let r=await e.engine.secrets.get("refreshToken");if(!r.ok||!r.value)return!1;if(!t.force){let a=await this.shouldRefreshNow(e);if(!a.ok)return e.notifier.info(`Auth: skip refresh (${a.reason})`,{scope:"system",category:["token-refresh"]}),!1}e.notifier.info(`Auth: dispatch refresh job (${t.reason})`,{scope:"system",category:["token-refresh"]});let o=Hi(new Ir(t.reason)),i=await e.engine.dispatch(o);if(e.notifier.info(`Auth: refresh job dispatch completed (status=${i.status})`,{scope:"system",category:["token-refresh"]}),i.status!=="success"){let a=i.error?.message??"Unknown error";e.notifier.error(`Auth: refresh job failed: ${a}`,{category:["token-refresh"],groupKey:"auth:refresh-failure"});let c=i.output;return c?.errorCode&&oo.includes(c.errorCode)?(await this.teardownTokens(e,c.errorCode),!1):(this.scheduleRefreshRetry(e,t.reason,c?.retryAfterSec,c?.errorCode,c?.driftMs),!1)}let s=i.output;if(!s.ok||!s.accessToken){let a=s.error??"Unknown refresh failure";return e.notifier.error(`Auth: refresh failed: ${a}`,{category:["token-refresh"],groupKey:"auth:refresh-failure"}),s.errorCode&&oo.includes(s.errorCode)?(await this.teardownTokens(e,s.errorCode),!1):(this.scheduleRefreshRetry(e,t.reason,s.retryAfterSec,s.errorCode,s.driftMs),!1)}return this.refreshRetryAttempt=0,this.accessToken=s.accessToken,this.persistTokens(e,s.accessToken,s.expiresInSec),await this.ensureRefreshScheduling(e,"manual"),e.bus.emit("auth:tokens:updated",{accessToken:s.accessToken,refreshToken:s.refreshToken??"",expSec:e.engine.configurationContext.configuration.tokens?.accessTokenExpSec}),!0}scheduleRefreshRetry(e,t,r,o,i){this.refreshRetryScheduler&&this.refreshRetryScheduler.stop(),this.refreshRetryAttempt+=1,o===qs&&this.warnAboutClockSkew(e,i);let s=this.computeRefreshRetryMs(e,t,r,o),a=Math.max(1,Math.ceil(s/1e3));this.refreshRetryScheduler=new Ct().schedule(()=>{this.requestRefresh(e,{force:!0,reason:"retry"}).then(c=>{c&&e.bus.emit("auth:ws:reconnect",void 0)})},a).start()}warnAboutClockSkew(e,t){let r=typeof t=="number"&&Number.isFinite(t)?`about ${Math.round(Math.abs(t)/1e3)}s`:"more than a minute";e.notifier.error(`Auth: this device\u2019s clock is ${r} away from the server, so sign-in cannot be renewed. Correct the system time, then run signin.`,{category:["token-refresh"],groupKey:"auth:clock-skew"})}computeRefreshRetryMs(e,t,r,o){let i=e.engine.configurationContext.loader,s=i.getConfigValue("DL_ACCESS_REFRESH_RETRY_AFTER_MIN_SEC",{defaultValue:1}),a=i.getConfigValue("DL_ACCESS_REFRESH_RETRY_AFTER_MAX_SEC",{defaultValue:300}),c=i.getConfigValue("DL_ACCESS_REFRESH_RETRY_BASE_SEC",{defaultValue:2}),u=i.getConfigValue("DL_ACCESS_REFRESH_RETRY_JITTER_SEC",{defaultValue:1}),d=i.getConfigValue("DL_ACCESS_REFRESH_RETRY_MAX_SEC",{defaultValue:30}),f=i.getConfigValue("DL_ACCESS_REFRESH_CLOCK_SKEW_MIN_SEC",{defaultValue:300}),p=Math.max(1,this.refreshRetryAttempt),m=o===qs?Math.max(d,f):d,{delayMs:g,honoredRetryAfter:h}=Rn({attempt:p,baseSec:c,jitterSec:Math.floor(Math.random()*(u+1)),ceilingSec:m,maxDoublings:Xu,retryAfterSec:r,retryAfterMinSec:s,retryAfterMaxSec:a}),b=Math.max(1,Math.ceil(g/1e3));return e.notifier.warn(h?`Auth: refresh retry scheduled in ${b}s (honoring Retry-After, ${t})`:`Auth: refresh retry scheduled in ${b}s (${t}, attempt ${p})`,{scope:"system",category:["token-refresh"],groupKey:"auth:refresh-retry"}),g}async ensureRefreshScheduling(e,t){let r=await e.engine.secrets.get("refreshToken");!r.ok||!r.value||(this.accessToken&&!e.engine.configurationContext.configuration.tokens?.accessTokenExpSec&&this.ensureAccessExpPersisted(e,t),this.refreshRetryScheduler&&(this.refreshRetryScheduler.stop(),this.refreshRetryScheduler=null),this.scheduleSilentRefresh(e,t))}async scheduleSilentRefresh(e,t){let r=await e.engine.secrets.get("refreshToken");if(!r.ok||!r.value)return;this.refreshScheduler&&this.refreshScheduler.stop();let o=e.engine.configurationContext.loader,i=o.getConfigValue("DL_ACCESS_REFRESH_MIN_DELAY_SEC",{defaultValue:2}),s=e.engine.configurationContext.configuration,a=this.accessToken,c=s.tokens?.accessTokenExpSec??(a?this.tryDecodeExp(a):null),u=c??null,d=this.getRefreshGroupKey(e);if(this.lastRefreshPlan&&this.lastRefreshPlan.exp===u&&this.lastRefreshPlan.groupKey===d)return;this.lastRefreshPlan={exp:u,groupKey:d};let f=v=>{let _=new Ct().schedule(()=>{this.requestRefresh(e,{force:v.force,reason:"timer"}).then(k=>{k&&e.notifier.success("Auth: refresh completed",{scope:"system",groupKey:d,category:["token-refresh"]})})},v.delaySec);v.log&&(_=_.onStep((k,I)=>v.log(I))),this.refreshScheduler=_.start()};if(!c){e.headless||e.notifier.info(`Auth: no exp; scheduling refresh in ${i}s [${t}]`,{scope:"system",groupKey:d,category:["token-refresh"]}),f({delaySec:i,force:!0});return}let p=Math.floor(Date.now()/1e3),m=o.getConfigValue("DL_ACCESS_REFRESH_MARGIN_SEC",{defaultValue:5}),g=o.getConfigValue("DL_ACCESS_REFRESH_JITTER_SEC",{defaultValue:2}),h=g>0?Math.floor(Math.random()*(g+1)):0,b=c-m-h,E=Math.max(i,b-p);e.headless||e.notifier.info(`Auth: refresh scheduled in ${E}s (exp=${c} now=${p} margin=${m} jitter=${h}) [${t}]`,{scope:"system",groupKey:d,category:["token-refresh"]}),f({delaySec:E,force:!1,log:v=>{e.headless||e.notifier.info(`Auth: refresh scheduled in ${v}s (exp=${c} now=${p} margin=${m} jitter=${h}) [${t}]`,{scope:"system",groupKey:d,category:["token-refresh"]})}})}getRefreshGroupKey(e){return this.refreshCycle++,`${this.refreshGroupKey}:${this.refreshCycle}`}async shouldRefreshNow(e){let t=await e.engine.secrets.get("refreshToken");if(!t.ok||!t.value)return{ok:!1,reason:"no_refresh_token"};let r=e.engine.configurationContext.configuration,o=this.accessToken,i=r.tokens?.accessTokenExpSec??(o?this.tryDecodeExp(o):null);if(!i)return{ok:!0,reason:"no_exp_assume_refresh"};let s=Math.floor(Date.now()/1e3),c=e.engine.configurationContext.loader.getConfigValue("DL_ACCESS_REFRESH_MARGIN_SEC",{defaultValue:300}),u=i-s;return u<=c?{ok:!0,reason:`within_margin remaining=${u}s margin=${c}s`}:{ok:!1,reason:`too_early remaining=${u}s margin=${c}s`}}ensureAccessExpPersisted(e,t){let r=e.engine.configurationContext.configuration,o=this.accessToken,i=r.tokens?.accessTokenExpSec;if(!o||typeof i=="number"&&Number.isFinite(i))return;let s=this.tryDecodeExp(o);if(!s)return;let a={...r,tokens:{...r.tokens??{},accessTokenExpSec:s}};e.engine.applyConfiguration(a),e.bus.emit("config:save:requested",a),e.notifier.info(`Auth: derived accessTokenExpSec=${s} (${t})`,{scope:"system"})}persistTokens(e,t,r){let o=e.engine.configurationContext.configuration,i=this.tryDecodeExp(t),s=typeof r=="number"&&Number.isFinite(r)?Math.floor(Date.now()/1e3)+r:void 0,a={...o,tokens:{...o.tokens??{},accessTokenExpSec:i??s}};e.engine.applyConfiguration(a),e.bus.emit("config:save:requested",a),e.notifier.info(`Auth: tokens updated exp=${a.tokens?.accessTokenExpSec??"-"}`,{scope:"system"})}async teardownTokens(e,t){this.accessToken=void 0;let o={...e.engine.configurationContext.configuration,tokens:void 0};e.engine.applyConfiguration(o),e.bus.emit("config:save:requested",o),this.clearTimers(),this.resetConnectionState(),e.bus.emit("auth:signout:requested",void 0),e.notifier.warn(`Auth: signed out (${t}). Please run signin.`)}tryDecodeExp(e){try{let t=Qu(e);return typeof t.exp=="number"?t.exp:null}catch{return null}}send(e,t){e.bus.emit("ws:tx",{text:JSON.stringify(t)})}resetConnectionState(){this.connectionId=null,this.sessionId=null,this.phase="IDLE",this.negotiatedCapabilities=[]}sessionHas(e){return Je(this.negotiatedCapabilities,e)}clearTimers(){this.refreshScheduler&&(this.refreshScheduler.stop(),this.refreshScheduler=null),this.refreshRetryScheduler&&(this.refreshRetryScheduler.stop(),this.refreshRetryScheduler=null),this.conflictTimer&&clearTimeout(this.conflictTimer),this.conflictTimer=null,this.pendingConflictRequest=null}};import wo from"node:fs/promises";import Co from"node:path";var G=class{config;constructor(e){this.config=e}async execute(e){try{let t=await this.executeTool(e);return hi(t)}catch(t){return ne(t)?Ue(t):Ue(j(t,{message:"An unexpected error occurred"}))}}};import Zu from"node:path";import Ws from"node:fs";function ed(n,e,t){let r=n.directories.find(s=>s.id===e);if(!r)return Qt;let o=[],i=Zu.join(r.path,".devicelinkignore");if(Ws.existsSync(i))try{o.push(...En(Ws.readFileSync(i,"utf-8")))}catch(s){console.warn(`[ignore] Failed to read .devicelinkignore: ${s}`)}return o.push(...Qt),o}function oe(n,e,t,r,o){return Sn(n,e,ed(r,t.directory_id,t.workspace_id),o)}import To from"node:fs/promises";import ke from"node:path";var Hs=(n,e,t)=>{throw P(n,e,t?{hint:t}:void 0)};function td(n){return vt(n,Hs)}async function de(n,e){let t=td(e),r=ke.resolve(n),o=await To.realpath(r),i=ke.resolve(o,t==="."?"":t),s=ke.relative(o,i);if(s.startsWith("..")||ke.isAbsolute(s))throw P("PATH_ESCAPE","Path escapes the root.",{hint:"The resolved path escapes the configured root directory. Ensure the path stays within the root boundaries."});try{let a=await To.realpath(i),c=ke.relative(o,a);if(c.startsWith("..")||ke.isAbsolute(c))throw P("PATH_ESCAPE","Symlink/junction escape detected.",{hint:"A symlink or junction in the path resolves outside the configured root directory. Ensure all symlinks stay within the root boundaries."});return{absTarget:a,rel:t}}catch(a){if(me(a)!=="ENOENT")throw a;let c=t.split("/").filter(Boolean);for(let u=c.length;u>0;u--){let d=c.slice(0,u).join("/"),f=c.slice(u).join("/"),p=ke.resolve(o,d);try{let m=await To.realpath(p),g=ke.relative(o,m);if(g.startsWith("..")||ke.isAbsolute(g))throw P("PATH_ESCAPE","Symlink/junction escape detected.",{hint:"A symlink or junction in the path resolves outside the configured root directory. Ensure all symlinks stay within the root boundaries."});return{absTarget:f?ke.join(m,f):m,rel:t}}catch(m){if(me(m)==="ENOENT")continue;throw m}}throw P("NOT_FOUND","Path not found.",{hint:"The specified path does not exist. Verify the path is correct and that the file or directory exists within the configured root."})}}function M(n){return _n(n,Hs)}function J(n,e){let t=String(me(n)??"");return t==="ENOENT"?lt("NOT_FOUND","Path not found.",{fs_code:t}):t==="ENOTDIR"?lt("NOT_A_DIRECTORY","Path is not a directory.",{fs_code:t}):t==="EISDIR"?lt("NOT_A_FILE","Path is a directory, not a file.",{fs_code:t}):t==="EACCES"||t==="EPERM"?lt("PERMISSION_DENIED","Permission denied.",{fs_code:t}):lt("INTERNAL",e,{fs_code:t})}function P(n,e,t){return lt(n,e,t)}function lt(n,e,t){return{code:n,message:e,details:t}}function re(n,e){if(Array.isArray(n.directories)&&n.directories.length===0)throw P("UNKNOWN_DIRECTORY","No directories configured.",{hint:"No directories configured. This may happen if the agent was restarted with different directory configuration. If you have only one directory configured, it will be used automatically.",requested_directory_id:e,available_directory_ids:n.directories.map(r=>r.id),available_paths:n.directories.map(r=>r.path),directory_count:n.directories.length});let t=n.directories.find(r=>r.id===e);if(!t&&n.directories.length===1&&(t=n.directories[0]),!t){let r=n.directories.map(s=>s.id).join(", ")||"none",o=n.directories.map(s=>s.path).join(", ")||"none",i=e===void 0?"undefined (missing)":String(e);throw P("UNKNOWN_DIRECTORY",`Unknown directory_id: ${i}`,{hint:`The directory_id "${i}" does not match any configured directory. Available directory IDs: ${r}. Available paths: ${o}. This may happen if the agent was restarted with different directory configuration. If you have only one directory configured, it will be used automatically.`,requested_directory_id:e,available_directory_ids:n.directories.map(s=>s.id),available_paths:n.directories.map(s=>s.path),directory_count:n.directories.length})}return t}function $(n,e,t,r,o){let i={operation:n,path:e.path||".",directory_id:e.directory_id,workspace_id:e.workspace_id,device_id:e.device_id,success:t,error:r?r.substring(0,200):void 0,metadata:o,timestamp:Date.now()},s=`[FS_AUDIT] ${n} ${t?"SUCCESS":"FAILED"} directory=${i.directory_id} path=${i.path}${i.workspace_id?` workspace=${i.workspace_id}`:""}${i.device_id?` device=${i.device_id}`:""}${i.error?` error=${i.error}`:""}${o?` ${JSON.stringify(o)}`:""}`}import Gs from"lodash/orderBy.js";import rd from"lodash/clamp.js";import nd from"lodash/take.js";import od from"lodash/map.js";function id(n,e,t){return Gs(n,[e==="name"?"name":e==="mtime"?o=>o.mtime??0:o=>o.size??0],[t])}function sd(n,e){return e==="all"?n:e==="files"?n.filter(t=>t.type==="file"||t.type==="symlink"):e==="dirs"?n.filter(t=>t.type==="dir"):n}var Xr=class extends G{async executeTool(e){let t=e.directory_id,r=re(this.config,t),{absTarget:o,rel:i}=await de(r.path,e.path),s=rd(e.limit??200,1,1e3),a=Math.max(e.offset??0,0),c=e.include_hidden??!1,u=e.only??"all",d=e.sort??"name",f=e.order??"asc",p=e.detail??"stat";try{if(!(await wo.stat(o)).isDirectory()){let D=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i});throw $("list",D,!1,"Path is not a directory."),P("NOT_A_DIRECTORY","Path is not a directory.",{path:i,hint:"The path must point to a directory, not a file. Use fs_read to read files, or provide a directory path for listing."})}}catch(T){if(ne(T)){let D=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i});throw $("list",D,!1,j(T).message),T}throw J(T,"Failed to list directory.")}let m;try{m=await wo.readdir(o,{withFileTypes:!0})}catch(T){throw J(T,"Failed to read directory.")}let g=c?m:m.filter(T=>!T.name.startsWith(".")),h=[],b=0,E={total_entries:0,files:0,dirs:0,symlinks:0,hidden:0,ignored:0,total_file_bytes:0},v=new Map,_=fe(e),k={directory_id:t,workspace_id:e.workspace_id,directory_path:r.path};for(let T of g){let D=Co.join(o,T.name),Fe=(i==="."?T.name:Co.posix.join(i,T.name)).replace(/\\/g,"/"),ge="other";T.isDirectory()?ge="dir":T.isFile()?ge="file":T.isSymbolicLink()&&(ge="symlink");let $t=T.name.startsWith(".");if(oe(Fe,T.isDirectory(),k,this.config,_).shouldIgnore){b++,E.ignored++;continue}E.total_entries++,ge==="file"?E.files++:ge==="dir"?E.dirs++:ge==="symlink"&&E.symlinks++,$t&&E.hidden++;let Ko,jo;if(p==="stat"||p==="digest")try{let Bt=await wo.stat(D);Bt.isFile()&&(Ko=Bt.size,E.total_file_bytes=(E.total_file_bytes??0)+Bt.size),jo=Math.floor(Bt.mtimeMs/1e3)}catch{}let Ut=ge==="file"?Co.extname(T.name).slice(1):void 0;Ut&&(p==="stat"||p==="digest")&&v.set(Ut,(v.get(Ut)??0)+1),h.push({name:T.name,path:Fe,type:ge,size:Ko,mtime:jo,ext:Ut,hidden:$t,ignored:!1})}p==="digest"&&v.size>0&&(E.by_ext=nd(Gs(od([...v.entries()],([T,D])=>({ext:T,count:D})),["count"],["desc"]),10));let I=sd(h,u),S=id(I,d,f),R=S.slice(a,a+s),x=a+R.length,A=x<S.length,ie={count:R.length,limit:s,offset:a,has_more:A,next_offset:A?x:void 0},q=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i}),W={items:R,meta:ie,context:q,filtered:{ignored_count:b}};return p==="digest"&&(W.summary=E),$("list",q,!0,void 0,{file_count:R.length}),W}};import Js from"node:fs/promises";var ut=class extends G{async executeTool(e){let t=e.directory_id,r=re(this.config,t),{absTarget:o,rel:i}=await de(r.path,e.path),s=fe(e),a={directory_id:t,workspace_id:e.workspace_id,directory_path:r.path},c=oe(i,!1,a,this.config,s);if(c.shouldIgnore){let h=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i});throw $("read",h,!1,`Access denied: ${c.reason||c.matchedRule||"blocked"}`),P("PERMISSION_DENIED",`Access denied: ${c.reason||c.matchedRule||"blocked"}`,{path:i,reason:c.reason})}let u=Math.max(e.offset??0,0),d=Math.min(Math.max(e.limit??4e4,1),2e5),f=e.encoding??"utf-8",p;try{p=await Js.stat(o)}catch(h){let b=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i});throw $("read",b,!1,J(h,"Failed to stat file.").message),J(h,"Failed to stat file.")}if(!p.isFile()){let h=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i});throw $("read",h,!1,"Path is not a file."),P("NOT_A_FILE","Path is not a file.",{path:i,hint:"The path must point to a file, not a directory. Use fs_list or fs_tree to explore directories, or provide a file path to read."})}let m=s?.max_file_size_bytes;if(typeof m=="number"&&m>0&&p.size>m){let h=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i});throw $("read",h,!1,`File exceeds the policy size limit (${p.size} > ${m}).`),P("PERMISSION_DENIED",`File exceeds the maximum size allowed by policy (${p.size} > ${m} bytes).`,{path:i,reason:"policy:max_file_size_bytes"})}let g;try{g=await Js.open(o,"r")}catch(h){let b=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i});throw $("read",b,!1,J(h,"Failed to open file.").message),J(h,"Failed to open file.")}try{let h=Buffer.alloc(d),{bytesRead:b}=await g.read(h,0,d,u),E=b<d,v=E?b:kn(h.subarray(0,b),f),k=h.subarray(0,v).toString(f),I=u+v,S=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i});return $("read",S,!0,void 0,{bytes_read:v}),{content:k,bytes_read:v,next_offset:I,eof:E,context:S}}catch(h){let b=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i});throw $("read",b,!1,j(h).message),h}finally{await g.close()}}};import xo from"node:fs/promises";var Zr=class extends G{async executeTool(e){let t=e.directory_id,r=re(this.config,t),{absTarget:o,rel:i}=await de(r.path,e.path),s=!1,a;try{a=await xo.readlink(o),s=!0}catch(f){if(me(f)==="ENOENT")throw J(f,"Path not found.")}let c;try{c=s?await xo.stat(o):await xo.lstat(o)}catch(f){throw J(f,"Failed to stat path.")}let u="other";c.isDirectory()?u="dir":c.isFile()?u="file":s&&(u="symlink");let d=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i});return $("info",d,!0),{type:u,size:c.isFile()?c.size:void 0,mtime:Math.floor(c.mtimeMs/1e3),ctime:Math.floor(c.ctimeMs/1e3),atime:Math.floor(c.atimeMs/1e3),is_symlink:s,target:s?a:void 0,context:d}}};import Io from"node:fs/promises";import Re from"node:path";import Do from"node:fs/promises";import zs from"node:path";import Ao from"lodash/clamp.js";function ad(n,e){let t="^",r=0;for(;r<e.length;){let o=e[r];if(o==="*")r+1<e.length&&e[r+1]==="*"?(t+=".*",r+=2):(t+="[^/]*",r++);else if(o==="?")t+="[^/]",r++;else if(o==="{"){let i=e.indexOf("}",r);if(i===-1)t+="\\{",r++;else{let s=e.substring(r+1,i).split(",");t+="("+s.map(a=>a.trim().replace(/[.*+?^${}()|[\]\\]/g,"\\$&")).join("|")+")",r=i+1}}else"\\^$|.+()[]".includes(o)?(t+="\\"+o,r++):(t+=o,r++)}t+="$";try{return new RegExp(t,"i").test(n)}catch{return!1}}async function cd(n,e,t,r,o,i,s,a){let c;try{c=await Do.readFile(n,"utf-8")}catch{return 0}let u=c.split(/\r?\n/),d=0,f;if(r==="regex")try{f=new RegExp(t,o?"g":"gi")}catch{let p=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");f=new RegExp(p,o?"g":"gi")}else{let p=t.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");f=new RegExp(p,o?"g":"gi")}for(let p=0;p<u.length&&d<s;p++){let m=u[p];if(f.test(m)){f.lastIndex=0;let g=Math.max(0,p-i),h=Math.min(u.length-1,p+i),b=u.slice(g,h+1);a.push({path:e,line:p+1,preview:m.trim(),snippet:b}),d++}}return d}async function Ys(n,e,t,r,o,i,s,a,c,u,d,f,p,m,g){if(d.value>=c||f.length>=u)return;let h;try{h=await Do.readdir(n,{withFileTypes:!0})}catch{return}for(let b of h){if(d.value>=c||f.length>=u)break;let E=zs.join(n,b.name),v=e==="."?b.name:zs.posix.join(e,b.name);if(oe(v,b.isDirectory(),m,g).shouldIgnore){p.value++;continue}if(b.isFile()){if(i&&!ad(v,i))continue;d.value++,await cd(E,v,r,o,s,a,u-f.length,f)}else b.isDirectory()&&await Ys(E,v,t,r,o,i,s,a,c,u,d,f,p,m,g)}}var dt=class extends G{async executeTool(e){let t=e.directory_id,r=re(this.config,t),o=e.query;if(!o||o.length===0)throw P("INVALID_INPUT","Query is required.",{hint:'Query should be a search pattern to find in file contents. Use a substring (default) or regex pattern (with mode="regex"). Examples: "function", "import.*from", "TODO"'});let i=e.mode??"substring",s=e.file_glob,a=Ao(e.max_files??2e3,1,1e4),c=Ao(e.max_matches??200,1,1e3),u=Ao(e.context_lines??2,0,10),d=e.case_sensitive??!1,{absTarget:f,rel:p}=await de(r.path,e.path??".");if(p!==".")try{if(!(await Do.stat(f)).isDirectory())throw P("NOT_A_DIRECTORY","Grep path is not a directory.",{path:p,hint:'The grep path must be a directory. Grep searches within directories recursively. Use "." to search from the root, or provide a directory path.'})}catch(v){throw ne(v)?v:J(v,"Failed to stat grep path.")}let m={directory_id:t,workspace_id:e.workspace_id,directory_path:r.path},g=[],h={value:0},b={value:0};await Ys(f,p,r.path,o,i,s,d,u,a,c,h,g,b,m,this.config);let E=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:p});return $("grep",E,!0,void 0,{file_count:h.value,match_count:g.length}),{matches:g,meta:{files_scanned:h.value,matches:g.length,truncated:h.value>=a||g.length>=c},context:E,filtered:{ignored_count:b.value}}}};import ld from"lodash/isEmpty.js";var pt=class extends G{async executeTool(e){let t=e.directory_id,r=re(this.config,t),o=e.default_limit??12e3,i=e.default_encoding??"utf-8",s=[];if(e.items&&Array.isArray(e.items)&&(s=e.items),ld(s))throw P("INVALID_INPUT","fs_read_many expects { items: [{path,...}] }",{receivedKeys:Object.keys(e),hint:'Provide an "items" array with at least one object containing a "path" property. Each item can optionally include "offset", "limit", and "encoding". Example: { items: [{ path: "file1.ts" }, { path: "file2.ts", limit: 5000 }] }'});let a=fe(e),c=[],u={directory_id:t,workspace_id:e.workspace_id,directory_path:r.path},d=new ut(this.config);for(let p of s)try{let m=oe(p.path,!1,u,this.config,a);if(m.shouldIgnore){c.push({path:p.path,content:"",bytes_read:0,truncated:!1,error:{code:"PERMISSION_DENIED",message:`Access denied: ${m.reason||m.matchedRule||"blocked"}`}});continue}let g={directory_id:t,path:p.path,workspace_id:e.workspace_id,device_id:e.device_id,offset:p.offset??0,limit:p.limit??o,encoding:p.encoding??i},h=await d.execute(g);if(!h.ok){c.push({path:p.path,content:"",bytes_read:0,truncated:!1,error:{code:h.error.code,message:h.error.message}});continue}c.push({path:p.path,content:h.data.content,bytes_read:h.data.bytes_read,truncated:!h.data.eof})}catch(m){let{code:g,message:h}=j(m);c.push({path:p.path,content:"",bytes_read:0,truncated:!1,error:{code:g,message:h}})}let f=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:"."});return $("read_many",f,!0,void 0,{file_count:c.length}),{files:c,context:f}}};import At from"lodash/clamp.js";import ud from"lodash/compact.js";import Xs from"lodash/orderBy.js";import dd from"lodash/uniq.js";import Qs from"lodash/take.js";function Zs(n,e,t){if(!(e.length>=t)){if(n.type==="file"){e.push(n.path);return}if(n.children)for(let r of n.children){if(e.length>=t)break;Zs(r,e,t)}}}function pd(n){let e=t=>{let r=t.toLowerCase(),o=r.split("/");return r==="readme.md"||r.endsWith("/readme.md")||r.includes("/readme.md")?0:r.endsWith(".md")?1:r.endsWith("package.json")||r.endsWith("pyproject.toml")||r.endsWith("go.mod")||r.endsWith("cargo.toml")||r.endsWith("pom.xml")||r.endsWith("build.gradle")?2:r.includes("dockerfile")||r.includes("compose")||r.endsWith(".env.example")?3:o.includes("config")||o.includes("conf")||o.includes("settings")?4:o.includes("ci")||o.includes(".github")||o.includes(".gitlab")||o.includes("jenkins")||r.includes("workflow")?5:r.endsWith(".ts")||r.endsWith(".tsx")||r.endsWith(".js")||r.endsWith(".jsx")||r.endsWith(".py")||r.endsWith(".go")||r.endsWith(".rs")||r.endsWith(".java")?6:7};return[...n].sort((t,r)=>{let o=e(t),i=e(r);return o!==i?o-i:t.localeCompare(r)})}function ea(n,e,t,r){let o={path:n.path,name:n.name,type:n.type,depth:e,size:n.size,mtime:n.mtime,ext:n.ext,hidden:n.hidden,ignored:n.ignored};if(r?.has(n.path)?o.error=r.get(n.path):n.type==="other"&&n.name==="<readdir_error>"&&(o.error={code:"INTERNAL",message:"Failed to read directory"}),t.push(o),n.children)for(let i of n.children)ea(i,e+1,t,r)}async function ta(n,e,t,r,o,i,s,a,c,u,d,f,p,m,g,h,b){if(a.value>=s)return g.reason="MAX_ENTRIES",null;if(t>r)return g.reason="MAX_DEPTH",null;let E=e==="."?".":e.replace(/\\/g,"/"),v;try{v=await Io.lstat(n)}catch(x){let{code:A,message:ie}=j(x);u.total_entries++;let q={name:Re.basename(e)||e,type:"other",path:E,hidden:Re.basename(e)?.startsWith("."),ignored:!1};return h&&h.set(E,{code:A,message:`Failed to stat: ${ie}`}),o==="files"||o==="dirs"?null:(a.value++,q)}let _="other";if(v.isDirectory()?_="dir":v.isFile()?_="file":v.isSymbolicLink()&&(_="symlink"),oe(E,v.isDirectory(),p,m,b).shouldIgnore)return c.value++,u.ignored++,null;u.total_entries++,_==="file"?u.files++:_==="dir"?u.dirs++:_==="symlink"&&u.symlinks++;let I=Re.basename(e)?.startsWith(".");I&&u.hidden++;let S=_==="file"?Re.extname(Re.basename(e)||e).slice(1):void 0;S&&(f==="stat"||f==="digest")&&d.set(S,(d.get(S)??0)+1),_==="file"&&(f==="stat"||f==="digest")&&(u.total_file_bytes=(u.total_file_bytes??0)+(v.size??0));let R={name:Re.basename(e)||e,type:_,path:E,size:(f==="stat"||f==="digest")&&v.isFile()?v.size:void 0,mtime:f==="stat"||f==="digest"?Math.floor(v.mtimeMs/1e3):void 0,ext:S,hidden:I,ignored:!1};if(o==="files"&&_!=="file"&&_!=="symlink"||o==="dirs"&&_!=="dir")return null;if(a.value++,_==="dir"&&t<r){let x,A;try{x=await Io.readdir(n,{withFileTypes:!0})}catch(C){A=j(C),x=[]}let ie=Xs(i?x:x.filter(C=>!C.name.startsWith(".")),[C=>C.isDirectory()?0:1,"name"],["asc","asc"]),q=[];A&&h&&h.set(E,{code:A.code,message:`Failed to read directory: ${A.message}`});for(let C of ie){if(a.value>=s)break;let W=Re.join(n,C.name),T=e==="."?C.name:Re.posix.join(e,C.name),D=T.replace(/\\/g,"/");if(oe(D,C.isDirectory(),p,m,b).shouldIgnore){c.value++,u.ignored++;continue}try{let Fe=await ta(W,T,t+1,r,o,i,s,a,c,u,d,f,p,m,g,h,b);Fe&&q.push(Fe)}catch(Fe){let{code:ge,message:$t}=j(Fe);h&&h.set(D,{code:ge,message:`Failed to build subtree: ${$t}`}),u.total_entries++;let Bo={name:Re.basename(T)||T,type:"other",path:D,hidden:Re.basename(T)?.startsWith("."),ignored:!1};if(o==="files"||o==="dirs")continue;a.value++,q.push(Bo)}}q.length>0&&(R.children=q)}return R}var en=class extends G{async executeTool(e){let t=e.directory_id,r=re(this.config,t),{absTarget:o,rel:i}=await de(r.path,e.path),s=At(e.max_depth??3,1,20),a=e.only??"all",c=e.include_hidden??!1,u=At(e.max_entries??5e3,1,2e4),d=e.detail??"stat",f=e.include_display??!1,p=At(e.max_display_rows??2e3,1,2e4);try{if(!(await Io.stat(o)).isDirectory())throw P("NOT_A_DIRECTORY","Path is not a directory.",{path:i,hint:"The path must point to a directory to build a tree. Provide a directory path, not a file."})}catch(C){throw ne(C)?C:J(C,"Failed to build tree.")}let m=fe(e),g={directory_id:t,workspace_id:e.workspace_id,directory_path:r.path},h={reason:void 0},b={value:0},E={value:0},v={total_entries:0,files:0,dirs:0,symlinks:0,hidden:0,ignored:0,total_file_bytes:0},_=new Map,k=new Map,I=await ta(o,i,0,s,a,c,u,b,E,v,_,d,g,this.config,h,k,m);if(!I)throw P("INTERNAL","Failed to build tree (empty result).");let S=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:i});d==="digest"&&_.size>0&&(v.by_ext=Qs(Xs([..._.entries()].map(([C,W])=>({ext:C,count:W})),["count"],["desc"]),10));let R={tree:I,context:S,filtered:{ignored_count:E.value}};if(f){let C=[];ea(I,0,C,k),C.length>p&&(C.length=p,R.truncated=R.truncated??{reason:"MAX_ENTRIES",continuation:"Display rows truncated; reduce max_entries/max_depth or lower max_display_rows"}),R.display={rows:C}}h.reason&&(R.truncated={reason:h.reason,continuation:h.reason==="MAX_ENTRIES"?"Reduce max_entries or list this folder with fs_list instead":"Reduce max_depth or list this folder with fs_list instead"}),(d==="digest"||e.include_summary)&&(R.summary=v);let x={};if(e.grep?.query)try{let C=new dt(this.config),W={directory_id:t,workspace_id:e.workspace_id,device_id:e.device_id,path:e.path??".",query:e.grep.query,mode:e.grep.mode??"substring",file_glob:e.grep.file_glob,max_files:e.grep.max_files??2e3,max_matches:e.grep.max_matches??200,context_lines:e.grep.context_lines??2,case_sensitive:e.grep.case_sensitive??!1},T=await C.execute(W);T.ok&&(x.grep={matches:T.data.matches,meta:T.data.meta,context:T.data.context})}catch{}let A=ud(e.read?.paths),ie=[];if(e.read?.auto){let C=At(e.read.auto.max_files??10,1,50),W=[];Zs(I,W,3e3),ie=pd(W).slice(0,C)}let q=Qs(dd([...A,...ie]),50);if(q.length>0)try{let C=At(e.read?.auto?.max_bytes_each??2e4,1,2e5),W=new pt(this.config),T={directory_id:t,workspace_id:e.workspace_id,device_id:e.device_id,default_limit:C,default_encoding:"utf-8",items:q.map(se=>({path:se}))},D=await W.execute(T);D.ok&&(x.read_many={files:D.data.files.map(se=>({path:se.path,content:se.content,bytes_read:se.bytes_read,truncated:se.truncated,error:se.error})),context:D.data.context})}catch{}return Object.keys(x).length>0&&(R.extras=x),$("tree",S,!0,void 0,{file_count:b.value}),R}};import Oo from"node:fs/promises";import Dt from"node:path";import fd from"lodash/clamp.js";import md from"lodash/orderBy.js";function hd(n,e){let t="^",r=0;for(;r<e.length;){let o=e[r];if(o==="*")r+1<e.length&&e[r+1]==="*"?(t+=".*",r+=2):(t+="[^/\\\\]*",r++);else if(o==="?")t+="[^/\\\\]",r++;else if(o==="["){let i=e.indexOf("]",r);if(i===-1)t+="\\[",r++;else{let s=e.substring(r+1,i);s.startsWith("!")?t+="[^"+s.substring(1)+"]":t+="["+s+"]",r=i+1}}else"\\^$|.+(){}[]".includes(o)?(t+="\\"+o,r++):(t+=o,r++)}t+="$";try{return new RegExp(t,"i").test(n)}catch{return n.toLowerCase().includes(e.toLowerCase())}}function gd(n,e,t){return t==="glob"?hd(n,e):n.toLowerCase().includes(e.toLowerCase())}function yd(n,e,t){let r=100;if(e){for(let o of e)if(n.path.startsWith(o)){r+=50;break}}if(t){for(let o of t)if(n.path.startsWith(o)){r-=30;break}}return n.name===n.path.split("/").pop()&&(r+=20),r}function bd(n,e){let t="^",r=0;for(;r<e.length;){let o=e[r];o==="*"?r+1<e.length&&e[r+1]==="*"?(t+=".*",r+=2):(t+="[^/]*",r++):o==="?"?(t+="[^/]",r++):"\\^$|.+(){}[]".includes(o)?(t+="\\"+o,r++):(t+=o,r++)}t+="$";try{return new RegExp(t,"i").test(n)}catch{return!1}}async function No(n,e,t,r,o,i,s,a,c,u,d,f,p,m,g,h,b,E){if(u.length>=c)return;let v;try{v=await Oo.readdir(n,{withFileTypes:!0})}catch{return}let _=a?v:v.filter(k=>!k.name.startsWith("."));for(let k of _){if(u.length>=c)break;let I=Dt.join(n,k.name),S=e==="."?k.name:Dt.posix.join(e,k.name);if(oe(S,k.isDirectory(),f,p,E).shouldIgnore){d.value++;continue}if(m&&!bd(S,m)){i&&k.isDirectory()&&await No(I,S,t,r,o,i,s,a,c,u,d,f,p,m,g,h,b,E);continue}let x=gd(k.name,r,o),A="other";if(k.isDirectory()?A="dir":k.isFile()?A="file":k.isSymbolicLink()&&(A="symlink"),x&&(s==="all"||s==="files"&&(A==="file"||A==="symlink")||s==="dirs"&&A==="dir")){let q,C;if(b!==!1)try{let D=await Oo.stat(I);q=D.isFile()?D.size:void 0,C=Math.floor(D.mtimeMs/1e3)}catch{}let W=A==="file"?Dt.extname(k.name).slice(1):void 0,T=yd({name:k.name,path:S},g,h);u.push({name:k.name,path:S,type:A,size:q,mtime:C,ext:W,hidden:k.name.startsWith("."),ignored:!1,score:T,matched:"name"})}i&&A==="dir"&&await No(I,S,t,r,o,i,s,a,c,u,d,f,p,m,g,h,b)}}var tn=class extends G{async executeTool(e){let t=e.directory_id,r=re(this.config,t),o=e.query;if(!o||o.length===0)throw P("INVALID_INPUT","Query is required.",{hint:'Query should be a pattern to match file or directory names. Use a substring (default) or glob pattern (with mode="glob"). Examples: "config", "*.ts", "test/**"'});let i=e.mode??"substring",s=e.recursive??!0,a=e.only??"all",c=e.include_hidden??!1,u=fd(e.max_results??200,1,2e4),d=Math.max(e.offset??0,0),f=e.file_glob,p=e.prefer_paths,m=e.avoid_paths,g=e.include_stats!==!1,{absTarget:h,rel:b}=await de(r.path,e.path??"."),E=h,v=b,_=[];if(b!==".")try{let D=await Oo.stat(h);if(!D.isDirectory())if(D.isFile()){E=Dt.dirname(h);let se=Dt.posix.dirname(b);v=se==="."?".":se,_.push({type:"warning",description:`Search path "${b}" is not a directory (it's a file). Searching the directory containing it instead: "${v}"`})}else throw P("NOT_A_DIRECTORY","Search path is not a directory.",{path:b,hint:'The search path must be a directory. Search looks for files/directories matching the query within directories. Use "." to search from the root, or provide a directory path.'})}catch(D){throw ne(D)?D:J(D,"Failed to stat search path.")}let k=fe(e),I={directory_id:t,workspace_id:e.workspace_id,directory_path:r.path},S=[],R={value:0};await No(E,v,r.path,o,i,s,a,c,u+d,S,R,I,this.config,f,p,m,g,k);let x=md(S,[D=>D.score??0,"name"],["desc","asc"]),A=x.slice(d,d+u),ie=d+A.length,q=ie<x.length,C={count:A.length,limit:u,offset:d,has_more:q,next_offset:q?ie:void 0},W=M({workspace_id:e.workspace_id,device_id:e.device_id,directory_id:t,path:v});$("search",W,!0,void 0,{file_count:A.length});let T={results:A,meta:C,context:W,filtered:{ignored_count:R.value}};return _.length>0&&(T.messages=_),T}};var rn=class extends G{async executeTool(e){let t={agent_version:ue(),platform:process.platform,answered_at:Date.now()};return e.echo!==void 0&&(t.echo=e.echo),t}};var nn=class{config;executers=new Map;constructor(e){this.config=e,this.initializeExecuters()}initializeExecuters(){this.executers.set("fs_list",new Xr(this.config)),this.executers.set("fs_read",new ut(this.config)),this.executers.set("fs_info",new Zr(this.config)),this.executers.set("fs_tree",new en(this.config)),this.executers.set("fs_search",new tn(this.config)),this.executers.set("fs_grep",new dt(this.config)),this.executers.set("fs_read_many",new pt(this.config)),this.executers.set("dl_ping",new rn(this.config))}async executeTool(e,t){let r=this.executers.get(e);if(!r)return Ue({code:"UNKNOWN_TOOL",message:`Unknown tool: ${e}`,details:{toolName:e}});try{return await r.execute(t)}catch(o){return ne(o)?Ue(o):Ue({...j(o),details:{raw:String(o)}})}}getExecuter(e){return this.executers.get(e)}hasTool(e){return this.executers.has(e)}getRegisteredTools(){return Array.from(this.executers.keys())}};import ra from"lodash/isObject.js";import He from"lodash/get.js";function vd(n){return ra(n)&&typeof He(n,"ok")=="boolean"}function Sd(n){let e=vd(n),t=e?!!He(n,"ok"):!0,r,o,i;if(t){if(e?r=He(n,"data")??He(n,"result")??n:r=n,ra(r)&&Array.isArray(He(r,"messages"))){i=He(r,"messages");let s={...r};delete s.messages,r=s}}else e?o=He(n,"error")??n:o=n;return{ok:t,result:r,error:o,messages:i}}function na(n,e,t,r){let o=$e(r),{ok:i,result:s,error:a,messages:c}=Sd(t);return Dn({type:"tool_result",job_id:n,tool:e,ok:i,timing:o,...i?{result:s??null}:{error:a??{code:"UNKNOWN",message:"Unknown error"}},messages:c})}function oa(n,e,t,r){let o=$e(r);return{type:"tool_result",job_id:n,tool:e,ok:!1,error:j(t),timing:o}}var V=class{toolName;jobId;ok;elapsedSec;raw;constructor(e,t,r,o){this.toolName=e,this.jobId=t,this.ok=r.ok,this.elapsedSec=o,this.raw=r}getErrorDescription(){return`error: ${K(this.raw.error)}`}getStatusIcon(){return this.ok?"\u2713":"\u2717"}getStatusText(){return this.ok?"SUCCESS":"FAILED"}toString(){let e=this.getStatusIcon(),t=this.getDescription();return`${e} ${this.toolName} (${t}, elapsed=${this.elapsedSec}s)`}};var It=class extends V{output;constructor(e,t,r,o){super(e,t,r,o),this.output=r.ok?r.data:void 0}getDescription(){if(!this.ok)return this.getErrorDescription();if(!this.output)return"no result";let{items:e,meta:t,filtered:r,context:o}=this.output,i=e?.length??0,s=r?.ignored_count??0,a=o?.path??"unknown",c=[];i>0&&c.push(`${i} item${i!==1?"s":""}`),s>0&&c.push(`${s} ignored`),t?.has_more&&c.push("has_more");let u=c.length>0?c.join(", "):"empty";return`path=${a}, ${u}`}};var Ot=class extends V{output;constructor(e,t,r,o){super(e,t,r,o),this.output=r.ok?r.data:void 0}getDescription(){if(!this.ok)return this.getErrorDescription();if(!this.output)return"no result";let{bytes_read:e,eof:t,context:r}=this.output,o=r?.path??"unknown",i=e??0,s=!t,a=[`path=${o}`,`${i} bytes`];return s&&a.push("truncated"),a.join(", ")}};var Nt=class extends V{output;constructor(e,t,r,o){super(e,t,r,o),this.output=r.ok?r.data:void 0}getDescription(){if(!this.ok)return this.getErrorDescription();if(!this.output)return"no result";let{type:e,size:t,context:r}=this.output,o=r?.path??"unknown",i=t!==void 0?`${t} bytes`:"no size";return`path=${o}, type=${e}, ${i}`}};var Pt=class extends V{output;constructor(e,t,r,o){super(e,t,r,o),this.output=r.ok?r.data:void 0}getDescription(){if(!this.ok)return this.getErrorDescription();if(!this.output)return"no result";let{tree:e,filtered:t,summary:r,context:o}=this.output,i=o?.path??"unknown",s=t?.ignored_count??0,a=[`path=${i}`];if(r){let{total_entries:c,files:u,dirs:d}=r;c!==void 0&&a.push(`${c} entries`),u!==void 0&&a.push(`${u} files`),d!==void 0&&a.push(`${d} dirs`)}else if(e){let c=d=>{let f=1;if(d.children)for(let p of d.children)f+=c(p);return f},u=c(e);a.push(`${u} nodes`)}return s>0&&a.push(`${s} ignored`),this.output.truncated&&a.push("truncated"),a.join(", ")}};var Ft=class extends V{output;constructor(e,t,r,o){super(e,t,r,o),this.output=r.ok?r.data:void 0}getDescription(){if(!this.ok)return this.getErrorDescription();if(!this.output)return"no result";let{results:e,meta:t,filtered:r,context:o}=this.output,i=o?.path??"unknown",s=e?.length??0,a=r?.ignored_count??0,c=[`path=${i}`,`${s} result${s!==1?"s":""}`];return a>0&&c.push(`${a} ignored`),t?.has_more&&c.push("has_more"),c.join(", ")}};var Lt=class extends V{output;constructor(e,t,r,o){super(e,t,r,o),this.output=r.ok?r.data:void 0}getDescription(){if(!this.ok)return this.getErrorDescription();if(!this.output)return"no result";let{matches:e,meta:t,filtered:r,context:o}=this.output,i=o?.path??"unknown",s=e?.length??0,a=t?.files_scanned??0,c=r?.ignored_count??0,u=[`path=${i}`,`${s} match${s!==1?"es":""}`,`${a} file${a!==1?"s":""} scanned`];return c>0&&u.push(`${c} ignored`),t?.truncated&&u.push("truncated"),u.join(", ")}};var Mt=class extends V{output;constructor(e,t,r,o){super(e,t,r,o),this.output=r.ok?r.data:void 0}getDescription(){if(!this.ok)return this.getErrorDescription();if(!this.output)return"no result";let{files:e}=this.output,t=e?.length??0,r=e?.filter(a=>!a.error).length??0,o=t-r,i=e?.reduce((a,c)=>a+(c.bytes_read??0),0)??0,s=[`${t} file${t!==1?"s":""}`,`${r} success`];return o>0&&s.push(`${o} error${o!==1?"s":""}`),i>0&&s.push(`${i} bytes`),s.join(", ")}};function Po(n,e,t,r){switch(n){case"fs_list":return new It(n,e,t,r);case"fs_read":return new Ot(n,e,t,r);case"fs_info":return new Nt(n,e,t,r);case"fs_tree":return new Pt(n,e,t,r);case"fs_search":return new Ft(n,e,t,r);case"fs_grep":return new Lt(n,e,t,r);case"fs_read_many":return new Mt(n,e,t,r);default:{class o extends V{getDescription(){return this.ok?"completed":"failed"}}return new o(n,e,t,r)}}}var Ed=64,_d=5*6e4,Fo=class{entries=new Map;max;ttlMs;now;constructor(e={}){this.max=Math.max(1,e.max??Ed),this.ttlMs=Math.max(1,e.ttlMs??_d),this.now=e.now??(()=>Date.now())}get size(){return this.prune(),this.entries.size}get(e){return this.prune(),this.entries.get(e)}has(e){return this.get(e)!==void 0}remember(e,t,r){this.prune(),this.entries.delete(e),this.entries.set(e,{jobId:e,text:t,at:this.now(),delivered:r}),this.evictOverflow()}markDelivered(e){let t=this.entries.get(e);t&&(t.delivered=!0)}undelivered(){return this.prune(),[...this.entries.values()].filter(e=>!e.delivered)}prune(){let e=this.now()-this.ttlMs;for(let[t,r]of this.entries)r.at<=e&&this.entries.delete(t)}evictOverflow(){for(;this.entries.size>this.max;){let e=this.entries.keys().next();if(e.done)return;this.entries.delete(e.value)}}},on=class{cache;inFlight=new Set;connected=!1;negotiated=!1;constructor(e={}){this.cache=new Fo(e)}get isConnected(){return this.connected}get redeliveryNegotiated(){return this.negotiated}onConnected(){this.connected=!0}onDisconnected(){this.connected=!1,this.negotiated=!1}onSessionAck(e){this.negotiated=e.ok===!0&&Je(e.capabilities,U.RESULT_REDELIVERY_V1)}decide(e){if(this.inFlight.has(e))return{action:"ignore",reason:"in_flight"};let t=this.cache.get(e);return t?{action:"resend",text:t.text}:{action:"execute"}}beginExecution(e){this.inFlight.add(e)}endExecution(e){this.inFlight.delete(e)}recordResult(e,t){return this.cache.remember(e,t,this.connected),{heldForRedelivery:!this.connected}}pendingRedeliveries(){return this.negotiated?this.cache.undelivered():[]}markDelivered(e){this.cache.markDelivered(e)}get cachedCount(){return this.cache.size}};var sn=class{name="tools-orchestrator";delivery=new on;handlers(){return{"ws:connected":async(e,t)=>{this.delivery.onConnected(),t.notifier.info(`WS connected: ${e.url}`,{scope:"system"})},"ws:disconnected":async()=>{this.delivery.onDisconnected()},"auth:session_init_ack":async(e,t)=>{this.delivery.onSessionAck(e),this.redeliverPendingResults(t)},"ws:rx":async(e,t)=>{let r;try{r=JSON.parse(e.text)}catch{return}if(or(r)!=="tool_call")return;let o=rr.safeParse(r);if(!o.success){t.notifier.error("Unexpected message format",{scope:"system"});return}let i=o.data,s=this.delivery.decide(i.job_id);if(s.action==="ignore"){t.notifier.info(`Tool call ${i.job_id} is already running; ignoring the repeat`,{scope:"system"});return}if(s.action==="resend"){t.notifier.info(`Tool call ${i.job_id} already ran; re-sending the stored result`,{scope:"system"}),this.sendResult(t,i.job_id,s.text);return}t.bus.emit("tool:call",i),await this.handleToolCall(i,t)}}}sendResult(e,t,r){let{heldForRedelivery:o}=this.delivery.recordResult(t,r);e.bus.emit("ws:tx",{text:r}),o&&e.notifier.info(`Tool result for ${t} produced while disconnected; holding it for redelivery`,{scope:"system"})}redeliverPendingResults(e){let t=this.delivery.pendingRedeliveries();if(t.length!==0){e.notifier.info(`Re-sending ${t.length} tool result${t.length===1?"":"s"} produced while disconnected`,{scope:"system"});for(let r of t)e.bus.emit("ws:tx",{text:r.text}),this.delivery.markDelivered(r.jobId)}}async handleToolCall(e,t){let r=e.tool,o=e.job_id,i=An(e.args).set("workspace_id",e.workspace_id).set("device_id",e.device_id).set("context",e.context).value(),s=i.directory_id,a=t.engine.configurationContext.configuration,c=a.directories.map(f=>f.id).join(", ")||"none",u=a.directories.map(f=>f.path).join(", ")||"none";t.notifier.info(`Tool call: ${r} (job=${o}, directory_id=${s||"MISSING"}, available_ids=[${c}], available_paths=[${u}], directory_count=${a.directories.length})`,{scope:"system"}),t.notifier.info(`Executing: ${r}`);let d=Date.now();this.delivery.beginExecution(o);try{let p=await new nn(a).executeTool(r,i),m=na(o,r,p,d);nr.parse(m),this.sendResult(t,o,JSON.stringify(m));let g=$e(d),h=Po(r,o,p,g.execution_sec);h.ok?t.notifier.success(h.toString()):t.notifier.error(h.toString())}catch(f){let p=oa(o,r,f,d);nr.parse(p),this.sendResult(t,o,JSON.stringify(p));let m=$e(d),g={ok:!1,error:j(f)},h=Po(r,o,g,m.execution_sec);t.notifier.error(h.toString())}finally{this.delivery.endExecution(o)}}};var Lo=class extends Y{constructor(){super(new z({name:"tools-job",lane:"worker",priority:1e3,locks:[],maxAttempts:1,cancellable:!1}))}async run(e,t){t.notifier.info("Executing supported tools job");let o=t.engine.configurationContext.configuration.device?.id;if(!o){t.notifier.error("Cannot publish tools: device ID not available");return}let i={type:"tools_publish",device_id:o,tools:Mn};t.bus.emit("ws:tx",{text:JSON.stringify(i)}),t.notifier.success(`\u2192 tools_publish (count=${Mn.length})`)}},Mo=new Lo;function ia(){return new pe(Mo,void 0)}var $o=class extends Y{constructor(){super(new z({name:"directories-job",lane:"worker",priority:1e3,locks:[],maxAttempts:1,cancellable:!1}))}async run(e,t){t.notifier.info("Executing directories job");let r=t.engine.configurationContext.configuration,o=r.device?.id;if(!o){t.notifier.error("Cannot publish directories: device ID not available");return}let i=r.directories.map(a=>({id:a.id,name:a.name,path:bn(a.path)??a.name,path_hint:a.tag||void 0})),s={type:"directories_publish",device_id:o,directories:i};t.bus.emit("ws:tx",{text:JSON.stringify(s)}),t.notifier.success(`\u2192 directories_publish (dirs=${s.directories.length})`)}},Uo=new $o;function sa(){return new pe(Uo,void 0)}var an=class{name="meta-data-orchestrator";onRegister(e){e.engine.register(Mo),e.engine.register(Uo)}handlers(){return{"meta:data:requested:tools":async(e,t)=>{t.notifier.info("MetaData: tools requested -> dispatching supported tools job"),t.engine.dispatch(ia())},"meta:data:requested:directories":async(e,t)=>{t.notifier.info("MetaData: directories requested -> dispatching directories job"),t.engine.dispatch(sa())}}}};var cn=class{name="discovery-orchestrator";refreshInFlight=!1;noticeShown=null;handlers(){return{"config:loaded":async(e,t)=>{this.surfaceNotice(e.discovery,t),!jn(e.discovery)&&this.refresh(t,"cache-missing-or-expired")},"discovery:refresh:requested":async(e,t)=>{await this.refresh(t,e.reason)},"discovery:document:received":async(e,t)=>{this.adopt(Kn(e.document,e.source),t,e.source)},"discovery:cache:discarded":async(e,t)=>{let r=t.engine.configurationContext.configuration;if(!r.discovery)return;t.notifier.info(`Discovery: dropping cached endpoint (${e.reason})`,{scope:"system"});let o={...r,discovery:void 0};t.engine.configurationContext.loader.withDiscoveryCache(null),t.engine.applyConfiguration(o),t.bus.emit("config:save:requested",o)}}}async refresh(e,t){if(!this.refreshInFlight){this.refreshInFlight=!0;try{let r=e.engine.configurationContext.configuration,o=await Ei(r.controlBaseUrl);if(!o){e.notifier.info(`Discovery: no document available (${t})`,{scope:"system"});return}this.adopt(Kn(o,"well_known"),e,"well_known")}catch{return}finally{this.refreshInFlight=!1}}}adopt(e,t,r){if(!e)return;let o=t.engine.configurationContext.configuration,i=vi(o.discovery,e);if(!i||i===o.discovery){t.notifier.info(`Discovery: keeping the cached document (${r} was not newer)`,{scope:"system"});return}let s={...o,discovery:i};t.engine.configurationContext.loader.withDiscoveryCache(i),t.engine.applyConfiguration(s),t.bus.emit("config:save:requested",s),t.notifier.info(`Discovery: cached ${r} document issued_at=${i.issuedAt??"-"} bridge=${(i.bridgeUrls??[]).join(",")||"-"}`,{scope:"system"}),this.surfaceNotice(i,t)}surfaceNotice(e,t){let r=e?.notice;!r||this.noticeShown===r||(this.noticeShown=r,t.notifier.warn(r))}};fs(()=>[new Ur,new Hr,new jr,new Vr,new Yr,new Qr,new cn,new Jr,new sn,new an]);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@devicelink/dlink",
3
- "version": "0.4.0",
3
+ "version": "0.4.2",
4
4
  "description": "DeviceLink CLI agent — secure, local-first device access with explicit user consent",
5
5
  "private": false,
6
6
  "type": "module",