@dezycro-ai/agent-plugin 2.6.1 → 2.6.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 (2) hide show
  1. package/dist/cli/dezycro.js +21 -19
  2. package/package.json +1 -1
@@ -1,48 +1,50 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var qe=Object.create;var M=Object.defineProperty;var Ke=Object.getOwnPropertyDescriptor;var Ye=Object.getOwnPropertyNames;var Xe=Object.getPrototypeOf,Qe=Object.prototype.hasOwnProperty;var et=(o,e)=>{for(var t in e)M(o,t,{get:e[t],enumerable:!0})},we=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Ye(e))!Qe.call(o,r)&&r!==t&&M(o,r,{get:()=>e[r],enumerable:!(n=Ke(e,r))||n.enumerable});return o};var p=(o,e,t)=>(t=o!=null?qe(Xe(o)):{},we(e||!o||!o.__esModule?M(t,"default",{value:o,enumerable:!0}):t,o)),tt=o=>we(M({},"__esModule",{value:!0}),o);var mt={};et(mt,{Command:()=>Ve});module.exports=tt(mt);var Pe=p(require("node:http")),$=p(require("node:path")),N=p(require("node:fs")),Ae=p(require("node:os")),re=require("node:child_process");var S={MessageStart:"message_start",ContentBlockStart:"content_block_start",ContentBlockDelta:"content_block_delta",ContentBlockStop:"content_block_stop",MessageDelta:"message_delta",MessageStop:"message_stop"};var be={UpdateTask:"update_task"},Se={Status:"status"},Q={Done:"DONE",Pushed:"PUSHED"};var T={SpecPublished:"specPublished",VerifiedRecently:"verifiedRecently"};var P={Claude:"claude",Codex:"codex"},ee={Health:"/__dz/health",Stop:"/__dz/stop"},Te="last-opus-model";var z=p(require("fs")),xe=p(require("os")),v=p(require("path")),k=class o{constructor(e){this.repoRoot=e;this.config=o.readJson(v.join(e,".dezycro","config.json"))}repoRoot;config;static at(e=process.cwd()){return new o(o.findRepoRoot(e)??v.resolve(e))}get workspaceId(){return o.env("DZ_WORKSPACE_ID")??o.str(this.config?.workspaceId)}get tenantId(){return o.env("DZ_TENANT_ID")??o.str(this.config?.tenantId)}get projectId(){return o.str(this.config?.projectId)}agent(e){let t=this.agentNode(e);return{context1m:o.boolFlag("DZ_1M",t?.context1m),toolSearch:o.env("DZ_TOOL_SEARCH")??o.str(t?.toolSearch)}}agentNode(e){let t=this.config?.agents;if(!o.isObj(t))return null;let n=t[e];return o.isObj(n)?n:null}static boolFlag(e,t){let n=o.env(e);return n!==null?n==="1"||n.toLowerCase()==="true":t===!0}get apiUrl(){let e=o.env("DZ_API_URL");if(e)return o.trimSlash(e);let t=Array.isArray(this.config?.environments)?this.config?.environments:[],n=t.find(i=>o.isObj(i)&&i.default===!0)??t[0],r=o.isObj(n)?o.str(n.apiUrl):null;return r?o.trimSlash(r):null}get token(){let e=o.env("DZ_TOKEN");if(e)return e;let t=[v.join(this.repoRoot,".dezycro","companion-token.local.json"),v.join(xe.homedir(),".dezycro","token.json")];for(let n of t){let r=o.str(o.readJson(n)?.token);if(r)return r}return null}activeFeature(){let e=o.readJson(v.join(this.repoRoot,".dezycro","active-feature.json")),t=o.str(e?.featureId);if(!t)return null;let n=o.str(e?.workspaceId)??this.workspaceId;return n?{workspaceId:n,featureId:t,active:e?.active===!0}:null}connection(){let e=this.apiUrl;if(!e)return{error:"no apiUrl (set DZ_API_URL or .dezycro/config.json environments[].apiUrl)"};let t=this.workspaceId;if(!t)return{error:"no workspaceId (set DZ_WORKSPACE_ID or .dezycro/config.json workspaceId)"};let n=this.token;return n?{apiUrl:e,workspaceId:t,token:n}:{error:"no token (run `dezycro setup` or set DZ_TOKEN)"}}static findRepoRoot(e){let t=v.resolve(e||process.cwd());for(let n=0;n<64;n+=1){if(z.existsSync(v.join(t,".dezycro")))return t;let r=v.dirname(t);if(r===t)return null;t=r}return null}static readJson(e){try{return JSON.parse(z.readFileSync(e,"utf8"))}catch{return null}}static isObj(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}static str(e){return typeof e=="string"&&e.length>0?e:null}static env(e){let t=process.env[e];return t&&t.length>0?t:null}static trimSlash(e){return e.replace(/\/$/,"")}};var Ce=p(require("node:fs")),j=p(require("node:path"));var U=class{constructor(e){this.ctx=e}ctx;launchEnv(e){return{}}adjustArgs(e,t){return{rest:e}}get base(){return`http://127.0.0.1:${this.ctx.port}`}},te=class o extends U{gatewayEnv(){return{ANTHROPIC_BASE_URL:this.base}}launchEnv(e){let t={};return e.context1m&&!process.env.ANTHROPIC_DEFAULT_OPUS_MODEL&&(t.ANTHROPIC_DEFAULT_OPUS_MODEL=this.opusModelId()),e.toolSearch&&!process.env.ENABLE_TOOL_SEARCH&&(t.ENABLE_TOOL_SEARCH=e.toolSearch),t}adjustArgs(e,t){return o.isResume(e)?t.context1m?e.some(r=>r==="--model"||r==="-m"||r.startsWith("--model="))?{rest:e}:{rest:[...e,"--model",this.opusModelId()]}:{rest:e,notice:"dezycro: 1M context off \u2014 window caps at 200k on resume. Enable with DZ_1M=1 or agents.claude.context1m:true in .dezycro/config.json"}:{rest:e}}opusModelId(){return o.with1m(process.env.DZ_OPUS_MODEL||this.lastSeenOpusModel()||"claude-opus-4-8")}lastSeenOpusModel(){try{let e=j.join(j.dirname(this.ctx.stateFile),Te);return Ce.readFileSync(e,"utf8").trim()||null}catch{return null}}static isResume(e){return e.some(t=>["--resume","-r","--continue","-c"].includes(t))}static with1m(e){return e.includes("[")?e:`${e}[1m]`}},ne=class extends U{gatewayEnv(){return{OPENAI_BASE_URL:`${this.base}/v1`}}};function Re(o,e){switch(o){case P.Codex:return new ne(e);case P.Claude:default:return new te(e)}}var Ee=p(require("node:fs")),x=p(require("node:path")),A=class o{static MAX_DEPTH=6;static dir(){let e=__dirname;for(let t=0;t<o.MAX_DEPTH;t+=1){if(Ee.existsSync(x.join(e,"package.json")))return e;e=x.dirname(e)}return x.resolve(__dirname,"..","..")}static file(...e){return x.join(o.dir(),...e)}};var _=class o{static DEFAULT_SHIM_CMDS=["npm","pnpm","yarn","pip","pip3","poetry","apt-get","apt","brew","gem","bundle","mvn","gradle","make"];port=Number(process.env.DZ_PORT||13579);proxyPath=A.file("dist","gateway","proxy.js");compactPath=A.file("dist","gateway","compact-cli.js");async run(e){let t=this.applyPortFlag(e),n=t[0];if(n==="--stop"){console.error(await this.control(ee.Stop)?"dezycro: stopped":"dezycro: not running");return}if(n==="--status"){console.error(await this.health()?"dezycro: up":"dezycro: down");return}let r=n||P.Claude,i=t.slice(1),s=await this.ensureDaemon();console.error(s?`dezycro: gateway on :${this.port} \u2014 launching ${r}`:`dezycro: gateway unavailable \u2014 launching ${r} DIRECTLY (fail-open)`);let l=Re(r,{port:this.port,stateFile:this.stateFile()}),c=k.at(process.cwd()).agent(r);if(s){let d=l.adjustArgs(i,c);i=d.rest,d.notice&&console.error(d.notice)}let m=this.setupShims(),a={...process.env,...s?l.gatewayEnv():{},...s?l.launchEnv(c):{},...m?.env??{}},u=()=>{if(m)try{N.default.rmSync(m.dir,{recursive:!0,force:!0})}catch{}},f=(0,re.spawn)(r,i,{env:a,stdio:"inherit"});f.on("exit",d=>{u(),process.exit(d??0)}),f.on("error",d=>{u(),console.error(`dezycro: failed to launch ${r}: ${d.message}`),process.exit(127)})}applyPortFlag(e){let t=[];for(let n=0;n<e.length;n+=1){let r=e[n];if(r==="--port"){let i=Number(e[n+1]);e[n+1]!==void 0&&Number.isInteger(i)&&i>0&&(this.port=i,n+=1);continue}if(r.startsWith("--port=")){let i=Number(r.slice(7));Number.isInteger(i)&&i>0&&(this.port=i);continue}t.push(r)}return t}stateFile(){return process.env.DZ_STATE_FILE||$.default.join(process.cwd(),".dezycro","companion-state.json")}static with1m(e){return e.includes("[")?e:`${e}[1m]`}async ensureDaemon(){if(await this.health())return!0;let e={...process.env,PORT:String(this.port),INJECT:process.env.INJECT||"1",GATE:process.env.GATE||"0",CAPTURE:process.env.CAPTURE||"0",DZ_STATE_FILE:this.stateFile()};(0,re.spawn)(process.execPath,[this.proxyPath],{env:e,detached:!0,stdio:"ignore"}).unref();for(let n=0;n<30;n+=1){if(await this.health())return!0;await o.sleep(100)}return!1}setupShims(){if(process.env.DZ_NO_SHIM==="1"||process.env.DZ_SHIMS==="0")return null;let e=(process.env.DZ_SHIM_CMDS||o.DEFAULT_SHIM_CMDS.join(",")).split(",").map(t=>t.trim()).filter(Boolean);if(!e.length)return null;try{let t=N.default.mkdtempSync($.default.join(Ae.default.tmpdir(),"dz-shims-")),n=process.env.PATH||"";for(let r of e){let i=`#!/usr/bin/env bash
2
+ "use strict";var Ke=Object.create;var M=Object.defineProperty;var qe=Object.getOwnPropertyDescriptor;var Ye=Object.getOwnPropertyNames;var Xe=Object.getPrototypeOf,Qe=Object.prototype.hasOwnProperty;var et=(o,e)=>{for(var t in e)M(o,t,{get:e[t],enumerable:!0})},be=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Ye(e))!Qe.call(o,r)&&r!==t&&M(o,r,{get:()=>e[r],enumerable:!(n=qe(e,r))||n.enumerable});return o};var p=(o,e,t)=>(t=o!=null?Ke(Xe(o)):{},be(e||!o||!o.__esModule?M(t,"default",{value:o,enumerable:!0}):t,o)),tt=o=>be(M({},"__esModule",{value:!0}),o);var gt={};et(gt,{Command:()=>Ve});module.exports=tt(gt);var $e=p(require("node:http")),A=p(require("node:path")),N=p(require("node:fs")),Ae=p(require("node:os")),re=require("node:child_process");var S={MessageStart:"message_start",ContentBlockStart:"content_block_start",ContentBlockDelta:"content_block_delta",ContentBlockStop:"content_block_stop",MessageDelta:"message_delta",MessageStop:"message_stop"};var Se={UpdateTask:"update_task"},Te={Status:"status"},Q={Done:"DONE",Pushed:"PUSHED"};var T={SpecPublished:"specPublished",VerifiedRecently:"verifiedRecently"};var P={Claude:"claude",Codex:"codex"},ee={Health:"/__dz/health",Stop:"/__dz/stop"},xe="last-opus-model";var z=p(require("fs")),Ce=p(require("os")),v=p(require("path")),y=class o{constructor(e){this.repoRoot=e;this.config=o.readJson(v.join(e,".dezycro","config.json"))}repoRoot;config;static at(e=process.cwd()){return new o(o.findRepoRoot(e)??v.resolve(e))}get workspaceId(){return o.env("DZ_WORKSPACE_ID")??o.str(this.config?.workspaceId)}get tenantId(){return o.env("DZ_TENANT_ID")??o.str(this.config?.tenantId)}get projectId(){return o.str(this.config?.projectId)}agent(e){let t=this.agentNode(e);return{context1m:o.boolFlag("DZ_1M",t?.context1m),toolSearch:o.env("DZ_TOOL_SEARCH")??o.str(t?.toolSearch)}}agentNode(e){let t=this.config?.agents;if(!o.isObj(t))return null;let n=t[e];return o.isObj(n)?n:null}static boolFlag(e,t){let n=o.env(e);return n!==null?n==="1"||n.toLowerCase()==="true":t===!0}get apiUrl(){let e=o.env("DZ_API_URL");if(e)return o.trimSlash(e);let t=Array.isArray(this.config?.environments)?this.config?.environments:[],n=t.find(i=>o.isObj(i)&&i.default===!0)??t[0],r=o.isObj(n)?o.str(n.apiUrl):null;return r?o.trimSlash(r):null}get token(){let e=o.env("DZ_TOKEN");if(e)return e;let t=[v.join(this.repoRoot,".dezycro","companion-token.local.json"),v.join(Ce.homedir(),".dezycro","token.json")];for(let n of t){let r=o.str(o.readJson(n)?.token);if(r)return r}return null}activeFeature(){let e=o.readJson(v.join(this.repoRoot,".dezycro","active-feature.json")),t=o.str(e?.featureId);if(!t)return null;let n=o.str(e?.workspaceId)??this.workspaceId;return n?{workspaceId:n,featureId:t,active:e?.active===!0}:null}connection(){let e=this.apiUrl;if(!e)return{error:"no apiUrl (set DZ_API_URL or .dezycro/config.json environments[].apiUrl)"};let t=this.workspaceId;if(!t)return{error:"no workspaceId (set DZ_WORKSPACE_ID or .dezycro/config.json workspaceId)"};let n=this.token;return n?{apiUrl:e,workspaceId:t,token:n}:{error:"no token (run `dezycro setup` or set DZ_TOKEN)"}}static findRepoRoot(e){let t=v.resolve(e||process.cwd());for(let n=0;n<64;n+=1){if(z.existsSync(v.join(t,".dezycro")))return t;let r=v.dirname(t);if(r===t)return null;t=r}return null}static readJson(e){try{return JSON.parse(z.readFileSync(e,"utf8"))}catch{return null}}static isObj(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}static str(e){return typeof e=="string"&&e.length>0?e:null}static env(e){let t=process.env[e];return t&&t.length>0?t:null}static trimSlash(e){return e.replace(/\/$/,"")}};var Re=p(require("node:fs")),j=p(require("node:path"));var U=class{constructor(e){this.ctx=e}ctx;launchEnv(e){return{}}adjustArgs(e,t){return{rest:e}}get base(){return`http://127.0.0.1:${this.ctx.port}`}},te=class o extends U{gatewayEnv(){return{ANTHROPIC_BASE_URL:this.base}}launchEnv(e){let t={};return e.context1m&&!process.env.ANTHROPIC_DEFAULT_OPUS_MODEL&&(t.ANTHROPIC_DEFAULT_OPUS_MODEL=this.opusModelId()),e.toolSearch&&!process.env.ENABLE_TOOL_SEARCH&&(t.ENABLE_TOOL_SEARCH=e.toolSearch),t}adjustArgs(e,t){return o.isResume(e)?t.context1m?e.some(r=>r==="--model"||r==="-m"||r.startsWith("--model="))?{rest:e}:{rest:[...e,"--model",this.opusModelId()]}:{rest:e,notice:"dezycro: 1M context off \u2014 window caps at 200k on resume. Enable with DZ_1M=1 or agents.claude.context1m:true in .dezycro/config.json"}:{rest:e}}opusModelId(){return o.with1m(process.env.DZ_OPUS_MODEL||this.lastSeenOpusModel()||"claude-opus-4-8")}lastSeenOpusModel(){try{let e=j.join(j.dirname(this.ctx.stateFile),xe);return Re.readFileSync(e,"utf8").trim()||null}catch{return null}}static isResume(e){return e.some(t=>["--resume","-r","--continue","-c"].includes(t))}static with1m(e){return e.includes("[")?e:`${e}[1m]`}},ne=class extends U{gatewayEnv(){return{OPENAI_BASE_URL:`${this.base}/v1`}}};function Ee(o,e){switch(o){case P.Codex:return new ne(e);case P.Claude:default:return new te(e)}}var Pe=p(require("node:fs")),x=p(require("node:path")),$=class o{static MAX_DEPTH=6;static dir(){let e=__dirname;for(let t=0;t<o.MAX_DEPTH;t+=1){if(Pe.existsSync(x.join(e,"package.json")))return e;e=x.dirname(e)}return x.resolve(__dirname,"..","..")}static file(...e){return x.join(o.dir(),...e)}};var _=class o{static DEFAULT_SHIM_CMDS=["npm","pnpm","yarn","pip","pip3","poetry","apt-get","apt","brew","gem","bundle","mvn","gradle","make"];port=Number(process.env.DZ_PORT||13579);proxyPath=$.file("dist","gateway","proxy.js");compactPath=$.file("dist","gateway","compact-cli.js");async run(e){let t=this.applyPortFlag(e),n=t[0];if(n==="--stop"){console.error(await this.control(ee.Stop)?"dezycro: stopped":"dezycro: not running");return}if(n==="--status"){console.error(await this.health()?"dezycro: up":"dezycro: down");return}let r=n||P.Claude,i=t.slice(1),s=await this.ensureDaemon();console.error(s?`dezycro: gateway on :${this.port} \u2014 launching ${r}`:`dezycro: gateway unavailable \u2014 launching ${r} DIRECTLY (fail-open)`);let l=Ee(r,{port:this.port,stateFile:this.stateFile()}),c=y.at(process.cwd()).agent(r);if(s){let d=l.adjustArgs(i,c);i=d.rest,d.notice&&console.error(d.notice)}let h=this.setupShims(),a={...process.env,...s?l.gatewayEnv():{},...s?l.launchEnv(c):{},...h?.env??{}},u=()=>{if(h)try{N.default.rmSync(h.dir,{recursive:!0,force:!0})}catch{}},f=(0,re.spawn)(r,i,{env:a,stdio:"inherit"});f.on("exit",d=>{u(),process.exit(d??0)}),f.on("error",d=>{u(),console.error(`dezycro: failed to launch ${r}: ${d.message}`),process.exit(127)})}applyPortFlag(e){let t=[];for(let n=0;n<e.length;n+=1){let r=e[n];if(r==="--port"){let i=Number(e[n+1]);e[n+1]!==void 0&&Number.isInteger(i)&&i>0&&(this.port=i,n+=1);continue}if(r.startsWith("--port=")){let i=Number(r.slice(7));Number.isInteger(i)&&i>0&&(this.port=i);continue}t.push(r)}return t}stateFile(){return process.env.DZ_STATE_FILE||A.default.join(process.cwd(),".dezycro","companion-state.json")}static with1m(e){return e.includes("[")?e:`${e}[1m]`}async ensureDaemon(){if(await this.health())return!0;let e={...process.env,PORT:String(this.port),INJECT:process.env.INJECT||"1",GATE:process.env.GATE||"0",CAPTURE:process.env.CAPTURE||"0",DZ_STATE_FILE:this.stateFile()};(0,re.spawn)(process.execPath,[this.proxyPath],{env:e,detached:!0,stdio:"ignore"}).unref();for(let n=0;n<30;n+=1){if(await this.health())return!0;await o.sleep(100)}return!1}setupShims(){if(process.env.DZ_NO_SHIM==="1"||process.env.DZ_SHIMS==="0")return null;let e=(process.env.DZ_SHIM_CMDS||o.DEFAULT_SHIM_CMDS.join(",")).split(",").map(t=>t.trim()).filter(Boolean);if(!e.length)return null;try{let t=N.default.mkdtempSync(A.default.join(Ae.default.tmpdir(),"dz-shims-")),n=process.env.PATH||"";for(let r of e){let i=`#!/usr/bin/env bash
3
3
  real="$(PATH="$DZ_REAL_PATH" command -v ${r} 2>/dev/null)"
4
4
  if [ -z "$real" ] || [ "\${DZ_NO_SHIM:-0}" = "1" ]; then exec "${r}" "$@"; fi
5
5
  out="$("$real" "$@" 2>&1)"; rc=$?
6
6
  printf '%s\\n' "$out" | DZ_CMD=${r} node "$DZ_COMPACT_PATH"
7
7
  exit $rc
8
- `;N.default.writeFileSync($.default.join(t,r),i,{mode:493})}return{dir:t,env:{PATH:`${t}${$.default.delimiter}${n}`,DZ_REAL_PATH:n,DZ_COMPACT_PATH:this.compactPath}}}catch{return null}}health(){return this.get(ee.Health)}control(e){return this.get(e,()=>!0)}get(e,t=n=>n.statusCode===200){return new Promise(n=>{let r=Pe.default.get({host:"127.0.0.1",port:this.port,path:e,timeout:800},i=>{i.resume(),n(t(i))});r.on("error",()=>n(!1)),r.on("timeout",()=>{r.destroy(),n(!1)})})}static sleep(e){return new Promise(t=>setTimeout(t,e))}};var oe=require("child_process"),se=p(require("fs")),$e=p(require("os")),ie=p(require("path")),De=p(require("readline")),B=class o{static MCP_URL="https://mcp.dezycro.ai";run(){console.log(`
8
+ `;N.default.writeFileSync(A.default.join(t,r),i,{mode:493})}return{dir:t,env:{PATH:`${t}${A.default.delimiter}${n}`,DZ_REAL_PATH:n,DZ_COMPACT_PATH:this.compactPath}}}catch{return null}}health(){return this.get(ee.Health)}control(e){return this.get(e,()=>!0)}get(e,t=n=>n.statusCode===200){return new Promise(n=>{let r=$e.default.get({host:"127.0.0.1",port:this.port,path:e,timeout:800},i=>{i.resume(),n(t(i))});r.on("error",()=>n(!1)),r.on("timeout",()=>{r.destroy(),n(!1)})})}static sleep(e){return new Promise(t=>setTimeout(t,e))}};var oe=require("child_process"),se=p(require("fs")),De=p(require("os")),ie=p(require("path")),Ie=p(require("readline")),B=class o{static MCP_URL="https://mcp.dezycro.ai";run(){console.log(`
9
9
  Dezycro Setup`),console.log(` Get your API key from Dezycro \u2192 Settings \u2192 API Keys
10
- `);let e=De.default.createInterface({input:process.stdin,output:process.stdout});e.question(" API key (dzy_...): ",t=>{let n=(t||"").trim();(!n||!n.startsWith("dzy_"))&&(console.log(`
10
+ `);let e=Ie.default.createInterface({input:process.stdin,output:process.stdout});e.question(" API key (dzy_...): ",t=>{let n=(t||"").trim();(!n||!n.startsWith("dzy_"))&&(console.log(`
11
11
  Invalid key. Must start with dzy_
12
12
  `),e.close(),process.exit(1)),this.configureMcp(n),this.saveToken(n),console.log(`
13
13
  You're all set! In Claude Code run: /dezycro:import-features
14
14
  `),e.close()})}configureMcp(e){let t=`claude mcp add --transport http dezycro "${o.MCP_URL}/mcp" --header "Authorization: Bearer ${e}"`;try{try{(0,oe.execSync)("claude mcp remove dezycro",{stdio:"ignore"})}catch{}(0,oe.execSync)(t,{stdio:"inherit"}),console.log(`
15
15
  \u2713 Dezycro MCP configured`)}catch{console.error(`
16
16
  Failed to configure MCP. Run manually:`),console.error(` ${t}
17
- `)}}saveToken(e){try{let t=ie.default.join($e.default.homedir(),".dezycro"),n=ie.default.join(t,"token.json");se.default.mkdirSync(t,{recursive:!0,mode:448}),se.default.writeFileSync(n,JSON.stringify({token:e},null,2),{mode:384}),console.log(` \u2713 Companion token saved to ${n}`)}catch(t){console.error(` Failed to save companion token: ${t.message}`),console.error(` Drop it manually at ~/.dezycro/token.json: {"token": "${e}"}
18
- `)}}};var F=p(require("fs")),Ie=p(require("os")),Oe=require("child_process"),L=class o{static DEFAULT_PATH=".dezycro/auth.local.json";static PLACEHOLDER=/\$\{([A-Z0-9_]+)\}/g;run(e=o.DEFAULT_PATH){if(!F.default.existsSync(e)){this.warn(`no auth file at ${e}; emitting nothing`);return}let t;try{t=JSON.parse(F.default.readFileSync(e,"utf8"))}catch(i){this.warn(`parse error in ${e}: ${i.message}`),process.exit(1)}let n=this.resolveSecrets(t.secrets||{}),r=this.personaExports(t.personas||{},n);r.length&&process.stdout.write(r.join(`
17
+ `)}}saveToken(e){try{let t=ie.default.join(De.default.homedir(),".dezycro"),n=ie.default.join(t,"token.json");se.default.mkdirSync(t,{recursive:!0,mode:448}),se.default.writeFileSync(n,JSON.stringify({token:e},null,2),{mode:384}),console.log(` \u2713 Companion token saved to ${n}`)}catch(t){console.error(` Failed to save companion token: ${t.message}`),console.error(` Drop it manually at ~/.dezycro/token.json: {"token": "${e}"}
18
+ `)}}};var F=p(require("fs")),Oe=p(require("os")),Me=require("child_process"),L=class o{static DEFAULT_PATH=".dezycro/auth.local.json";static PLACEHOLDER=/\$\{([A-Z0-9_]+)\}/g;run(e=o.DEFAULT_PATH){if(!F.default.existsSync(e)){this.warn(`no auth file at ${e}; emitting nothing`);return}let t;try{t=JSON.parse(F.default.readFileSync(e,"utf8"))}catch(i){this.warn(`parse error in ${e}: ${i.message}`),process.exit(1)}let n=this.resolveSecrets(t.secrets||{}),r=this.personaExports(t.personas||{},n);r.length&&process.stdout.write(r.join(`
19
19
  `)+`
20
- `)}resolveSecrets(e){let t={};for(let[n,r]of Object.entries(e))try{t[n]=this.resolveSecret(r)}catch(i){this.warn(`secret ${n}: ${i.message}`)}return t}personaExports(e,t){let n=[];for(let[r,i]of Object.entries(e))if(!(!i||!i.envVar))try{let s=this.substitute(i.config||{},t);n.push(`export ${i.envVar}=${o.shQuote(JSON.stringify(s))}`)}catch(s){this.warn(`persona '${r}' skipped: ${s.message}`)}return n}resolveSecret(e){if(typeof e!="string")return e;if(e.startsWith("!file:")){let t=e.slice(6);return(t==="~"||t.startsWith("~/"))&&(t=Ie.default.homedir()+t.slice(1)),F.default.readFileSync(t,"utf8").trimEnd()}if(e.startsWith("!env:")){let t=e.slice(5);if(!(t in process.env))throw new Error(`env var not set: ${t}`);return process.env[t]}if(e.startsWith("!cmd:")){let t=e.slice(5),r=(0,Oe.execSync)(t,{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).trimEnd();if(!r)throw new Error(`empty stdout from: ${t}`);return r}return e}substitute(e,t){if(typeof e=="string")return e.replace(o.PLACEHOLDER,(n,r)=>{if(!(r in t))throw new Error(`\${${r}} not in secrets`);return String(t[r])});if(Array.isArray(e))return e.map(n=>this.substitute(n,t));if(e&&typeof e=="object"){let n={};for(let[r,i]of Object.entries(e))n[r]=this.substitute(i,t);return n}return e}warn(e){process.stderr.write(`[dezycro resolve-auth] ${e}
20
+ `)}resolveSecrets(e){let t={};for(let[n,r]of Object.entries(e))try{t[n]=this.resolveSecret(r)}catch(i){this.warn(`secret ${n}: ${i.message}`)}return t}personaExports(e,t){let n=[];for(let[r,i]of Object.entries(e))if(!(!i||!i.envVar))try{let s=this.substitute(i.config||{},t);n.push(`export ${i.envVar}=${o.shQuote(JSON.stringify(s))}`)}catch(s){this.warn(`persona '${r}' skipped: ${s.message}`)}return n}resolveSecret(e){if(typeof e!="string")return e;if(e.startsWith("!file:")){let t=e.slice(6);return(t==="~"||t.startsWith("~/"))&&(t=Oe.default.homedir()+t.slice(1)),F.default.readFileSync(t,"utf8").trimEnd()}if(e.startsWith("!env:")){let t=e.slice(5);if(!(t in process.env))throw new Error(`env var not set: ${t}`);return process.env[t]}if(e.startsWith("!cmd:")){let t=e.slice(5),r=(0,Me.execSync)(t,{encoding:"utf8",stdio:["ignore","pipe","pipe"]}).trimEnd();if(!r)throw new Error(`empty stdout from: ${t}`);return r}return e}substitute(e,t){if(typeof e=="string")return e.replace(o.PLACEHOLDER,(n,r)=>{if(!(r in t))throw new Error(`\${${r}} not in secrets`);return String(t[r])});if(Array.isArray(e))return e.map(n=>this.substitute(n,t));if(e&&typeof e=="object"){let n={};for(let[r,i]of Object.entries(e))n[r]=this.substitute(i,t);return n}return e}warn(e){process.stderr.write(`[dezycro resolve-auth] ${e}
21
21
  `)}static shQuote(e){return"'"+String(e).replaceAll("'","'\\''")+"'"}};var J=class o{run(e){let t=e[0],n=o.scriptFor(t);n===null&&(process.stderr.write(`Usage: dezycro completion <bash|zsh|fish>
22
22
  `),process.stderr.write(`Then load it in your shell, e.g.: eval "$(dezycro completion zsh)"
23
23
  `),process.exit(2)),process.stdout.write(n)}static scriptFor(e){switch(e){case"bash":return o.bash();case"zsh":return o.zsh();case"fish":return o.fish();default:return null}}static bash(){return["_dezycro() {"," local cur prev cmd",' cur="${COMP_WORDS[COMP_CWORD]}"',' prev="${COMP_WORDS[COMP_CWORD-1]}"',' if [ "$COMP_CWORD" -eq 1 ]; then',' COMPREPLY=( $(compgen -W "run setup resolve-auth completion help --help" -- "$cur") )'," return 0"," fi",' cmd="${COMP_WORDS[1]}"',' case "$cmd" in'," run)",' if [ "$prev" = "--port" ]; then return 0; fi',' COMPREPLY=( $(compgen -W "claude --status --stop --port" -- "$cur") ) ;;'," completion)",' COMPREPLY=( $(compgen -W "bash zsh fish" -- "$cur") ) ;;'," resolve-auth)",' COMPREPLY=( $(compgen -f -- "$cur") ) ;;'," esac"," return 0","}","complete -F _dezycro dezycro",""].join(`
24
24
  `)}static zsh(){return["_dezycro() {"," local -a commands"," commands=(run setup resolve-auth completion help)"," if (( CURRENT == 2 )); then"," compadd -- $commands"," return"," fi"," case ${words[2]} in"," run)"," if [[ ${words[CURRENT-1]} == --port ]]; then return; fi"," compadd -- claude --status --stop --port ;;"," completion) compadd -- bash zsh fish ;;"," resolve-auth) _files ;;"," esac","}","compdef _dezycro dezycro",""].join(`
25
25
  `)}static fish(){return["complete -c dezycro -f","complete -c dezycro -n __fish_use_subcommand -a run -d 'Run an agent through the gateway'","complete -c dezycro -n __fish_use_subcommand -a setup -d 'Configure the Dezycro MCP connection'","complete -c dezycro -n __fish_use_subcommand -a resolve-auth -d 'Print verifier credential exports'","complete -c dezycro -n __fish_use_subcommand -a completion -d 'Print a shell completion script'","complete -c dezycro -n '__fish_seen_subcommand_from run' -a 'claude --status --stop --port'","complete -c dezycro -n '__fish_seen_subcommand_from completion' -a 'bash zsh fish'",""].join(`
26
- `)}};var Be=p(require("node:path"));var H=p(require("node:fs")),Me=p(require("node:os")),C=p(require("node:path")),nt="DZ_METRICS_DIR",rt="DZ_METRICS",R=class o{file;constructor(e="gateway"){this.file=o.prepare(e)}static enabled(){return process.env[rt]!=="0"}static dir(){let e=process.env[nt];if(e)return e;let t=Me.homedir();switch(process.platform){case"win32":return C.join(process.env.LOCALAPPDATA||C.join(t,"AppData","Local"),"Dezycro","metrics");case"darwin":return C.join(t,"Library","Application Support","Dezycro","metrics");default:return C.join(process.env.XDG_STATE_HOME||C.join(t,".local","state"),"dezycro","metrics")}}record(e){if(this.file)try{H.appendFileSync(this.file,`${JSON.stringify({ts:new Date().toISOString(),...e})}
27
- `)}catch{}}static prepare(e){if(!o.enabled())return null;try{let t=o.dir();return H.mkdirSync(t,{recursive:!0}),C.join(t,`${e}.jsonl`)}catch{return null}}};var ot={rules:[{nameIncludes:be.UpdateTask,inputField:Se.Status,inputValues:[Q.Done,Q.Pushed],requireAll:[T.SpecPublished,T.VerifiedRecently],reason:"Cannot mark a task DONE/PUSHED yet."}]},ae=class o{constructor(e,t){this.policy=e;this.state=t}policy;state;static STATE_PREDICATES={[T.SpecPublished]:e=>!!e&&e.needsSpecPublish!==!0,[T.VerifiedRecently]:e=>!e||!e.lastVerifyCompletionTs?!1:e.lastEditTs?Date.parse(e.lastVerifyCompletionTs)>=Date.parse(e.lastEditTs):!0};static FAILED_HINT={[T.SpecPublished]:"spec not published (controller/API changed) \u2014 run /dezycro:publish-spec",[T.VerifiedRecently]:"no passing verify since last edit \u2014 run /dezycro:verify"};decide(e,t){for(let n of this.policy?.rules??[]){if(!e||!e.includes(n.nameIncludes))continue;if(n.inputField){let l=t?.[n.inputField],c=(n.inputValues??[]).map(m=>String(m).toUpperCase());if(l==null||!c.includes(String(l).toUpperCase()))continue}let r=n.requireAll??[];if(r.length===0)return this.blocked(e,n.reason);let i=r.filter(l=>!o.STATE_PREDICATES[l]?.(this.state));if(i.length===0)continue;let s=i.map(l=>o.FAILED_HINT[l]||l).join("; ");return this.blocked(e,`${n.reason||"Blocked by Dezycro policy."} ${s}.`)}return null}blocked(e,t){return{toolName:e||"?",detail:t||"Blocked by Dezycro policy."}}};var Lt=new Set([S.ContentBlockStart,S.ContentBlockDelta,S.ContentBlockStop]);var je=p(require("node:fs")),Ne=p(require("node:path"));var E=class o{static BIG_TOOL_CHARS=4e3;static defaultFile(){return Ne.join(R.dir(),"gateway.jsonl")}static fromFile(e=o.defaultFile()){let t;try{t=je.readFileSync(e,"utf8")}catch{return o.empty()}return o.aggregate(t.split(`
28
- `))}static aggregate(e){let t=o.empty();for(let n of e){let r=o.parse(n);r&&(r.type==="turn"?o.addTurn(t,r):r.type==="compaction"&&o.addCompaction(t,r),o.trackTime(t,r.ts))}return t}static addTurn(e,t){e.turns+=1,e.inputTokens+=o.num(t.inputTokens),e.outputTokens+=o.num(t.outputTokens),e.cacheReadTokens+=o.num(t.cacheReadTokens),e.cacheCreationTokens+=o.num(t.cacheCreationTokens),e.totalDurationMs+=o.num(t.durationMs),e.gateBlocks+=o.num(t.blockedToolCalls);let n=o.num(t.freshToolChars);if(e.maxFreshToolChars=Math.max(e.maxFreshToolChars,n),n>o.BIG_TOOL_CHARS&&(e.bigToolTurns+=1),e.maxToolDefChars=Math.max(e.maxToolDefChars,o.num(t.toolDefChars)),e.maxSystemChars=Math.max(e.maxSystemChars,o.num(t.systemChars)),e.tailResultChars+=o.num(t.tailResultChars),e.tailTextChars+=o.num(t.tailTextChars),e.maxCacheCreationTokens=Math.max(e.maxCacheCreationTokens,o.num(t.cacheCreationTokens)),typeof t.status=="number"&&t.status!==200&&(e.errorTurns+=1),o.bump(e.models,typeof t.model=="string"?t.model:"(unknown)"),Array.isArray(t.skillsTriggered))for(let r of t.skillsTriggered)o.bump(e.skillsTriggered,String(r))}static addCompaction(e,t){e.compactions+=1,e.charsSaved+=o.num(t.charsSaved),e.estTokensSaved+=o.num(t.estTokensSaved),e.linesElided+=o.num(t.elidedLines),o.bump(e.commands,typeof t.command=="string"?t.command:"(unknown)")}static trackTime(e,t){typeof t=="string"&&((!e.firstTs||t<e.firstTs)&&(e.firstTs=t),(!e.lastTs||t>e.lastTs)&&(e.lastTs=t))}static parse(e){if(!e.trim())return null;try{return JSON.parse(e)}catch{return null}}static bump(e,t){e[t]=(e[t]??0)+1}static num(e){return typeof e=="number"&&Number.isFinite(e)?e:0}static empty(){return{turns:0,inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheCreationTokens:0,totalDurationMs:0,errorTurns:0,gateBlocks:0,maxFreshToolChars:0,bigToolTurns:0,maxToolDefChars:0,maxSystemChars:0,tailResultChars:0,tailTextChars:0,maxCacheCreationTokens:0,models:{},skillsTriggered:{},compactions:0,charsSaved:0,estTokensSaved:0,linesElided:0,commands:{},firstTs:null,lastTs:null}}};var y=p(require("node:fs")),_e=p(require("node:path")),I=class o{apiUrl;workspaceId;token;metricsFile;cursorFile;batchSize;timeoutMs;fetchImpl;constructor(e){this.apiUrl=e.apiUrl,this.workspaceId=e.workspaceId,this.token=e.token,this.metricsFile=e.metricsFile,this.cursorFile=e.cursorFile,this.batchSize=e.batchSize??1e3,this.timeoutMs=e.timeoutMs??15e3,this.fetchImpl=e.fetchImpl??fetch}async upload({dryRun:e=!1}={}){let{lines:t,newOffset:n}=this.readNewLines(),r=o.toBatch(t),i=r.turns.length+r.compactions.length,s={turns:r.turns.length,compactions:r.compactions.length,newOffset:n,sent:!1,dryRun:e};return e?s:i===0?(n!==this.readCursor()&&this.writeCursor(n),s):(await this.postAll(r),this.writeCursor(n),{...s,sent:!0})}static toBatch(e){let t=[],n=[];for(let r of e){let i;try{i=JSON.parse(r)}catch{continue}typeof i.ts=="string"&&(i.type==="turn"?t.push(o.mapTurn(i)):i.type==="compaction"&&n.push(o.mapCompaction(i)))}return{turns:t,compactions:n}}static mapTurn(e){return{timestamp:e.ts,provider:e.provider??null,model:e.model??null,status:e.status??null,durationMs:e.durationMs??null,inputTokens:e.inputTokens??null,outputTokens:e.outputTokens??null,cacheReadTokens:e.cacheReadTokens??null,cacheCreationTokens:e.cacheCreationTokens??null,toolDefChars:e.toolDefChars??null,systemChars:e.systemChars??null,freshToolChars:e.freshToolChars??null,tailResultChars:e.tailResultChars??null,tailTextChars:e.tailTextChars??null,blockedToolCalls:e.blockedToolCalls??null,skillsFired:Array.isArray(e.skillsTriggered)?e.skillsTriggered:[]}}static mapCompaction(e){return{timestamp:e.ts,command:e.command??null,originalChars:e.originalChars??null,outputChars:e.outputChars??null,charsSaved:e.charsSaved??null,estTokensSaved:e.estTokensSaved??null,originalLines:e.originalLines??null,outputLines:e.outputLines??null,elidedLines:e.elidedLines??null}}readNewLines(){let e=this.readCursor(),t;try{t=y.statSync(this.metricsFile).size}catch{return{lines:[],newOffset:e}}if(e>t&&(e=0),e===t)return{lines:[],newOffset:e};let n=y.openSync(this.metricsFile,"r");try{let r=t-e,i=Buffer.alloc(r);y.readSync(n,i,0,r,e);let s=i.toString("utf8"),l=s.lastIndexOf(`
29
- `);if(l<0)return{lines:[],newOffset:e};let c=s.slice(0,l+1),m=e+Buffer.byteLength(c,"utf8");return{lines:c.split(`
30
- `).filter(u=>u.trim().length>0),newOffset:m}}finally{y.closeSync(n)}}readCursor(){try{let e=JSON.parse(y.readFileSync(this.cursorFile,"utf8"));return typeof e.offset=="number"&&e.offset>=0?e.offset:0}catch{return 0}}writeCursor(e){try{y.mkdirSync(_e.dirname(this.cursorFile),{recursive:!0}),y.writeFileSync(this.cursorFile,JSON.stringify({offset:e,uploadedAt:new Date().toISOString()}))}catch{}}async postAll(e){for(let t=0;t<e.turns.length;t+=this.batchSize)await this.postBatch({turns:e.turns.slice(t,t+this.batchSize),compactions:[]});for(let t=0;t<e.compactions.length;t+=this.batchSize)await this.postBatch({turns:[],compactions:e.compactions.slice(t,t+this.batchSize)})}async postBatch(e){let t=`${this.apiUrl}/api/v1/workspaces/${this.workspaceId}/usage-telemetry`,n=new AbortController,r=setTimeout(()=>n.abort(),this.timeoutMs);try{let i=await this.fetchImpl(t,{method:"POST",headers:{Authorization:`Bearer ${this.token}`,"content-type":"application/json",accept:"application/json"},body:JSON.stringify(e),signal:n.signal});if(!i.ok)throw new Error(`usage-telemetry upload returned ${i.status}`)}finally{clearTimeout(r)}}};var W=class o{run(e){if(e.includes("--upload-dry-run")){this.uploadDryRun();return}let t=E.defaultFile(),n=E.fromFile(t);if(e.includes("--json")){process.stdout.write(`${JSON.stringify(n,null,2)}
26
+ `)}};var Fe=p(require("node:path"));var W=p(require("node:fs")),ze=p(require("node:os")),C=p(require("node:path")),nt="DZ_METRICS_DIR",rt="DZ_METRICS",R=class o{file;constructor(e="gateway"){this.file=o.prepare(e)}static enabled(){return process.env[rt]!=="0"}static dir(){let e=process.env[nt];if(e)return e;let t=ze.homedir();switch(process.platform){case"win32":return C.join(process.env.LOCALAPPDATA||C.join(t,"AppData","Local"),"Dezycro","metrics");case"darwin":return C.join(t,"Library","Application Support","Dezycro","metrics");default:return C.join(process.env.XDG_STATE_HOME||C.join(t,".local","state"),"dezycro","metrics")}}record(e){if(this.file)try{W.appendFileSync(this.file,`${JSON.stringify({ts:new Date().toISOString(),...e})}
27
+ `)}catch{}}static prepare(e){if(!o.enabled())return null;try{let t=o.dir();return W.mkdirSync(t,{recursive:!0}),C.join(t,`${e}.jsonl`)}catch{return null}}};var ot={rules:[{nameIncludes:Se.UpdateTask,inputField:Te.Status,inputValues:[Q.Done,Q.Pushed],requireAll:[T.SpecPublished,T.VerifiedRecently],reason:"Cannot mark a task DONE/PUSHED yet."}]},ae=class o{constructor(e,t){this.policy=e;this.state=t}policy;state;static STATE_PREDICATES={[T.SpecPublished]:e=>!!e&&e.needsSpecPublish!==!0,[T.VerifiedRecently]:e=>!e||!e.lastVerifyCompletionTs?!1:e.lastEditTs?Date.parse(e.lastVerifyCompletionTs)>=Date.parse(e.lastEditTs):!0};static FAILED_HINT={[T.SpecPublished]:"spec not published (controller/API changed) \u2014 run /dezycro:publish-spec",[T.VerifiedRecently]:"no passing verify since last edit \u2014 run /dezycro:verify"};decide(e,t){for(let n of this.policy?.rules??[]){if(!e||!e.includes(n.nameIncludes))continue;if(n.inputField){let l=t?.[n.inputField],c=(n.inputValues??[]).map(h=>String(h).toUpperCase());if(l==null||!c.includes(String(l).toUpperCase()))continue}let r=n.requireAll??[];if(r.length===0)return this.blocked(e,n.reason);let i=r.filter(l=>!o.STATE_PREDICATES[l]?.(this.state));if(i.length===0)continue;let s=i.map(l=>o.FAILED_HINT[l]||l).join("; ");return this.blocked(e,`${n.reason||"Blocked by Dezycro policy."} ${s}.`)}return null}blocked(e,t){return{toolName:e||"?",detail:t||"Blocked by Dezycro policy."}}};var Jt=new Set([S.ContentBlockStart,S.ContentBlockDelta,S.ContentBlockStop]);var Ne=p(require("node:fs")),_e=p(require("node:path"));var E=class o{static BIG_TOOL_CHARS=4e3;static defaultFile(){return _e.join(R.dir(),"gateway.jsonl")}static fromFile(e=o.defaultFile()){let t;try{t=Ne.readFileSync(e,"utf8")}catch{return o.empty()}return o.aggregate(t.split(`
28
+ `))}static aggregate(e){let t=o.empty();for(let n of e){let r=o.parse(n);r&&(r.type==="turn"?o.addTurn(t,r):r.type==="compaction"&&o.addCompaction(t,r),o.trackTime(t,r.ts))}return t}static addTurn(e,t){e.turns+=1,e.inputTokens+=o.num(t.inputTokens),e.outputTokens+=o.num(t.outputTokens),e.cacheReadTokens+=o.num(t.cacheReadTokens),e.cacheCreationTokens+=o.num(t.cacheCreationTokens),e.totalDurationMs+=o.num(t.durationMs),e.gateBlocks+=o.num(t.blockedToolCalls);let n=o.num(t.freshToolChars);if(e.maxFreshToolChars=Math.max(e.maxFreshToolChars,n),n>o.BIG_TOOL_CHARS&&(e.bigToolTurns+=1),e.maxToolDefChars=Math.max(e.maxToolDefChars,o.num(t.toolDefChars)),e.maxSystemChars=Math.max(e.maxSystemChars,o.num(t.systemChars)),e.tailResultChars+=o.num(t.tailResultChars),e.tailTextChars+=o.num(t.tailTextChars),e.maxCacheCreationTokens=Math.max(e.maxCacheCreationTokens,o.num(t.cacheCreationTokens)),typeof t.status=="number"&&t.status!==200&&(e.errorTurns+=1),o.bump(e.models,typeof t.model=="string"?t.model:"(unknown)"),Array.isArray(t.skillsTriggered))for(let r of t.skillsTriggered)o.bump(e.skillsTriggered,String(r))}static addCompaction(e,t){e.compactions+=1,e.charsSaved+=o.num(t.charsSaved),e.estTokensSaved+=o.num(t.estTokensSaved),e.linesElided+=o.num(t.elidedLines),o.bump(e.commands,typeof t.command=="string"?t.command:"(unknown)")}static trackTime(e,t){typeof t=="string"&&((!e.firstTs||t<e.firstTs)&&(e.firstTs=t),(!e.lastTs||t>e.lastTs)&&(e.lastTs=t))}static parse(e){if(!e.trim())return null;try{return JSON.parse(e)}catch{return null}}static bump(e,t){e[t]=(e[t]??0)+1}static num(e){return typeof e=="number"&&Number.isFinite(e)?e:0}static empty(){return{turns:0,inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheCreationTokens:0,totalDurationMs:0,errorTurns:0,gateBlocks:0,maxFreshToolChars:0,bigToolTurns:0,maxToolDefChars:0,maxSystemChars:0,tailResultChars:0,tailTextChars:0,maxCacheCreationTokens:0,models:{},skillsTriggered:{},compactions:0,charsSaved:0,estTokensSaved:0,linesElided:0,commands:{},firstTs:null,lastTs:null}}};var k=p(require("node:fs")),Be=p(require("node:path")),I=class o{apiUrl;workspaceId;token;metricsFile;cursorFile;batchSize;timeoutMs;fetchImpl;constructor(e){this.apiUrl=e.apiUrl,this.workspaceId=e.workspaceId,this.token=e.token,this.metricsFile=e.metricsFile,this.cursorFile=e.cursorFile,this.batchSize=e.batchSize??1e3,this.timeoutMs=e.timeoutMs??15e3,this.fetchImpl=e.fetchImpl??fetch}async upload({dryRun:e=!1}={}){let{lines:t,newOffset:n}=this.readNewLines(),r=o.toBatch(t),i=r.turns.length+r.compactions.length,s={turns:r.turns.length,compactions:r.compactions.length,newOffset:n,sent:!1,dryRun:e};return e?s:i===0?(n!==this.readCursor()&&this.writeCursor(n),s):(await this.postAll(r),this.writeCursor(n),{...s,sent:!0})}static toBatch(e){let t=[],n=[];for(let r of e){let i;try{i=JSON.parse(r)}catch{continue}typeof i.ts=="string"&&(i.type==="turn"?t.push(o.mapTurn(i)):i.type==="compaction"&&n.push(o.mapCompaction(i)))}return{turns:t,compactions:n}}static mapTurn(e){return{timestamp:e.ts,provider:e.provider??null,model:e.model??null,status:e.status??null,durationMs:e.durationMs??null,inputTokens:e.inputTokens??null,outputTokens:e.outputTokens??null,cacheReadTokens:e.cacheReadTokens??null,cacheCreationTokens:e.cacheCreationTokens??null,toolDefChars:e.toolDefChars??null,systemChars:e.systemChars??null,freshToolChars:e.freshToolChars??null,tailResultChars:e.tailResultChars??null,tailTextChars:e.tailTextChars??null,blockedToolCalls:e.blockedToolCalls??null,skillsFired:Array.isArray(e.skillsTriggered)?e.skillsTriggered:[]}}static mapCompaction(e){return{timestamp:e.ts,command:e.command??null,originalChars:e.originalChars??null,outputChars:e.outputChars??null,charsSaved:e.charsSaved??null,estTokensSaved:e.estTokensSaved??null,originalLines:e.originalLines??null,outputLines:e.outputLines??null,elidedLines:e.elidedLines??null}}readNewLines(){let e=this.readCursor(),t;try{t=k.statSync(this.metricsFile).size}catch{return{lines:[],newOffset:e}}if(e>t&&(e=0),e===t)return{lines:[],newOffset:e};let n=k.openSync(this.metricsFile,"r");try{let r=t-e,i=Buffer.alloc(r);k.readSync(n,i,0,r,e);let s=i.toString("utf8"),l=s.lastIndexOf(`
29
+ `);if(l<0)return{lines:[],newOffset:e};let c=s.slice(0,l+1),h=e+Buffer.byteLength(c,"utf8");return{lines:c.split(`
30
+ `).filter(u=>u.trim().length>0),newOffset:h}}finally{k.closeSync(n)}}readCursor(){try{let e=JSON.parse(k.readFileSync(this.cursorFile,"utf8"));return typeof e.offset=="number"&&e.offset>=0?e.offset:0}catch{return 0}}writeCursor(e){try{k.mkdirSync(Be.dirname(this.cursorFile),{recursive:!0}),k.writeFileSync(this.cursorFile,JSON.stringify({offset:e,uploadedAt:new Date().toISOString()}))}catch{}}async postAll(e){for(let t=0;t<e.turns.length;t+=this.batchSize)await this.postBatch({turns:e.turns.slice(t,t+this.batchSize),compactions:[]});for(let t=0;t<e.compactions.length;t+=this.batchSize)await this.postBatch({turns:[],compactions:e.compactions.slice(t,t+this.batchSize)})}async postBatch(e){let t=`${this.apiUrl}/api/v1/workspaces/${this.workspaceId}/usage-telemetry`,n=new AbortController,r=setTimeout(()=>n.abort(),this.timeoutMs);try{let i=await this.fetchImpl(t,{method:"POST",headers:{Authorization:`Bearer ${this.token}`,"content-type":"application/json",accept:"application/json"},body:JSON.stringify(e),signal:n.signal});if(!i.ok)throw new Error(`usage-telemetry upload returned ${i.status}`)}finally{clearTimeout(r)}}};var H=class o{run(e){if(e.includes("--upload-dry-run")){this.uploadDryRun();return}let t=E.defaultFile(),n=E.fromFile(t);if(e.includes("--json")){process.stdout.write(`${JSON.stringify(n,null,2)}
31
31
  `);return}process.stdout.write(o.format(n,t))}async uploadDryRun(){let e=c=>{process.stdout.write(`${c}
32
- `)},t=k.at(process.cwd()),n=t.connection(),r=E.defaultFile(),i=Be.join(R.dir(),"gateway.upload-cursor.json"),s="error"in n?{apiUrl:"(unset)",workspaceId:t.workspaceId??"(unset)",token:"(unset)"}:n,l=await new I({...s,metricsFile:r,cursorFile:i}).upload({dryRun:!0});e("Dezycro telemetry \u2014 dry run (nothing sent)"),e(` metrics file ${r}`),e(` target ${s.apiUrl}/api/v1/workspaces/${s.workspaceId}/usage-telemetry`),"error"in n&&e(` connection NOT configured \u2014 ${n.error}`),e(` pending upload ${l.turns} turn + ${l.compactions} compaction event(s) since the cursor`)}static format(e,t){if(e.turns===0&&e.compactions===0)return`No metrics yet at ${t}
32
+ `)},t=y.at(process.cwd()),n=t.connection(),r=E.defaultFile(),i=Fe.join(R.dir(),"gateway.upload-cursor.json"),s="error"in n?{apiUrl:"(unset)",workspaceId:t.workspaceId??"(unset)",token:"(unset)"}:n,l=await new I({...s,metricsFile:r,cursorFile:i}).upload({dryRun:!0});e("Dezycro telemetry \u2014 dry run (nothing sent)"),e(` metrics file ${r}`),e(` target ${s.apiUrl}/api/v1/workspaces/${s.workspaceId}/usage-telemetry`),"error"in n&&e(` connection NOT configured \u2014 ${n.error}`),e(` pending upload ${l.turns} turn + ${l.compactions} compaction event(s) since the cursor`)}static format(e,t){if(e.turns===0&&e.compactions===0)return`No metrics yet at ${t}
33
33
  (They're written as you run agents through \`dezycro run\`. DZ_METRICS=0 disables.)
34
34
  `;let n=c=>c.toLocaleString("en-US"),r=c=>n(Math.round(c/4)),i=c=>e.turns>0?n(Math.round(c/e.turns)):"0",s=[];s.push("Dezycro gateway metrics"),s.push(` ${t}`),e.firstTs&&e.lastTs&&s.push(` ${e.firstTs} \u2192 ${e.lastTs}`),s.push(""),s.push(`Turns: ${n(e.turns)} errors: ${n(e.errorTurns)} model time: ${(e.totalDurationMs/1e3).toFixed(0)}s`);let l=[`fresh input ~${i(e.inputTokens)} tok/turn`,`output ~${i(e.outputTokens)} tok/turn`];if(e.cacheReadTokens+e.inputTokens>0){let c=100*e.cacheReadTokens/(e.cacheReadTokens+e.inputTokens);l.push(`cache hit ${c.toFixed(1)}%`)}return s.push(l.join(" \xB7 ")),s.push(""),s.push("Where the tokens are (per request \u2014 content-free)"),s.push(` tool definitions ${n(e.maxToolDefChars)} chars (~${r(e.maxToolDefChars)} tok) \u2190 fixed per-request cost; schema-bloat lever`),s.push(` system prompt ${n(e.maxSystemChars)} chars (~${r(e.maxSystemChars)} tok)`),s.push(` fresh tool results ${n(e.tailResultChars)} chars (~${r(e.tailResultChars)} tok) total \xB7 biggest single ${n(e.maxFreshToolChars)} chars (~${r(e.maxFreshToolChars)} tok)`),s.push(` fresh user text ${n(e.tailTextChars)} chars (~${r(e.tailTextChars)} tok) total`),s.push(""),s.push("Cache"),s.push(` read ${n(e.cacheReadTokens)} tok \xB7 create ${n(e.cacheCreationTokens)} tok`),e.maxCacheCreationTokens>0&&s.push(` largest prefix write ${n(e.maxCacheCreationTokens)} tok (a spike here = cache-bust \u2014 the costly case)`),s.push(""),s.push("Request-side compaction opportunity (not yet compacted)"),s.push(` turns with >1k-tok fresh tool output ${n(e.bigToolTurns)}`),s.push(" (fresh tool results are the safe headroom; reversible elision is the lever \u2014 needs sizing first)"),s.push(""),s.push("Source-side compaction (shell output \u2014 already applied)"),s.push(` est. tokens saved ${n(e.estTokensSaved)} over ${n(e.compactions)} compaction(s)${o.breakdown(e.commands)}`),s.push(` lines elided ${n(e.linesElided)}`),s.push(""),s.push(`Totals: input ${n(e.inputTokens)} \xB7 output ${n(e.outputTokens)} \xB7 cache read ${n(e.cacheReadTokens)} \xB7 cache create ${n(e.cacheCreationTokens)}`),s.push(`Gate blocks: ${n(e.gateBlocks)}`),s.push(`Skills fired:${o.breakdown(e.skillsTriggered)||" none"}`),s.push(`Models:${o.breakdown(e.models)||" (none)"}`),s.push(""),`${s.join(`
35
35
  `)}
36
- `}static breakdown(e){let t=Object.entries(e).sort((n,r)=>r[1]-n[1]);return t.length===0?"":` ${t.map(([n,r])=>`${n}=${r}`).join(", ")}`}};var le=class{now(){return Date.now()}nowIso(){return new Date().toISOString()}sleep(e){return new Promise(t=>setTimeout(t,e))}},ue=class{constructor(e,t,n,r,i){this.apiUrl=e;this.workspaceId=t;this.featureId=n;this.token=r;this.eventTypes=i}apiUrl;workspaceId;featureId;token;eventTypes;async wait(e,t){let n=new URL(`${this.apiUrl}/api/v1/workspaces/${this.workspaceId}/features/${this.featureId}/inbox/wait`);this.eventTypes&&n.searchParams.set("eventTypes",this.eventTypes),n.searchParams.set("since",e),n.searchParams.set("timeoutSec",String(t));let r=new AbortController,i=setTimeout(()=>r.abort(),(t+10)*1e3);try{let s=await fetch(n.toString(),{method:"GET",headers:{Authorization:`Bearer ${this.token}`,Accept:"application/json"},signal:r.signal});if(!s.ok)throw new Error(`inbox/wait returned ${s.status}`);let l=await s.json();return{nextCursor:typeof l.nextCursor=="string"?l.nextCursor:e,events:Array.isArray(l.events)?l.events:[]}}finally{clearTimeout(i)}}},Z=class{constructor(e,t=30,n=1e3){this.totalTimeoutSec=e;this.perPollSec=t;this.errorBackoffMs=n}totalTimeoutSec;perPollSec;errorBackoffMs;static DEFAULT_TOTAL_TIMEOUT_SEC=600},pe=class{constructor(e,t,n){this.gateway=e;this.clock=t;this.policy=n}gateway;clock;policy;async awaitEvent(){let e=this.clock.now()+this.policy.totalTimeoutSec*1e3,t=this.clock.nowIso(),n=!1,r="";for(;this.clock.now()<e;){let i=Math.ceil((e-this.clock.now())/1e3);if(i<=0)break;let s=Math.min(this.policy.perPollSec,i);try{let l=await this.gateway.wait(t,s);n=!0;let[c]=l.events;if(c)return{outcome:"EVENT",event:c};t=l.nextCursor||t}catch(l){r=l instanceof Error?l.message:String(l),this.clock.now()<e&&await this.clock.sleep(this.policy.errorBackoffMs)}}return n?{outcome:"TIMEOUT"}:{outcome:"ERROR",error:r||"event wait failed"}}},de=class{constructor(e,t,n){this.result=e;this.eventTypes=t;this.timeoutSec=n}result;eventTypes;timeoutSec;render(){switch(this.result.outcome){case"EVENT":return JSON.stringify(this.result.event);case"TIMEOUT":return`TIMEOUT: no ${this.eventTypes??"any"} event within ${this.timeoutSec}s.`;case"ERROR":return`ERROR: ${this.result.error??"unknown"}`}}exitCode(){switch(this.result.outcome){case"EVENT":return 0;case"TIMEOUT":return 5;case"ERROR":return 2}}},fe=class o{constructor(e,t,n,r){this.eventTypes=e;this.feature=t;this.timeoutSec=n;this.json=r}eventTypes;feature;timeoutSec;json;static fromArgv(e){let t=null,n=null,r=Z.DEFAULT_TOTAL_TIMEOUT_SEC,i=!1;for(let s=0;s<e.length;s+=1){let l=e[s];if(l==="--event-types")t=e[s+1]??null,s+=1;else if(l==="--feature")n=e[s+1]??null,s+=1;else if(l==="--timeout"){let c=Number(e[s+1]);Number.isFinite(c)&&c>0&&(r=c),s+=1}else l==="--json"&&(i=!0)}return new o(t,n,r,i)}},G=class{constructor(e=new le){this.clock=e}clock;async run(e){let t=fe.fromArgv(e),n=k.at(process.cwd()),r=n.connection();if("error"in r){this.fail(`not configured \u2014 ${r.error}`);return}let i=t.feature??n.activeFeature()?.featureId??null;if(!i){this.fail("no feature (pass --feature <id>, or run /dezycro:work to bind one)");return}let s=new ue(r.apiUrl,r.workspaceId,i,r.token,t.eventTypes),l=await new pe(s,this.clock,new Z(t.timeoutSec)).awaitEvent(),c=new de(l,t.eventTypes,t.timeoutSec);process.stdout.write(`${t.json?JSON.stringify(l):c.render()}
36
+ `}static breakdown(e){let t=Object.entries(e).sort((n,r)=>r[1]-n[1]);return t.length===0?"":` ${t.map(([n,r])=>`${n}=${r}`).join(", ")}`}};var le=class{now(){return Date.now()}nowIso(){return new Date().toISOString()}sleep(e){return new Promise(t=>setTimeout(t,e))}},ue=class{constructor(e,t,n,r,i){this.apiUrl=e;this.workspaceId=t;this.featureId=n;this.token=r;this.eventTypes=i}apiUrl;workspaceId;featureId;token;eventTypes;async wait(e,t){let n=new URL(`${this.apiUrl}/api/v1/workspaces/${this.workspaceId}/features/${this.featureId}/inbox/wait`);this.eventTypes&&n.searchParams.set("eventTypes",this.eventTypes),n.searchParams.set("since",e),n.searchParams.set("timeoutSec",String(t));let r=new AbortController,i=setTimeout(()=>r.abort(),(t+10)*1e3);try{let s=await fetch(n.toString(),{method:"GET",headers:{Authorization:`Bearer ${this.token}`,Accept:"application/json"},signal:r.signal});if(!s.ok)throw new Error(`inbox/wait returned ${s.status}`);let l=await s.json();return{nextCursor:typeof l.nextCursor=="string"?l.nextCursor:e,events:Array.isArray(l.events)?l.events:[]}}finally{clearTimeout(i)}}},Z=class{constructor(e,t=30,n=1e3){this.totalTimeoutSec=e;this.perPollSec=t;this.errorBackoffMs=n}totalTimeoutSec;perPollSec;errorBackoffMs;static DEFAULT_TOTAL_TIMEOUT_SEC=600},pe=class{constructor(e,t,n){this.gateway=e;this.clock=t;this.policy=n}gateway;clock;policy;async awaitEvent(){let e=this.clock.now()+this.policy.totalTimeoutSec*1e3,t=this.clock.nowIso(),n=!1,r="";for(;this.clock.now()<e;){let i=Math.ceil((e-this.clock.now())/1e3);if(i<=0)break;let s=Math.min(this.policy.perPollSec,i);try{let l=await this.gateway.wait(t,s);n=!0;let[c]=l.events;if(c)return{outcome:"EVENT",event:c};t=l.nextCursor||t}catch(l){r=l instanceof Error?l.message:String(l),this.clock.now()<e&&await this.clock.sleep(this.policy.errorBackoffMs)}}return n?{outcome:"TIMEOUT"}:{outcome:"ERROR",error:r||"event wait failed"}}},de=class{constructor(e,t,n){this.result=e;this.eventTypes=t;this.timeoutSec=n}result;eventTypes;timeoutSec;render(){switch(this.result.outcome){case"EVENT":return JSON.stringify(this.result.event);case"TIMEOUT":return`TIMEOUT: no ${this.eventTypes??"any"} event within ${this.timeoutSec}s.`;case"ERROR":return`ERROR: ${this.result.error??"unknown"}`}}exitCode(){switch(this.result.outcome){case"EVENT":return 0;case"TIMEOUT":return 5;case"ERROR":return 2}}},fe=class o{constructor(e,t,n,r){this.eventTypes=e;this.feature=t;this.timeoutSec=n;this.json=r}eventTypes;feature;timeoutSec;json;static fromArgv(e){let t=null,n=null,r=Z.DEFAULT_TOTAL_TIMEOUT_SEC,i=!1;for(let s=0;s<e.length;s+=1){let l=e[s];if(l==="--event-types")t=e[s+1]??null,s+=1;else if(l==="--feature")n=e[s+1]??null,s+=1;else if(l==="--timeout"){let c=Number(e[s+1]);Number.isFinite(c)&&c>0&&(r=c),s+=1}else l==="--json"&&(i=!0)}return new o(t,n,r,i)}},G=class{constructor(e=new le){this.clock=e}clock;async run(e){let t=fe.fromArgv(e),n=y.at(process.cwd()),r=n.connection();if("error"in r){this.fail(`not configured \u2014 ${r.error}`);return}let i=t.feature??n.activeFeature()?.featureId??null;if(!i){this.fail("no feature (pass --feature <id>, or run /dezycro:work to bind one)");return}let s=new ue(r.apiUrl,r.workspaceId,i,r.token,t.eventTypes),l=await new pe(s,this.clock,new Z(t.timeoutSec)).awaitEvent(),c=new de(l,t.eventTypes,t.timeoutSec);process.stdout.write(`${t.json?JSON.stringify(l):c.render()}
37
37
  `),process.exit(c.exitCode())}fail(e){process.stderr.write(`dezycro await-event: ${e}
38
- `),process.exit(2)}};var b=p(require("fs")),Fe=p(require("path"));var V=class{file;constructor(e){this.file=Fe.join(e,".dezycro","active-feature.json")}read(){try{let e=JSON.parse(b.readFileSync(this.file,"utf8")),t=typeof e.featureId=="string"?e.featureId:null;return t?{featureId:t,featureName:typeof e.featureName=="string"?e.featureName:void 0,workspaceId:typeof e.workspaceId=="string"?e.workspaceId:void 0,selectedAt:typeof e.selectedAt=="string"?e.selectedAt:void 0,active:e.active===!0}:null}catch{return null}}setActive(e){let t=this.read();if(!t||(t.active??!1)===e)return!1;try{return b.writeFileSync(this.file,`${JSON.stringify({...t,active:e},null,2)}
39
- `),!0}catch{return!1}}clear(){try{if(b.existsSync(this.file))return b.unlinkSync(this.file),!0}catch{}return!1}};var q=class{run(e){let t=k.at(process.cwd()).repoRoot,n=new V(t);if(e.includes("--clear")){let s=n.read()!==null;n.clear(),process.stdout.write(s?`dezycro: active feature cleared.
38
+ `),process.exit(2)}};var b=p(require("fs")),Le=p(require("path"));var V=class{file;constructor(e){this.file=Le.join(e,".dezycro","active-feature.json")}read(){try{let e=JSON.parse(b.readFileSync(this.file,"utf8")),t=typeof e.featureId=="string"?e.featureId:null;return t?{featureId:t,featureName:typeof e.featureName=="string"?e.featureName:void 0,workspaceId:typeof e.workspaceId=="string"?e.workspaceId:void 0,selectedAt:typeof e.selectedAt=="string"?e.selectedAt:void 0,active:e.active===!0}:null}catch{return null}}setActive(e){let t=this.read();if(!t||(t.active??!1)===e)return!1;try{return b.writeFileSync(this.file,`${JSON.stringify({...t,active:e},null,2)}
39
+ `),!0}catch{return!1}}clear(){try{if(b.existsSync(this.file))return b.unlinkSync(this.file),!0}catch{}return!1}};var K=class{run(e){let t=y.at(process.cwd()).repoRoot,n=new V(t);if(e.includes("--clear")){let s=n.read()!==null;n.clear(),process.stdout.write(s?`dezycro: active feature cleared.
40
40
  `:`dezycro: no active feature to clear.
41
41
  `);return}let r=n.read();if(!r){process.stdout.write(`dezycro: no active feature bound (run /dezycro:work to bind one).
42
42
  `);return}let i=r.featureName?`${r.featureName} (${r.featureId})`:r.featureId;process.stdout.write(`dezycro feature: ${i}
43
43
  active this session: ${r.active?"yes":"no"}
44
- `)}};var We=p(require("crypto")),h=p(require("fs")),O=p(require("os")),g=p(require("path")),Ze=p(require("readline"));var he=class{constructor(e,t){this.apiUrl=e;this.token=t}apiUrl;token;async listWorkspaces(){let e=await this.get(`${this.apiUrl}/api/v1/workspaces`);return(Array.isArray(e?.data)?e.data:[]).map(n=>({id:String(n.id??""),name:String(n.name??"")})).filter(n=>n.id.length>0)}async fetchManifest(e,t){let n=`${this.apiUrl}/api/v1/workspaces/${e}/skills/sync-manifest`,r={Authorization:`Bearer ${this.token}`};t&&(r["If-None-Match"]=t);let i=await fetch(n,{headers:r});if(i.status===304)return{kind:"not-modified"};if(i.status===403||i.status===404)return{kind:"unavailable"};if(!i.ok)throw new Error(`GET ${n} \u2192 HTTP ${i.status}`);return{kind:"ok",manifest:await i.json(),etag:i.headers.get("etag")}}async get(e){let t=await fetch(e,{headers:{Authorization:`Bearer ${this.token}`}});if(!t.ok)throw new Error(`GET ${e} \u2192 HTTP ${t.status}`);return await t.json()}},Le=/^[a-z0-9][a-z0-9-]*$/,ct=500,lt=10;function ut(){return{stateDir:g.join(O.homedir(),".dezycro"),commandsDir:g.join(O.homedir(),".claude","commands")}}var me=class{constructor(e,t,n=r=>console.log(r)){this.gateway=e;this.paths=t;this.log=n}gateway;paths;log;configPath(){return g.join(this.paths.stateDir,"skills.json")}statePath(){return g.join(this.paths.stateDir,"skills-state.json")}readConfig(){let e=X(this.configPath());if(!e||typeof e!="object")return null;let t=e.workspaces&&typeof e.workspaces=="object"?e.workspaces:{};return{enabled:e.enabled!==!1,apiUrl:typeof e.apiUrl=="string"?e.apiUrl:null,workspaces:t}}writeConfig(e){h.mkdirSync(this.paths.stateDir,{recursive:!0}),K(this.configPath(),JSON.stringify(e,null,2))}readState(){let e=X(this.statePath());return e&&typeof e=="object"&&e.workspaces&&typeof e.workspaces=="object"?{version:1,workspaces:e.workspaces,lastSyncTs:typeof e.lastSyncTs=="string"?e.lastSyncTs:null}:{version:1,workspaces:{},lastSyncTs:null}}async sync(e){let t={added:0,updated:0,restored:0,removed:0,skipped:[],synced:!1},n=this.readConfig();if(!n||Object.keys(n.workspaces).length===0)return this.log("No workspaces configured for skills sync. Run `dezycro skills sync --configure` to pick."),t;if(!n.enabled)return this.log("Skills sync is disabled (~/.dezycro/skills.json enabled=false)."),t;if(!this.acquireLock())throw new Error("Another skills sync is already running (lock held). Retry in a moment.");try{let r=Object.keys(n.workspaces).filter(a=>a!=="*");if("*"in n.workspaces){let a=new Set(r);for(let u of await this.gateway.listWorkspaces())a.has(u.id)||r.push(u.id)}let i=this.readState(),s=new Map,l=new Map;for(let a of r){let u=e.force?void 0:this.cachedEtag(n,i,a),f=await this.gateway.fetchManifest(a,u);if(f.kind==="not-modified"&&this.hasLocalDrift(i,a)&&(f=await this.gateway.fetchManifest(a)),f.kind==="unavailable"){t.skipped.push({what:`workspace ${a}`,reason:"skills not available (flag off or no access)"});continue}f.kind!=="not-modified"&&(s.set(a,f.manifest),l.set(a,f.etag??null))}let c=new Map,m=new Map;for(let[a,u]of s){let d=n.workspaces[a]?.prefixAlias??u.prefix;c.set(a,d),m.set(d,[...m.get(d)??[],a])}for(let[a,u]of m)if(u.length>1){this.log(`\u26A0 prefix collision on '${a}' between workspaces ${u.join(", ")} \u2014 skipping all of them. Change a prefixAlias in ${this.configPath()} to resolve.`);for(let f of u)s.delete(f),t.skipped.push({what:`workspace ${f}`,reason:`prefix collision on '${a}'`})}for(let[a,u]of s)this.syncWorkspace(a,u,c.get(a)??u.prefix,i,e.force,t,l.get(a)??null);return i.lastSyncTs=new Date().toISOString(),h.mkdirSync(this.paths.stateDir,{recursive:!0}),K(this.statePath(),JSON.stringify(i,null,2)),t.synced=!0,t}finally{this.releaseLock()}}cachedEtag(e,t,n){let r=t.workspaces[n];if(!(!r?.etag||(e.workspaces[n]?.prefixAlias??r.canonicalPrefix)!==r.aliasUsed))return r.etag}syncWorkspace(e,t,n,r,i,s,l){if(!Le.test(n)){s.skipped.push({what:`workspace ${e}`,reason:`invalid prefix '${n}'`});return}let c=r.workspaces[e]??{canonicalPrefix:t.prefix,aliasUsed:n,skills:{}};if(c.aliasUsed!==n&&Object.keys(c.skills).length>0){for(let[a,u]of Object.entries(c.skills))this.removeOwned(u,s),delete c.skills[a];this.log(`Prefix changed for workspace ${e}: '${c.aliasUsed}' \u2192 '${n}'`)}c.canonicalPrefix=t.prefix,c.aliasUsed=n,c.etag=l;let m=new Set(t.skills.map(a=>a.id));for(let[a,u]of Object.entries(c.skills))m.has(a)||(this.removeOwned(u,s),delete c.skills[a]);for(let a of t.skills){if(!Le.test(a.name)){s.skipped.push({what:`skill '${a.name}'`,reason:"invalid name (not a slug)"});continue}let u=g.join(n,`${a.name}.md`),f=g.join(this.paths.commandsDir,u),d=c.skills[a.id],w=He(a.content);if(d&&d.version===a.version&&d.relPath===u){if(Je(f)===a.content){d.contentHash!==w&&(c.skills[a.id]={...d,contentHash:w});continue}h.mkdirSync(g.dirname(f),{recursive:!0}),K(f,a.content),c.skills[a.id]={name:a.name,version:a.version,relPath:u,contentHash:w},s.restored+=1,this.log(`restored /${n}:${a.name} \u2014 local edits to synced skills are overwritten; edit skills in the Dezycro platform`);continue}if(d&&d.relPath!==u&&(this.removeOwned(d,s),s.removed-=1),h.existsSync(f)&&!this.owns(r,f)&&!i){s.skipped.push({what:`skill '${a.name}'`,reason:`foreign file exists at ${f} \u2014 remove it or rerun with --force to take ownership`});continue}h.mkdirSync(g.dirname(f),{recursive:!0}),K(f,a.content),d?s.updated+=1:s.added+=1,c.skills[a.id]={name:a.name,version:a.version,relPath:u,contentHash:w}}r.workspaces[e]=c}hasLocalDrift(e,t){let n=e.workspaces[t];if(!n)return!1;for(let r of Object.values(n.skills)){if(r.contentHash===void 0)continue;let i=Je(g.join(this.paths.commandsDir,r.relPath));if(i===null||He(i)!==r.contentHash)return!0}return!1}owns(e,t){for(let n of Object.values(e.workspaces))for(let r of Object.values(n.skills))if(g.join(this.paths.commandsDir,r.relPath)===t)return!0;return!1}removeOwned(e,t){let n=g.join(this.paths.commandsDir,e.relPath);try{h.unlinkSync(n),t.removed+=1}catch{}}lockPath(){return g.join(this.paths.stateDir,".skills-state.lock")}acquireLock(){h.mkdirSync(this.paths.stateDir,{recursive:!0});let e=Date.now()+ct;for(;;)try{let t=h.openSync(this.lockPath(),"wx");return h.closeSync(t),!0}catch{if(Date.now()>=e)return!1;dt(lt)}}releaseLock(){try{h.unlinkSync(this.lockPath())}catch{}}},ge=class{async pick(e){if(e.length===0)return[];console.log(`
45
- Workspaces you belong to:`),e.forEach((i,s)=>console.log(` ${s+1}. ${i.name} (${i.id})`));let n=(await ft('Sync skills from which workspaces? (e.g. "1,3", "all" = every workspace incl. future ones, empty = none): ')).trim().toLowerCase();if(n==="")return[];if(n==="all"||n==="*")return"*";let r=[];for(let i of n.split(",")){let s=Number.parseInt(i.trim(),10);Number.isInteger(s)&&s>=1&&s<=e.length&&r.push(e[s-1])}return r}},pt=`dezycro skills \u2014 sync workspace-authored skills to Claude Code
44
+ `)}};var Ze=p(require("crypto")),m=p(require("fs")),O=p(require("os")),g=p(require("path")),ke=p(require("readline"));var he=class{constructor(e,t){this.apiUrl=e;this.token=t}apiUrl;token;async listWorkspaces(){let e=await this.get(`${this.apiUrl}/api/v1/workspaces`);return(Array.isArray(e?.data)?e.data:[]).map(n=>({id:String(n.id??""),name:String(n.name??"")})).filter(n=>n.id.length>0)}async fetchManifest(e,t){let n=`${this.apiUrl}/api/v1/workspaces/${e}/skills/sync-manifest`,r={Authorization:`Bearer ${this.token}`};t&&(r["If-None-Match"]=t);let i=await fetch(n,{headers:r});if(i.status===304)return{kind:"not-modified"};if(i.status===403||i.status===404)return{kind:"unavailable"};if(!i.ok)throw new Error(`GET ${n} \u2192 HTTP ${i.status}`);return{kind:"ok",manifest:await i.json(),etag:i.headers.get("etag")}}async get(e){let t=await fetch(e,{headers:{Authorization:`Bearer ${this.token}`}});if(!t.ok)throw new Error(`GET ${e} \u2192 HTTP ${t.status}`);return await t.json()}},Je=/^[a-z0-9][a-z0-9-]*$/,ct=500,lt=10;function ut(){return{stateDir:g.join(O.homedir(),".dezycro"),commandsDir:g.join(O.homedir(),".claude","commands")}}var me=class{constructor(e,t,n=r=>console.log(r)){this.gateway=e;this.paths=t;this.log=n}gateway;paths;log;configPath(){return g.join(this.paths.stateDir,"skills.json")}statePath(){return g.join(this.paths.stateDir,"skills-state.json")}readConfig(){let e=X(this.configPath());if(!e||typeof e!="object")return null;let t=e.workspaces&&typeof e.workspaces=="object"?e.workspaces:{};return{enabled:e.enabled!==!1,apiUrl:typeof e.apiUrl=="string"?e.apiUrl:null,workspaces:t}}writeConfig(e){m.mkdirSync(this.paths.stateDir,{recursive:!0}),q(this.configPath(),JSON.stringify(e,null,2))}readState(){let e=X(this.statePath());return e&&typeof e=="object"&&e.workspaces&&typeof e.workspaces=="object"?{version:1,workspaces:e.workspaces,lastSyncTs:typeof e.lastSyncTs=="string"?e.lastSyncTs:null}:{version:1,workspaces:{},lastSyncTs:null}}async sync(e){let t={added:0,updated:0,restored:0,removed:0,skipped:[],synced:!1},n=this.readConfig();if(!n||Object.keys(n.workspaces).length===0)return this.log("No workspaces configured for skills sync. Run `dezycro skills sync --configure` to pick."),t;if(!n.enabled)return this.log("Skills sync is disabled (~/.dezycro/skills.json enabled=false)."),t;if(!this.acquireLock())throw new Error("Another skills sync is already running (lock held). Retry in a moment.");try{let r=Object.keys(n.workspaces).filter(a=>a!=="*");if("*"in n.workspaces){let a=new Set(r);for(let u of await this.gateway.listWorkspaces())a.has(u.id)||r.push(u.id)}let i=this.readState(),s=new Map,l=new Map;for(let a of r){let u=e.force?void 0:this.cachedEtag(n,i,a),f=await this.gateway.fetchManifest(a,u);if(f.kind==="not-modified"&&this.hasLocalDrift(i,a)&&(f=await this.gateway.fetchManifest(a)),f.kind==="unavailable"){t.skipped.push({what:`workspace ${a}`,reason:"skills not available (flag off or no access)"});continue}f.kind!=="not-modified"&&(s.set(a,f.manifest),l.set(a,f.etag??null))}let c=new Map,h=new Map;for(let[a,u]of s){let d=n.workspaces[a]?.prefixAlias??u.prefix;c.set(a,d),h.set(d,[...h.get(d)??[],a])}for(let[a,u]of h)if(u.length>1){this.log(`\u26A0 prefix collision on '${a}' between workspaces ${u.join(", ")} \u2014 skipping all of them. Change a prefixAlias in ${this.configPath()} to resolve.`);for(let f of u)s.delete(f),t.skipped.push({what:`workspace ${f}`,reason:`prefix collision on '${a}'`})}for(let[a,u]of s)this.syncWorkspace(a,u,c.get(a)??u.prefix,i,e.force,t,l.get(a)??null);return i.lastSyncTs=new Date().toISOString(),m.mkdirSync(this.paths.stateDir,{recursive:!0}),q(this.statePath(),JSON.stringify(i,null,2)),t.synced=!0,t}finally{this.releaseLock()}}cachedEtag(e,t,n){let r=t.workspaces[n];if(!(!r?.etag||(e.workspaces[n]?.prefixAlias??r.canonicalPrefix)!==r.aliasUsed))return r.etag}syncWorkspace(e,t,n,r,i,s,l){if(!Je.test(n)){s.skipped.push({what:`workspace ${e}`,reason:`invalid prefix '${n}'`});return}let c=r.workspaces[e]??{canonicalPrefix:t.prefix,aliasUsed:n,skills:{}};if(c.aliasUsed!==n&&Object.keys(c.skills).length>0){for(let[a,u]of Object.entries(c.skills))this.removeOwned(u,s),delete c.skills[a];this.log(`Prefix changed for workspace ${e}: '${c.aliasUsed}' \u2192 '${n}'`)}c.canonicalPrefix=t.prefix,c.aliasUsed=n,c.etag=l;let h=new Set(t.skills.map(a=>a.id));for(let[a,u]of Object.entries(c.skills))h.has(a)||(this.removeOwned(u,s),delete c.skills[a]);for(let a of t.skills){if(!Je.test(a.name)){s.skipped.push({what:`skill '${a.name}'`,reason:"invalid name (not a slug)"});continue}let u=g.join(n,`${a.name}.md`),f=g.join(this.paths.commandsDir,u),d=c.skills[a.id],w=He(a.content);if(d&&d.version===a.version&&d.relPath===u){if(We(f)===a.content){d.contentHash!==w&&(c.skills[a.id]={...d,contentHash:w});continue}m.mkdirSync(g.dirname(f),{recursive:!0}),q(f,a.content),c.skills[a.id]={name:a.name,version:a.version,relPath:u,contentHash:w},s.restored+=1,this.log(`restored /${n}:${a.name} \u2014 local edits to synced skills are overwritten; edit skills in the Dezycro platform`);continue}if(d&&d.relPath!==u&&(this.removeOwned(d,s),s.removed-=1),m.existsSync(f)&&!this.owns(r,f)&&!i){s.skipped.push({what:`skill '${a.name}'`,reason:`foreign file exists at ${f} \u2014 remove it or rerun with --force to take ownership`});continue}m.mkdirSync(g.dirname(f),{recursive:!0}),q(f,a.content),d?s.updated+=1:s.added+=1,c.skills[a.id]={name:a.name,version:a.version,relPath:u,contentHash:w}}r.workspaces[e]=c}hasLocalDrift(e,t){let n=e.workspaces[t];if(!n)return!1;for(let r of Object.values(n.skills)){if(r.contentHash===void 0)continue;let i=We(g.join(this.paths.commandsDir,r.relPath));if(i===null||He(i)!==r.contentHash)return!0}return!1}owns(e,t){for(let n of Object.values(e.workspaces))for(let r of Object.values(n.skills))if(g.join(this.paths.commandsDir,r.relPath)===t)return!0;return!1}removeOwned(e,t){let n=g.join(this.paths.commandsDir,e.relPath);try{m.unlinkSync(n),t.removed+=1}catch{}}lockPath(){return g.join(this.paths.stateDir,".skills-state.lock")}acquireLock(){m.mkdirSync(this.paths.stateDir,{recursive:!0});let e=Date.now()+ct;for(;;)try{let t=m.openSync(this.lockPath(),"wx");return m.closeSync(t),!0}catch{if(Date.now()>=e)return!1;ft(lt)}}releaseLock(){try{m.unlinkSync(this.lockPath())}catch{}}};function pt(o,e){let t=o.checked.length;switch(e){case"up":return{...o,cursor:(o.cursor+t-1)%t};case"down":return{...o,cursor:(o.cursor+1)%t};case"space":{let n=o.checked.slice();return n[o.cursor]=!n[o.cursor],o.cursor===0&&n[0]&&n.fill(!1,1),o.cursor>0&&n[o.cursor]&&(n[0]=!1),{...o,checked:n}}case"return":return{...o,done:!0};default:return o}}var ge=class{async pick(e,t=new Set){if(e.length===0)return[];if(!process.stdin.isTTY)return this.pickNumbered(e);let n={cursor:0,checked:[t.has("*"),...e.map(s=>t.has(s.id))],done:!1},r=["All workspaces (incl. future ones)",...e.map(s=>`${s.name} (${s.id})`)],i=s=>{s||process.stdout.write(`\x1B[${r.length}A`),r.forEach((l,c)=>{let h=c===n.cursor?"\u276F":" ",a=n.checked[c]?"\u25C9":"\u25CB";process.stdout.write(`\x1B[2K${h} ${a} ${l}
45
+ `)})};return console.log(`
46
+ Sync skills from which workspaces? (\u2191/\u2193 move, space toggle, enter confirm)`),i(!0),ke.default.emitKeypressEvents(process.stdin),process.stdin.setRawMode(!0),process.stdin.resume(),await new Promise(s=>{let l=(c,h)=>{h.ctrl&&h.name==="c"&&process.exit(130),n=pt(n,h.name??""),i(!1),n.done&&(process.stdin.setRawMode(!1),process.stdin.pause(),process.stdin.off("keypress",l),s())};process.stdin.on("keypress",l)}),n.checked[0]?"*":e.filter((s,l)=>n.checked[l+1])}async pickNumbered(e){console.log(`
47
+ Workspaces you belong to:`),e.forEach((i,s)=>console.log(` ${s+1}. ${i.name} (${i.id})`));let n=(await ht('Sync skills from which workspaces? (e.g. "1,3", "all" = every workspace incl. future ones, empty = none): ')).trim().toLowerCase();if(n==="")return[];if(n==="all"||n==="*")return"*";let r=[];for(let i of n.split(",")){let s=Number.parseInt(i.trim(),10);Number.isInteger(s)&&s>=1&&s<=e.length&&r.push(e[s-1])}return r}},dt=`dezycro skills \u2014 sync workspace-authored skills to Claude Code
46
48
 
47
49
  Usage:
48
50
  dezycro skills sync Sync configured workspaces' skills to ~/.claude/commands/
@@ -50,7 +52,7 @@ Usage:
50
52
  dezycro skills sync --force Also overwrite conflicting foreign files (takes ownership)
51
53
 
52
54
  Synced skills appear as /<prefix>:<name> slash commands in Claude Code.
53
- Config: ~/.dezycro/skills.json \xB7 Ledger: ~/.dezycro/skills-state.json`,Y=class{async run(e){let[t,...n]=e;if(t!=="sync"){console.log(pt),process.exitCode=t===void 0||t==="help"?0:2;return}let r=n.includes("--force"),i=n.includes("--configure"),s=this.resolveConnection();if("error"in s){console.error(`dezycro skills: not authenticated \u2014 ${s.error}`),console.error("Run `dezycro setup` to save your API key."),process.exitCode=1;return}let l=ut(),c=new he(s.apiUrl,s.token),m=new me(c,l);try{let a=m.readConfig();if(i||!a||Object.keys(a.workspaces).length===0){let f=await c.listWorkspaces();if(f.length===0){console.log("You are not a member of any workspace. Nothing to sync.");return}let d=await new ge().pick(f);if(d!=="*"&&d.length===0){console.log("No workspaces selected. Nothing to sync.");return}let w=a?.workspaces??{},ke=d==="*"?{...w,"*":w["*"]??{}}:Object.fromEntries(d.map(ve=>[ve.id,w[ve.id]??{}]));a={enabled:a?.enabled??!0,apiUrl:s.apiUrl,workspaces:ke},m.writeConfig(a),console.log(d==="*"?`Saved wildcard (all workspaces, resolved each sync) to ${m.configPath()}`:`Saved ${d.length} workspace(s) to ${m.configPath()}`)}let u=await m.sync({force:r});if(u.synced){console.log(`Synced skills: ${u.added} added, ${u.updated} updated, ${u.restored} restored, ${u.removed} removed, ${u.skipped.length} skipped`);for(let f of u.skipped)console.log(` skipped ${f.what}: ${f.reason}`);(process.env.CURSOR_TRACE_ID||process.env.TERM_PROGRAM==="cursor")&&console.log("Cursor skill delivery is coming in a future release. Skills are synced and ready for when support ships.")}}catch(a){console.error(`dezycro skills: sync failed \u2014 ${a instanceof Error?a.message:String(a)}`),console.error("No local files were modified. Check your connection and retry."),process.exitCode=1}}resolveConnection(){let e=k.findRepoRoot(process.cwd()),t=e?new k(e):null,n=process.env.DZ_TOKEN||t?.token||X(g.join(O.homedir(),".dezycro","token.json"))?.token;if(typeof n!="string"||n.length===0)return{error:"no token (DZ_TOKEN or ~/.dezycro/token.json)"};let r=X(g.join(O.homedir(),".dezycro","skills.json"));return{apiUrl:(process.env.DZ_API_URL||(typeof r?.apiUrl=="string"?r.apiUrl:null)||t?.apiUrl||"https://api.dezycro.ai").replace(/\/+$/,""),token:n}}};function X(o){try{return JSON.parse(h.readFileSync(o,"utf8"))}catch{return null}}function Je(o){try{return h.readFileSync(o,"utf8")}catch{return null}}function He(o){return We.createHash("sha256").update(o,"utf8").digest("hex")}function K(o,e){let t=`${o}.tmp-${process.pid}`;h.writeFileSync(t,e,"utf8"),h.renameSync(t,o)}function dt(o){let e=new SharedArrayBuffer(4);Atomics.wait(new Int32Array(e),0,0,o)}function ft(o){let e=Ze.default.createInterface({input:process.stdin,output:process.stdout});return new Promise(t=>e.question(o,n=>{e.close(),t(n)}))}var Ve=(c=>(c.Run="run",c.Setup="setup",c.ResolveAuth="resolve-auth",c.Completion="completion",c.Metrics="metrics",c.AwaitEvent="await-event",c.Feature="feature",c.Skills="skills",c))(Ve||{}),ht=new Set(["help","-h","--help"]),Ge=`dezycro \u2014 Dezycro for AI coding agents
55
+ Config: ~/.dezycro/skills.json \xB7 Ledger: ~/.dezycro/skills-state.json`,Y=class{async run(e){let[t,...n]=e;if(t!=="sync"){console.log(dt),process.exitCode=t===void 0||t==="help"?0:2;return}let r=n.includes("--force"),i=n.includes("--configure"),s=this.resolveConnection();if("error"in s){console.error(`dezycro skills: not authenticated \u2014 ${s.error}`),console.error("Run `dezycro setup` to save your API key."),process.exitCode=1;return}let l=ut(),c=new he(s.apiUrl,s.token),h=new me(c,l);try{let a=h.readConfig();if(i||!a||Object.keys(a.workspaces).length===0){let f=await c.listWorkspaces();if(f.length===0){console.log("You are not a member of any workspace. Nothing to sync.");return}let d=await new ge().pick(f,new Set(Object.keys(a?.workspaces??{})));if(d!=="*"&&d.length===0){console.log("No workspaces selected. Nothing to sync.");return}let w=a?.workspaces??{},ve=d==="*"?{...w,"*":w["*"]??{}}:Object.fromEntries(d.map(we=>[we.id,w[we.id]??{}]));a={enabled:a?.enabled??!0,apiUrl:s.apiUrl,workspaces:ve},h.writeConfig(a),console.log(d==="*"?`Saved wildcard (all workspaces, resolved each sync) to ${h.configPath()}`:`Saved ${d.length} workspace(s) to ${h.configPath()}`)}let u=await h.sync({force:r});if(u.synced){console.log(`Synced skills: ${u.added} added, ${u.updated} updated, ${u.restored} restored, ${u.removed} removed, ${u.skipped.length} skipped`);for(let f of u.skipped)console.log(` skipped ${f.what}: ${f.reason}`);(process.env.CURSOR_TRACE_ID||process.env.TERM_PROGRAM==="cursor")&&console.log("Cursor skill delivery is coming in a future release. Skills are synced and ready for when support ships.")}}catch(a){console.error(`dezycro skills: sync failed \u2014 ${a instanceof Error?a.message:String(a)}`),console.error("No local files were modified. Check your connection and retry."),process.exitCode=1}}resolveConnection(){let e=y.findRepoRoot(process.cwd()),t=e?new y(e):null,n=process.env.DZ_TOKEN||t?.token||X(g.join(O.homedir(),".dezycro","token.json"))?.token;if(typeof n!="string"||n.length===0)return{error:"no token (DZ_TOKEN or ~/.dezycro/token.json)"};let r=X(g.join(O.homedir(),".dezycro","skills.json"));return{apiUrl:(process.env.DZ_API_URL||(typeof r?.apiUrl=="string"?r.apiUrl:null)||t?.apiUrl||"https://api.dezycro.ai").replace(/\/+$/,""),token:n}}};function X(o){try{return JSON.parse(m.readFileSync(o,"utf8"))}catch{return null}}function We(o){try{return m.readFileSync(o,"utf8")}catch{return null}}function He(o){return Ze.createHash("sha256").update(o,"utf8").digest("hex")}function q(o,e){let t=`${o}.tmp-${process.pid}`;m.writeFileSync(t,e,"utf8"),m.renameSync(t,o)}function ft(o){let e=new SharedArrayBuffer(4);Atomics.wait(new Int32Array(e),0,0,o)}function ht(o){let e=ke.default.createInterface({input:process.stdin,output:process.stdout});return new Promise(t=>e.question(o,n=>{e.close(),t(n)}))}var Ve=(c=>(c.Run="run",c.Setup="setup",c.ResolveAuth="resolve-auth",c.Completion="completion",c.Metrics="metrics",c.AwaitEvent="await-event",c.Feature="feature",c.Skills="skills",c))(Ve||{}),mt=new Set(["help","-h","--help"]),Ge=`dezycro \u2014 Dezycro for AI coding agents
54
56
 
55
57
  Usage: dezycro <command> [args]
56
58
 
@@ -68,5 +70,5 @@ Commands:
68
70
  Sync workspace-authored skills to ~/.claude/commands/ as /<prefix>:<name> slash commands
69
71
 
70
72
  Gateway control: dezycro run --status dezycro run --stop
71
- Custom port: dezycro run --port <n> <agent> (overrides DZ_PORT, default 13579)`,ye=class{handlers=new Map([["run",e=>{new _().run(e)}],["setup",()=>new B().run()],["resolve-auth",e=>new L().run(e[0])],["completion",e=>new J().run(e)],["metrics",e=>new W().run(e)],["await-event",e=>{new G().run(e)}],["feature",e=>new q().run(e)],["skills",e=>{new Y().run(e)}]]);run(e){let[t,...n]=e,r=this.handlers.get(t);if(r){r(n);return}if(t===void 0||ht.has(t)){console.log(Ge);return}console.error(`dezycro: unknown command '${t}'
73
+ Custom port: dezycro run --port <n> <agent> (overrides DZ_PORT, default 13579)`,ye=class{handlers=new Map([["run",e=>{new _().run(e)}],["setup",()=>new B().run()],["resolve-auth",e=>new L().run(e[0])],["completion",e=>new J().run(e)],["metrics",e=>new H().run(e)],["await-event",e=>{new G().run(e)}],["feature",e=>new K().run(e)],["skills",e=>{new Y().run(e)}]]);run(e){let[t,...n]=e,r=this.handlers.get(t);if(r){r(n);return}if(t===void 0||mt.has(t)){console.log(Ge);return}console.error(`dezycro: unknown command '${t}'
72
74
  `),console.error(Ge),process.exit(2)}};new ye().run(process.argv.slice(2));0&&(module.exports={Command});
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dezycro-ai/agent-plugin",
3
- "version": "2.6.1",
3
+ "version": "2.6.2",
4
4
  "description": "Official Dezycro plugin for AI coding agents (Claude Code today, more to come) — reverse-engineer your codebase into features, PRDs, TRDs, and live verification.",
5
5
  "bin": {
6
6
  "dezycro": "./dist/cli/dezycro.js"