@dezycro-ai/agent-plugin 2.5.0 → 2.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,47 +1,47 @@
1
1
  #!/usr/bin/env node
2
- "use strict";var Se=Object.create;var R=Object.defineProperty;var xe=Object.getOwnPropertyDescriptor;var Ce=Object.getOwnPropertyNames;var Re=Object.getPrototypeOf,Ee=Object.prototype.hasOwnProperty;var Ie=(o,e)=>{for(var t in e)R(o,t,{get:e[t],enumerable:!0})},te=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Ce(e))!Ee.call(o,r)&&r!==t&&R(o,r,{get:()=>e[r],enumerable:!(n=xe(e,r))||n.enumerable});return o};var l=(o,e,t)=>(t=o!=null?Se(Re(o)):{},te(e||!o||!o.__esModule?R(t,"default",{value:o,enumerable:!0}):t,o)),Ae=o=>te(R({},"__esModule",{value:!0}),o);var Be={};Ie(Be,{Command:()=>we});module.exports=Ae(Be);var se=l(require("node:http")),S=l(require("node:path")),E=l(require("node:fs")),ie=l(require("node:os")),H=require("node:child_process");var h={MessageStart:"message_start",ContentBlockStart:"content_block_start",ContentBlockDelta:"content_block_delta",ContentBlockStop:"content_block_stop",MessageDelta:"message_delta",MessageStop:"message_stop"};var ne={UpdateTask:"update_task"},re={Status:"status"},j={Done:"DONE",Pushed:"PUSHED"};var f={SpecPublished:"specPublished",VerifiedRecently:"verifiedRecently"};var L={Claude:"claude",Codex:"codex"},J={Health:"/__dz/health",Stop:"/__dz/stop"};var oe=l(require("node:fs")),g=l(require("node:path")),w=class o{static MAX_DEPTH=6;static dir(){let e=__dirname;for(let t=0;t<o.MAX_DEPTH;t+=1){if(oe.existsSync(g.join(e,"package.json")))return e;e=g.dirname(e)}return g.resolve(__dirname,"..","..")}static file(...e){return g.join(o.dir(),...e)}};var I=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=w.file("dist","gateway","proxy.js");compactPath=w.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(J.Stop)?"dezycro: stopped":"dezycro: not running");return}if(n==="--status"){console.error(await this.health()?"dezycro: up":"dezycro: down");return}let r=n||L.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 a=this.setupShims(),c={...process.env,...s?this.gatewayUrlEnv(r):{},...a?.env??{}},T=()=>{if(a)try{E.default.rmSync(a.dir,{recursive:!0,force:!0})}catch{}},F=(0,H.spawn)(r,i,{env:c,stdio:"inherit"});F.on("exit",b=>{T(),process.exit(b??0)}),F.on("error",b=>{T(),console.error(`dezycro: failed to launch ${r}: ${b.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}gatewayUrlEnv(e){let t=`http://127.0.0.1:${this.port}`;return e===L.Codex?{OPENAI_BASE_URL:`${t}/v1`}:{ANTHROPIC_BASE_URL:t}}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:process.env.DZ_STATE_FILE||S.default.join(process.cwd(),".dezycro","companion-state.json")};(0,H.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=E.default.mkdtempSync(S.default.join(ie.default.tmpdir(),"dz-shims-")),n=process.env.PATH||"";for(let r of e){let i=`#!/usr/bin/env bash
2
+ "use strict";var xe=Object.create;var I=Object.defineProperty;var Ce=Object.getOwnPropertyDescriptor;var Ee=Object.getOwnPropertyNames;var Re=Object.getPrototypeOf,Ie=Object.prototype.hasOwnProperty;var Ae=(o,e)=>{for(var t in e)I(o,t,{get:e[t],enumerable:!0})},te=(o,e,t,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Ee(e))!Ie.call(o,r)&&r!==t&&I(o,r,{get:()=>e[r],enumerable:!(n=Ce(e,r))||n.enumerable});return o};var l=(o,e,t)=>(t=o!=null?xe(Re(o)):{},te(e||!o||!o.__esModule?I(t,"default",{value:o,enumerable:!0}):t,o)),De=o=>te(I({},"__esModule",{value:!0}),o);var _e={};Ae(_e,{Command:()=>Se});module.exports=De(_e);var ie=l(require("node:http")),y=l(require("node:path")),C=l(require("node:fs")),ae=l(require("node:os")),H=require("node:child_process");var h={MessageStart:"message_start",ContentBlockStart:"content_block_start",ContentBlockDelta:"content_block_delta",ContentBlockStop:"content_block_stop",MessageDelta:"message_delta",MessageStop:"message_stop"};var ne={UpdateTask:"update_task"},re={Status:"status"},L={Done:"DONE",Pushed:"PUSHED"};var f={SpecPublished:"specPublished",VerifiedRecently:"verifiedRecently"};var S={Claude:"claude",Codex:"codex"},J={Health:"/__dz/health",Stop:"/__dz/stop"},oe="last-opus-model";var se=l(require("node:fs")),g=l(require("node:path")),x=class o{static MAX_DEPTH=6;static dir(){let e=__dirname;for(let t=0;t<o.MAX_DEPTH;t+=1){if(se.existsSync(g.join(e,"package.json")))return e;e=g.dirname(e)}return g.resolve(__dirname,"..","..")}static file(...e){return g.join(o.dir(),...e)}};var A=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=x.file("dist","gateway","proxy.js");compactPath=x.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(J.Stop)?"dezycro: stopped":"dezycro: not running");return}if(n==="--status"){console.error(await this.health()?"dezycro: up":"dezycro: down");return}let r=n||S.Claude,s=t.slice(1),i=await this.ensureDaemon();console.error(i?`dezycro: gateway on :${this.port} \u2014 launching ${r}`:`dezycro: gateway unavailable \u2014 launching ${r} DIRECTLY (fail-open)`),i&&(s=this.pinResumeModel(r,s));let a=this.setupShims(),c={...process.env,...i?this.gatewayUrlEnv(r):{},...i?this.contextWindowEnv(r):{},...a?.env??{}},b=()=>{if(a)try{C.default.rmSync(a.dir,{recursive:!0,force:!0})}catch{}},j=(0,H.spawn)(r,s,{env:c,stdio:"inherit"});j.on("exit",w=>{b(),process.exit(w??0)}),j.on("error",w=>{b(),console.error(`dezycro: failed to launch ${r}: ${w.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 s=Number(e[n+1]);e[n+1]!==void 0&&Number.isInteger(s)&&s>0&&(this.port=s,n+=1);continue}if(r.startsWith("--port=")){let s=Number(r.slice(7));Number.isInteger(s)&&s>0&&(this.port=s);continue}t.push(r)}return t}gatewayUrlEnv(e){let t=`http://127.0.0.1:${this.port}`;return e===S.Codex?{OPENAI_BASE_URL:`${t}/v1`}:{ANTHROPIC_BASE_URL:t}}contextWindowEnv(e){return e!==S.Claude||process.env.ANTHROPIC_DEFAULT_OPUS_MODEL?{}:{ANTHROPIC_DEFAULT_OPUS_MODEL:this.opusModelId()}}pinResumeModel(e,t){if(e!==S.Claude)return t;let n=t.some(s=>["--resume","-r","--continue","-c"].includes(s)),r=t.some(s=>s==="--model"||s==="-m"||s.startsWith("--model="));return!n||r?t:[...t,"--model",this.opusModelId()]}opusModelId(){return o.with1m(process.env.DZ_OPUS_MODEL||this.lastSeenOpusModel()||"claude-opus-4-8")}lastSeenOpusModel(){try{return C.default.readFileSync(y.default.join(y.default.dirname(this.stateFile()),oe),"utf8").trim()||null}catch{return null}}stateFile(){return process.env.DZ_STATE_FILE||y.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,H.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=C.default.mkdtempSync(y.default.join(ae.default.tmpdir(),"dz-shims-")),n=process.env.PATH||"";for(let r of e){let s=`#!/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
- `;E.default.writeFileSync(S.default.join(t,r),i,{mode:493})}return{dir:t,env:{PATH:`${t}${S.default.delimiter}${n}`,DZ_REAL_PATH:n,DZ_COMPACT_PATH:this.compactPath}}}catch{return null}}health(){return this.get(J.Health)}control(e){return this.get(e,()=>!0)}get(e,t=n=>n.statusCode===200){return new Promise(n=>{let r=se.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 ae=require("child_process"),W=l(require("fs")),ce=l(require("os")),Z=l(require("path")),le=l(require("readline")),A=class o{static MCP_URL="https://mcp.dezycro.ai";run(){console.log(`
8
+ `;C.default.writeFileSync(y.default.join(t,r),s,{mode:493})}return{dir:t,env:{PATH:`${t}${y.default.delimiter}${n}`,DZ_REAL_PATH:n,DZ_COMPACT_PATH:this.compactPath}}}catch{return null}}health(){return this.get(J.Health)}control(e){return this.get(e,()=>!0)}get(e,t=n=>n.statusCode===200){return new Promise(n=>{let r=ie.default.get({host:"127.0.0.1",port:this.port,path:e,timeout:800},s=>{s.resume(),n(t(s))});r.on("error",()=>n(!1)),r.on("timeout",()=>{r.destroy(),n(!1)})})}static sleep(e){return new Promise(t=>setTimeout(t,e))}};var ce=require("child_process"),W=l(require("fs")),le=l(require("os")),Z=l(require("path")),ue=l(require("readline")),D=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=le.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=ue.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
- `),e.close()})}configureMcp(e){let t=`claude mcp add --transport http dezycro "${o.MCP_URL}/mcp" --header "Authorization: Bearer ${e}"`;try{(0,ae.execSync)(t,{stdio:"inherit"}),console.log(`
14
+ `),e.close()})}configureMcp(e){let t=`claude mcp add --transport http dezycro "${o.MCP_URL}/mcp" --header "Authorization: Bearer ${e}"`;try{(0,ce.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=Z.default.join(ce.default.homedir(),".dezycro"),n=Z.default.join(t,"token.json");W.default.mkdirSync(t,{recursive:!0,mode:448}),W.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 $=l(require("fs")),ue=l(require("os")),pe=require("child_process"),D=class o{static DEFAULT_PATH=".dezycro/auth.local.json";static PLACEHOLDER=/\$\{([A-Z0-9_]+)\}/g;run(e=o.DEFAULT_PATH){if(!$.default.existsSync(e)){this.warn(`no auth file at ${e}; emitting nothing`);return}let t;try{t=JSON.parse($.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=Z.default.join(le.default.homedir(),".dezycro"),n=Z.default.join(t,"token.json");W.default.mkdirSync(t,{recursive:!0,mode:448}),W.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 $=l(require("fs")),pe=l(require("os")),de=require("child_process"),P=class o{static DEFAULT_PATH=".dezycro/auth.local.json";static PLACEHOLDER=/\$\{([A-Z0-9_]+)\}/g;run(e=o.DEFAULT_PATH){if(!$.default.existsSync(e)){this.warn(`no auth file at ${e}; emitting nothing`);return}let t;try{t=JSON.parse($.default.readFileSync(e,"utf8"))}catch(s){this.warn(`parse error in ${e}: ${s.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=ue.default.homedir()+t.slice(1)),$.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,pe.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
- `)}static shQuote(e){return"'"+String(e).replaceAll("'","'\\''")+"'"}};var P=class o{run(e){let t=e[0],n=o.scriptFor(t);n===null&&(process.stderr.write(`Usage: dezycro completion <bash|zsh|fish>
20
+ `)}resolveSecrets(e){let t={};for(let[n,r]of Object.entries(e))try{t[n]=this.resolveSecret(r)}catch(s){this.warn(`secret ${n}: ${s.message}`)}return t}personaExports(e,t){let n=[];for(let[r,s]of Object.entries(e))if(!(!s||!s.envVar))try{let i=this.substitute(s.config||{},t);n.push(`export ${s.envVar}=${o.shQuote(JSON.stringify(i))}`)}catch(i){this.warn(`persona '${r}' skipped: ${i.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=pe.default.homedir()+t.slice(1)),$.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,de.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,s]of Object.entries(e))n[r]=this.substitute(s,t);return n}return e}warn(e){process.stderr.write(`[dezycro resolve-auth] ${e}
21
+ `)}static shQuote(e){return"'"+String(e).replaceAll("'","'\\''")+"'"}};var M=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 ve=l(require("node:path"));var z=l(require("node:fs")),de=l(require("node:os")),y=l(require("node:path")),$e="DZ_METRICS_DIR",De="DZ_METRICS",k=class o{file;constructor(e="gateway"){this.file=o.prepare(e)}static enabled(){return process.env[De]!=="0"}static dir(){let e=process.env[$e];if(e)return e;let t=de.homedir();switch(process.platform){case"win32":return y.join(process.env.LOCALAPPDATA||y.join(t,"AppData","Local"),"Dezycro","metrics");case"darwin":return y.join(t,"Library","Application Support","Dezycro","metrics");default:return y.join(process.env.XDG_STATE_HOME||y.join(t,".local","state"),"dezycro","metrics")}}record(e){if(this.file)try{z.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 z.mkdirSync(t,{recursive:!0}),y.join(t,`${e}.jsonl`)}catch{return null}}};var Pe={rules:[{nameIncludes:ne.UpdateTask,inputField:re.Status,inputValues:[j.Done,j.Pushed],requireAll:[f.SpecPublished,f.VerifiedRecently],reason:"Cannot mark a task DONE/PUSHED yet."}]},G=class o{constructor(e,t){this.policy=e;this.state=t}policy;state;static STATE_PREDICATES={[f.SpecPublished]:e=>!!e&&e.needsSpecPublish!==!0,[f.VerifiedRecently]:e=>!e||!e.lastVerifyCompletionTs?!1:e.lastEditTs?Date.parse(e.lastVerifyCompletionTs)>=Date.parse(e.lastEditTs):!0};static FAILED_HINT={[f.SpecPublished]:"spec not published (controller/API changed) \u2014 run /dezycro:publish-spec",[f.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 a=t?.[n.inputField],c=(n.inputValues??[]).map(T=>String(T).toUpperCase());if(a==null||!c.includes(String(a).toUpperCase()))continue}let r=n.requireAll??[];if(r.length===0)return this.blocked(e,n.reason);let i=r.filter(a=>!o.STATE_PREDICATES[a]?.(this.state));if(i.length===0)continue;let s=i.map(a=>o.FAILED_HINT[a]||a).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 st=new Set([h.ContentBlockStart,h.ContentBlockDelta,h.ContentBlockStop]);var fe=l(require("node:fs")),ge=l(require("node:path"));var v=class o{static BIG_TOOL_CHARS=4e3;static defaultFile(){return ge.join(k.dir(),"gateway.jsonl")}static fromFile(e=o.defaultFile()){let t;try{t=fe.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 u=l(require("node:fs")),ye=l(require("node:path")),C=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=u.statSync(this.metricsFile).size}catch{return{lines:[],newOffset:e}}if(e>t&&(e=0),e===t)return{lines:[],newOffset:e};let n=u.openSync(this.metricsFile,"r");try{let r=t-e,i=Buffer.alloc(r);u.readSync(n,i,0,r,e);let s=i.toString("utf8"),a=s.lastIndexOf(`
29
- `);if(a<0)return{lines:[],newOffset:e};let c=s.slice(0,a+1),T=e+Buffer.byteLength(c,"utf8");return{lines:c.split(`
30
- `).filter(b=>b.trim().length>0),newOffset:T}}finally{u.closeSync(n)}}readCursor(){try{let e=JSON.parse(u.readFileSync(this.cursorFile,"utf8"));return typeof e.offset=="number"&&e.offset>=0?e.offset:0}catch{return 0}}writeCursor(e){try{u.mkdirSync(ye.dirname(this.cursorFile),{recursive:!0}),u.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 M=l(require("fs")),ke=l(require("os")),p=l(require("path")),d=class o{constructor(e){this.repoRoot=e;this.config=o.readJson(p.join(e,".dezycro","config.json"))}repoRoot;config;static at(e=process.cwd()){return new o(o.findRepoRoot(e)??p.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)}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=[p.join(this.repoRoot,".dezycro","companion-token.local.json"),p.join(ke.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(p.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=p.resolve(e||process.cwd());for(let n=0;n<64;n+=1){if(M.existsSync(p.join(t,".dezycro")))return t;let r=p.dirname(t);if(r===t)return null;t=r}return null}static readJson(e){try{return JSON.parse(M.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 O=class o{run(e){if(e.includes("--upload-dry-run")){this.uploadDryRun();return}let t=v.defaultFile(),n=v.fromFile(t);if(e.includes("--json")){process.stdout.write(`${JSON.stringify(n,null,2)}
26
+ `)}};var Te=l(require("node:path"));var O=l(require("node:fs")),me=l(require("node:os")),k=l(require("node:path")),$e="DZ_METRICS_DIR",Pe="DZ_METRICS",v=class o{file;constructor(e="gateway"){this.file=o.prepare(e)}static enabled(){return process.env[Pe]!=="0"}static dir(){let e=process.env[$e];if(e)return e;let t=me.homedir();switch(process.platform){case"win32":return k.join(process.env.LOCALAPPDATA||k.join(t,"AppData","Local"),"Dezycro","metrics");case"darwin":return k.join(t,"Library","Application Support","Dezycro","metrics");default:return k.join(process.env.XDG_STATE_HOME||k.join(t,".local","state"),"dezycro","metrics")}}record(e){if(this.file)try{O.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 O.mkdirSync(t,{recursive:!0}),k.join(t,`${e}.jsonl`)}catch{return null}}};var Me={rules:[{nameIncludes:ne.UpdateTask,inputField:re.Status,inputValues:[L.Done,L.Pushed],requireAll:[f.SpecPublished,f.VerifiedRecently],reason:"Cannot mark a task DONE/PUSHED yet."}]},G=class o{constructor(e,t){this.policy=e;this.state=t}policy;state;static STATE_PREDICATES={[f.SpecPublished]:e=>!!e&&e.needsSpecPublish!==!0,[f.VerifiedRecently]:e=>!e||!e.lastVerifyCompletionTs?!1:e.lastEditTs?Date.parse(e.lastVerifyCompletionTs)>=Date.parse(e.lastEditTs):!0};static FAILED_HINT={[f.SpecPublished]:"spec not published (controller/API changed) \u2014 run /dezycro:publish-spec",[f.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 a=t?.[n.inputField],c=(n.inputValues??[]).map(b=>String(b).toUpperCase());if(a==null||!c.includes(String(a).toUpperCase()))continue}let r=n.requireAll??[];if(r.length===0)return this.blocked(e,n.reason);let s=r.filter(a=>!o.STATE_PREDICATES[a]?.(this.state));if(s.length===0)continue;let i=s.map(a=>o.FAILED_HINT[a]||a).join("; ");return this.blocked(e,`${n.reason||"Blocked by Dezycro policy."} ${i}.`)}return null}blocked(e,t){return{toolName:e||"?",detail:t||"Blocked by Dezycro policy."}}};var it=new Set([h.ContentBlockStart,h.ContentBlockDelta,h.ContentBlockStop]);var ge=l(require("node:fs")),ye=l(require("node:path"));var T=class o{static BIG_TOOL_CHARS=4e3;static defaultFile(){return ye.join(v.dir(),"gateway.jsonl")}static fromFile(e=o.defaultFile()){let t;try{t=ge.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 u=l(require("node:fs")),ke=l(require("node:path")),R=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),s=r.turns.length+r.compactions.length,i={turns:r.turns.length,compactions:r.compactions.length,newOffset:n,sent:!1,dryRun:e};return e?i:s===0?(n!==this.readCursor()&&this.writeCursor(n),i):(await this.postAll(r),this.writeCursor(n),{...i,sent:!0})}static toBatch(e){let t=[],n=[];for(let r of e){let s;try{s=JSON.parse(r)}catch{continue}typeof s.ts=="string"&&(s.type==="turn"?t.push(o.mapTurn(s)):s.type==="compaction"&&n.push(o.mapCompaction(s)))}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=u.statSync(this.metricsFile).size}catch{return{lines:[],newOffset:e}}if(e>t&&(e=0),e===t)return{lines:[],newOffset:e};let n=u.openSync(this.metricsFile,"r");try{let r=t-e,s=Buffer.alloc(r);u.readSync(n,s,0,r,e);let i=s.toString("utf8"),a=i.lastIndexOf(`
29
+ `);if(a<0)return{lines:[],newOffset:e};let c=i.slice(0,a+1),b=e+Buffer.byteLength(c,"utf8");return{lines:c.split(`
30
+ `).filter(w=>w.trim().length>0),newOffset:b}}finally{u.closeSync(n)}}readCursor(){try{let e=JSON.parse(u.readFileSync(this.cursorFile,"utf8"));return typeof e.offset=="number"&&e.offset>=0?e.offset:0}catch{return 0}}writeCursor(e){try{u.mkdirSync(ke.dirname(this.cursorFile),{recursive:!0}),u.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 s=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(!s.ok)throw new Error(`usage-telemetry upload returned ${s.status}`)}finally{clearTimeout(r)}}};var z=l(require("fs")),ve=l(require("os")),p=l(require("path")),d=class o{constructor(e){this.repoRoot=e;this.config=o.readJson(p.join(e,".dezycro","config.json"))}repoRoot;config;static at(e=process.cwd()){return new o(o.findRepoRoot(e)??p.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)}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(s=>o.isObj(s)&&s.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=[p.join(this.repoRoot,".dezycro","companion-token.local.json"),p.join(ve.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(p.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=p.resolve(e||process.cwd());for(let n=0;n<64;n+=1){if(z.existsSync(p.join(t,".dezycro")))return t;let r=p.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 U=class o{run(e){if(e.includes("--upload-dry-run")){this.uploadDryRun();return}let t=T.defaultFile(),n=T.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=d.at(process.cwd()),n=t.connection(),r=v.defaultFile(),i=ve.join(k.dir(),"gateway.upload-cursor.json"),s="error"in n?{apiUrl:"(unset)",workspaceId:t.workspaceId??"(unset)",token:"(unset)"}:n,a=await new C({...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 ${a.turns} turn + ${a.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=d.at(process.cwd()),n=t.connection(),r=T.defaultFile(),s=Te.join(v.dir(),"gateway.upload-cursor.json"),i="error"in n?{apiUrl:"(unset)",workspaceId:t.workspaceId??"(unset)",token:"(unset)"}:n,a=await new R({...i,metricsFile:r,cursorFile:s}).upload({dryRun:!0});e("Dezycro telemetry \u2014 dry run (nothing sent)"),e(` metrics file ${r}`),e(` target ${i.apiUrl}/api/v1/workspaces/${i.workspaceId}/usage-telemetry`),"error"in n&&e(` connection NOT configured \u2014 ${n.error}`),e(` pending upload ${a.turns} turn + ${a.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
- `;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 a=[`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);a.push(`cache hit ${c.toFixed(1)}%`)}return s.push(a.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(`
34
+ `;let n=c=>c.toLocaleString("en-US"),r=c=>n(Math.round(c/4)),s=c=>e.turns>0?n(Math.round(c/e.turns)):"0",i=[];i.push("Dezycro gateway metrics"),i.push(` ${t}`),e.firstTs&&e.lastTs&&i.push(` ${e.firstTs} \u2192 ${e.lastTs}`),i.push(""),i.push(`Turns: ${n(e.turns)} errors: ${n(e.errorTurns)} model time: ${(e.totalDurationMs/1e3).toFixed(0)}s`);let a=[`fresh input ~${s(e.inputTokens)} tok/turn`,`output ~${s(e.outputTokens)} tok/turn`];if(e.cacheReadTokens+e.inputTokens>0){let c=100*e.cacheReadTokens/(e.cacheReadTokens+e.inputTokens);a.push(`cache hit ${c.toFixed(1)}%`)}return i.push(a.join(" \xB7 ")),i.push(""),i.push("Where the tokens are (per request \u2014 content-free)"),i.push(` tool definitions ${n(e.maxToolDefChars)} chars (~${r(e.maxToolDefChars)} tok) \u2190 fixed per-request cost; schema-bloat lever`),i.push(` system prompt ${n(e.maxSystemChars)} chars (~${r(e.maxSystemChars)} tok)`),i.push(` fresh tool results ${n(e.tailResultChars)} chars (~${r(e.tailResultChars)} tok) total \xB7 biggest single ${n(e.maxFreshToolChars)} chars (~${r(e.maxFreshToolChars)} tok)`),i.push(` fresh user text ${n(e.tailTextChars)} chars (~${r(e.tailTextChars)} tok) total`),i.push(""),i.push("Cache"),i.push(` read ${n(e.cacheReadTokens)} tok \xB7 create ${n(e.cacheCreationTokens)} tok`),e.maxCacheCreationTokens>0&&i.push(` largest prefix write ${n(e.maxCacheCreationTokens)} tok (a spike here = cache-bust \u2014 the costly case)`),i.push(""),i.push("Request-side compaction opportunity (not yet compacted)"),i.push(` turns with >1k-tok fresh tool output ${n(e.bigToolTurns)}`),i.push(" (fresh tool results are the safe headroom; reversible elision is the lever \u2014 needs sizing first)"),i.push(""),i.push("Source-side compaction (shell output \u2014 already applied)"),i.push(` est. tokens saved ${n(e.estTokensSaved)} over ${n(e.compactions)} compaction(s)${o.breakdown(e.commands)}`),i.push(` lines elided ${n(e.linesElided)}`),i.push(""),i.push(`Totals: input ${n(e.inputTokens)} \xB7 output ${n(e.outputTokens)} \xB7 cache read ${n(e.cacheReadTokens)} \xB7 cache create ${n(e.cacheCreationTokens)}`),i.push(`Gate blocks: ${n(e.gateBlocks)}`),i.push(`Skills fired:${o.breakdown(e.skillsTriggered)||" none"}`),i.push(`Models:${o.breakdown(e.models)||" (none)"}`),i.push(""),`${i.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 q=class{now(){return Date.now()}nowIso(){return new Date().toISOString()}sleep(e){return new Promise(t=>setTimeout(t,e))}},Y=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 a=await s.json();return{nextCursor:typeof a.nextCursor=="string"?a.nextCursor:e,events:Array.isArray(a.events)?a.events:[]}}finally{clearTimeout(i)}}},U=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},K=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 a=await this.gateway.wait(t,s);n=!0;let[c]=a.events;if(c)return{outcome:"EVENT",event:c};t=a.nextCursor||t}catch(a){r=a instanceof Error?a.message:String(a),this.clock.now()<e&&await this.clock.sleep(this.policy.errorBackoffMs)}}return n?{outcome:"TIMEOUT"}:{outcome:"ERROR",error:r||"event wait failed"}}},X=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}}},Q=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=U.DEFAULT_TOTAL_TIMEOUT_SEC,i=!1;for(let s=0;s<e.length;s+=1){let a=e[s];if(a==="--event-types")t=e[s+1]??null,s+=1;else if(a==="--feature")n=e[s+1]??null,s+=1;else if(a==="--timeout"){let c=Number(e[s+1]);Number.isFinite(c)&&c>0&&(r=c),s+=1}else a==="--json"&&(i=!0)}return new o(t,n,r,i)}},B=class{constructor(e=new q){this.clock=e}clock;async run(e){let t=Q.fromArgv(e),n=d.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 Y(r.apiUrl,r.workspaceId,i,r.token,t.eventTypes),a=await new K(s,this.clock,new U(t.timeoutSec)).awaitEvent(),c=new X(a,t.eventTypes,t.timeoutSec);process.stdout.write(`${t.json?JSON.stringify(a):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 q=class{now(){return Date.now()}nowIso(){return new Date().toISOString()}sleep(e){return new Promise(t=>setTimeout(t,e))}},Y=class{constructor(e,t,n,r,s){this.apiUrl=e;this.workspaceId=t;this.featureId=n;this.token=r;this.eventTypes=s}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,s=setTimeout(()=>r.abort(),(t+10)*1e3);try{let i=await fetch(n.toString(),{method:"GET",headers:{Authorization:`Bearer ${this.token}`,Accept:"application/json"},signal:r.signal});if(!i.ok)throw new Error(`inbox/wait returned ${i.status}`);let a=await i.json();return{nextCursor:typeof a.nextCursor=="string"?a.nextCursor:e,events:Array.isArray(a.events)?a.events:[]}}finally{clearTimeout(s)}}},B=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},K=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 s=Math.ceil((e-this.clock.now())/1e3);if(s<=0)break;let i=Math.min(this.policy.perPollSec,s);try{let a=await this.gateway.wait(t,i);n=!0;let[c]=a.events;if(c)return{outcome:"EVENT",event:c};t=a.nextCursor||t}catch(a){r=a instanceof Error?a.message:String(a),this.clock.now()<e&&await this.clock.sleep(this.policy.errorBackoffMs)}}return n?{outcome:"TIMEOUT"}:{outcome:"ERROR",error:r||"event wait failed"}}},X=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}}},Q=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=B.DEFAULT_TOTAL_TIMEOUT_SEC,s=!1;for(let i=0;i<e.length;i+=1){let a=e[i];if(a==="--event-types")t=e[i+1]??null,i+=1;else if(a==="--feature")n=e[i+1]??null,i+=1;else if(a==="--timeout"){let c=Number(e[i+1]);Number.isFinite(c)&&c>0&&(r=c),i+=1}else a==="--json"&&(s=!0)}return new o(t,n,r,s)}},_=class{constructor(e=new q){this.clock=e}clock;async run(e){let t=Q.fromArgv(e),n=d.at(process.cwd()),r=n.connection();if("error"in r){this.fail(`not configured \u2014 ${r.error}`);return}let s=t.feature??n.activeFeature()?.featureId??null;if(!s){this.fail("no feature (pass --feature <id>, or run /dezycro:work to bind one)");return}let i=new Y(r.apiUrl,r.workspaceId,s,r.token,t.eventTypes),a=await new K(i,this.clock,new B(t.timeoutSec)).awaitEvent(),c=new X(a,t.eventTypes,t.timeoutSec);process.stdout.write(`${t.json?JSON.stringify(a):c.render()}
37
37
  `),process.exit(c.exitCode())}fail(e){process.stderr.write(`dezycro await-event: ${e}
38
- `),process.exit(2)}};var m=l(require("fs")),Te=l(require("path"));var _=class{file;constructor(e){this.file=Te.join(e,".dezycro","active-feature.json")}read(){try{let e=JSON.parse(m.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 m.writeFileSync(this.file,`${JSON.stringify({...t,active:e},null,2)}
39
- `),!0}catch{return!1}}clear(){try{if(m.existsSync(this.file))return m.unlinkSync(this.file),!0}catch{}return!1}};var N=class{run(e){let t=d.at(process.cwd()).repoRoot,n=new _(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 m=l(require("fs")),be=l(require("path"));var N=class{file;constructor(e){this.file=be.join(e,".dezycro","active-feature.json")}read(){try{let e=JSON.parse(m.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 m.writeFileSync(this.file,`${JSON.stringify({...t,active:e},null,2)}
39
+ `),!0}catch{return!1}}clear(){try{if(m.existsSync(this.file))return m.unlinkSync(this.file),!0}catch{}return!1}};var F=class{run(e){let t=d.at(process.cwd()).repoRoot,n=new N(t);if(e.includes("--clear")){let i=n.read()!==null;n.clear(),process.stdout.write(i?`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
- `);return}let i=r.featureName?`${r.featureName} (${r.featureId})`:r.featureId;process.stdout.write(`dezycro feature: ${i}
42
+ `);return}let s=r.featureName?`${r.featureName} (${r.featureId})`:r.featureId;process.stdout.write(`dezycro feature: ${s}
43
43
  active this session: ${r.active?"yes":"no"}
44
- `)}};var we=(a=>(a.Run="run",a.Setup="setup",a.ResolveAuth="resolve-auth",a.Completion="completion",a.Metrics="metrics",a.AwaitEvent="await-event",a.Feature="feature",a))(we||{}),Ue=new Set(["help","-h","--help"]),be=`dezycro \u2014 Dezycro for AI coding agents
44
+ `)}};var Se=(a=>(a.Run="run",a.Setup="setup",a.ResolveAuth="resolve-auth",a.Completion="completion",a.Metrics="metrics",a.AwaitEvent="await-event",a.Feature="feature",a))(Se||{}),Be=new Set(["help","-h","--help"]),we=`dezycro \u2014 Dezycro for AI coding agents
45
45
 
46
46
  Usage: dezycro <command> [args]
47
47
 
@@ -57,5 +57,5 @@ Commands:
57
57
  feature [--clear] Show the bound feature (and whether it's active this session); --clear wipes it (done with this feature)
58
58
 
59
59
  Gateway control: dezycro run --status dezycro run --stop
60
- Custom port: dezycro run --port <n> <agent> (overrides DZ_PORT, default 13579)`,ee=class{handlers=new Map([["run",e=>{new I().run(e)}],["setup",()=>new A().run()],["resolve-auth",e=>new D().run(e[0])],["completion",e=>new P().run(e)],["metrics",e=>new O().run(e)],["await-event",e=>{new B().run(e)}],["feature",e=>new N().run(e)]]);run(e){let[t,...n]=e,r=this.handlers.get(t);if(r){r(n);return}if(t===void 0||Ue.has(t)){console.log(be);return}console.error(`dezycro: unknown command '${t}'
61
- `),console.error(be),process.exit(2)}};new ee().run(process.argv.slice(2));0&&(module.exports={Command});
60
+ Custom port: dezycro run --port <n> <agent> (overrides DZ_PORT, default 13579)`,ee=class{handlers=new Map([["run",e=>{new A().run(e)}],["setup",()=>new D().run()],["resolve-auth",e=>new P().run(e[0])],["completion",e=>new M().run(e)],["metrics",e=>new U().run(e)],["await-event",e=>{new _().run(e)}],["feature",e=>new F().run(e)]]);run(e){let[t,...n]=e,r=this.handlers.get(t);if(r){r(n);return}if(t===void 0||Be.has(t)){console.log(we);return}console.error(`dezycro: unknown command '${t}'
61
+ `),console.error(we),process.exit(2)}};new ee().run(process.argv.slice(2));0&&(module.exports={Command});
@@ -1,35 +1,35 @@
1
- "use strict";var Se=Object.create;var z=Object.defineProperty;var ve=Object.getOwnPropertyDescriptor;var Ce=Object.getOwnPropertyNames;var xe=Object.getPrototypeOf,we=Object.prototype.hasOwnProperty;var Re=(n,e)=>{for(var t in e)z(n,t,{get:e[t],enumerable:!0})},oe=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of Ce(e))!we.call(n,o)&&o!==t&&z(n,o,{get:()=>e[o],enumerable:!(r=ve(e,o))||r.enumerable});return n};var c=(n,e,t)=>(t=n!=null?Se(xe(n)):{},oe(e||!n||!n.__esModule?z(t,"default",{value:n,enumerable:!0}):t,n)),Ee=n=>oe(z({},"__esModule",{value:!0}),n);var Oe={};Re(Oe,{Gateway:()=>F,createGatewayServer:()=>Le});module.exports=Ee(Oe);var ye=c(require("node:http")),ke=c(require("node:fs")),Te=c(require("node:path")),be=require("node:stream");var G=c(require("fs")),se=c(require("os")),g=c(require("path")),J=class n{constructor(e){this.repoRoot=e;this.config=n.readJson(g.join(e,".dezycro","config.json"))}repoRoot;config;static at(e=process.cwd()){return new n(n.findRepoRoot(e)??g.resolve(e))}get workspaceId(){return n.env("DZ_WORKSPACE_ID")??n.str(this.config?.workspaceId)}get tenantId(){return n.env("DZ_TENANT_ID")??n.str(this.config?.tenantId)}get projectId(){return n.str(this.config?.projectId)}get apiUrl(){let e=n.env("DZ_API_URL");if(e)return n.trimSlash(e);let t=Array.isArray(this.config?.environments)?this.config?.environments:[],r=t.find(s=>n.isObj(s)&&s.default===!0)??t[0],o=n.isObj(r)?n.str(r.apiUrl):null;return o?n.trimSlash(o):null}get token(){let e=n.env("DZ_TOKEN");if(e)return e;let t=[g.join(this.repoRoot,".dezycro","companion-token.local.json"),g.join(se.homedir(),".dezycro","token.json")];for(let r of t){let o=n.str(n.readJson(r)?.token);if(o)return o}return null}activeFeature(){let e=n.readJson(g.join(this.repoRoot,".dezycro","active-feature.json")),t=n.str(e?.featureId);if(!t)return null;let r=n.str(e?.workspaceId)??this.workspaceId;return r?{workspaceId:r,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 r=this.token;return r?{apiUrl:e,workspaceId:t,token:r}:{error:"no token (run `dezycro setup` or set DZ_TOKEN)"}}static findRepoRoot(e){let t=g.resolve(e||process.cwd());for(let r=0;r<64;r+=1){if(G.existsSync(g.join(t,".dezycro")))return t;let o=g.dirname(t);if(o===t)return null;t=o}return null}static readJson(e){try{return JSON.parse(G.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 d={MessageStart:"message_start",ContentBlockStart:"content_block_start",ContentBlockDelta:"content_block_delta",ContentBlockStop:"content_block_stop",MessageDelta:"message_delta",MessageStop:"message_stop"},$={User:"user",Assistant:"assistant",System:"system"},y={Text:"text",ToolUse:"tool_use"},H={Text:"text_delta",InputJson:"input_json_delta"},x={ToolUse:"tool_use",EndTurn:"end_turn"};var ie={UpdateTask:"update_task"},ae={Status:"status"},q={Done:"DONE",Pushed:"PUSHED"};var b={SpecPublished:"specPublished",VerifiedRecently:"verifiedRecently"};var w={Anthropic:"anthropic",OpenAI:"openai"};var X={Health:"/__dz/health",Stop:"/__dz/stop"},R={EventStream:"text/event-stream",Json:"application/json"};var k=class n{constructor(e){this.skills=e}skills;apply(e,t){let r=n.lastUserText(e),o=this.triggeredSkills(r),s=this.build(r);return s&&n.appendToLastUserMessage(e,t,s),{text:s,triggers:o}}triggeredSkills(e){let t=[];for(let r of Object.keys(this.skills??{}))e.includes(r)&&t.push(r);return t}static composition(e){return{toolDefChars:n.toolDefChars(e),systemChars:n.systemChars(e),...n.tailComposition(e)}}static emptyComposition(){return{toolDefChars:0,systemChars:0,tailResultChars:0,tailTextChars:0,freshToolChars:0}}static maxToolResultChars(e){return n.tailComposition(e).freshToolChars}static toolDefChars(e){return Array.isArray(e.tools)&&e.tools.length?JSON.stringify(e.tools).length:0}static systemChars(e){let t=e.system;if(typeof t=="string")return t.length;if(!Array.isArray(t))return 0;let r=0;for(let o of t)o&&typeof o.text=="string"&&(r+=o.text.length);return r}static tailComposition(e){let t=n.lastUserContent(e);if(typeof t=="string")return{tailResultChars:0,tailTextChars:t.length,freshToolChars:0};if(!Array.isArray(t))return{tailResultChars:0,tailTextChars:0,freshToolChars:0};let r=0,o=0,s=0;for(let i of t)if(i)if(i.type==="tool_result"){let a=n.textLength(i.content);r+=a,s=Math.max(s,a)}else typeof i.text=="string"&&(o+=i.text.length);return{tailResultChars:r,tailTextChars:o,freshToolChars:s}}static lastUserContent(e){let t=Array.isArray(e.messages)?e.messages:null;if(!t)return null;let r=t.length-1;for(;r>=0&&t[r].role!==$.User;)r-=1;if(r<0)return null;let o=t[r].content;return typeof o=="string"||Array.isArray(o)?o:null}static textLength(e){if(typeof e=="string")return e.length;if(!Array.isArray(e))return 0;let t=0;for(let r of e)r&&typeof r.text=="string"&&(t+=r.text.length);return t}build(e){let t=[];for(let[r,o]of Object.entries(this.skills??{}))e.includes(r)&&t.push(o);return t.join(`
2
- `)}static lastUserText(e){let t=Array.isArray(e.messages)?e.messages:null;if(!t)return"";for(let r=t.length-1;r>=0;r-=1){let o=t[r];if(o.role===$.User){if(typeof o.content=="string")return o.content;if(Array.isArray(o.content))return o.content.map(s=>typeof s=="string"?s:"text"in s&&typeof s.text=="string"?s.text:"").join(" ")}}return""}static appendToLastUserMessage(e,t,r){if(!r)return e;let o=Array.isArray(e.messages)?e.messages:null;if(!o||!o.length)return t===w.OpenAI&&typeof e.input=="string"&&(e.input+=`
1
+ "use strict";var ve=Object.create;var G=Object.defineProperty;var Ce=Object.getOwnPropertyDescriptor;var xe=Object.getOwnPropertyNames;var we=Object.getPrototypeOf,Re=Object.prototype.hasOwnProperty;var Ee=(n,e)=>{for(var t in e)G(n,t,{get:e[t],enumerable:!0})},ie=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of xe(e))!Re.call(n,o)&&o!==t&&G(n,o,{get:()=>e[o],enumerable:!(r=Ce(e,o))||r.enumerable});return n};var c=(n,e,t)=>(t=n!=null?ve(we(n)):{},ie(e||!n||!n.__esModule?G(t,"default",{value:n,enumerable:!0}):t,n)),Ae=n=>ie(G({},"__esModule",{value:!0}),n);var Pe={};Ee(Pe,{Gateway:()=>_,createGatewayServer:()=>Le});module.exports=Ae(Pe);var be=c(require("node:http")),F=c(require("node:fs")),z=c(require("node:path")),Se=require("node:stream");var H=c(require("fs")),ae=c(require("os")),g=c(require("path")),$=class n{constructor(e){this.repoRoot=e;this.config=n.readJson(g.join(e,".dezycro","config.json"))}repoRoot;config;static at(e=process.cwd()){return new n(n.findRepoRoot(e)??g.resolve(e))}get workspaceId(){return n.env("DZ_WORKSPACE_ID")??n.str(this.config?.workspaceId)}get tenantId(){return n.env("DZ_TENANT_ID")??n.str(this.config?.tenantId)}get projectId(){return n.str(this.config?.projectId)}get apiUrl(){let e=n.env("DZ_API_URL");if(e)return n.trimSlash(e);let t=Array.isArray(this.config?.environments)?this.config?.environments:[],r=t.find(s=>n.isObj(s)&&s.default===!0)??t[0],o=n.isObj(r)?n.str(r.apiUrl):null;return o?n.trimSlash(o):null}get token(){let e=n.env("DZ_TOKEN");if(e)return e;let t=[g.join(this.repoRoot,".dezycro","companion-token.local.json"),g.join(ae.homedir(),".dezycro","token.json")];for(let r of t){let o=n.str(n.readJson(r)?.token);if(o)return o}return null}activeFeature(){let e=n.readJson(g.join(this.repoRoot,".dezycro","active-feature.json")),t=n.str(e?.featureId);if(!t)return null;let r=n.str(e?.workspaceId)??this.workspaceId;return r?{workspaceId:r,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 r=this.token;return r?{apiUrl:e,workspaceId:t,token:r}:{error:"no token (run `dezycro setup` or set DZ_TOKEN)"}}static findRepoRoot(e){let t=g.resolve(e||process.cwd());for(let r=0;r<64;r+=1){if(H.existsSync(g.join(t,".dezycro")))return t;let o=g.dirname(t);if(o===t)return null;t=o}return null}static readJson(e){try{return JSON.parse(H.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 d={MessageStart:"message_start",ContentBlockStart:"content_block_start",ContentBlockDelta:"content_block_delta",ContentBlockStop:"content_block_stop",MessageDelta:"message_delta",MessageStop:"message_stop"},V={User:"user",Assistant:"assistant",System:"system"},y={Text:"text",ToolUse:"tool_use"},W={Text:"text_delta",InputJson:"input_json_delta"},x={ToolUse:"tool_use",EndTurn:"end_turn"};var le={UpdateTask:"update_task"},ce={Status:"status"},Q={Done:"DONE",Pushed:"PUSHED"};var b={SpecPublished:"specPublished",VerifiedRecently:"verifiedRecently"};var w={Anthropic:"anthropic",OpenAI:"openai"};var ee={Health:"/__dz/health",Stop:"/__dz/stop"},pe="last-opus-model",R={EventStream:"text/event-stream",Json:"application/json"};var k=class n{constructor(e){this.skills=e}skills;apply(e,t){let r=n.lastUserText(e),o=this.triggeredSkills(r),s=this.build(r);return s&&n.appendToLastUserMessage(e,t,s),{text:s,triggers:o}}triggeredSkills(e){let t=[];for(let r of Object.keys(this.skills??{}))e.includes(r)&&t.push(r);return t}static composition(e){return{toolDefChars:n.toolDefChars(e),systemChars:n.systemChars(e),...n.tailComposition(e)}}static emptyComposition(){return{toolDefChars:0,systemChars:0,tailResultChars:0,tailTextChars:0,freshToolChars:0}}static maxToolResultChars(e){return n.tailComposition(e).freshToolChars}static toolDefChars(e){return Array.isArray(e.tools)&&e.tools.length?JSON.stringify(e.tools).length:0}static systemChars(e){let t=e.system;if(typeof t=="string")return t.length;if(!Array.isArray(t))return 0;let r=0;for(let o of t)o&&typeof o.text=="string"&&(r+=o.text.length);return r}static tailComposition(e){let t=n.lastUserContent(e);if(typeof t=="string")return{tailResultChars:0,tailTextChars:t.length,freshToolChars:0};if(!Array.isArray(t))return{tailResultChars:0,tailTextChars:0,freshToolChars:0};let r=0,o=0,s=0;for(let i of t)if(i)if(i.type==="tool_result"){let a=n.textLength(i.content);r+=a,s=Math.max(s,a)}else typeof i.text=="string"&&(o+=i.text.length);return{tailResultChars:r,tailTextChars:o,freshToolChars:s}}static lastUserContent(e){let t=Array.isArray(e.messages)?e.messages:null;if(!t)return null;let r=t.length-1;for(;r>=0&&t[r].role!==V.User;)r-=1;if(r<0)return null;let o=t[r].content;return typeof o=="string"||Array.isArray(o)?o:null}static textLength(e){if(typeof e=="string")return e.length;if(!Array.isArray(e))return 0;let t=0;for(let r of e)r&&typeof r.text=="string"&&(t+=r.text.length);return t}build(e){let t=[];for(let[r,o]of Object.entries(this.skills??{}))e.includes(r)&&t.push(o);return t.join(`
2
+ `)}static lastUserText(e){let t=Array.isArray(e.messages)?e.messages:null;if(!t)return"";for(let r=t.length-1;r>=0;r-=1){let o=t[r];if(o.role===V.User){if(typeof o.content=="string")return o.content;if(Array.isArray(o.content))return o.content.map(s=>typeof s=="string"?s:"text"in s&&typeof s.text=="string"?s.text:"").join(" ")}}return""}static appendToLastUserMessage(e,t,r){if(!r)return e;let o=Array.isArray(e.messages)?e.messages:null;if(!o||!o.length)return t===w.OpenAI&&typeof e.input=="string"&&(e.input+=`
3
3
 
4
- ${n.tagged(r)}`),e;let s=o.length-1;for(;s>=0&&o[s].role!==$.User;)s-=1;if(s<0)return e;let i=o[s],a=n.tagged(r);return typeof i.content=="string"?i.content+=`
4
+ ${n.tagged(r)}`),e;let s=o.length-1;for(;s>=0&&o[s].role!==V.User;)s-=1;if(s<0)return e;let i=o[s],a=n.tagged(r);return typeof i.content=="string"?i.content+=`
5
5
 
6
6
  ${a}`:Array.isArray(i.content)&&i.content.push({type:y.Text,text:a}),e}static tagged(e){return`<dezycro-companion>
7
7
  ${e}
8
- </dezycro-companion>`}};var Q={rules:[{nameIncludes:ie.UpdateTask,inputField:ae.Status,inputValues:[q.Done,q.Pushed],requireAll:[b.SpecPublished,b.VerifiedRecently],reason:"Cannot mark a task DONE/PUSHED yet."}]},A=class n{constructor(e,t){this.policy=e;this.state=t}policy;state;static STATE_PREDICATES={[b.SpecPublished]:e=>!!e&&e.needsSpecPublish!==!0,[b.VerifiedRecently]:e=>!e||!e.lastVerifyCompletionTs?!1:e.lastEditTs?Date.parse(e.lastVerifyCompletionTs)>=Date.parse(e.lastEditTs):!0};static FAILED_HINT={[b.SpecPublished]:"spec not published (controller/API changed) \u2014 run /dezycro:publish-spec",[b.VerifiedRecently]:"no passing verify since last edit \u2014 run /dezycro:verify"};decide(e,t){for(let r of this.policy?.rules??[]){if(!e||!e.includes(r.nameIncludes))continue;if(r.inputField){let a=t?.[r.inputField],l=(r.inputValues??[]).map(u=>String(u).toUpperCase());if(a==null||!l.includes(String(a).toUpperCase()))continue}let o=r.requireAll??[];if(o.length===0)return this.blocked(e,r.reason);let s=o.filter(a=>!n.STATE_PREDICATES[a]?.(this.state));if(s.length===0)continue;let i=s.map(a=>n.FAILED_HINT[a]||a).join("; ");return this.blocked(e,`${r.reason||"Blocked by Dezycro policy."} ${i}.`)}return null}blocked(e,t){return{toolName:e||"?",detail:t||"Blocked by Dezycro policy."}}};var Ae=new Set([d.ContentBlockStart,d.ContentBlockDelta,d.ContentBlockStop]),m=class n{constructor(e,t){this.name=e;this.data=t}name;data;static parse(e){let t=null,r=null;for(let s of e.split(`
8
+ </dezycro-companion>`}};var te={rules:[{nameIncludes:le.UpdateTask,inputField:ce.Status,inputValues:[Q.Done,Q.Pushed],requireAll:[b.SpecPublished,b.VerifiedRecently],reason:"Cannot mark a task DONE/PUSHED yet."}]},A=class n{constructor(e,t){this.policy=e;this.state=t}policy;state;static STATE_PREDICATES={[b.SpecPublished]:e=>!!e&&e.needsSpecPublish!==!0,[b.VerifiedRecently]:e=>!e||!e.lastVerifyCompletionTs?!1:e.lastEditTs?Date.parse(e.lastVerifyCompletionTs)>=Date.parse(e.lastEditTs):!0};static FAILED_HINT={[b.SpecPublished]:"spec not published (controller/API changed) \u2014 run /dezycro:publish-spec",[b.VerifiedRecently]:"no passing verify since last edit \u2014 run /dezycro:verify"};decide(e,t){for(let r of this.policy?.rules??[]){if(!e||!e.includes(r.nameIncludes))continue;if(r.inputField){let a=t?.[r.inputField],l=(r.inputValues??[]).map(u=>String(u).toUpperCase());if(a==null||!l.includes(String(a).toUpperCase()))continue}let o=r.requireAll??[];if(o.length===0)return this.blocked(e,r.reason);let s=o.filter(a=>!n.STATE_PREDICATES[a]?.(this.state));if(s.length===0)continue;let i=s.map(a=>n.FAILED_HINT[a]||a).join("; ");return this.blocked(e,`${r.reason||"Blocked by Dezycro policy."} ${i}.`)}return null}blocked(e,t){return{toolName:e||"?",detail:t||"Blocked by Dezycro policy."}}};var Be=new Set([d.ContentBlockStart,d.ContentBlockDelta,d.ContentBlockStop]),m=class n{constructor(e,t){this.name=e;this.data=t}name;data;static parse(e){let t=null,r=null;for(let s of e.split(`
9
9
  `))s.startsWith("event:")?t=s.slice(6).trim():s.startsWith("data:")&&(r=s.slice(5).trim());let o=null;try{o=r?JSON.parse(r):null}catch{o=null}return o?new n(t??String(o.type??""),o):null}static parseStream(e){return e.split(`
10
10
 
11
- `).filter(t=>t.trim().length>0).map(t=>n.parse(t)).filter(t=>t!==null)}static of(e){return new n(e.type,e)}static toolUseOf(e){return e?.type===y.ToolUse?e:null}get type(){return String(this.data.type??"")}get index(){return Number(this.data.index)}is(e){return this.type===e}get isContentBlockEvent(){return Ae.has(this.type)}get toolUse(){return n.toolUseOf(this.data.content_block)}get inputJsonChunk(){let e=this.data.delta;return e?.type===H.InputJson?e.partial_json??"":""}get usage(){let e=this.data.message,t=this.data.usage??e?.usage;return t?{inputTokens:t.input_tokens,outputTokens:t.output_tokens,cacheReadTokens:t.cache_read_input_tokens,cacheCreationTokens:t.cache_creation_input_tokens}:null}get model(){return this.data.message?.model??null}withIndex(e){return new n(this.name,{...this.data,index:e})}withStopReasonEnded(){let e=JSON.parse(JSON.stringify(this.data));return e.delta?.stop_reason===x.ToolUse&&(e.delta.stop_reason=x.EndTurn),new n(this.name,e)}serialize(){return`event: ${this.name}
11
+ `).filter(t=>t.trim().length>0).map(t=>n.parse(t)).filter(t=>t!==null)}static of(e){return new n(e.type,e)}static toolUseOf(e){return e?.type===y.ToolUse?e:null}get type(){return String(this.data.type??"")}get index(){return Number(this.data.index)}is(e){return this.type===e}get isContentBlockEvent(){return Be.has(this.type)}get toolUse(){return n.toolUseOf(this.data.content_block)}get inputJsonChunk(){let e=this.data.delta;return e?.type===W.InputJson?e.partial_json??"":""}get usage(){let e=this.data.message,t=this.data.usage??e?.usage;return t?{inputTokens:t.input_tokens,outputTokens:t.output_tokens,cacheReadTokens:t.cache_read_input_tokens,cacheCreationTokens:t.cache_creation_input_tokens}:null}get model(){return this.data.message?.model??null}withIndex(e){return new n(this.name,{...this.data,index:e})}withStopReasonEnded(){let e=JSON.parse(JSON.stringify(this.data));return e.delta?.stop_reason===x.ToolUse&&(e.delta.stop_reason=x.EndTurn),new n(this.name,e)}serialize(){return`event: ${this.name}
12
12
  data: ${JSON.stringify(this.data)}
13
13
 
14
14
  `}};var B=class{constructor(e){this.reasons=e}reasons;get isEmpty(){return this.reasons.length===0}text(){let e=this.reasons.map(t=>`\u2022 ${t.toolName}: ${t.detail}`).join(`
15
15
  `);return`\u26D4 Dezycro blocked ${this.reasons.length} tool call(s):
16
16
  ${e}
17
- Do the required step, then retry.`}sseEvents(e){return[m.of({type:d.ContentBlockStart,index:e,content_block:{type:y.Text,text:""}}),m.of({type:d.ContentBlockDelta,index:e,delta:{type:H.Text,text:this.text()}}),m.of({type:d.ContentBlockStop,index:e})].map(t=>t.serialize()).join("")}};var E=class{next=0;mapped=new Map;take(e){let t=this.next++;return this.mapped.set(e,t),t}of(e){return this.mapped.get(e)??e}reserve(){return this.next++}};var T=class{constructor(e){this.engine=e}engine;blockedReasons=[];sawAllowedToolUse=!1;judge(e,t){let r=this.engine.decide(e,t);return r?(this.blockedReasons.push(r),!0):(this.sawAllowedToolUse=!0,!1)}parseToolInput(e){try{return e?JSON.parse(e):{}}catch{return{}}}get denial(){return new B(this.blockedReasons)}get blockedCount(){return this.blockedReasons.length}};var D=class extends T{rewrite(e){try{if(!e||!Array.isArray(e.content))return e;let t=e.content.filter(o=>{let s=m.toolUseOf(o);return s?!this.judge(s.name,s.input??{}):!0}),r=this.denial;return r.isEmpty||(t.push({type:y.Text,text:r.text()}),e.content=t,!this.sawAllowedToolUse&&e.stop_reason===x.ToolUse&&(e.stop_reason=x.EndTurn)),e}catch{return e}}};var I=class extends T{pending="";remapper=new E;openTool=null;denialEmitted=!1;push(e){this.pending+=e;let t="",r;for(;(r=this.pending.indexOf(`
17
+ Do the required step, then retry.`}sseEvents(e){return[m.of({type:d.ContentBlockStart,index:e,content_block:{type:y.Text,text:""}}),m.of({type:d.ContentBlockDelta,index:e,delta:{type:W.Text,text:this.text()}}),m.of({type:d.ContentBlockStop,index:e})].map(t=>t.serialize()).join("")}};var E=class{next=0;mapped=new Map;take(e){let t=this.next++;return this.mapped.set(e,t),t}of(e){return this.mapped.get(e)??e}reserve(){return this.next++}};var T=class{constructor(e){this.engine=e}engine;blockedReasons=[];sawAllowedToolUse=!1;judge(e,t){let r=this.engine.decide(e,t);return r?(this.blockedReasons.push(r),!0):(this.sawAllowedToolUse=!0,!1)}parseToolInput(e){try{return e?JSON.parse(e):{}}catch{return{}}}get denial(){return new B(this.blockedReasons)}get blockedCount(){return this.blockedReasons.length}};var D=class extends T{rewrite(e){try{if(!e||!Array.isArray(e.content))return e;let t=e.content.filter(o=>{let s=m.toolUseOf(o);return s?!this.judge(s.name,s.input??{}):!0}),r=this.denial;return r.isEmpty||(t.push({type:y.Text,text:r.text()}),e.content=t,!this.sawAllowedToolUse&&e.stop_reason===x.ToolUse&&(e.stop_reason=x.EndTurn)),e}catch{return e}}};var I=class extends T{pending="";remapper=new E;openTool=null;denialEmitted=!1;push(e){this.pending+=e;let t="",r;for(;(r=this.pending.indexOf(`
18
18
 
19
19
  `))!==-1;){let o=this.pending.slice(0,r);this.pending=this.pending.slice(r+2),o.trim()&&(t+=this.handle(o))}return t}flush(){let e="";return this.pending.trim()&&(e+=this.handle(this.pending),this.pending=""),e+this.emitDenialIfNeeded()}handle(e){let t=m.parse(e);if(!t)return`${e}
20
20
 
21
- `;switch(t.type){case d.ContentBlockStart:return this.onBlockStart(t);case d.ContentBlockDelta:return this.onBlockDelta(t);case d.ContentBlockStop:return this.onBlockStop(t);case d.MessageDelta:return this.emitDenialIfNeeded()+(this.sawAllowedToolUse?t:t.withStopReasonEnded()).serialize();default:return t.serialize()}}onBlockStart(e){let t=e.toolUse;return t?(this.openTool={originalIndex:e.index,toolName:t.name,inputJson:"",bufferedEvents:[e]},""):e.withIndex(this.remapper.take(e.index)).serialize()}onBlockDelta(e){return this.openTool&&e.index===this.openTool.originalIndex?(this.openTool.inputJson+=e.inputJsonChunk,this.openTool.bufferedEvents.push(e),""):e.withIndex(this.remapper.of(e.index)).serialize()}onBlockStop(e){return this.openTool&&e.index===this.openTool.originalIndex?this.closeOpenTool(e):e.withIndex(this.remapper.of(e.index)).serialize()}closeOpenTool(e){let t=this.openTool;if(this.openTool=null,this.judge(t.toolName,this.parseToolInput(t.inputJson)))return"";let r=this.remapper.take(t.originalIndex);return t.bufferedEvents.map(s=>s.withIndex(r).serialize()).join("")+e.withIndex(r).serialize()}emitDenialIfNeeded(){let e=this.denial;return e.isEmpty||this.denialEmitted?"":(this.denialEmitted=!0,e.sseEvents(this.remapper.reserve()))}};var ce=require("node:util"),pe=require("tslog");var V=c(require("node:fs")),le=c(require("node:os")),S=c(require("node:path")),Be="DZ_LOG_DIR",U=class n{stream;constructor(e){this.stream=n.open(e)}static dir(){let e=process.env[Be];if(e)return e;let t=le.homedir();switch(process.platform){case"win32":return S.join(process.env.LOCALAPPDATA||S.join(t,"AppData","Local"),"Dezycro","logs");case"darwin":return S.join(t,"Library","Logs","Dezycro");default:return S.join(process.env.XDG_STATE_HOME||S.join(t,".local","state"),"dezycro","logs")}}write(e){(this.stream??process.stderr).write(e)}static open(e){try{let t=n.dir();return V.mkdirSync(t,{recursive:!0}),V.createWriteStream(S.join(t,`${e}.log`),{flags:"a"})}catch{return null}}};var ee={silly:0,trace:1,debug:2,info:3,warn:4,error:5,fatal:6},W=3,te="DZ_LOG_LEVEL";var De="{{dateIsoStr}} {{logLevelName}} [{{name}}] ",L=class n{constructor(e,t=new U(e),r=n.resolveMinLevel(process.env[te])){this.tag=e;this.impl=new pe.Logger({name:e,type:"pretty",minLevel:r,stylePrettyLogs:!1,prettyLogTimeZone:"UTC",prettyLogTemplate:De,hideLogPositionForProduction:!0,overwrite:{transportFormatted:(o,s,i)=>t.write(n.format(o,s,i))}})}tag;impl;silly(...e){this.impl.silly(...e)}trace(...e){this.impl.trace(...e)}debug(...e){this.impl.debug(...e)}info(...e){this.impl.info(...e)}warn(...e){this.impl.warn(...e)}error(...e){this.impl.error(...e)}fatal(...e){this.impl.fatal(...e)}static resolveMinLevel(e){return e?ee[e.trim().toLowerCase()]??W:W}static format(e,t,r){return`${[e.trimEnd(),...t.map(n.stringify),...r].join(" ")}
22
- `}static stringify(e){return typeof e=="string"?e:(0,ce.inspect)(e,{depth:3,breakLength:1/0})}};var Y=c(require("node:fs")),de=c(require("node:path"));var ue=c(require("node:fs")),v=c(require("node:path")),Z=class n{static MAX_DEPTH=6;static dir(){let e=__dirname;for(let t=0;t<n.MAX_DEPTH;t+=1){if(ue.existsSync(v.join(e,"package.json")))return e;e=v.dirname(e)}return v.resolve(__dirname,"..","..")}static file(...e){return v.join(n.dir(),...e)}};var O=class n{constructor(e=n.defaultDir()){this.dir=e}dir;load(){return Promise.resolve(n.scan(this.dir))}static defaultDir(){return Z.file("skills")}static scan(e){let t={},r;try{r=Y.readdirSync(e,{withFileTypes:!0})}catch{return t}for(let o of r){if(!o.isDirectory())continue;let s=de.join(e,o.name,"SKILL.md"),i;try{i=Y.readFileSync(s,"utf8")}catch{continue}let{name:a,body:l}=n.parseSkill(i),u=a||o.name;t[`/dezycro:${u}`]=n.instructionFor(u,l)}return t}static parseSkill(e){if(e.startsWith("---")){let t=e.indexOf(`
21
+ `;switch(t.type){case d.ContentBlockStart:return this.onBlockStart(t);case d.ContentBlockDelta:return this.onBlockDelta(t);case d.ContentBlockStop:return this.onBlockStop(t);case d.MessageDelta:return this.emitDenialIfNeeded()+(this.sawAllowedToolUse?t:t.withStopReasonEnded()).serialize();default:return t.serialize()}}onBlockStart(e){let t=e.toolUse;return t?(this.openTool={originalIndex:e.index,toolName:t.name,inputJson:"",bufferedEvents:[e]},""):e.withIndex(this.remapper.take(e.index)).serialize()}onBlockDelta(e){return this.openTool&&e.index===this.openTool.originalIndex?(this.openTool.inputJson+=e.inputJsonChunk,this.openTool.bufferedEvents.push(e),""):e.withIndex(this.remapper.of(e.index)).serialize()}onBlockStop(e){return this.openTool&&e.index===this.openTool.originalIndex?this.closeOpenTool(e):e.withIndex(this.remapper.of(e.index)).serialize()}closeOpenTool(e){let t=this.openTool;if(this.openTool=null,this.judge(t.toolName,this.parseToolInput(t.inputJson)))return"";let r=this.remapper.take(t.originalIndex);return t.bufferedEvents.map(s=>s.withIndex(r).serialize()).join("")+e.withIndex(r).serialize()}emitDenialIfNeeded(){let e=this.denial;return e.isEmpty||this.denialEmitted?"":(this.denialEmitted=!0,e.sseEvents(this.remapper.reserve()))}};var de=require("node:util"),me=require("tslog");var Z=c(require("node:fs")),ue=c(require("node:os")),S=c(require("node:path")),De="DZ_LOG_DIR",U=class n{stream;constructor(e){this.stream=n.open(e)}static dir(){let e=process.env[De];if(e)return e;let t=ue.homedir();switch(process.platform){case"win32":return S.join(process.env.LOCALAPPDATA||S.join(t,"AppData","Local"),"Dezycro","logs");case"darwin":return S.join(t,"Library","Logs","Dezycro");default:return S.join(process.env.XDG_STATE_HOME||S.join(t,".local","state"),"dezycro","logs")}}write(e){(this.stream??process.stderr).write(e)}static open(e){try{let t=n.dir();return Z.mkdirSync(t,{recursive:!0}),Z.createWriteStream(S.join(t,`${e}.log`),{flags:"a"})}catch{return null}}};var re={silly:0,trace:1,debug:2,info:3,warn:4,error:5,fatal:6},Y=3,ne="DZ_LOG_LEVEL";var Ie="{{dateIsoStr}} {{logLevelName}} [{{name}}] ",O=class n{constructor(e,t=new U(e),r=n.resolveMinLevel(process.env[ne])){this.tag=e;this.impl=new me.Logger({name:e,type:"pretty",minLevel:r,stylePrettyLogs:!1,prettyLogTimeZone:"UTC",prettyLogTemplate:Ie,hideLogPositionForProduction:!0,overwrite:{transportFormatted:(o,s,i)=>t.write(n.format(o,s,i))}})}tag;impl;silly(...e){this.impl.silly(...e)}trace(...e){this.impl.trace(...e)}debug(...e){this.impl.debug(...e)}info(...e){this.impl.info(...e)}warn(...e){this.impl.warn(...e)}error(...e){this.impl.error(...e)}fatal(...e){this.impl.fatal(...e)}static resolveMinLevel(e){return e?re[e.trim().toLowerCase()]??Y:Y}static format(e,t,r){return`${[e.trimEnd(),...t.map(n.stringify),...r].join(" ")}
22
+ `}static stringify(e){return typeof e=="string"?e:(0,de.inspect)(e,{depth:3,breakLength:1/0})}};var q=c(require("node:fs")),he=c(require("node:path"));var fe=c(require("node:fs")),v=c(require("node:path")),K=class n{static MAX_DEPTH=6;static dir(){let e=__dirname;for(let t=0;t<n.MAX_DEPTH;t+=1){if(fe.existsSync(v.join(e,"package.json")))return e;e=v.dirname(e)}return v.resolve(__dirname,"..","..")}static file(...e){return v.join(n.dir(),...e)}};var L=class n{constructor(e=n.defaultDir()){this.dir=e}dir;load(){return Promise.resolve(n.scan(this.dir))}static defaultDir(){return K.file("skills")}static scan(e){let t={},r;try{r=q.readdirSync(e,{withFileTypes:!0})}catch{return t}for(let o of r){if(!o.isDirectory())continue;let s=he.join(e,o.name,"SKILL.md"),i;try{i=q.readFileSync(s,"utf8")}catch{continue}let{name:a,body:l}=n.parseSkill(i),u=a||o.name;t[`/dezycro:${u}`]=n.instructionFor(u,l)}return t}static parseSkill(e){if(e.startsWith("---")){let t=e.indexOf(`
23
23
  ---`,3);if(t!==-1){let r=e.slice(3,t),o=e.slice(t+4).trimStart();return{name:n.frontmatterName(r),body:o}}}return{name:null,body:e}}static frontmatterName(e){let t="name:";for(let r of e.split(`
24
24
  `)){let o=r.trim();if(o.startsWith(t))return o.slice(t.length).trim()||null}return null}static instructionFor(e,t){return`The user invoked the Dezycro \`/dezycro:${e}\` command. Your harness may not support it natively \u2014 follow these instructions:
25
25
 
26
- ${t}`}};var P=class{constructor(e){this.sources=e}sources;async load(){return(await Promise.all(this.sources.map(t=>t.load()))).reduce((t,r)=>({...t,...r}),{})}};var K=c(require("node:fs")),me=c(require("node:os")),C=c(require("node:path")),Ie="DZ_METRICS_DIR",Ue="DZ_METRICS",h=class n{file;constructor(e="gateway"){this.file=n.prepare(e)}static enabled(){return process.env[Ue]!=="0"}static dir(){let e=process.env[Ie];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{K.appendFileSync(this.file,`${JSON.stringify({ts:new Date().toISOString(),...e})}
27
- `)}catch{}}static prepare(e){if(!n.enabled())return null;try{let t=n.dir();return K.mkdirSync(t,{recursive:!0}),C.join(t,`${e}.jsonl`)}catch{return null}}};var N=class{pending="";modelId=null;totals={inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheCreationTokens:0};feed(e){this.pending+=e;let t=this.pending.indexOf(`
26
+ ${t}`}};var P=class{constructor(e){this.sources=e}sources;async load(){return(await Promise.all(this.sources.map(t=>t.load()))).reduce((t,r)=>({...t,...r}),{})}};var X=c(require("node:fs")),ge=c(require("node:os")),C=c(require("node:path")),Ue="DZ_METRICS_DIR",Oe="DZ_METRICS",h=class n{file;constructor(e="gateway"){this.file=n.prepare(e)}static enabled(){return process.env[Oe]!=="0"}static dir(){let e=process.env[Ue];if(e)return e;let t=ge.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{X.appendFileSync(this.file,`${JSON.stringify({ts:new Date().toISOString(),...e})}
27
+ `)}catch{}}static prepare(e){if(!n.enabled())return null;try{let t=n.dir();return X.mkdirSync(t,{recursive:!0}),C.join(t,`${e}.jsonl`)}catch{return null}}};var M=class{pending="";modelId=null;totals={inputTokens:0,outputTokens:0,cacheReadTokens:0,cacheCreationTokens:0};feed(e){this.pending+=e;let t=this.pending.indexOf(`
28
28
 
29
29
  `);for(;t!==-1;)this.observe(this.pending.slice(0,t)),this.pending=this.pending.slice(t+2),t=this.pending.indexOf(`
30
30
 
31
- `)}get model(){return this.modelId}get usage(){return{...this.totals}}observe(e){let t=m.parse(e);if(!t)return;this.modelId??=t.model;let r=t.usage;r&&(r.inputTokens!=null&&(this.totals.inputTokens=r.inputTokens),r.outputTokens!=null&&(this.totals.outputTokens=r.outputTokens),r.cacheReadTokens!=null&&(this.totals.cacheReadTokens=r.cacheReadTokens),r.cacheCreationTokens!=null&&(this.totals.cacheCreationTokens=r.cacheCreationTokens))}};var fe=c(require("node:fs")),he=c(require("node:path"));var M=class n{static BIG_TOOL_CHARS=4e3;static defaultFile(){return he.join(h.dir(),"gateway.jsonl")}static fromFile(e=n.defaultFile()){let t;try{t=fe.readFileSync(e,"utf8")}catch{return n.empty()}return n.aggregate(t.split(`
32
- `))}static aggregate(e){let t=n.empty();for(let r of e){let o=n.parse(r);o&&(o.type==="turn"?n.addTurn(t,o):o.type==="compaction"&&n.addCompaction(t,o),n.trackTime(t,o.ts))}return t}static addTurn(e,t){e.turns+=1,e.inputTokens+=n.num(t.inputTokens),e.outputTokens+=n.num(t.outputTokens),e.cacheReadTokens+=n.num(t.cacheReadTokens),e.cacheCreationTokens+=n.num(t.cacheCreationTokens),e.totalDurationMs+=n.num(t.durationMs),e.gateBlocks+=n.num(t.blockedToolCalls);let r=n.num(t.freshToolChars);if(e.maxFreshToolChars=Math.max(e.maxFreshToolChars,r),r>n.BIG_TOOL_CHARS&&(e.bigToolTurns+=1),e.maxToolDefChars=Math.max(e.maxToolDefChars,n.num(t.toolDefChars)),e.maxSystemChars=Math.max(e.maxSystemChars,n.num(t.systemChars)),e.tailResultChars+=n.num(t.tailResultChars),e.tailTextChars+=n.num(t.tailTextChars),e.maxCacheCreationTokens=Math.max(e.maxCacheCreationTokens,n.num(t.cacheCreationTokens)),typeof t.status=="number"&&t.status!==200&&(e.errorTurns+=1),n.bump(e.models,typeof t.model=="string"?t.model:"(unknown)"),Array.isArray(t.skillsTriggered))for(let o of t.skillsTriggered)n.bump(e.skillsTriggered,String(o))}static addCompaction(e,t){e.compactions+=1,e.charsSaved+=n.num(t.charsSaved),e.estTokensSaved+=n.num(t.estTokensSaved),e.linesElided+=n.num(t.elidedLines),n.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 f=c(require("node:fs")),ge=c(require("node:path")),j=class n{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:r}=this.readNewLines(),o=n.toBatch(t),s=o.turns.length+o.compactions.length,i={turns:o.turns.length,compactions:o.compactions.length,newOffset:r,sent:!1,dryRun:e};return e?i:s===0?(r!==this.readCursor()&&this.writeCursor(r),i):(await this.postAll(o),this.writeCursor(r),{...i,sent:!0})}static toBatch(e){let t=[],r=[];for(let o of e){let s;try{s=JSON.parse(o)}catch{continue}typeof s.ts=="string"&&(s.type==="turn"?t.push(n.mapTurn(s)):s.type==="compaction"&&r.push(n.mapCompaction(s)))}return{turns:t,compactions:r}}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=f.statSync(this.metricsFile).size}catch{return{lines:[],newOffset:e}}if(e>t&&(e=0),e===t)return{lines:[],newOffset:e};let r=f.openSync(this.metricsFile,"r");try{let o=t-e,s=Buffer.alloc(o);f.readSync(r,s,0,o,e);let i=s.toString("utf8"),a=i.lastIndexOf(`
31
+ `)}get model(){return this.modelId}get usage(){return{...this.totals}}observe(e){let t=m.parse(e);if(!t)return;this.modelId??=t.model;let r=t.usage;r&&(r.inputTokens!=null&&(this.totals.inputTokens=r.inputTokens),r.outputTokens!=null&&(this.totals.outputTokens=r.outputTokens),r.cacheReadTokens!=null&&(this.totals.cacheReadTokens=r.cacheReadTokens),r.cacheCreationTokens!=null&&(this.totals.cacheCreationTokens=r.cacheCreationTokens))}};var ye=c(require("node:fs")),ke=c(require("node:path"));var N=class n{static BIG_TOOL_CHARS=4e3;static defaultFile(){return ke.join(h.dir(),"gateway.jsonl")}static fromFile(e=n.defaultFile()){let t;try{t=ye.readFileSync(e,"utf8")}catch{return n.empty()}return n.aggregate(t.split(`
32
+ `))}static aggregate(e){let t=n.empty();for(let r of e){let o=n.parse(r);o&&(o.type==="turn"?n.addTurn(t,o):o.type==="compaction"&&n.addCompaction(t,o),n.trackTime(t,o.ts))}return t}static addTurn(e,t){e.turns+=1,e.inputTokens+=n.num(t.inputTokens),e.outputTokens+=n.num(t.outputTokens),e.cacheReadTokens+=n.num(t.cacheReadTokens),e.cacheCreationTokens+=n.num(t.cacheCreationTokens),e.totalDurationMs+=n.num(t.durationMs),e.gateBlocks+=n.num(t.blockedToolCalls);let r=n.num(t.freshToolChars);if(e.maxFreshToolChars=Math.max(e.maxFreshToolChars,r),r>n.BIG_TOOL_CHARS&&(e.bigToolTurns+=1),e.maxToolDefChars=Math.max(e.maxToolDefChars,n.num(t.toolDefChars)),e.maxSystemChars=Math.max(e.maxSystemChars,n.num(t.systemChars)),e.tailResultChars+=n.num(t.tailResultChars),e.tailTextChars+=n.num(t.tailTextChars),e.maxCacheCreationTokens=Math.max(e.maxCacheCreationTokens,n.num(t.cacheCreationTokens)),typeof t.status=="number"&&t.status!==200&&(e.errorTurns+=1),n.bump(e.models,typeof t.model=="string"?t.model:"(unknown)"),Array.isArray(t.skillsTriggered))for(let o of t.skillsTriggered)n.bump(e.skillsTriggered,String(o))}static addCompaction(e,t){e.compactions+=1,e.charsSaved+=n.num(t.charsSaved),e.estTokensSaved+=n.num(t.estTokensSaved),e.linesElided+=n.num(t.elidedLines),n.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 f=c(require("node:fs")),Te=c(require("node:path")),j=class n{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:r}=this.readNewLines(),o=n.toBatch(t),s=o.turns.length+o.compactions.length,i={turns:o.turns.length,compactions:o.compactions.length,newOffset:r,sent:!1,dryRun:e};return e?i:s===0?(r!==this.readCursor()&&this.writeCursor(r),i):(await this.postAll(o),this.writeCursor(r),{...i,sent:!0})}static toBatch(e){let t=[],r=[];for(let o of e){let s;try{s=JSON.parse(o)}catch{continue}typeof s.ts=="string"&&(s.type==="turn"?t.push(n.mapTurn(s)):s.type==="compaction"&&r.push(n.mapCompaction(s)))}return{turns:t,compactions:r}}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=f.statSync(this.metricsFile).size}catch{return{lines:[],newOffset:e}}if(e>t&&(e=0),e===t)return{lines:[],newOffset:e};let r=f.openSync(this.metricsFile,"r");try{let o=t-e,s=Buffer.alloc(o);f.readSync(r,s,0,o,e);let i=s.toString("utf8"),a=i.lastIndexOf(`
33
33
  `);if(a<0)return{lines:[],newOffset:e};let l=i.slice(0,a+1),u=e+Buffer.byteLength(l,"utf8");return{lines:l.split(`
34
- `).filter(_=>_.trim().length>0),newOffset:u}}finally{f.closeSync(r)}}readCursor(){try{let e=JSON.parse(f.readFileSync(this.cursorFile,"utf8"));return typeof e.offset=="number"&&e.offset>=0?e.offset:0}catch{return 0}}writeCursor(e){try{f.mkdirSync(ge.dirname(this.cursorFile),{recursive:!0}),f.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`,r=new AbortController,o=setTimeout(()=>r.abort(),this.timeoutMs);try{let s=await this.fetchImpl(t,{method:"POST",headers:{Authorization:`Bearer ${this.token}`,"content-type":"application/json",accept:"application/json"},body:JSON.stringify(e),signal:r.signal});if(!s.ok)throw new Error(`usage-telemetry upload returned ${s.status}`)}finally{clearTimeout(o)}}};var F=class n{constructor(e,t){this.config=e;this.deps=t;this.injector=new k(t.skills)}config;deps;static UPSTREAMS=[{match:e=>e.startsWith("/v1/messages"),base:"https://api.anthropic.com",provider:w.Anthropic},{match:e=>e.startsWith("/v1/chat/completions")||e.startsWith("/v1/responses")||e.startsWith("/v1/completions"),base:"https://api.openai.com",provider:w.OpenAI}];static HOP_BY_HOP_REQUEST=["host","content-length","connection","accept-encoding","transfer-encoding"];static HOP_BY_HOP_RESPONSE=["content-encoding","content-length","transfer-encoding","connection"];injector;logger=new L("gateway");metrics=new h("gateway");telemetryTimer=null;telemetryUploader=null;static async fromEnv(){let e={port:Number(process.env.PORT||13579),inject:process.env.INJECT==="1",gate:process.env.GATE==="1",capture:process.env.CAPTURE==="1",stateFile:process.env.DZ_STATE_FILE||null},t={skills:await n.loadSkills(),policy:n.loadJson(process.env.DZ_POLICY_FILE)||Q,loadState:()=>n.loadJson(e.stateFile)};return new n(e,t)}static loadSkills(){return new P(n.skillSources()).load()}static skillSources(){return[new O]}createServer(){return ye.createServer((e,t)=>this.handle(e,t))}listen(){let e=this.createServer();return e.on("error",t=>{t.code==="EADDRINUSE"&&(this.logger.warn(`port ${this.config.port} already in use \u2014 a gateway is probably running.`),process.exit(1)),this.logger.error(`server error: ${t.message}`),process.exit(1)}),e.listen(this.config.port,"127.0.0.1",()=>{this.logger.info(`listening on http://127.0.0.1:${this.config.port} (inject=${this.config.inject} gate=${this.config.gate}) skills=${Object.keys(this.deps.skills).length}`)}),this.startTelemetry(),e}startTelemetry(){if(!h.enabled()||process.env.DZ_TELEMETRY==="0")return;let e=J.at(process.cwd()).connection();if("error"in e){this.logger.debug(`telemetry: off (${e.error})`);return}this.telemetryUploader=new j({...e,metricsFile:M.defaultFile(),cursorFile:Te.join(h.dir(),"gateway.upload-cursor.json")});let t=Math.max(3e4,Number(process.env.DZ_TELEMETRY_INTERVAL_MS)||3e5),r=()=>{this.flushTelemetry()};this.telemetryTimer=setInterval(r,t),this.telemetryTimer.unref?.(),setTimeout(r,15e3).unref?.(),this.logger.info(`telemetry: background upload every ${Math.round(t/1e3)}s \u2192 ws ${e.workspaceId}`)}async flushTelemetry(){if(this.telemetryUploader)try{let e=await this.telemetryUploader.upload();e.sent&&this.logger.info(`telemetry: uploaded ${e.turns} turn + ${e.compactions} compaction event(s)`)}catch(e){this.logger.warn(`telemetry upload failed: ${e.message}`)}}handle(e,t){if(this.handleControlPlane(e,t))return;let r=n.pickUpstream(e.url||""),o=[];e.on("data",s=>o.push(s)),e.on("end",()=>this.forward(e,t,r,o))}handleControlPlane(e,t){return e.url===X.Health?(t.writeHead(200,{"content-type":R.Json}),t.end(JSON.stringify({ok:!0,dz:!0,pid:process.pid,port:this.config.port,inject:this.config.inject,gate:this.config.gate})),!0):e.url===X.Stop?(t.writeHead(200,{"content-type":R.Json}),t.end(JSON.stringify({ok:!0,stopping:!0})),this.telemetryTimer&&clearInterval(this.telemetryTimer),this.flushTelemetry().finally(()=>setTimeout(()=>process.exit(0),50)),setTimeout(()=>process.exit(0),3e3).unref?.(),!0):!1}async forward(e,t,r,o){let s=Date.now(),i=Buffer.concat(o),a=[],l=k.emptyComposition();if(this.config.inject&&r&&e.method==="POST"&&i.length){let p=this.injectBody(i.toString("utf8"),r.provider);i=Buffer.from(p.bodyText,"utf8"),a=p.triggers,l=p.composition}let u=process.env.FORCE_UPSTREAM||(r?r.base:"https://api.anthropic.com");try{let p=await fetch(u+e.url,{method:e.method,headers:n.buildForwardHeaders(e.headers),body:["GET","HEAD"].includes(e.method||"")?void 0:i,redirect:"manual"}),_=(p.headers.get("content-type")||"").toLowerCase();if(r?.provider===w.Anthropic&&p.ok&&p.body&&(this.config.gate||h.enabled())){let re=this.config.gate?new A(this.deps.policy,this.deps.loadState()):null,ne={startedAt:s,provider:r.provider,status:p.status,triggers:a,...l};if(_.includes(R.EventStream))return this.streamResponse(p,t,re,ne);if(_.includes(R.Json))return this.jsonResponse(p,t,re,ne)}t.writeHead(p.status,n.filterResponseHeaders(p.headers)),p.body?n.webToNode(p.body).pipe(t):t.end()}catch(p){this.logger.error(`upstream error: ${p.message}`),t.writeHead(502,{"content-type":R.Json}),t.end(JSON.stringify({error:"gateway upstream failed",detail:String(p)}))}}injectBody(e,t){try{let r=JSON.parse(e),{text:o,triggers:s}=this.injector.apply(r,t),i=h.enabled()?k.composition(r):k.emptyComposition();return o?(this.logger.debug(`-> ${t} injected(${o.split(`
35
- `).length} line(s))`),{bodyText:JSON.stringify(r),triggers:s,composition:i}):{bodyText:e,triggers:s,composition:i}}catch{return{bodyText:e,triggers:[],composition:k.emptyComposition()}}}streamResponse(e,t,r,o){t.writeHead(e.status,n.filterResponseHeaders(e.headers));let s=r?new I(r):null,i=h.enabled()?new N:null,a=n.webToNode(e.body);a.setEncoding("utf8"),a.on("data",l=>{if(i&&i.feed(l),!s){t.write(l);return}try{let u=s.push(l);u&&t.write(u)}catch{t.write(l)}}),a.on("end",()=>{if(s)try{let l=s.flush();l&&t.write(l)}catch{}t.end(),this.recordTurn(o,i,s)}),a.on("error",()=>{try{t.end()}catch{}this.recordTurn(o,i,s)})}async jsonResponse(e,t,r,o){let s=await e.text(),i=s,a=null,l={model:null,usage:{}};try{let u=JSON.parse(s);l={model:u.model??null,usage:n.usageOf(u)},r&&(a=new D(r),i=JSON.stringify(a.rewrite(u)))}catch{i=s}a&&i!==s&&this.logger.info("\u26D4 gate rewrote response (blocked tool_use)"),t.writeHead(e.status,n.filterResponseHeaders(e.headers)),t.end(i),this.recordTurn(o,l,a)}recordTurn(e,t,r){let o=t?.usage??{};this.metrics.record({type:"turn",provider:e.provider,model:t?.model??null,durationMs:Date.now()-e.startedAt,status:e.status,inputTokens:o.inputTokens,outputTokens:o.outputTokens,cacheReadTokens:o.cacheReadTokens,cacheCreationTokens:o.cacheCreationTokens,skillsTriggered:e.triggers.length?e.triggers:void 0,blockedToolCalls:r?r.blockedCount:void 0,gated:r?r.blockedCount>0:void 0,freshToolChars:e.freshToolChars||void 0,toolDefChars:e.toolDefChars||void 0,systemChars:e.systemChars||void 0,tailResultChars:e.tailResultChars||void 0,tailTextChars:e.tailTextChars||void 0})}static usageOf(e){let t=e.usage;return t?{inputTokens:t.input_tokens,outputTokens:t.output_tokens,cacheReadTokens:t.cache_read_input_tokens,cacheCreationTokens:t.cache_creation_input_tokens}:{}}static pickUpstream(e){return n.UPSTREAMS.find(t=>t.match(e))??null}static buildForwardHeaders(e){let t={};for(let[r,o]of Object.entries(e))n.HOP_BY_HOP_REQUEST.includes(r.toLowerCase())||(typeof o=="string"?t[r]=o:Array.isArray(o)&&(t[r]=o.join(", ")));return t}static filterResponseHeaders(e){let t={};return e.forEach((r,o)=>{n.HOP_BY_HOP_RESPONSE.includes(o.toLowerCase())||(t[o]=r)}),t}static webToNode(e){return be.Readable.fromWeb(e)}static loadJson(e){try{return e?JSON.parse(ke.readFileSync(e,"utf8")):null}catch{return null}}};function Le(n,e){return new F(n,e).createServer()}require.main===module&&F.fromEnv().then(n=>n.listen());0&&(module.exports={Gateway,createGatewayServer});
34
+ `).filter(J=>J.trim().length>0),newOffset:u}}finally{f.closeSync(r)}}readCursor(){try{let e=JSON.parse(f.readFileSync(this.cursorFile,"utf8"));return typeof e.offset=="number"&&e.offset>=0?e.offset:0}catch{return 0}}writeCursor(e){try{f.mkdirSync(Te.dirname(this.cursorFile),{recursive:!0}),f.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`,r=new AbortController,o=setTimeout(()=>r.abort(),this.timeoutMs);try{let s=await this.fetchImpl(t,{method:"POST",headers:{Authorization:`Bearer ${this.token}`,"content-type":"application/json",accept:"application/json"},body:JSON.stringify(e),signal:r.signal});if(!s.ok)throw new Error(`usage-telemetry upload returned ${s.status}`)}finally{clearTimeout(o)}}};var _=class n{constructor(e,t){this.config=e;this.deps=t;this.injector=new k(t.skills)}config;deps;static UPSTREAMS=[{match:e=>e.startsWith("/v1/messages"),base:"https://api.anthropic.com",provider:w.Anthropic},{match:e=>e.startsWith("/v1/chat/completions")||e.startsWith("/v1/responses")||e.startsWith("/v1/completions"),base:"https://api.openai.com",provider:w.OpenAI}];static HOP_BY_HOP_REQUEST=["host","content-length","connection","accept-encoding","transfer-encoding"];static HOP_BY_HOP_RESPONSE=["content-encoding","content-length","transfer-encoding","connection"];injector;logger=new O("gateway");metrics=new h("gateway");telemetryTimer=null;telemetryUploader=null;static async fromEnv(){let e={port:Number(process.env.PORT||13579),inject:process.env.INJECT==="1",gate:process.env.GATE==="1",capture:process.env.CAPTURE==="1",stateFile:process.env.DZ_STATE_FILE||null},t={skills:await n.loadSkills(),policy:n.loadJson(process.env.DZ_POLICY_FILE)||te,loadState:()=>n.loadJson(e.stateFile)};return new n(e,t)}static loadSkills(){return new P(n.skillSources()).load()}static skillSources(){return[new L]}createServer(){return be.createServer((e,t)=>this.handle(e,t))}listen(){let e=this.createServer();return e.on("error",t=>{t.code==="EADDRINUSE"&&(this.logger.warn(`port ${this.config.port} already in use \u2014 a gateway is probably running.`),process.exit(1)),this.logger.error(`server error: ${t.message}`),process.exit(1)}),e.listen(this.config.port,"127.0.0.1",()=>{this.logger.info(`listening on http://127.0.0.1:${this.config.port} (inject=${this.config.inject} gate=${this.config.gate}) skills=${Object.keys(this.deps.skills).length}`)}),this.startTelemetry(),e}startTelemetry(){if(!h.enabled()||process.env.DZ_TELEMETRY==="0")return;let e=$.at(process.cwd()).connection();if("error"in e){this.logger.debug(`telemetry: off (${e.error})`);return}this.telemetryUploader=new j({...e,metricsFile:N.defaultFile(),cursorFile:z.join(h.dir(),"gateway.upload-cursor.json")});let t=Math.max(3e4,Number(process.env.DZ_TELEMETRY_INTERVAL_MS)||3e5),r=()=>{this.flushTelemetry()};this.telemetryTimer=setInterval(r,t),this.telemetryTimer.unref?.(),setTimeout(r,15e3).unref?.(),this.logger.info(`telemetry: background upload every ${Math.round(t/1e3)}s \u2192 ws ${e.workspaceId}`)}async flushTelemetry(){if(this.telemetryUploader)try{let e=await this.telemetryUploader.upload();e.sent&&this.logger.info(`telemetry: uploaded ${e.turns} turn + ${e.compactions} compaction event(s)`)}catch(e){this.logger.warn(`telemetry upload failed: ${e.message}`)}}handle(e,t){if(this.handleControlPlane(e,t))return;let r=n.pickUpstream(e.url||""),o=[];e.on("data",s=>o.push(s)),e.on("end",()=>this.forward(e,t,r,o))}handleControlPlane(e,t){return e.url===ee.Health?(t.writeHead(200,{"content-type":R.Json}),t.end(JSON.stringify({ok:!0,dz:!0,pid:process.pid,port:this.config.port,inject:this.config.inject,gate:this.config.gate})),!0):e.url===ee.Stop?(t.writeHead(200,{"content-type":R.Json}),t.end(JSON.stringify({ok:!0,stopping:!0})),this.telemetryTimer&&clearInterval(this.telemetryTimer),this.flushTelemetry().finally(()=>setTimeout(()=>process.exit(0),50)),setTimeout(()=>process.exit(0),3e3).unref?.(),!0):!1}async forward(e,t,r,o){let s=Date.now(),i=Buffer.concat(o),a=[],l=k.emptyComposition();if(this.config.inject&&r&&e.method==="POST"&&i.length){let p=this.injectBody(i.toString("utf8"),r.provider);i=Buffer.from(p.bodyText,"utf8"),a=p.triggers,l=p.composition,this.persistOpusModel(p.model)}let u=process.env.FORCE_UPSTREAM||(r?r.base:"https://api.anthropic.com");try{let p=await fetch(u+e.url,{method:e.method,headers:n.buildForwardHeaders(e.headers),body:["GET","HEAD"].includes(e.method||"")?void 0:i,redirect:"manual"}),J=(p.headers.get("content-type")||"").toLowerCase();if(r?.provider===w.Anthropic&&p.ok&&p.body&&(this.config.gate||h.enabled())){let oe=this.config.gate?new A(this.deps.policy,this.deps.loadState()):null,se={startedAt:s,provider:r.provider,status:p.status,triggers:a,...l};if(J.includes(R.EventStream))return this.streamResponse(p,t,oe,se);if(J.includes(R.Json))return this.jsonResponse(p,t,oe,se)}t.writeHead(p.status,n.filterResponseHeaders(p.headers)),p.body?n.webToNode(p.body).pipe(t):t.end()}catch(p){this.logger.error(`upstream error: ${p.message}`),t.writeHead(502,{"content-type":R.Json}),t.end(JSON.stringify({error:"gateway upstream failed",detail:String(p)}))}}injectBody(e,t){try{let r=JSON.parse(e),o=typeof r.model=="string"?r.model:null,{text:s,triggers:i}=this.injector.apply(r,t),a=h.enabled()?k.composition(r):k.emptyComposition();return s?(this.logger.debug(`-> ${t} injected(${s.split(`
35
+ `).length} line(s))`),{bodyText:JSON.stringify(r),triggers:i,composition:a,model:o}):{bodyText:e,triggers:i,composition:a,model:o}}catch{return{bodyText:e,triggers:[],composition:k.emptyComposition(),model:null}}}persistOpusModel(e){if(!(!e||!/opus/i.test(e)||!this.config.stateFile))try{let t=e.replace(/\[.*$/,""),r=z.join(z.dirname(this.config.stateFile),pe);if(n.readFileTrim(r)===t)return;F.writeFileSync(r,t)}catch{}}static readFileTrim(e){try{return F.readFileSync(e,"utf8").trim()}catch{return null}}streamResponse(e,t,r,o){t.writeHead(e.status,n.filterResponseHeaders(e.headers));let s=r?new I(r):null,i=h.enabled()?new M:null,a=n.webToNode(e.body);a.setEncoding("utf8"),a.on("data",l=>{if(i&&i.feed(l),!s){t.write(l);return}try{let u=s.push(l);u&&t.write(u)}catch{t.write(l)}}),a.on("end",()=>{if(s)try{let l=s.flush();l&&t.write(l)}catch{}t.end(),this.recordTurn(o,i,s)}),a.on("error",()=>{try{t.end()}catch{}this.recordTurn(o,i,s)})}async jsonResponse(e,t,r,o){let s=await e.text(),i=s,a=null,l={model:null,usage:{}};try{let u=JSON.parse(s);l={model:u.model??null,usage:n.usageOf(u)},r&&(a=new D(r),i=JSON.stringify(a.rewrite(u)))}catch{i=s}a&&i!==s&&this.logger.info("\u26D4 gate rewrote response (blocked tool_use)"),t.writeHead(e.status,n.filterResponseHeaders(e.headers)),t.end(i),this.recordTurn(o,l,a)}recordTurn(e,t,r){let o=t?.usage??{};this.metrics.record({type:"turn",provider:e.provider,model:t?.model??null,durationMs:Date.now()-e.startedAt,status:e.status,inputTokens:o.inputTokens,outputTokens:o.outputTokens,cacheReadTokens:o.cacheReadTokens,cacheCreationTokens:o.cacheCreationTokens,skillsTriggered:e.triggers.length?e.triggers:void 0,blockedToolCalls:r?r.blockedCount:void 0,gated:r?r.blockedCount>0:void 0,freshToolChars:e.freshToolChars||void 0,toolDefChars:e.toolDefChars||void 0,systemChars:e.systemChars||void 0,tailResultChars:e.tailResultChars||void 0,tailTextChars:e.tailTextChars||void 0})}static usageOf(e){let t=e.usage;return t?{inputTokens:t.input_tokens,outputTokens:t.output_tokens,cacheReadTokens:t.cache_read_input_tokens,cacheCreationTokens:t.cache_creation_input_tokens}:{}}static pickUpstream(e){return n.UPSTREAMS.find(t=>t.match(e))??null}static buildForwardHeaders(e){let t={};for(let[r,o]of Object.entries(e))n.HOP_BY_HOP_REQUEST.includes(r.toLowerCase())||(typeof o=="string"?t[r]=o:Array.isArray(o)&&(t[r]=o.join(", ")));return t}static filterResponseHeaders(e){let t={};return e.forEach((r,o)=>{n.HOP_BY_HOP_RESPONSE.includes(o.toLowerCase())||(t[o]=r)}),t}static webToNode(e){return Se.Readable.fromWeb(e)}static loadJson(e){try{return e?JSON.parse(F.readFileSync(e,"utf8")):null}catch{return null}}};function Le(n,e){return new _(n,e).createServer()}require.main===module&&_.fromEnv().then(n=>n.listen());0&&(module.exports={Gateway,createGatewayServer});
@@ -21,6 +21,13 @@ export declare const ControlPath: {
21
21
  readonly Health: "/__dz/health";
22
22
  readonly Stop: "/__dz/stop";
23
23
  };
24
+ /**
25
+ * Filename (written next to the companion state file) where the proxy records the
26
+ * bare Opus model id it last saw a request use. The launcher reads it back and pins
27
+ * the 1M context window to that id, self-healing when the model rolls — no hardcoded
28
+ * version. Shared so proxy (writer) and launcher (reader) can't drift.
29
+ */
30
+ export declare const OpusModelCacheFile = "last-opus-model";
24
31
  /** Response content-types the gate special-cases. */
25
32
  export declare const ContentType: {
26
33
  readonly EventStream: "text/event-stream";
@@ -7,7 +7,7 @@
7
7
  * native support, via request injection (cache-safe) and response tool gating.
8
8
  */
9
9
  Object.defineProperty(exports, "__esModule", { value: true });
10
- exports.ContentType = exports.ControlPath = exports.Agent = exports.Provider = void 0;
10
+ exports.ContentType = exports.OpusModelCacheFile = exports.ControlPath = exports.Agent = exports.Provider = void 0;
11
11
  /** Model providers the gateway can adapt (value + type share the name). */
12
12
  exports.Provider = {
13
13
  Anthropic: 'anthropic',
@@ -23,6 +23,13 @@ exports.ControlPath = {
23
23
  Health: '/__dz/health',
24
24
  Stop: '/__dz/stop',
25
25
  };
26
+ /**
27
+ * Filename (written next to the companion state file) where the proxy records the
28
+ * bare Opus model id it last saw a request use. The launcher reads it back and pins
29
+ * the 1M context window to that id, self-healing when the model rolls — no hardcoded
30
+ * version. Shared so proxy (writer) and launcher (reader) can't drift.
31
+ */
32
+ exports.OpusModelCacheFile = 'last-opus-model';
26
33
  /** Response content-types the gate special-cases. */
27
34
  exports.ContentType = {
28
35
  EventStream: 'text/event-stream',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dezycro-ai/agent-plugin",
3
- "version": "2.5.0",
3
+ "version": "2.5.1",
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"
@@ -92,10 +92,29 @@ Where `openApiFragment` is the JSON string of the spec. The MCP tool uploads it
92
92
 
93
93
  ## Step 7: Report
94
94
 
95
- Tell the user:
95
+ Publishing is async — it triggers JEP generation → verifier compile (typically 2-5 minutes). Tell the user:
96
96
 
97
- > Spec published for "<featureName>". JEP generation workflow has been triggered this typically takes 2-5 minutes.
98
- >
99
- > Once complete, run `/dezycro:verify` to pull the verifier binary and test your implementation.
100
- >
101
- > You can check generation status by running `/dezycro:status`.
97
+ > Spec published for "<featureName>". Generation is running (~2-5 min); I'll pick up the verifier when it's ready.
98
+
99
+ ## Step 8: Don't Wait by Hand Keep Working or Block on the Event
100
+
101
+ The `VERIFIER_STATUS_UPDATE` event reaches you **either way** when generation finishes the Dezycro companion injects it as a background nudge. So **never write your own polling loop** (no `sleep`/`curl`/`while` waiting on the binary — those silently wedge and strand you).
102
+
103
+ Pick based on whether you have other work:
104
+
105
+ - **You still have tasks (the common case — e.g. you finished mutating endpoints and only the logic is left)**: just keep going. Publish, then implement. When the background nudge lands, read its `payload` (handling below) and act then.
106
+ - **You're otherwise idle**: block on the pushed event with the bundled CLI. It server-side long-polls, prints the first matching event as JSON the moment it lands, and exits 0 (event) / 5 (timeout) / 2 (error). It reads token/workspace/active-feature from `.dezycro/` itself; pass the feature id from Step 1:
107
+
108
+ ```bash
109
+ dezycro await-event --event-types VERIFIER_STATUS_UPDATE --feature "<featureId>" --timeout 600
110
+ echo "exit=$?"
111
+ ```
112
+
113
+ - **exit 5 (TIMEOUT)**: no event in the budget — generation is likely still running. Tell the user to check `/dezycro:status` and re-run `/dezycro:verify` once ready. Do NOT claim it finished.
114
+ - **exit 2 (ERROR / not configured)**: couldn't reach the endpoint or no feature is bound. Show the line; the user can run `/dezycro:verify` later.
115
+
116
+ **Handling the `payload`** (same whether it came from the CLI's exit-0 JSON or the background nudge):
117
+
118
+ - **`payload.status` = `READY`**: binary is ready. Run `/dezycro:verify` (or tell the user it's ready, if you're mid-task and want to finish first).
119
+ - **`payload.status` = `EMPTY`, or `payload.stage` = `JEP_GENERATION`**: generation produced no executable checks (the journeys aren't checkable API outcomes). STOP. Quote `payload.message`/`payload.reasonCode`, tell the user to fix the spec, and re-run `/dezycro:publish-spec`. Do NOT claim generation succeeded.
120
+ - **`payload.status` = `FAILED`** (typically `payload.stage` = `COMPILE`): the verifier build failed. STOP. Quote the message and offer to retry via the `retry_verifier_build` MCP tool. Do NOT claim generation succeeded.