@routecraft/cli 0.7.2-canary-20261003210535 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{acp-BQMPXMXQ.js → acp-JAOUSF3F.js} +3 -3
- package/dist/{acp-BQMPXMXQ.js.map → acp-JAOUSF3F.js.map} +1 -1
- package/dist/{chunk-5N7YMHE4.js → chunk-DJD3H3G5.js} +3 -3
- package/dist/{chunk-5N7YMHE4.js.map → chunk-DJD3H3G5.js.map} +1 -1
- package/dist/chunk-WCEUG34O.js +2 -0
- package/dist/chunk-WCEUG34O.js.map +1 -0
- package/dist/chunk-WYVHXXTI.js +4 -0
- package/dist/chunk-WYVHXXTI.js.map +1 -0
- package/dist/exec-LJZY4IXV.js +2 -0
- package/dist/{exec-3X7SDVNN.js.map → exec-LJZY4IXV.js.map} +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/{ops-EJMP5OLL.js → ops-B6N4ATXZ.js} +2 -2
- package/dist/{ops-EJMP5OLL.js.map → ops-B6N4ATXZ.js.map} +1 -1
- package/dist/settings-XW6WNPDV.js +2 -0
- package/dist/{settings-TJKUAC35.js.map → settings-XW6WNPDV.js.map} +1 -1
- package/dist/tui/app.js +1 -1
- package/package.json +2 -2
- package/dist/chunk-6CUX4CM4.js +0 -2
- package/dist/chunk-6CUX4CM4.js.map +0 -1
- package/dist/chunk-V56CL7XK.js +0 -4
- package/dist/chunk-V56CL7XK.js.map +0 -1
- package/dist/exec-3X7SDVNN.js +0 -2
- package/dist/settings-TJKUAC35.js +0 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/settings.ts"],"names":["DEFAULT_URL","SETTINGS_FILES","join","resolveSettingsPath","resolveIn","candidates","present","path","existsSync","SettingsError","FORMATS","ENV_URL","ENV_TOKEN","ENV_FORMAT","ENV_AGENT","ENV_PROFILE","supplied","value","trimmed","readSettingsFile","text","readFileSync","error","code","messageOf","parsed","parse","firstLine","profiles","isPlainObject","name","entry","assertFormat","where","projectDir","project","dir","resolve","isDirectory","statSync","resolveSettings","overrides","cwd","env","projectPath","file","home","homedir","globalPath","global","profile","pickProfile","pick","key","flag","fromEnvironment","fromFlag","fromEnv","fromFiles","fileLayers","url","describeSource","parsedUrl","token","formatRaw","format","agent","envValue","pickEnv","known","describeKnown","chosen","profileIn","settings","resolved","empty","isPlainStringMap","layers","layer"],"mappings":"mLA2JaA,CAAAA,CAAc,uBAAA,CAUrBC,EAAiB,CACrBC,IAAAA,CAAK,cAAe,eAAe,CAAA,CACnCA,IAAAA,CAAK,aAAA,CAAe,cAAc,CACpC,EAOA,SAASC,CAAAA,CAAoBC,CAAAA,CAA6C,CACxE,IAAMC,CAAAA,CAAaJ,CAAAA,CAAe,GAAA,CAAIG,CAAS,CAAA,CACzCE,CAAAA,CAAUD,EAAW,MAAA,CAAQE,CAAAA,EAASC,WAAWD,CAAI,CAAC,CAAA,CAC5D,GAAID,EAAQ,MAAA,CAAS,CAAA,CACnB,MAAM,IAAIG,CAAAA,CACR,QAAQH,CAAAA,CAAQ,CAAC,CAAC,CAAA,KAAA,EAAQA,EAAQ,CAAC,CAAC,8FACtC,CAAA,CAEF,OAAOA,EAAQ,CAAC,CAAA,EAAKD,CAAAA,CAAW,CAAC,CACnC,CAEA,IAAMK,EAAmC,CAAC,QAAA,CAAU,OAAQ,KAAK,CAAA,CAG3DC,CAAAA,CAAU,WAAA,CACVC,EAAY,aAAA,CACZC,CAAAA,CAAa,eACbC,CAAAA,CAAY,aAAA,CACZC,EAAc,eAAA,CAGPN,CAAAA,CAAN,cAA4B,KAAM,GAelC,SAASO,EAASC,CAAAA,CAA+C,CACtE,IAAMC,CAAAA,CAAUD,CAAAA,EAAO,IAAA,EAAK,CAC5B,OAAOC,CAAAA,GAAY,MAAA,EAAaA,IAAY,EAAA,CAAK,MAAA,CAAYA,CAC/D,CAUA,SAASC,CAAAA,CAAiBZ,CAAAA,CAAyC,CACjE,IAAIa,CAAAA,CACJ,GAAI,CACFA,CAAAA,CAAOC,aAAad,CAAAA,CAAM,MAAM,EAClC,CAAA,MAASe,EAAgB,CAKvB,IAAMC,EAAQD,CAAAA,EAA6C,IAAA,CAC3D,GAAIC,CAAAA,GAAS,QAAA,EAAYA,CAAAA,GAAS,SAAA,CAAW,OAC7C,MAAM,IAAId,EACR,CAAA,EAAGF,CAAI,kCAAkCiB,GAAAA,CAAUF,CAAK,CAAC,CAAA,CAC3D,CACF,CACA,IAAIG,EACJ,GAAI,CACFA,EAASC,KAAAA,CAAMN,CAAI,EACrB,CAAA,MAASE,EAAgB,CAKvB,IAAMK,EAAYH,GAAAA,CAAUF,CAAK,EAAE,KAAA,CAAM;AAAA,CAAA,CAAM,CAAC,EAAE,CAAC,CAAA,CACnD,MAAM,IAAIb,CAAAA,CAAc,CAAA,EAAGF,CAAI,CAAA,oBAAA,EAAuBoB,CAAS,EAAE,CACnE,CACA,GAAIF,CAAAA,EAAW,IAAA,CAA8B,OAAO,EAAC,CACrD,GAAI,OAAOA,CAAAA,EAAW,QAAA,EAAY,KAAA,CAAM,QAAQA,CAAM,CAAA,CACpD,MAAM,IAAIhB,CAAAA,CACR,CAAA,EAAGF,CAAI,CAAA,iFAAA,CACT,CAAA,CAQF,IAAMqB,CAAAA,CAAYH,CAAAA,CAAkC,QAAA,CAMpD,GADIG,CAAAA,GAAa,IAAA,EAAM,OAAQH,CAAAA,CAAkC,QAAA,CACnCG,CAAAA,EAAa,KAAM,CAC/C,GAAI,CAACC,CAAAA,CAAcD,CAAQ,CAAA,CACzB,MAAM,IAAInB,CAAAA,CACR,CAAA,kBAAA,EAAqBF,CAAI,CAAA,kDAAA,CAC3B,CAAA,CAEF,OAAW,CAACuB,CAAAA,CAAMC,CAAK,CAAA,GAAK,MAAA,CAAO,OAAA,CAAQH,CAAQ,CAAA,CACjD,GAA2BG,CAAAA,EAAU,IAAA,EACjC,CAACF,CAAAA,CAAcE,CAAK,CAAA,CACtB,MAAM,IAAItB,CAAAA,CACR,CAAA,aAAA,EAAgBqB,CAAI,QAAQvB,CAAI,CAAA,+CAAA,CAClC,CAGN,CACA,OAAOkB,CACT,CAEA,SAASO,CAAAA,CAAaf,CAAAA,CAAegB,CAAAA,CAA6B,CAChE,GAAKvB,EAA8B,QAAA,CAASO,CAAK,CAAA,CAC/C,OAAOA,CAAAA,CAET,MAAM,IAAIR,CAAAA,CACR,CAAA,EAAGwB,CAAK,CAAA,gBAAA,EAAmBvB,CAAAA,CAAQ,IAAA,CAAK,IAAI,CAAC,CAAA,YAAA,EAAeO,CAAK,CAAA,EAAA,CACnE,CACF,CAGA,SAASiB,CAAAA,CAAWC,CAAAA,CAAiD,CACnE,GAAIA,CAAAA,GAAY,MAAA,CAAW,OAC3B,IAAMC,CAAAA,CAAMC,OAAAA,CAAQ,OAAA,CAAQ,GAAA,EAAI,CAAGF,CAAO,CAAA,CACtCG,CAAAA,CAAc,KAAA,CAClB,GAAI,CACFA,CAAAA,CACEC,SAASH,CAAAA,CAAK,CAAE,cAAA,CAAgB,CAAA,CAAM,CAAC,CAAA,EAAG,aAAY,EAAK,CAAA,EAC/D,CAAA,KAAQ,CAER,CACA,GAAI,CAACE,CAAAA,CACH,MAAM,IAAI7B,CAAAA,CACR,CAAA,WAAA,EAAc0B,CAAO,qCAAqCC,CAAG,CAAA,EAAA,CAC/D,CAAA,CAEF,OAAOA,CACT,CASO,SAASI,EAAAA,CACdC,CAAAA,CAA+B,EAAC,CACd,CAClB,IAAMC,EAAMD,CAAAA,CAAU,GAAA,EAAOP,CAAAA,CAAWO,CAAAA,CAAU,OAAO,CAAA,EAAK,QAAQ,GAAA,EAAI,CACpEE,CAAAA,CAAMF,CAAAA,CAAU,GAAA,EAAO,OAAA,CAAQ,IAC/BG,CAAAA,CAAczC,CAAAA,CAAqB0C,CAAAA,EAASR,OAAAA,CAAQK,CAAAA,CAAKG,CAAI,CAAC,CAAA,CAC9DC,CAAAA,CAAOL,CAAAA,CAAU,IAAA,EAAQM,OAAAA,EAAQ,CACjCC,EAAa7C,CAAAA,CAAqB0C,CAAAA,EAAS3C,IAAAA,CAAK4C,CAAAA,CAAMD,CAAI,CAAC,EAC3DV,CAAAA,CAAUhB,CAAAA,CAAiByB,CAAW,CAAA,CAGtCK,CAAAA,CACJL,CAAAA,GAAgBI,EAAa,MAAA,CAAY7B,CAAAA,CAAiB6B,CAAU,CAAA,CAEhEE,CAAAA,CAAUC,CAAAA,CACdV,EAAU,OAAA,CACVE,CAAAA,CAAI5B,CAAW,CAAA,CACf,CAAE,SAAUoB,CAAAA,CAAS,IAAA,CAAMS,CAAY,CAAA,CACvC,CAAE,QAAA,CAAUK,EAAQ,IAAA,CAAMD,CAAW,CACvC,CAAA,CAaMI,CAAAA,CAAO,CACXC,EACAC,CAAAA,CACAC,CAAAA,GAC6D,CAC7D,IAAMC,CAAAA,CAAWxC,CAAAA,CAASsC,CAAI,CAAA,CACxBG,CAAAA,CAAUzC,CAAAA,CAASuC,CAAe,CAAA,CACxC,OAAIC,IAAa,MAAA,CACR,CACL,KAAA,CAAOA,CAAAA,CACP,MAAA,CAAQ,MACV,EAEEC,CAAAA,GAAY,MAAA,CACP,CACL,KAAA,CAAOA,CAAAA,CACP,MAAA,CAAQ,aACV,CAAA,CAEKC,CAAAA,CACLL,CAAAA,CACAM,CAAAA,CAAWT,CAAAA,CAASf,CAAAA,CAASS,EAAaK,CAAAA,CAAQD,CAAU,CAC9D,CACF,CAAA,CAEMY,CAAAA,CAAMR,EAAK,KAAA,CAAOX,CAAAA,CAAU,GAAA,CAAKE,CAAAA,CAAIhC,CAAO,CAAC,GAAK,CACtD,KAAA,CAAOX,CAAAA,CACP,MAAA,CAAQ,SACV,CAAA,CACA,GAAI,OAAO4D,CAAAA,CAAI,KAAA,EAAU,QAAA,EAAYA,CAAAA,CAAI,KAAA,CAAM,MAAK,GAAM,EAAA,CACxD,MAAM,IAAInD,CAAAA,CACR,CAAA,0BAAA,EAA6BoD,EAAeD,CAAG,CAAC,CAAA,mEAAA,CAClD,CAAA,CAKF,IAAIE,CAAAA,CACJ,GAAI,CACFA,CAAAA,CAAY,IAAI,GAAA,CAAIF,CAAAA,CAAI,KAAK,EAC/B,CAAA,KAAQ,CACN,MAAM,IAAInD,CAAAA,CACR,CAAA,0BAAA,EAA6BoD,EAAeD,CAAG,CAAC,CAAA,gBAAA,EAAmBA,CAAAA,CAAI,KAAK,CAAA,2DAAA,CAC9E,CACF,CACA,GAAIE,CAAAA,CAAU,QAAA,GAAa,OAAA,EAAWA,CAAAA,CAAU,WAAa,QAAA,CAC3D,MAAM,IAAIrD,CAAAA,CACR,CAAA,0BAAA,EAA6BoD,CAAAA,CAAeD,CAAG,CAAC,CAAA,OAAA,EAAUE,CAAAA,CAAU,QAAQ,CAAA,gDAAA,CAC9E,CAAA,CAGF,IAAMC,CAAAA,CAAQX,CAAAA,CAAK,OAAA,CAASX,CAAAA,CAAU,KAAA,CAAOE,CAAAA,CAAI/B,CAAS,CAAC,CAAA,CAC3D,GAAImD,CAAAA,GAAU,MAAA,EAAa,OAAOA,EAAM,KAAA,EAAU,QAAA,CAChD,MAAM,IAAItD,CAAAA,CACR,CAAA,mBAAA,EAAsBsD,EAAM,MAAM,CAAA,kBAAA,CACpC,CAAA,CAOF,GAAIA,CAAAA,GAAU,MAAA,EAAaA,EAAM,KAAA,CAAM,IAAA,EAAK,GAAM,EAAA,CAChD,MAAM,IAAItD,EACR,CAAA,mBAAA,EAAsBoD,CAAAA,CAAeE,CAAK,CAAC,CAAA,qDAAA,CAC7C,CAAA,CAGF,IAAMC,CAAAA,CAAYZ,CAAAA,CAAK,QAAA,CAAUX,CAAAA,CAAU,MAAA,CAAQE,CAAAA,CAAI9B,CAAU,CAAC,CAAA,CAC5DoD,CAAAA,CACJD,CAAAA,GAAc,MAAA,CACV,CAAE,MAAO,QAAA,CAAU,MAAA,CAAQ,SAAU,CAAA,CACrC,CACE,GAAGA,EACH,KAAA,CAAOhC,CAAAA,CACL,MAAA,CAAOgC,CAAAA,CAAU,KAAK,CAAA,CACtB,8BAA8BA,CAAAA,CAAU,MAAM,CAAA,CAChD,CACF,CAAA,CAEAE,CAAAA,CAAQd,EAAK,OAAA,CAASX,CAAAA,CAAU,KAAA,CAAOE,CAAAA,CAAI7B,CAAS,CAAC,EAC3D,GAAIoD,CAAAA,GAAU,QAAa,OAAOA,CAAAA,CAAM,OAAU,QAAA,CAChD,MAAM,IAAIzD,CAAAA,CACR,CAAA,wBAAA,EAA2BoD,CAAAA,CAAeK,CAAK,CAAC,CAAA,kBAAA,CAClD,CAAA,CAEF,GAAIA,CAAAA,GAAU,MAAA,EAAaA,EAAM,KAAA,CAAM,IAAA,EAAK,GAAM,EAAA,CAChD,MAAM,IAAIzD,EACR,CAAA,wBAAA,EAA2BoD,CAAAA,CAAeK,CAAK,CAAC,CAAA,4CAAA,CAClD,CAAA,CAGF,IAAMC,CAAAA,CAAWC,CAAAA,CAAQlB,CAAAA,CAASf,CAAAA,CAASS,CAAAA,CAAaK,CAAAA,CAAQD,CAAU,CAAA,CAE1E,OAAO,CACL,GAAA,CAAAY,CAAAA,CACA,KAAA,CAAAG,EACA,MAAA,CAAAE,CAAAA,CACA,KAAA,CAAAC,CAAAA,CACA,OAAA,CAAAhB,CAAAA,CACA,IAAKiB,CACP,CACF,CASA,SAAShB,CAAAA,CACPG,CAAAA,CACAC,EACApB,CAAAA,CACAc,CAAAA,CAC8B,CAC9B,IAAMoB,CAAAA,CAAQ,IAAI,IAAI,CACpB,GAAG,MAAA,CAAO,IAAA,CAAKlC,CAAAA,CAAQ,QAAA,EAAU,UAAY,EAAE,CAAA,CAC/C,GAAG,MAAA,CAAO,IAAA,CAAKc,EAAO,QAAA,EAAU,QAAA,EAAY,EAAE,CAChD,CAAC,EACKqB,CAAAA,CAAgB,IACpBD,CAAAA,CAAM,IAAA,GAAS,CAAA,CACX,iDAAA,CACA,qBAAqB,CAAC,GAAGA,CAAK,CAAA,CAAE,IAAA,EAAK,CAAE,KAAK,IAAI,CAAC,CAAA,CAAA,CAEjDE,CAAAA,CACJvD,CAAAA,CAASsC,CAAI,IAAM,MAAA,CACf,CAAE,KAAA,CAAOtC,CAAAA,CAASsC,CAAI,CAAA,CAAI,OAAQ,MAAO,CAAA,CACzCtC,CAAAA,CAASuC,CAAe,CAAA,GAAM,MAAA,CAC5B,CAAE,KAAA,CAAOvC,CAAAA,CAASuC,CAAe,CAAA,CAAI,MAAA,CAAQ,aAAc,EAC3DpB,CAAAA,CAAQ,QAAA,EAAU,OAAA,GAAY,MAAA,CAC5B,CACE,KAAA,CAAOA,EAAQ,QAAA,CAAS,OAAA,CACxB,MAAA,CAAQ,cAAA,CACR,IAAA,CAAMA,CAAAA,CAAQ,IAChB,CAAA,CACAc,CAAAA,CAAO,QAAA,EAAU,OAAA,GAAY,MAAA,CAC3B,CACE,MAAOA,CAAAA,CAAO,QAAA,CAAS,OAAA,CACvB,MAAA,CAAQ,aAAA,CACR,IAAA,CAAMA,EAAO,IACf,CAAA,CACA,MAAA,CAEZ,GAAIsB,CAAAA,GAAW,MAAA,CACf,IAAI,OAAOA,CAAAA,CAAO,KAAA,EAAU,QAAA,EAAYA,CAAAA,CAAO,KAAA,CAAM,MAAK,GAAM,EAAA,CAC9D,MAAM,IAAI9D,CAAAA,CACR,CAAA,qBAAA,EAAwBoD,EAAeU,CAAM,CAAC,CAAA,gBAAA,EAAmBD,CAAAA,EAAe,CAAA,CAAA,CAClF,EAEF,GAAI,CAACD,CAAAA,CAAM,GAAA,CAAIE,CAAAA,CAAO,KAAK,EACzB,MAAM,IAAI9D,CAAAA,CACR,CAAA,YAAA,EAAe8D,CAAAA,CAAO,KAAK,mBAAmBV,CAAAA,CAAeU,CAAM,CAAC,CAAA,GAAA,EAAMD,CAAAA,EAAe,GAC3F,CAAA,CAEF,OAAOC,CAAAA,CACT,CAGA,SAASC,CAAAA,CACPC,EACAvB,CAAAA,CACgC,CAChC,GAAIuB,CAAAA,GAAa,MAAA,EAAavB,CAAAA,GAAY,OAAW,OACrD,IAAMtB,CAAAA,CAAW6C,CAAAA,CAAS,QAAA,CAC1B,GAAI7C,IAAa,MAAA,CAIjB,OAAO,MAAA,CAAO,SAAA,CAAU,cAAA,CAAe,IAAA,CAAKA,EAAUsB,CAAO,CAAA,CACzDtB,CAAAA,CAASsB,CAAO,CAAA,CAChB,MACN,CAUA,SAASkB,CAAAA,CACPlB,CAAAA,CACAf,CAAAA,CACAS,CAAAA,CACAK,CAAAA,CACAD,EACkC,CAClC,IAAM0B,CAAAA,CAAWhB,CAAAA,CACf,KAAA,CACAC,CAAAA,CAAWT,EAASf,CAAAA,CAASS,CAAAA,CAAaK,CAAAA,CAAQD,CAAU,CAC9D,CAAA,CACA,GAAI0B,CAAAA,GAAa,MAAA,CAAW,OAC5B,GAAM,CAAE,KAAA,CAAAzD,CAAM,CAAA,CAAIyD,CAAAA,CAIZC,CAAAA,CAAQ,OAAO1D,CAAAA,EAAU,QAAA,EAAYA,EAAM,IAAA,EAAK,GAAM,EAAA,CAC5D,GAAK,OAAOA,CAAAA,EAAU,UAAY,CAAC2D,CAAAA,CAAiB3D,CAAK,CAAA,EAAM0D,CAAAA,CAC7D,MAAM,IAAIlE,CAAAA,CACR,CAAA,mBAAA,EAAsBoD,CAAAA,CAAea,CAAQ,CAAC,CAAA,kEAAA,CAChD,EAEF,OAAOA,CACT,CASA,SAAShB,CAAAA,CACPL,CAAAA,CACAwB,EAC0D,CAC1D,IAAA,IAAWC,CAAAA,IAASD,CAAAA,CAAQ,CAC1B,IAAM5D,EAAQ6D,CAAAA,CAAM,MAAA,GAASzB,CAAG,CAAA,CAChC,GAAIpC,CAAAA,GAAU,OACZ,OAAO,CACL,KAAA,CAAOA,CAAAA,CACP,MAAA,CAAQ6D,CAAAA,CAAM,OACd,IAAA,CAAMA,CAAAA,CAAM,IACd,CAEJ,CAEF,CAQA,SAASnB,CAAAA,CACPT,CAAAA,CACAf,CAAAA,CACAS,CAAAA,CACAK,CAAAA,CACAD,CAAAA,CAKC,CACD,OAAO,CACL,CACE,MAAA,CAAQwB,CAAAA,CAAUrC,CAAAA,CAASe,GAAS,KAAK,CAAA,CACzC,MAAA,CAAQ,iBAAA,CACR,IAAA,CAAMN,CACR,EACA,CAAE,MAAA,CAAQT,CAAAA,CAAS,MAAA,CAAQ,cAAA,CAAgB,IAAA,CAAMS,CAAY,CAAA,CAC7D,CACE,MAAA,CAAQ4B,CAAAA,CAAUvB,CAAAA,CAAQC,CAAAA,EAAS,KAAK,CAAA,CACxC,MAAA,CAAQ,gBAAA,CACR,IAAA,CAAMF,CACR,CAAA,CACA,CAAE,MAAA,CAAQC,CAAAA,CAAQ,MAAA,CAAQ,aAAA,CAAe,IAAA,CAAMD,CAAW,CAC5D,CACF,CAGA,SAASnB,CAAAA,CAAcZ,CAAAA,CAAkD,CACvE,OAAO,OAAOA,CAAAA,EAAU,QAAA,EAAYA,CAAAA,GAAU,IAAA,EAAQ,CAAC,MAAM,OAAA,CAAQA,CAAK,CAC5E,CAEA,SAAS2D,CAAAA,CAAiB3D,EAAiD,CACzE,OAAIA,CAAAA,GAAU,IAAA,EAAQ,OAAOA,CAAAA,EAAU,UAAY,KAAA,CAAM,OAAA,CAAQA,CAAK,CAAA,CAC7D,KAAA,CAEF,MAAA,CAAO,OAAOA,CAAK,CAAA,CAAE,KAAA,CAAOc,CAAAA,EAAU,OAAOA,CAAAA,EAAU,QAAQ,CACxE,CAOO,SAAS8B,CAAAA,CAAea,CAAAA,CAAqC,CAClE,OAAOA,CAAAA,CAAS,IAAA,GAAS,MAAA,CACrBA,CAAAA,CAAS,MAAA,CACT,CAAA,EAAGA,EAAS,MAAM,CAAA,CAAA,EAAIA,CAAAA,CAAS,IAAI,CAAA,CACzC","file":"chunk-WYVHXXTI.js","sourcesContent":["/**\n * The CLI's personal settings file.\n *\n * This is the person's file, not the app's. `craft.config.ts` decides what\n * exists in an instance and what it exposes; this decides how one operator\n * likes to talk to it: which address, which credential, which output\n * format. The distinction matters because the two have different owners and\n * different lifetimes, and a setting that drifts across it ends up either\n * committed with a token in it or lost on another machine.\n *\n * Two locations, both YAML, both optional:\n *\n * - project-local: `.routecraft/settings.yaml` under the working directory\n * - global: `.routecraft/settings.yaml` under the user's home\n *\n * `.yml` is accepted as an alternate spelling in either location; a\n * location carrying both spellings is refused with both paths named.\n *\n * Project-local wins over global, an environment variable wins over both,\n * and a flag wins over everything. `.routecraft/` is already gitignored,\n * which is what keeps a pasted token out of a commit; the scaffolder half\n * of that lives in #588.\n *\n * A profile is a named set of those values, and selecting one selects the\n * instance, the credential, the output format, the agent and the\n * environment together. Inside one file a profile beats a bare key,\n * because it is the more specific thing the person asked for; between\n * files the project still beats the home directory, because a profile\n * somebody keeps in their home directory must never be able to redirect\n * an instance a repository pinned.\n *\n * Every resolved value remembers where it came from, because the one\n * question a failed connection has to answer is \"which address did it\n * actually use, and who told it that\".\n */\n\nimport { homedir } from \"node:os\";\nimport { join, resolve } from \"node:path\";\nimport { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { parse } from \"yaml\";\n\nimport { messageOf } from \"./util.js\";\n\n/** Where a resolved value came from, in precedence order. */\nexport type SettingSource =\n | \"flag\"\n | \"environment\"\n | \"project profile\"\n | \"project file\"\n | \"global profile\"\n | \"global file\"\n | \"default\";\n\n/** A resolved value and the reason it holds. */\nexport interface Resolved<T> {\n value: T;\n source: SettingSource;\n /** The file a `project file` or `global file` value was read from. */\n path?: string;\n}\n\n/** Output rendering, shared by every command in the family. */\nexport type OutputFormat = \"pretty\" | \"json\" | \"raw\";\n\n/**\n * Environment for one profile: a file to load, or values written inline.\n *\n * A path is resolved against the project root rather than against the file\n * that declared it, because an env file is a project artefact and a path\n * relative to somebody's home directory would mean nothing on another\n * machine. The inline map is for a value that does not deserve a file.\n */\nexport type ProfileEnv = string | Record<string, string>;\n\n/** The keys a profile carries, and the keys a file carries at its top level. */\nexport interface CraftSettingValues {\n /** Base URL of the instance's ops server. */\n url?: string;\n /** Bearer token presented to the management door and to health. */\n token?: string;\n /** Default output format. */\n format?: OutputFormat;\n /** Which agent `craft acp` asks the instance to talk to. */\n agent?: string;\n /** The environment this profile selects. */\n env?: ProfileEnv;\n}\n\n/** What the settings file may carry. Every key is optional. */\nexport interface CraftSettings extends CraftSettingValues {\n /** The profile selected when no flag and no environment variable name one. */\n profile?: string;\n /** Named sets of the values above. */\n profiles?: Record<string, CraftSettingValues>;\n}\n\n/** Flags that override the file, per command invocation. */\nexport interface SettingsOverrides {\n url?: string;\n token?: string;\n format?: string;\n /** The agent `craft acp` asks for. */\n agent?: string;\n /** Which profile to select, above every other way of choosing one. */\n profile?: string;\n /**\n * The project whose `.routecraft/settings.yaml` is the project-local file,\n * from `--project`. An editor starts `craft acp` from whichever project it\n * has open, so the profile's project has to be named. Must be a directory:\n * a mistyped path refuses rather than falling through to the global file.\n */\n project?: string;\n /**\n * Directory the project-local settings file is looked for under.\n * Defaults to the working directory; pinned by tests so a developer's\n * own settings file cannot supply a credential to a case whose whole\n * point is that none was presented.\n */\n cwd?: string;\n /** Environment to read. Defaults to the process environment. */\n env?: NodeJS.ProcessEnv;\n /**\n * Directory the global settings file is looked for under. Defaults to the\n * user's home. Pinned by tests for the same reason as `cwd`: a developer's\n * own `~/.routecraft/settings.yaml` would otherwise decide what a case\n * about defaults resolves to.\n */\n home?: string;\n}\n\n/** Everything a command needs, each value carrying its provenance. */\nexport interface ResolvedSettings {\n url: Resolved<string>;\n token: Resolved<string> | undefined;\n format: Resolved<OutputFormat>;\n /** The agent `craft acp` asks for, when one was named. */\n agent: Resolved<string> | undefined;\n /**\n * The selected profile, when one was selected. The value is its name and\n * the source says who chose it, which is the first thing to check when a\n * command reaches an instance nobody expected.\n */\n profile: Resolved<string> | undefined;\n /** The environment the selected profile names, when it names one. */\n env: Resolved<ProfileEnv> | undefined;\n}\n\n/**\n * Address used when nothing names one.\n *\n * The ops surface mounts on the `default` server unless configured\n * elsewhere, and `8080` is that server's conventional port throughout the\n * documentation. Loopback rather than a hostname, because a bare `craft\n * ops health` means \"the instance I am running here\".\n */\nexport const DEFAULT_URL = \"http://127.0.0.1:8080\";\n\n/**\n * File names looked for in both locations, in preference order. `.yaml` is\n * the documented spelling; `.yml` is accepted because half the world types\n * it. Order only names the default for a fresh location: when both exist\n * the resolver refuses rather than silently preferring one, because a\n * setting edited in the file that is not being read is a debugging trap\n * with nothing to say for itself.\n */\nconst SETTINGS_FILES = [\n join(\".routecraft\", \"settings.yaml\"),\n join(\".routecraft\", \"settings.yml\"),\n] as const;\n\n/**\n * Resolve which settings file one location uses, or refuse when the answer\n * is ambiguous. A location with neither file resolves to the canonical\n * `.yaml` path so error messages and provenance still name a real place.\n */\nfunction resolveSettingsPath(resolveIn: (file: string) => string): string {\n const candidates = SETTINGS_FILES.map(resolveIn);\n const present = candidates.filter((path) => existsSync(path));\n if (present.length > 1) {\n throw new SettingsError(\n `Both ${present[0]} and ${present[1]} exist. Settings are read from exactly one file per location; keep one and remove the other.`,\n );\n }\n return present[0] ?? candidates[0]!;\n}\n\nconst FORMATS: readonly OutputFormat[] = [\"pretty\", \"json\", \"raw\"];\n\n/** Environment variables read between the flags and the files. */\nconst ENV_URL = \"CRAFT_URL\";\nconst ENV_TOKEN = \"CRAFT_TOKEN\";\nconst ENV_FORMAT = \"CRAFT_FORMAT\";\nconst ENV_AGENT = \"CRAFT_AGENT\";\nconst ENV_PROFILE = \"CRAFT_PROFILE\";\n\n/** A settings file that exists but cannot be used. */\nexport class SettingsError extends Error {}\n\n/**\n * A blank flag or environment value, read as not supplied.\n *\n * `--url \"$CRAFT_URL\"` with the variable unset, and an exported `CRAFT_URL=`,\n * both arrive as an empty string; treating one as supplied lets it win the\n * precedence it never earned and silently override the settings file with\n * nothing. Trimmed rather than merely tested, so a value pasted with a\n * trailing newline is not refused as invalid with nothing to suggest the\n * whitespace is why.\n *\n * A blank value written into a settings file is not this: somebody typed it\n * there, and the refusal is what tells them.\n */\nexport function supplied(value: string | undefined): string | undefined {\n const trimmed = value?.trim();\n return trimmed === undefined || trimmed === \"\" ? undefined : trimmed;\n}\n\n/**\n * Read one settings file, or `undefined` when it is not there.\n *\n * A missing file is the normal case and says nothing. A file that exists\n * and cannot be parsed is an error rather than a silent fallback: an\n * operator who wrote a settings file and got default behaviour would\n * reasonably conclude the setting does not work.\n */\nfunction readSettingsFile(path: string): CraftSettings | undefined {\n let text: string;\n try {\n text = readFileSync(path, \"utf8\");\n } catch (error: unknown) {\n // Only \"it is not there\" means no settings. A file that exists and cannot\n // be read (no permission, or the path is a directory) is the same class of\n // problem as one that cannot be parsed: the operator wrote settings and\n // would otherwise get default behaviour with nothing said.\n const code = (error as NodeJS.ErrnoException | undefined)?.code;\n if (code === \"ENOENT\" || code === \"ENOTDIR\") return undefined;\n throw new SettingsError(\n `${path} exists but could not be read: ${messageOf(error)}`,\n );\n }\n let parsed: unknown;\n try {\n parsed = parse(text);\n } catch (error: unknown) {\n // First line only: the parser's message appends a code frame quoting the\n // offending source line, and in this file that line can be the token.\n // stderr is often captured (CI logs), so the credential must not ride\n // along with the diagnosis.\n const firstLine = messageOf(error).split(\"\\n\", 1)[0];\n throw new SettingsError(`${path} is not valid YAML: ${firstLine}`);\n }\n if (parsed === null || parsed === undefined) return {};\n if (typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new SettingsError(\n `${path} must contain a mapping of settings (for example \\`url: http://127.0.0.1:8080\\`).`,\n );\n }\n // `profiles` is checked here, at the boundary, because every other key\n // this file reads is guarded and an unguarded one fails silently rather\n // than loudly: `profiles: local` makes a string whose character indices\n // read as profile names, and a scalar entry makes a profile whose every\n // setting is undefined, which resolves to the defaults while looking\n // like it was honoured.\n const profiles = (parsed as { profiles?: unknown }).profiles;\n // `profiles:` with nothing after it parses as null, which is somebody\n // starting a map and not finishing it rather than somebody declaring\n // none. Normalised away here so nothing downstream meets it: the reader\n // that did threw a raw TypeError instead of naming the file.\n if (profiles === null) delete (parsed as { profiles?: unknown }).profiles;\n if (profiles !== undefined && profiles !== null) {\n if (!isPlainObject(profiles)) {\n throw new SettingsError(\n `The \"profiles\" in ${path} must be a map of profile names to their settings.`,\n );\n }\n for (const [name, entry] of Object.entries(profiles)) {\n if (entry === undefined || entry === null) continue;\n if (!isPlainObject(entry)) {\n throw new SettingsError(\n `The profile \"${name}\" in ${path} must be a map of settings, not a single value.`,\n );\n }\n }\n }\n return parsed as CraftSettings;\n}\n\nfunction assertFormat(value: string, where: string): OutputFormat {\n if ((FORMATS as readonly string[]).includes(value)) {\n return value as OutputFormat;\n }\n throw new SettingsError(\n `${where} must be one of ${FORMATS.join(\", \")}; received \"${value}\".`,\n );\n}\n\n/** `--project`, resolved against the working directory and checked to exist. */\nfunction projectDir(project: string | undefined): string | undefined {\n if (project === undefined) return undefined;\n const dir = resolve(process.cwd(), project);\n let isDirectory = false;\n try {\n isDirectory =\n statSync(dir, { throwIfNoEntry: false })?.isDirectory() ?? false;\n } catch {\n // An unreadable path is as unusable as a missing one, and gets the same answer.\n }\n if (!isDirectory) {\n throw new SettingsError(\n `--project \"${project}\" is not a directory (resolved to ${dir}).`,\n );\n }\n return dir;\n}\n\n/**\n * Resolve the effective settings for one invocation.\n *\n * @param overrides - Flags given on the command line\n * @param cwd - Working directory the project-local file is looked for under\n * @param env - Environment to read, injectable for tests\n */\nexport function resolveSettings(\n overrides: SettingsOverrides = {},\n): ResolvedSettings {\n const cwd = overrides.cwd ?? projectDir(overrides.project) ?? process.cwd();\n const env = overrides.env ?? process.env;\n const projectPath = resolveSettingsPath((file) => resolve(cwd, file));\n const home = overrides.home ?? homedir();\n const globalPath = resolveSettingsPath((file) => join(home, file));\n const project = readSettingsFile(projectPath);\n // A project file that IS the global file (running in the home directory)\n // must not be reported as two independent sources agreeing.\n const global =\n projectPath === globalPath ? undefined : readSettingsFile(globalPath);\n\n const profile = pickProfile(\n overrides.profile,\n env[ENV_PROFILE],\n { settings: project, path: projectPath },\n { settings: global, path: globalPath },\n );\n\n /**\n * One value, through the whole chain.\n *\n * Flag, then environment, then per file: the selected profile before\n * that file's own top level. Environment variables sit above every file\n * because what somebody changes on a server is what has to win, and it\n * is already how this CLI behaves. Inside a file the profile is the more\n * specific answer; between files the project still beats the home\n * directory, so a profile in a home directory can never redirect an\n * instance a repository pinned.\n */\n const pick = <K extends keyof CraftSettingValues>(\n key: K,\n flag: string | undefined,\n fromEnvironment: string | undefined,\n ): Resolved<NonNullable<CraftSettingValues[K]>> | undefined => {\n const fromFlag = supplied(flag);\n const fromEnv = supplied(fromEnvironment);\n if (fromFlag !== undefined) {\n return {\n value: fromFlag as NonNullable<CraftSettingValues[K]>,\n source: \"flag\",\n };\n }\n if (fromEnv !== undefined) {\n return {\n value: fromEnv as NonNullable<CraftSettingValues[K]>,\n source: \"environment\",\n };\n }\n return fromFiles(\n key,\n fileLayers(profile, project, projectPath, global, globalPath),\n );\n };\n\n const url = pick(\"url\", overrides.url, env[ENV_URL]) ?? {\n value: DEFAULT_URL,\n source: \"default\" as const,\n };\n if (typeof url.value !== \"string\" || url.value.trim() === \"\") {\n throw new SettingsError(\n `The instance URL from the ${describeSource(url)} is empty. Give a full base URL, for example http://127.0.0.1:8080.`,\n );\n }\n // A typo'd address is invalid configuration, not an instance that is down.\n // Reaching `fetch()` with it would report \"could not reach a running\n // instance\", sending the reader to look at a server that is fine.\n let parsedUrl: URL;\n try {\n parsedUrl = new URL(url.value);\n } catch {\n throw new SettingsError(\n `The instance URL from the ${describeSource(url)} is not a URL: \"${url.value}\". Give a full base URL, for example http://127.0.0.1:8080.`,\n );\n }\n if (parsedUrl.protocol !== \"http:\" && parsedUrl.protocol !== \"https:\") {\n throw new SettingsError(\n `The instance URL from the ${describeSource(url)} uses \"${parsedUrl.protocol}\"; the ops server is reached over http or https.`,\n );\n }\n\n const token = pick(\"token\", overrides.token, env[ENV_TOKEN]);\n if (token !== undefined && typeof token.value !== \"string\") {\n throw new SettingsError(\n `The token from the ${token.source} must be a string.`,\n );\n }\n // The file half of the blank rule, and the reason it is checked here: a\n // blank flag or environment value never reaches this point, so a blank\n // token can only have been written into a file by hand. Left alone it\n // presents `Bearer` with nothing after it and the operator is told their\n // credential was rejected.\n if (token !== undefined && token.value.trim() === \"\") {\n throw new SettingsError(\n `The token from the ${describeSource(token)} is empty. Put a credential there, or remove the key.`,\n );\n }\n\n const formatRaw = pick(\"format\", overrides.format, env[ENV_FORMAT]);\n const format: Resolved<OutputFormat> =\n formatRaw === undefined\n ? { value: \"pretty\", source: \"default\" }\n : {\n ...formatRaw,\n value: assertFormat(\n String(formatRaw.value),\n `The output format from the ${formatRaw.source}`,\n ),\n };\n\n const agent = pick(\"agent\", overrides.agent, env[ENV_AGENT]);\n if (agent !== undefined && typeof agent.value !== \"string\") {\n throw new SettingsError(\n `The agent name from the ${describeSource(agent)} must be a string.`,\n );\n }\n if (agent !== undefined && agent.value.trim() === \"\") {\n throw new SettingsError(\n `The agent name from the ${describeSource(agent)} is empty. Name an agent, or remove the key.`,\n );\n }\n\n const envValue = pickEnv(profile, project, projectPath, global, globalPath);\n\n return {\n url,\n token,\n format,\n agent,\n profile,\n env: envValue,\n };\n}\n\n/**\n * Which profile is selected, and who chose it.\n *\n * A profile named by anybody has to exist somewhere, and the refusal names\n * the profiles that do: a typo would otherwise resolve to the defaults and\n * reach an instance nobody meant.\n */\nfunction pickProfile(\n flag: string | undefined,\n fromEnvironment: string | undefined,\n project: { settings: CraftSettings | undefined; path: string },\n global: { settings: CraftSettings | undefined; path: string },\n): Resolved<string> | undefined {\n const known = new Set([\n ...Object.keys(project.settings?.profiles ?? {}),\n ...Object.keys(global.settings?.profiles ?? {}),\n ]);\n const describeKnown = (): string =>\n known.size === 0\n ? \"no profiles are defined in either settings file\"\n : `defined profiles: ${[...known].sort().join(\", \")}`;\n\n const chosen: Resolved<string> | undefined =\n supplied(flag) !== undefined\n ? { value: supplied(flag)!, source: \"flag\" }\n : supplied(fromEnvironment) !== undefined\n ? { value: supplied(fromEnvironment)!, source: \"environment\" }\n : project.settings?.profile !== undefined\n ? {\n value: project.settings.profile,\n source: \"project file\",\n path: project.path,\n }\n : global.settings?.profile !== undefined\n ? {\n value: global.settings.profile,\n source: \"global file\",\n path: global.path,\n }\n : undefined;\n\n if (chosen === undefined) return undefined;\n if (typeof chosen.value !== \"string\" || chosen.value.trim() === \"\") {\n throw new SettingsError(\n `The profile from the ${describeSource(chosen)} is not a name; ${describeKnown()}.`,\n );\n }\n if (!known.has(chosen.value)) {\n throw new SettingsError(\n `No profile \"${chosen.value}\" (named by the ${describeSource(chosen)}); ${describeKnown()}.`,\n );\n }\n return chosen;\n}\n\n/** One file's entry for the selected profile, when it has one. */\nfunction profileIn(\n settings: CraftSettings | undefined,\n profile: string | undefined,\n): CraftSettingValues | undefined {\n if (settings === undefined || profile === undefined) return undefined;\n const profiles = settings.profiles;\n if (profiles === undefined) return undefined;\n // `readSettingsFile` refuses a `profiles` that is not a map of maps, and\n // normalises the empty `profiles:` to absent, so what reaches here is a\n // map or nothing.\n return Object.prototype.hasOwnProperty.call(profiles, profile)\n ? profiles[profile]\n : undefined;\n}\n\n/**\n * The environment the selected profile names, if it names one.\n *\n * Not part of `pick` because it is not a string: it is a path or an inline\n * map, and there is no environment variable or flag form of it. `--env`\n * wins over it and is handled by the commands that take one, because the\n * flag names a file to load rather than a setting to resolve.\n */\nfunction pickEnv(\n profile: Resolved<string> | undefined,\n project: CraftSettings | undefined,\n projectPath: string,\n global: CraftSettings | undefined,\n globalPath: string,\n): Resolved<ProfileEnv> | undefined {\n const resolved = fromFiles(\n \"env\",\n fileLayers(profile, project, projectPath, global, globalPath),\n );\n if (resolved === undefined) return undefined;\n const { value } = resolved;\n // An empty string is not a path. Left alone it resolves to the project\n // directory and the command runs on without the environment the person\n // selected, which is the silence this file exists to refuse.\n const empty = typeof value === \"string\" && value.trim() === \"\";\n if ((typeof value !== \"string\" && !isPlainStringMap(value)) || empty) {\n throw new SettingsError(\n `The \"env\" from the ${describeSource(resolved)} must be a path to an env file or a map of names to string values.`,\n );\n }\n return resolved as Resolved<ProfileEnv>;\n}\n\n/**\n * The first layer that carries `key`, with where it came from.\n *\n * The list and the walk over it are one rule: resolving what counts as\n * present, and which of `source` and `path` rides on the answer, in two\n * places is two rules the moment one of them is edited.\n */\nfunction fromFiles<K extends keyof CraftSettingValues>(\n key: K,\n layers: ReturnType<typeof fileLayers>,\n): Resolved<NonNullable<CraftSettingValues[K]>> | undefined {\n for (const layer of layers) {\n const value = layer.values?.[key];\n if (value !== undefined) {\n return {\n value: value as NonNullable<CraftSettingValues[K]>,\n source: layer.source,\n path: layer.path,\n };\n }\n }\n return undefined;\n}\n\n/**\n * The file-backed layers, most specific first: the selected profile in a\n * file before that file's own top level, and the project's file before the\n * home directory's. Built once, because a precedence list that exists in\n * two places is two lists the moment one of them is edited.\n */\nfunction fileLayers(\n profile: Resolved<string> | undefined,\n project: CraftSettings | undefined,\n projectPath: string,\n global: CraftSettings | undefined,\n globalPath: string,\n): ReadonlyArray<{\n values: CraftSettingValues | undefined;\n source: SettingSource;\n path: string;\n}> {\n return [\n {\n values: profileIn(project, profile?.value),\n source: \"project profile\",\n path: projectPath,\n },\n { values: project, source: \"project file\", path: projectPath },\n {\n values: profileIn(global, profile?.value),\n source: \"global profile\",\n path: globalPath,\n },\n { values: global, source: \"global file\", path: globalPath },\n ];\n}\n\n/** Whether a value is a flat map of strings, which is what an inline env is. */\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isPlainStringMap(value: unknown): value is Record<string, string> {\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n return false;\n }\n return Object.values(value).every((entry) => typeof entry === \"string\");\n}\n\n/**\n * Describe where a value came from, for an error a reader has to act on.\n * A wrong pinned address should be diagnosable from the message alone,\n * without the reader guessing which of four places supplied it.\n */\nexport function describeSource(resolved: Resolved<unknown>): string {\n return resolved.path === undefined\n ? resolved.source\n : `${resolved.source} ${resolved.path}`;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"exec-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"exec-LJZY4IXV.js"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env bun
|
|
2
|
-
import {a as a$1}from'./chunk-
|
|
3
|
-
`,()=>n());})}function
|
|
2
|
+
import {a as a$1}from'./chunk-WCEUG34O.js';import {b as b$1}from'./chunk-OKX5YME7.js';import {resolve}from'path';process.versions.bun||(console.error(b$1),process.exit(1));var{relaunchOutsideProject:O}=await import('./relaunch-7TTF2OEI.js'),y=O(import.meta.url);y&&process.exit(await y);var{Command:S}=await import('commander'),s=new S;f(s.name("craft").description("A modern routing framework for TypeScript").version(a$1).enablePositionalOptions()).showSuggestionAfterError().showHelpAfterError().exitOverride(t=>{t.code==="commander.unknownCommand"&&process.exit(0);});s.hook("preAction",async(t,e)=>{await E(e);});process.argv.length<=2&&s.help({error:false});async function E(t){let e=await P(t),n=R(t.opts()),{checkBunRuntime:o}=await import('./runtime-gate-NEYB2HPB.js'),r=o();r.ok||await l(1,r.message);let{logFileDiversion:c,logger:d}=await import('@routecraft/routecraft'),i=c();if(i!==void 0){let p=n===void 0?i.source:"--log-file";await l(2,`Cannot write logs to ${i.path} (from ${p}): ${i.reason}. Point it at a file this process can create or append to.`);}for(let p of e)d[p.level](p.message);}async function l(t,e){await C(process.stderr,e),process.exit(t);}function C(t,e){return new Promise(n=>{t.write(`${e}
|
|
3
|
+
`,()=>n());})}function R(t){let e=s.opts(),n=t.logLevel??e.logLevel,o=t.logFile??e.logFile;return n!==void 0&&(process.env.LOG_LEVEL=n,process.env.CRAFT_LOG_LEVEL=n),o!==void 0&&(process.env.LOG_FILE=o,process.env.CRAFT_LOG_FILE=o),o}function f(t){return t.option("--log-level <level>","Log level (e.g. info, warn, error, silent to disable)").option("--log-file <path>","Write logs to a file instead of stdout")}var b=new WeakMap,g="--project <dir>",h="Project whose .routecraft/settings.yaml is read (default: the working directory)";function L(t,e){return b.set(t,e),t.option("--env <path>","Load environment variables from a .env file (default: .env)").option("--profile <name>","Settings profile to select")}async function P(t){let e=b.get(t)?.(t.args);if(e===void 0)return [];let n=t.opts(),{EnvFileError:o,loadEnvironment:r}=await import('./util-CSBMQ2PQ.js'),{resolveSettings:c,SettingsError:d}=await import('./settings-XW6WNPDV.js');try{let i=c({cwd:e,...n.profile===void 0?{}:{profile:n.profile}});return r({explicit:n.env,profile:i.profile?.value,env:i.env?.value,defaultsFrom:e})}catch(i){if(i instanceof d||i instanceof o)return l(2,i.message);throw i}}f(L(s.command("run").description("Run routes from a single TypeScript/JavaScript file").argument("<file>","Path to a file containing routes").argument("[args...]","CLI command and flags to pass through to CLI adapter routes"),()=>process.cwd())).passThroughOptions().action(async(t,e)=>{let{runCommand:n}=await import('./run-BYR62OGM.js'),o=await n(t,e);if(!o.success){a({code:o.code??1,...o.message?{error:o.message}:{}});return}});f(L(s.command("start").description("Start a project from its folder convention (capabilities, plugins, agents, skills)").argument("[dir]","Project root (default: current directory)"),t=>resolve(process.cwd(),t[0]??".")).option("--once","Shut down after the first exchange reaches a terminal outcome").option("--timeout <duration>",'With --once, give up and exit non-zero after this long (milliseconds, or a duration string like "30s")')).action(async(t,e)=>{let{startCommand:n}=await import('./start-OFODWBWZ.js'),o;if(e.timeout!==void 0){let{parseDuration:c}=await import('@routecraft/routecraft'),d=/^\d+(\.\d+)?$/.test(e.timeout.trim())?Number(e.timeout):e.timeout;try{o=c(d,"--timeout");}catch{a({code:1,error:`--timeout must be a number of milliseconds (at least 1) or a duration string like "30s". Received "${String(e.timeout)}".`});return}}if(o!==void 0&&e.once!==true){a({code:1,error:"--timeout bounds the wait for the first exchange, which only --once waits for. Add --once, or drop --timeout."});return}let r=await n(t,{once:e.once===true,...o===void 0?{}:{timeoutMs:o}});if(!r.success){a({code:r.code??1,...r.message?{error:r.message}:{}});return}});function a(t){let e=[];t.output!==void 0&&e.push([process.stdout,t.output]),t.error!==void 0&&e.push([process.stderr,t.error]);let n=()=>{setImmediate(()=>process.exit(t.code));};if(e.length===0){n();return}process.exitCode=t.code,Promise.all(e.map(([o,r])=>C(o,r))).then(n);}async function x(){let{fstatSync:t}=await import('fs');try{let o=t(0);if(!o.isFIFO()&&!o.isFile())return}catch{return}let e=[];for await(let o of process.stdin)e.push(Buffer.from(o));let n=Buffer.concat(e).toString("utf8");return n.length===0?void 0:n}s.command("exec").description("Dispatch to a route on a running instance and print the result").argument("[route]","Route id to dispatch to; omit for the endpoint list").argument("[args...]","Route input as --field=value pairs").option("--profile <name>","Settings profile to select").option(g,h).option("--url <url>","Ops server base URL of the target instance").option("--token <token>","Bearer credential for the management door").option("--format <format>","pretty (default), json, or raw").passThroughOptions().allowUnknownOption().action(async(t,e,n)=>{let{execCommand:o}=await import('./exec-LJZY4IXV.js'),r=t===void 0||e.length>0?void 0:await x();a(await o(t,e,{...n,...r===void 0?{}:{stdin:r}}));});s.command("acp").description("Bridge an editor to an instance over the Agent Client Protocol").option("--profile <name>","Settings profile to select").option(g,h).option("--url <url>","Ops server base URL of the target instance").option("--token <token>","Bearer credential for the management door").option("--agent <name>","Agent to talk to; the instance's default otherwise").action(async t=>{let{acpCommand:e}=await import('./acp-JAOUSF3F.js');a(await e(t));});var m=s.command("ops").description("Inspect a running instance: health, readiness, routes, deferrals, indicators");function u(t){return t.option("--profile <name>","Settings profile to select").option(g,h).option("--url <url>","Ops server base URL of the target instance").option("--token <token>","Bearer credential for the management door").option("--format <format>","pretty (default), json, or raw")}u(m.command("health").description("Operational health: every component, whatever its domain")).action(async t=>{let{healthCommand:e}=await import('./ops-B6N4ATXZ.js');a(await e(t));});u(m.command("ready").description("Readiness: whether this replica should receive traffic")).action(async t=>{let{readyCommand:e}=await import('./ops-B6N4ATXZ.js');a(await e(t));});u(m.command("routes").description("List routes, or describe one").argument("[id]","Route id; omit to list").option("--dispatchable","Only routes that can be dispatched to").option("--source <kind>","Only routes carrying a source of this kind")).action(async(t,e)=>{let{routesCommand:n,routeCommand:o}=await import('./ops-B6N4ATXZ.js');a(t===void 0?await n(e):await o(t,e));});u(m.command("deferrals").description("List what is waiting, or describe one deferral").argument("[id]","Deferral id; omit to list").option("--state <state>","waiting (default), settled, or all").option("--route <id>","Only deferrals belonging to this route").option("--limit <n>","Rows in one page").option("--after <cursor>","Continue from a previous page's cursor")).action(async(t,e)=>{let{deferralsCommand:n,deferralCommand:o}=await import('./ops-B6N4ATXZ.js');a(t===void 0?await n(e):await o(t,e));});u(m.command("indicators").description("List indicators, or read one").argument("[name]","Indicator name; omit to list")).action(async(t,e)=>{let{indicatorsCommand:n,indicatorCommand:o}=await import('./ops-B6N4ATXZ.js');a(t===void 0?await n(e):await o(t,e));});s.command("tui").description("Launch the Terminal UI to monitor Routecraft execution history").option("--db <path>","Path to the telemetry SQLite database",".routecraft/telemetry.db").action(async t=>{let{resolve:e,isAbsolute:n}=await import('path'),o=n(t.db)?t.db:e(process.cwd(),t.db),{renderTui:r}=await import('./tui/app.js');await r(o);});await s.parseAsync();//# sourceMappingURL=index.js.map
|
|
4
4
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"names":["MISSING_BUN_MESSAGE","relaunchOutsideProject","relaunched","Command","program","withLogOptions","version","err","_program","actionCommand","prepareCommand","command","notes","selectEnvironment","flaggedLogFile","applyLogOptions","checkBunRuntime","gate","refuse","logFileDiversion","logger","diverted","source","note","code","message","writeLine","stream","text","done","local","globalOpts","level","file","projectRoots","withEnvironment","projectRoot","options","EnvFileError","loadEnvironment","resolveSettings","SettingsError","settings","error","filePath","args","runCommand","result","settle","resolve","dir","startCommand","timeoutMs","parseDuration","raw","writes","finish","readStdin","fstatSync","stat","chunks","chunk","route","execCommand","stdin","acpCommand","ops","opsOption","healthCommand","readyCommand","id","routesCommand","routeCommand","deferralsCommand","deferralCommand","name","indicatorsCommand","indicatorCommand","isAbsolute","dbPath","renderTui"],"mappings":"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","file":"index.js","sourcesContent":["#!/usr/bin/env bun\n\n/**\n * Routecraft CLI: single entry point.\n *\n * The CLI runs on Bun. For Node-based usage, embed @routecraft/routecraft\n * programmatically (see https://routecraft.dev/docs/advanced/programmatic-invocation).\n *\n * Nothing here may import `@routecraft/routecraft` at module scope, and\n * nothing `prepareCommand()` imports before the runtime gate may either.\n * Core builds its logger when it loads, from the environment as it stands\n * then, so a core import that runs before a command has settled its\n * environment fixes the logger for the life of the process. The program's\n * `preAction` hook runs `prepareCommand()` before every command: it loads\n * the environment the command selects, applies the logging flags over it,\n * checks the log file can be written, and only then runs the Bun version\n * check, the first thing that loads core. Whether Bun is present at all is\n * checked here, before anything, without core.\n */\n\nimport { resolve } from \"node:path\";\n\nimport { version } from \"../package.json\";\nimport { MISSING_BUN_MESSAGE } from \"./bun-requirement.js\";\nimport type { EnvironmentNote } from \"./util.js\";\n\nif (!process.versions[\"bun\"]) {\n // eslint-disable-next-line no-console\n console.error(MISSING_BUN_MESSAGE);\n process.exit(1);\n}\n\nconst { relaunchOutsideProject } = await import(\"./relaunch.js\");\nconst relaunched = relaunchOutsideProject(import.meta.url);\nif (relaunched) process.exit(await relaunched);\n\nconst { Command } = await import(\"commander\");\nconst program = new Command();\n\nwithLogOptions(\n program\n .name(\"craft\")\n .description(\"A modern routing framework for TypeScript\")\n .version(version)\n .enablePositionalOptions(),\n)\n .showSuggestionAfterError()\n .showHelpAfterError()\n .exitOverride((err) => {\n if (err.code === \"commander.unknownCommand\") {\n process.exit(0);\n }\n });\n\nprogram.hook(\"preAction\", async (_program, actionCommand) => {\n await prepareCommand(actionCommand);\n});\n\n// Show help by default if no arguments provided\nif (process.argv.length <= 2) {\n program.help({ error: false });\n}\n\n/**\n * Ready a command to run. Runs from the `preAction` hook, so no command can\n * skip it, and a refusal here stops the command before its action starts.\n *\n * The order is the contract:\n *\n * 1. The environment the command selects, so an env file can configure the\n * logger like any other setting.\n * 2. The logging flags, over it: a flag is the more specific thing said.\n * 3. The Bun version gate, which reads the version with core's parser and\n * so is the first thing that loads core and builds the logger.\n * 4. The log file core was asked for, which it diverts somewhere nobody\n * looks when it cannot open it; the CLI owns the setting, so it refuses.\n */\nasync function prepareCommand(command: CommanderCommand): Promise<void> {\n const notes = await selectEnvironment(command);\n const flaggedLogFile = applyLogOptions(command.opts() as LogOptions);\n\n const { checkBunRuntime } = await import(\"./runtime-gate.js\");\n const gate = checkBunRuntime();\n if (!gate.ok) await refuse(1, gate.message);\n\n const { logFileDiversion, logger } = await import(\"@routecraft/routecraft\");\n const diverted = logFileDiversion();\n if (diverted !== undefined) {\n const source =\n flaggedLogFile === undefined ? diverted.source : \"--log-file\";\n await refuse(\n 2,\n `Cannot write logs to ${diverted.path} (from ${source}): ${diverted.reason}. Point it at a file this process can create or append to.`,\n );\n }\n\n for (const note of notes) logger[note.level](note.message);\n}\n\n/**\n * Stop the command with a message on standard error.\n *\n * The write is awaited before exiting for the reason `settle` gives: an exit\n * discards whatever a pipe still holds.\n */\nasync function refuse(code: number, message: string): Promise<never> {\n await writeLine(process.stderr, message);\n process.exit(code);\n}\n\n/** Write one line and resolve once the stream has taken it. */\nfunction writeLine(stream: NodeJS.WriteStream, text: string): Promise<void> {\n return new Promise((done) => {\n stream.write(`${text}\\n`, () => done());\n });\n}\n\n/**\n * Push the logging flags onto the environment the logger is built from.\n *\n * @returns The log file the flags named, if they named one\n */\nfunction applyLogOptions(local: LogOptions): string | undefined {\n const globalOpts = program.opts();\n // The command's own flag wins, so `craft --log-level warn start --log-level\n // debug` reads the way a reader expects: the nearer one.\n const level = local.logLevel ?? globalOpts[\"logLevel\"];\n const file = local.logFile ?? globalOpts[\"logFile\"];\n if (level !== undefined) {\n process.env[\"LOG_LEVEL\"] = level;\n process.env[\"CRAFT_LOG_LEVEL\"] = level;\n }\n if (file !== undefined) {\n process.env[\"LOG_FILE\"] = file;\n process.env[\"CRAFT_LOG_FILE\"] = file;\n }\n return file;\n}\n\n/**\n * The logging flags a command may carry as well as the program.\n *\n * `enablePositionalOptions()` confines a global option to the space before\n * the subcommand, so `craft start --log-level info` died on \"unknown\n * option\" and `craft run app.ts --log-level info` was swallowed whole by the\n * pass-through and handed to the route. That is the spelling everyone\n * reaches for, and the rule bought nothing here but a lesson every user had\n * to learn once.\n *\n * `run` keeps its pass-through contract: a flag written after the file still\n * belongs to the route, because that is the only way a CLI-adapter route can\n * own a flag the CLI also defines.\n */\ninterface LogOptions {\n logLevel?: string;\n logFile?: string;\n}\n\ntype CommanderCommand = InstanceType<typeof Command>;\n\n/** Attach the logging flags to a command that boots a context. */\nfunction withLogOptions(command: CommanderCommand): CommanderCommand {\n return command\n .option(\n \"--log-level <level>\",\n \"Log level (e.g. info, warn, error, silent to disable)\",\n )\n .option(\"--log-file <path>\", \"Write logs to a file instead of stdout\");\n}\n\n/**\n * The commands that load a project's environment, each with how it finds\n * the project root from its own arguments.\n */\nconst projectRoots = new WeakMap<\n CommanderCommand,\n (args: readonly string[]) => string\n>();\n\n/**\n * Give a command `--env` and `--profile`, and have `prepareCommand()` load\n * the environment they select before anything else runs.\n *\n * The project root has to be knowable from the arguments alone, because the\n * environment is loaded before the action and so before core exists.\n */\nfunction withEnvironment(\n command: CommanderCommand,\n projectRoot: (args: readonly string[]) => string,\n): CommanderCommand {\n projectRoots.set(command, projectRoot);\n return command\n .option(\n \"--env <path>\",\n \"Load environment variables from a .env file (default: .env)\",\n )\n .option(\"--profile <name>\", \"Settings profile to select\");\n}\n\n/**\n * Resolve the selected profile and load the environment it names, when the\n * command is one that loads a project.\n *\n * Ordering is the whole point: a config file reads `process.env` at module\n * scope, and core reads its log settings from it when it loads, so the\n * environment has to be in place before either, and the profile is what\n * says which environment that is.\n *\n * A settings file that cannot be used stops the command rather than\n * falling back to the defaults, because an operator who wrote a profile\n * and silently got the loopback default would have no way to tell.\n */\nasync function selectEnvironment(\n command: CommanderCommand,\n): Promise<EnvironmentNote[]> {\n const projectRoot = projectRoots.get(command)?.(command.args);\n if (projectRoot === undefined) return [];\n const options = command.opts() as { env?: string; profile?: string };\n const { EnvFileError, loadEnvironment } = await import(\"./util.js\");\n const { resolveSettings, SettingsError } = await import(\"./settings.js\");\n try {\n // Resolved under the project root, not the shell's directory: the file\n // that declares a profile and the env files that profile selects have\n // to be the same project's, or `craft start ./apps/acme` reads one\n // project's profile and another's environment.\n const settings = resolveSettings({\n cwd: projectRoot,\n ...(options.profile === undefined ? {} : { profile: options.profile }),\n });\n return loadEnvironment({\n explicit: options.env,\n profile: settings.profile?.value,\n env: settings.env?.value,\n defaultsFrom: projectRoot,\n });\n } catch (error: unknown) {\n if (error instanceof SettingsError || error instanceof EnvFileError) {\n return refuse(2, error.message);\n }\n throw error;\n }\n}\n\n/**\n * The 'run' command executes routes from a single file.\n *\n * Example:\n * craft run ./my-routes.ts\n * craft run ./my-cli.ts greet --name World\n */\nwithLogOptions(\n withEnvironment(\n program\n .command(\"run\")\n .description(\"Run routes from a single TypeScript/JavaScript file\")\n .argument(\"<file>\", \"Path to a file containing routes\")\n .argument(\n \"[args...]\",\n \"CLI command and flags to pass through to CLI adapter routes\",\n ),\n () => process.cwd(),\n ),\n)\n .passThroughOptions()\n .action(async (filePath, args: string[]) => {\n const { runCommand } = await import(\"./run.js\");\n const result = await runCommand(filePath, args);\n if (!result.success) {\n settle({\n code: result.code ?? 1,\n ...(result.message ? { error: result.message } : {}),\n });\n return;\n }\n // Don't call process.exit(); let the event loop drain naturally.\n // process.exit() triggers C++ static destructors that race with ONNX\n // Runtime cleanup (onnxruntime#25038: \"mutex lock failed\").\n });\n\n/**\n * The 'start' command boots a whole project from the folder convention.\n *\n * Example:\n * craft start\n * craft start ./apps/acme --once\n */\nwithLogOptions(\n withEnvironment(\n program\n .command(\"start\")\n .description(\n \"Start a project from its folder convention (capabilities, plugins, agents, skills)\",\n )\n .argument(\"[dir]\", \"Project root (default: current directory)\"),\n // The conventional files belong to the project being started, not to\n // whatever directory the shell happens to sit in.\n (args) => resolve(process.cwd(), args[0] ?? \".\"),\n )\n .option(\n \"--once\",\n \"Shut down after the first exchange reaches a terminal outcome\",\n )\n .option(\n \"--timeout <duration>\",\n 'With --once, give up and exit non-zero after this long (milliseconds, or a duration string like \"30s\")',\n ),\n).action(\n async (\n dir: string | undefined,\n options: {\n once?: boolean;\n timeout?: string;\n },\n ) => {\n const { startCommand } = await import(\"./start.js\");\n // A bare number stays milliseconds, so every existing invocation keeps\n // working; anything else goes through the framework's duration grammar\n // so `--timeout 30s` means what it reads as.\n let timeoutMs: number | undefined;\n if (options.timeout !== undefined) {\n const { parseDuration } = await import(\"@routecraft/routecraft\");\n const raw = /^\\d+(\\.\\d+)?$/.test(options.timeout.trim())\n ? Number(options.timeout)\n : (options.timeout as `${number}s`);\n try {\n timeoutMs = parseDuration(raw, \"--timeout\");\n } catch {\n settle({\n code: 1,\n error: `--timeout must be a number of milliseconds (at least 1) or a duration string like \"30s\". Received \"${String(options.timeout)}\".`,\n });\n return;\n }\n }\n if (timeoutMs !== undefined && options.once !== true) {\n settle({\n code: 1,\n error: `--timeout bounds the wait for the first exchange, which only --once waits for. Add --once, or drop --timeout.`,\n });\n return;\n }\n const result = await startCommand(dir, {\n once: options.once === true,\n ...(timeoutMs === undefined ? {} : { timeoutMs }),\n });\n if (!result.success) {\n settle({\n code: result.code ?? 1,\n ...(result.message ? { error: result.message } : {}),\n });\n return;\n }\n // Don't call process.exit(); let the event loop drain naturally.\n },\n);\n\n/**\n * Print a command's result and exit with its code.\n *\n * The write is awaited rather than fired and forgotten. `process.stdout` is\n * asynchronous when it is a pipe, and `process.exit` discards whatever is\n * still queued, so `craft exec --format json | jq` would lose the tail of a\n * large result. Exiting from the write callback is what makes the payload\n * whole; the exit itself stays deferred so pino/sonic-boom can finish\n * initialising.\n */\nfunction settle(result: {\n code: number;\n output?: string;\n error?: string;\n}): void {\n const writes: Array<[NodeJS.WriteStream, string]> = [];\n if (result.output !== undefined) writes.push([process.stdout, result.output]);\n if (result.error !== undefined) writes.push([process.stderr, result.error]);\n\n const finish = (): void => {\n setImmediate(() => process.exit(result.code));\n };\n if (writes.length === 0) {\n finish();\n return;\n }\n // Set early so a stream that never drains still exits with the right code\n // rather than reporting success on the way out.\n process.exitCode = result.code;\n void Promise.all(\n writes.map(([stream, text]) => writeLine(stream, text)),\n ).then(finish);\n}\n\n/**\n * Read route input piped on stdin, or undefined when none was.\n *\n * Gated on stdin actually being a redirect (a pipe or a file) rather than\n * on it not being a TTY. The two are not the same: a process launched by\n * CI, a supervisor, or another program routinely inherits a socket on fd 0\n * that is neither a terminal nor ever going to close, and reading it waits\n * for an EOF that never comes. `craft exec` would hang with no output,\n * which is the worst way to fail.\n */\nasync function readStdin(): Promise<string | undefined> {\n const { fstatSync } = await import(\"node:fs\");\n try {\n const stat = fstatSync(0);\n if (!stat.isFIFO() && !stat.isFile()) return undefined;\n } catch {\n return undefined;\n }\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(Buffer.from(chunk as Buffer));\n }\n const text = Buffer.concat(chunks).toString(\"utf8\");\n return text.length === 0 ? undefined : text;\n}\n\n/**\n * The 'exec' command dispatches to a route on a running instance.\n *\n * Craft's own flags come before the route name and the route's input comes\n * after it, the same split `craft run` uses, so a route field can never\n * collide with a CLI flag.\n *\n * Example:\n * craft exec greet --name World\n * craft exec --url http://10.0.0.5:8080 --token \"$TOKEN\" greet --name World\n */\nprogram\n .command(\"exec\")\n .description(\"Dispatch to a route on a running instance and print the result\")\n .argument(\"[route]\", \"Route id to dispatch to; omit for the endpoint list\")\n .argument(\"[args...]\", \"Route input as --field=value pairs\")\n .option(\"--profile <name>\", \"Settings profile to select\")\n .option(\"--url <url>\", \"Ops server base URL of the target instance\")\n .option(\"--token <token>\", \"Bearer credential for the management door\")\n .option(\"--format <format>\", \"pretty (default), json, or raw\")\n .passThroughOptions()\n .allowUnknownOption()\n .action(\n async (\n route: string | undefined,\n args: string[],\n options: {\n profile?: string;\n url?: string;\n token?: string;\n format?: string;\n },\n ) => {\n const { execCommand } = await import(\"./exec.js\");\n // Args and stdin are mutually exclusive, so a command that already\n // carries args must not read stdin at all: in `tail -f x | while read\n // l; do craft exec r --line=\\\"$l\\\"; done` the inherited pipe never\n // closes, and reading it would hang and swallow the loop's own input.\n const stdin =\n route === undefined || args.length > 0 ? undefined : await readStdin();\n settle(\n await execCommand(route, args, {\n ...options,\n ...(stdin === undefined ? {} : { stdin }),\n }),\n );\n },\n );\n\n/**\n * The 'acp' command is the pipe an editor runs.\n *\n * An editor starts it and speaks the Agent Client Protocol over its\n * standard input and output; it forwards every message to the instance the\n * profile names, and forwards everything the instance says back. It never\n * starts an app: `craft start` owns running, which is what lets one editor\n * entry reach a laptop or a company instance by switching a profile.\n *\n * Example:\n * craft acp\n * craft acp --profile company\n * craft acp --url https://acme.example --token \"$TOKEN\" --agent aria\n */\nprogram\n .command(\"acp\")\n .description(\"Bridge an editor to an instance over the Agent Client Protocol\")\n .option(\"--profile <name>\", \"Settings profile to select\")\n .option(\"--url <url>\", \"Ops server base URL of the target instance\")\n .option(\"--token <token>\", \"Bearer credential for the management door\")\n .option(\n \"--agent <name>\",\n \"Agent to talk to; the instance's default otherwise\",\n )\n .action(\n async (options: {\n profile?: string;\n url?: string;\n token?: string;\n agent?: string;\n }) => {\n const { acpCommand } = await import(\"./acp.js\");\n // Standard output is the protocol's, and `settle` writes there only\n // for a result carrying `output`, which this one never does. What it\n // adds is the awaited write: an editor spawns this with a pipe on\n // standard error, where an exit discards whatever is still queued.\n settle(await acpCommand(options));\n },\n );\n\n/**\n * The 'ops' command family reads a running instance's own state.\n *\n * Grouped by operator task rather than by URL prefix: `craft ops health`\n * reads `/health/**` while `craft ops routes` reads `/ops/routes`, because\n * the two surfaces have deliberately different auth postures and the\n * command family answers a different question from the path layout.\n *\n * Example:\n * craft ops health\n * craft ops routes --dispatchable\n */\nconst ops = program\n .command(\"ops\")\n .description(\n \"Inspect a running instance: health, readiness, routes, deferrals, indicators\",\n );\n\nfunction opsOption<T extends import(\"commander\").Command>(command: T): T {\n return command\n .option(\"--profile <name>\", \"Settings profile to select\")\n .option(\"--url <url>\", \"Ops server base URL of the target instance\")\n .option(\"--token <token>\", \"Bearer credential for the management door\")\n .option(\"--format <format>\", \"pretty (default), json, or raw\") as T;\n}\n\nopsOption(\n ops\n .command(\"health\")\n .description(\"Operational health: every component, whatever its domain\"),\n).action(async (options: Record<string, string>) => {\n const { healthCommand } = await import(\"./ops.js\");\n settle(await healthCommand(options));\n});\n\nopsOption(\n ops\n .command(\"ready\")\n .description(\"Readiness: whether this replica should receive traffic\"),\n).action(async (options: Record<string, string>) => {\n const { readyCommand } = await import(\"./ops.js\");\n settle(await readyCommand(options));\n});\n\nopsOption(\n ops\n .command(\"routes\")\n .description(\"List routes, or describe one\")\n .argument(\"[id]\", \"Route id; omit to list\")\n .option(\"--dispatchable\", \"Only routes that can be dispatched to\")\n .option(\"--source <kind>\", \"Only routes carrying a source of this kind\"),\n).action(\n async (\n id: string | undefined,\n options: {\n dispatchable?: boolean;\n source?: string;\n profile?: string;\n url?: string;\n token?: string;\n format?: string;\n },\n ) => {\n const { routesCommand, routeCommand } = await import(\"./ops.js\");\n settle(\n id === undefined\n ? await routesCommand(options)\n : await routeCommand(id, options),\n );\n },\n);\n\nopsOption(\n ops\n .command(\"deferrals\")\n .description(\"List what is waiting, or describe one deferral\")\n .argument(\"[id]\", \"Deferral id; omit to list\")\n .option(\"--state <state>\", \"waiting (default), settled, or all\")\n .option(\"--route <id>\", \"Only deferrals belonging to this route\")\n .option(\"--limit <n>\", \"Rows in one page\")\n .option(\"--after <cursor>\", \"Continue from a previous page's cursor\"),\n).action(\n async (\n id: string | undefined,\n options: {\n state?: string;\n route?: string;\n limit?: string;\n after?: string;\n profile?: string;\n url?: string;\n token?: string;\n format?: string;\n },\n ) => {\n const { deferralsCommand, deferralCommand } = await import(\"./ops.js\");\n settle(\n id === undefined\n ? await deferralsCommand(options)\n : await deferralCommand(id, options),\n );\n },\n);\n\nopsOption(\n ops\n .command(\"indicators\")\n .description(\"List indicators, or read one\")\n .argument(\"[name]\", \"Indicator name; omit to list\"),\n).action(async (name: string | undefined, options: Record<string, string>) => {\n const { indicatorsCommand, indicatorCommand } = await import(\"./ops.js\");\n settle(\n name === undefined\n ? await indicatorsCommand(options)\n : await indicatorCommand(name, options),\n );\n});\n\n/**\n * The 'tui' command launches the Terminal UI for monitoring Routecraft execution.\n *\n * Example:\n * craft tui\n * craft tui --db .routecraft/telemetry.db\n */\nprogram\n .command(\"tui\")\n .description(\"Launch the Terminal UI to monitor Routecraft execution history\")\n .option(\n \"--db <path>\",\n \"Path to the telemetry SQLite database\",\n \".routecraft/telemetry.db\",\n )\n .action(async (options) => {\n const { resolve, isAbsolute } = await import(\"node:path\");\n const dbPath = isAbsolute(options.db)\n ? options.db\n : resolve(process.cwd(), options.db);\n\n const { renderTui } = await import(\"./tui/app.js\");\n await renderTui(dbPath);\n });\n\n// Parse the command line arguments and execute the appropriate command\nawait program.parseAsync();\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"names":["MISSING_BUN_MESSAGE","relaunchOutsideProject","relaunched","Command","program","withLogOptions","version","err","_program","actionCommand","prepareCommand","command","notes","selectEnvironment","flaggedLogFile","applyLogOptions","checkBunRuntime","gate","refuse","logFileDiversion","logger","diverted","source","note","code","message","writeLine","stream","text","done","local","globalOpts","level","file","projectRoots","PROJECT_FLAG","PROJECT_HELP","withEnvironment","projectRoot","options","EnvFileError","loadEnvironment","resolveSettings","SettingsError","settings","error","filePath","args","runCommand","result","settle","resolve","dir","startCommand","timeoutMs","parseDuration","raw","writes","finish","readStdin","fstatSync","stat","chunks","chunk","route","execCommand","stdin","acpCommand","ops","opsOption","healthCommand","readyCommand","id","routesCommand","routeCommand","deferralsCommand","deferralCommand","name","indicatorsCommand","indicatorCommand","isAbsolute","dbPath","renderTui"],"mappings":"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","file":"index.js","sourcesContent":["#!/usr/bin/env bun\n\n/**\n * Routecraft CLI: single entry point.\n *\n * The CLI runs on Bun. For Node-based usage, embed @routecraft/routecraft\n * programmatically (see https://routecraft.dev/docs/advanced/programmatic-invocation).\n *\n * Nothing here may import `@routecraft/routecraft` at module scope, and\n * nothing `prepareCommand()` imports before the runtime gate may either.\n * Core builds its logger when it loads, from the environment as it stands\n * then, so a core import that runs before a command has settled its\n * environment fixes the logger for the life of the process. The program's\n * `preAction` hook runs `prepareCommand()` before every command: it loads\n * the environment the command selects, applies the logging flags over it,\n * checks the log file can be written, and only then runs the Bun version\n * check, the first thing that loads core. Whether Bun is present at all is\n * checked here, before anything, without core.\n */\n\nimport { resolve } from \"node:path\";\n\nimport { version } from \"../package.json\";\nimport { MISSING_BUN_MESSAGE } from \"./bun-requirement.js\";\nimport type { EnvironmentNote } from \"./util.js\";\n\nif (!process.versions[\"bun\"]) {\n // eslint-disable-next-line no-console\n console.error(MISSING_BUN_MESSAGE);\n process.exit(1);\n}\n\nconst { relaunchOutsideProject } = await import(\"./relaunch.js\");\nconst relaunched = relaunchOutsideProject(import.meta.url);\nif (relaunched) process.exit(await relaunched);\n\nconst { Command } = await import(\"commander\");\nconst program = new Command();\n\nwithLogOptions(\n program\n .name(\"craft\")\n .description(\"A modern routing framework for TypeScript\")\n .version(version)\n .enablePositionalOptions(),\n)\n .showSuggestionAfterError()\n .showHelpAfterError()\n .exitOverride((err) => {\n if (err.code === \"commander.unknownCommand\") {\n process.exit(0);\n }\n });\n\nprogram.hook(\"preAction\", async (_program, actionCommand) => {\n await prepareCommand(actionCommand);\n});\n\n// Show help by default if no arguments provided\nif (process.argv.length <= 2) {\n program.help({ error: false });\n}\n\n/**\n * Ready a command to run. Runs from the `preAction` hook, so no command can\n * skip it, and a refusal here stops the command before its action starts.\n *\n * The order is the contract:\n *\n * 1. The environment the command selects, so an env file can configure the\n * logger like any other setting.\n * 2. The logging flags, over it: a flag is the more specific thing said.\n * 3. The Bun version gate, which reads the version with core's parser and\n * so is the first thing that loads core and builds the logger.\n * 4. The log file core was asked for, which it diverts somewhere nobody\n * looks when it cannot open it; the CLI owns the setting, so it refuses.\n */\nasync function prepareCommand(command: CommanderCommand): Promise<void> {\n const notes = await selectEnvironment(command);\n const flaggedLogFile = applyLogOptions(command.opts() as LogOptions);\n\n const { checkBunRuntime } = await import(\"./runtime-gate.js\");\n const gate = checkBunRuntime();\n if (!gate.ok) await refuse(1, gate.message);\n\n const { logFileDiversion, logger } = await import(\"@routecraft/routecraft\");\n const diverted = logFileDiversion();\n if (diverted !== undefined) {\n const source =\n flaggedLogFile === undefined ? diverted.source : \"--log-file\";\n await refuse(\n 2,\n `Cannot write logs to ${diverted.path} (from ${source}): ${diverted.reason}. Point it at a file this process can create or append to.`,\n );\n }\n\n for (const note of notes) logger[note.level](note.message);\n}\n\n/**\n * Stop the command with a message on standard error.\n *\n * The write is awaited before exiting for the reason `settle` gives: an exit\n * discards whatever a pipe still holds.\n */\nasync function refuse(code: number, message: string): Promise<never> {\n await writeLine(process.stderr, message);\n process.exit(code);\n}\n\n/** Write one line and resolve once the stream has taken it. */\nfunction writeLine(stream: NodeJS.WriteStream, text: string): Promise<void> {\n return new Promise((done) => {\n stream.write(`${text}\\n`, () => done());\n });\n}\n\n/**\n * Push the logging flags onto the environment the logger is built from.\n *\n * @returns The log file the flags named, if they named one\n */\nfunction applyLogOptions(local: LogOptions): string | undefined {\n const globalOpts = program.opts();\n // The command's own flag wins, so `craft --log-level warn start --log-level\n // debug` reads the way a reader expects: the nearer one.\n const level = local.logLevel ?? globalOpts[\"logLevel\"];\n const file = local.logFile ?? globalOpts[\"logFile\"];\n if (level !== undefined) {\n process.env[\"LOG_LEVEL\"] = level;\n process.env[\"CRAFT_LOG_LEVEL\"] = level;\n }\n if (file !== undefined) {\n process.env[\"LOG_FILE\"] = file;\n process.env[\"CRAFT_LOG_FILE\"] = file;\n }\n return file;\n}\n\n/**\n * The logging flags a command may carry as well as the program.\n *\n * `enablePositionalOptions()` confines a global option to the space before\n * the subcommand, so `craft start --log-level info` died on \"unknown\n * option\" and `craft run app.ts --log-level info` was swallowed whole by the\n * pass-through and handed to the route. That is the spelling everyone\n * reaches for, and the rule bought nothing here but a lesson every user had\n * to learn once.\n *\n * `run` keeps its pass-through contract: a flag written after the file still\n * belongs to the route, because that is the only way a CLI-adapter route can\n * own a flag the CLI also defines.\n */\ninterface LogOptions {\n logLevel?: string;\n logFile?: string;\n}\n\ntype CommanderCommand = InstanceType<typeof Command>;\n\n/** Attach the logging flags to a command that boots a context. */\nfunction withLogOptions(command: CommanderCommand): CommanderCommand {\n return command\n .option(\n \"--log-level <level>\",\n \"Log level (e.g. info, warn, error, silent to disable)\",\n )\n .option(\"--log-file <path>\", \"Write logs to a file instead of stdout\");\n}\n\n/**\n * The commands that load a project's environment, each with how it finds\n * the project root from its own arguments.\n */\nconst projectRoots = new WeakMap<\n CommanderCommand,\n (args: readonly string[]) => string\n>();\n\n/**\n * `--project`, shared by every command that reads the settings file to reach\n * an instance. The settings file is looked for under the working directory,\n * which an editor running `craft acp` chooses, not the person.\n */\nconst PROJECT_FLAG = \"--project <dir>\";\nconst PROJECT_HELP =\n \"Project whose .routecraft/settings.yaml is read (default: the working directory)\";\n\n/**\n * Give a command `--env` and `--profile`, and have `prepareCommand()` load\n * the environment they select before anything else runs.\n *\n * The project root has to be knowable from the arguments alone, because the\n * environment is loaded before the action and so before core exists.\n */\nfunction withEnvironment(\n command: CommanderCommand,\n projectRoot: (args: readonly string[]) => string,\n): CommanderCommand {\n projectRoots.set(command, projectRoot);\n return command\n .option(\n \"--env <path>\",\n \"Load environment variables from a .env file (default: .env)\",\n )\n .option(\"--profile <name>\", \"Settings profile to select\");\n}\n\n/**\n * Resolve the selected profile and load the environment it names, when the\n * command is one that loads a project.\n *\n * Ordering is the whole point: a config file reads `process.env` at module\n * scope, and core reads its log settings from it when it loads, so the\n * environment has to be in place before either, and the profile is what\n * says which environment that is.\n *\n * A settings file that cannot be used stops the command rather than\n * falling back to the defaults, because an operator who wrote a profile\n * and silently got the loopback default would have no way to tell.\n */\nasync function selectEnvironment(\n command: CommanderCommand,\n): Promise<EnvironmentNote[]> {\n const projectRoot = projectRoots.get(command)?.(command.args);\n if (projectRoot === undefined) return [];\n const options = command.opts() as { env?: string; profile?: string };\n const { EnvFileError, loadEnvironment } = await import(\"./util.js\");\n const { resolveSettings, SettingsError } = await import(\"./settings.js\");\n try {\n // Resolved under the project root, not the shell's directory: the file\n // that declares a profile and the env files that profile selects have\n // to be the same project's, or `craft start ./apps/acme` reads one\n // project's profile and another's environment.\n const settings = resolveSettings({\n cwd: projectRoot,\n ...(options.profile === undefined ? {} : { profile: options.profile }),\n });\n return loadEnvironment({\n explicit: options.env,\n profile: settings.profile?.value,\n env: settings.env?.value,\n defaultsFrom: projectRoot,\n });\n } catch (error: unknown) {\n if (error instanceof SettingsError || error instanceof EnvFileError) {\n return refuse(2, error.message);\n }\n throw error;\n }\n}\n\n/**\n * The 'run' command executes routes from a single file.\n *\n * Example:\n * craft run ./my-routes.ts\n * craft run ./my-cli.ts greet --name World\n */\nwithLogOptions(\n withEnvironment(\n program\n .command(\"run\")\n .description(\"Run routes from a single TypeScript/JavaScript file\")\n .argument(\"<file>\", \"Path to a file containing routes\")\n .argument(\n \"[args...]\",\n \"CLI command and flags to pass through to CLI adapter routes\",\n ),\n () => process.cwd(),\n ),\n)\n .passThroughOptions()\n .action(async (filePath, args: string[]) => {\n const { runCommand } = await import(\"./run.js\");\n const result = await runCommand(filePath, args);\n if (!result.success) {\n settle({\n code: result.code ?? 1,\n ...(result.message ? { error: result.message } : {}),\n });\n return;\n }\n // Don't call process.exit(); let the event loop drain naturally.\n // process.exit() triggers C++ static destructors that race with ONNX\n // Runtime cleanup (onnxruntime#25038: \"mutex lock failed\").\n });\n\n/**\n * The 'start' command boots a whole project from the folder convention.\n *\n * Example:\n * craft start\n * craft start ./apps/acme --once\n */\nwithLogOptions(\n withEnvironment(\n program\n .command(\"start\")\n .description(\n \"Start a project from its folder convention (capabilities, plugins, agents, skills)\",\n )\n .argument(\"[dir]\", \"Project root (default: current directory)\"),\n // The conventional files belong to the project being started, not to\n // whatever directory the shell happens to sit in.\n (args) => resolve(process.cwd(), args[0] ?? \".\"),\n )\n .option(\n \"--once\",\n \"Shut down after the first exchange reaches a terminal outcome\",\n )\n .option(\n \"--timeout <duration>\",\n 'With --once, give up and exit non-zero after this long (milliseconds, or a duration string like \"30s\")',\n ),\n).action(\n async (\n dir: string | undefined,\n options: {\n once?: boolean;\n timeout?: string;\n },\n ) => {\n const { startCommand } = await import(\"./start.js\");\n // A bare number stays milliseconds, so every existing invocation keeps\n // working; anything else goes through the framework's duration grammar\n // so `--timeout 30s` means what it reads as.\n let timeoutMs: number | undefined;\n if (options.timeout !== undefined) {\n const { parseDuration } = await import(\"@routecraft/routecraft\");\n const raw = /^\\d+(\\.\\d+)?$/.test(options.timeout.trim())\n ? Number(options.timeout)\n : (options.timeout as `${number}s`);\n try {\n timeoutMs = parseDuration(raw, \"--timeout\");\n } catch {\n settle({\n code: 1,\n error: `--timeout must be a number of milliseconds (at least 1) or a duration string like \"30s\". Received \"${String(options.timeout)}\".`,\n });\n return;\n }\n }\n if (timeoutMs !== undefined && options.once !== true) {\n settle({\n code: 1,\n error: `--timeout bounds the wait for the first exchange, which only --once waits for. Add --once, or drop --timeout.`,\n });\n return;\n }\n const result = await startCommand(dir, {\n once: options.once === true,\n ...(timeoutMs === undefined ? {} : { timeoutMs }),\n });\n if (!result.success) {\n settle({\n code: result.code ?? 1,\n ...(result.message ? { error: result.message } : {}),\n });\n return;\n }\n // Don't call process.exit(); let the event loop drain naturally.\n },\n);\n\n/**\n * Print a command's result and exit with its code.\n *\n * The write is awaited rather than fired and forgotten. `process.stdout` is\n * asynchronous when it is a pipe, and `process.exit` discards whatever is\n * still queued, so `craft exec --format json | jq` would lose the tail of a\n * large result. Exiting from the write callback is what makes the payload\n * whole; the exit itself stays deferred so pino/sonic-boom can finish\n * initialising.\n */\nfunction settle(result: {\n code: number;\n output?: string;\n error?: string;\n}): void {\n const writes: Array<[NodeJS.WriteStream, string]> = [];\n if (result.output !== undefined) writes.push([process.stdout, result.output]);\n if (result.error !== undefined) writes.push([process.stderr, result.error]);\n\n const finish = (): void => {\n setImmediate(() => process.exit(result.code));\n };\n if (writes.length === 0) {\n finish();\n return;\n }\n // Set early so a stream that never drains still exits with the right code\n // rather than reporting success on the way out.\n process.exitCode = result.code;\n void Promise.all(\n writes.map(([stream, text]) => writeLine(stream, text)),\n ).then(finish);\n}\n\n/**\n * Read route input piped on stdin, or undefined when none was.\n *\n * Gated on stdin actually being a redirect (a pipe or a file) rather than\n * on it not being a TTY. The two are not the same: a process launched by\n * CI, a supervisor, or another program routinely inherits a socket on fd 0\n * that is neither a terminal nor ever going to close, and reading it waits\n * for an EOF that never comes. `craft exec` would hang with no output,\n * which is the worst way to fail.\n */\nasync function readStdin(): Promise<string | undefined> {\n const { fstatSync } = await import(\"node:fs\");\n try {\n const stat = fstatSync(0);\n if (!stat.isFIFO() && !stat.isFile()) return undefined;\n } catch {\n return undefined;\n }\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(Buffer.from(chunk as Buffer));\n }\n const text = Buffer.concat(chunks).toString(\"utf8\");\n return text.length === 0 ? undefined : text;\n}\n\n/**\n * The 'exec' command dispatches to a route on a running instance.\n *\n * Craft's own flags come before the route name and the route's input comes\n * after it, the same split `craft run` uses, so a route field can never\n * collide with a CLI flag.\n *\n * Example:\n * craft exec greet --name World\n * craft exec --url http://10.0.0.5:8080 --token \"$TOKEN\" greet --name World\n */\nprogram\n .command(\"exec\")\n .description(\"Dispatch to a route on a running instance and print the result\")\n .argument(\"[route]\", \"Route id to dispatch to; omit for the endpoint list\")\n .argument(\"[args...]\", \"Route input as --field=value pairs\")\n .option(\"--profile <name>\", \"Settings profile to select\")\n .option(PROJECT_FLAG, PROJECT_HELP)\n .option(\"--url <url>\", \"Ops server base URL of the target instance\")\n .option(\"--token <token>\", \"Bearer credential for the management door\")\n .option(\"--format <format>\", \"pretty (default), json, or raw\")\n .passThroughOptions()\n .allowUnknownOption()\n .action(\n async (\n route: string | undefined,\n args: string[],\n options: {\n profile?: string;\n project?: string;\n url?: string;\n token?: string;\n format?: string;\n },\n ) => {\n const { execCommand } = await import(\"./exec.js\");\n // Args and stdin are mutually exclusive, so a command that already\n // carries args must not read stdin at all: in `tail -f x | while read\n // l; do craft exec r --line=\\\"$l\\\"; done` the inherited pipe never\n // closes, and reading it would hang and swallow the loop's own input.\n const stdin =\n route === undefined || args.length > 0 ? undefined : await readStdin();\n settle(\n await execCommand(route, args, {\n ...options,\n ...(stdin === undefined ? {} : { stdin }),\n }),\n );\n },\n );\n\n/**\n * The 'acp' command is the pipe an editor runs.\n *\n * An editor starts it and speaks the Agent Client Protocol over its\n * standard input and output; it forwards every message to the instance the\n * profile names, and forwards everything the instance says back. It never\n * starts an app: `craft start` owns running, which is what lets one editor\n * entry reach a laptop or a company instance by switching a profile.\n *\n * An editor starts this from whatever project it has open, so `--project`\n * names the one whose `.routecraft/settings.yaml` holds the profile.\n *\n * Example:\n * craft acp\n * craft acp --profile company\n * craft acp --project /path/to/my-agent --profile editor\n * craft acp --url https://acme.example --token \"$TOKEN\" --agent aria\n */\nprogram\n .command(\"acp\")\n .description(\"Bridge an editor to an instance over the Agent Client Protocol\")\n .option(\"--profile <name>\", \"Settings profile to select\")\n .option(PROJECT_FLAG, PROJECT_HELP)\n .option(\"--url <url>\", \"Ops server base URL of the target instance\")\n .option(\"--token <token>\", \"Bearer credential for the management door\")\n .option(\n \"--agent <name>\",\n \"Agent to talk to; the instance's default otherwise\",\n )\n .action(\n async (options: {\n profile?: string;\n project?: string;\n url?: string;\n token?: string;\n agent?: string;\n }) => {\n const { acpCommand } = await import(\"./acp.js\");\n // Standard output is the protocol's, and `settle` writes there only\n // for a result carrying `output`, which this one never does. What it\n // adds is the awaited write: an editor spawns this with a pipe on\n // standard error, where an exit discards whatever is still queued.\n settle(await acpCommand(options));\n },\n );\n\n/**\n * The 'ops' command family reads a running instance's own state.\n *\n * Grouped by operator task rather than by URL prefix: `craft ops health`\n * reads `/health/**` while `craft ops routes` reads `/ops/routes`, because\n * the two surfaces have deliberately different auth postures and the\n * command family answers a different question from the path layout.\n *\n * Example:\n * craft ops health\n * craft ops routes --dispatchable\n */\nconst ops = program\n .command(\"ops\")\n .description(\n \"Inspect a running instance: health, readiness, routes, deferrals, indicators\",\n );\n\nfunction opsOption<T extends import(\"commander\").Command>(command: T): T {\n return command\n .option(\"--profile <name>\", \"Settings profile to select\")\n .option(PROJECT_FLAG, PROJECT_HELP)\n .option(\"--url <url>\", \"Ops server base URL of the target instance\")\n .option(\"--token <token>\", \"Bearer credential for the management door\")\n .option(\"--format <format>\", \"pretty (default), json, or raw\") as T;\n}\n\nopsOption(\n ops\n .command(\"health\")\n .description(\"Operational health: every component, whatever its domain\"),\n).action(async (options: Record<string, string>) => {\n const { healthCommand } = await import(\"./ops.js\");\n settle(await healthCommand(options));\n});\n\nopsOption(\n ops\n .command(\"ready\")\n .description(\"Readiness: whether this replica should receive traffic\"),\n).action(async (options: Record<string, string>) => {\n const { readyCommand } = await import(\"./ops.js\");\n settle(await readyCommand(options));\n});\n\nopsOption(\n ops\n .command(\"routes\")\n .description(\"List routes, or describe one\")\n .argument(\"[id]\", \"Route id; omit to list\")\n .option(\"--dispatchable\", \"Only routes that can be dispatched to\")\n .option(\"--source <kind>\", \"Only routes carrying a source of this kind\"),\n).action(\n async (\n id: string | undefined,\n options: {\n dispatchable?: boolean;\n source?: string;\n profile?: string;\n url?: string;\n token?: string;\n format?: string;\n },\n ) => {\n const { routesCommand, routeCommand } = await import(\"./ops.js\");\n settle(\n id === undefined\n ? await routesCommand(options)\n : await routeCommand(id, options),\n );\n },\n);\n\nopsOption(\n ops\n .command(\"deferrals\")\n .description(\"List what is waiting, or describe one deferral\")\n .argument(\"[id]\", \"Deferral id; omit to list\")\n .option(\"--state <state>\", \"waiting (default), settled, or all\")\n .option(\"--route <id>\", \"Only deferrals belonging to this route\")\n .option(\"--limit <n>\", \"Rows in one page\")\n .option(\"--after <cursor>\", \"Continue from a previous page's cursor\"),\n).action(\n async (\n id: string | undefined,\n options: {\n state?: string;\n route?: string;\n limit?: string;\n after?: string;\n profile?: string;\n url?: string;\n token?: string;\n format?: string;\n },\n ) => {\n const { deferralsCommand, deferralCommand } = await import(\"./ops.js\");\n settle(\n id === undefined\n ? await deferralsCommand(options)\n : await deferralCommand(id, options),\n );\n },\n);\n\nopsOption(\n ops\n .command(\"indicators\")\n .description(\"List indicators, or read one\")\n .argument(\"[name]\", \"Indicator name; omit to list\"),\n).action(async (name: string | undefined, options: Record<string, string>) => {\n const { indicatorsCommand, indicatorCommand } = await import(\"./ops.js\");\n settle(\n name === undefined\n ? await indicatorsCommand(options)\n : await indicatorCommand(name, options),\n );\n});\n\n/**\n * The 'tui' command launches the Terminal UI for monitoring Routecraft execution.\n *\n * Example:\n * craft tui\n * craft tui --db .routecraft/telemetry.db\n */\nprogram\n .command(\"tui\")\n .description(\"Launch the Terminal UI to monitor Routecraft execution history\")\n .option(\n \"--db <path>\",\n \"Path to the telemetry SQLite database\",\n \".routecraft/telemetry.db\",\n )\n .action(async (options) => {\n const { resolve, isAbsolute } = await import(\"node:path\");\n const dbPath = isAbsolute(options.db)\n ? options.db\n : resolve(process.cwd(), options.db);\n\n const { renderTui } = await import(\"./tui/app.js\");\n await renderTui(dbPath);\n });\n\n// Parse the command line arguments and execute the appropriate command\nawait program.parseAsync();\n"]}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {j,k as k$1,b,m,g,c,f,d,e,h,i as i$1}from'./chunk-
|
|
2
|
-
//# sourceMappingURL=ops-
|
|
1
|
+
import {j,k as k$1,b,m,g,c,f,d,e,h,i as i$1}from'./chunk-DJD3H3G5.js';import'./chunk-WYVHXXTI.js';import'./chunk-FFSMJDUF.js';async function i(e,r){let t=j(e);if(!t.ok)return {code:k$1.usage,error:t.error};try{return {code:k$1.ok,output:await r(t.client,t.format,t.view)}}catch(n){if(!(n instanceof b))throw n;return {code:m(n),error:n.message}}}function C(e={}){return i(e,async(r,t,n)=>g(await r.health(),t,n))}function P(e={}){return i(e,async(r,t,n)=>g(await r.ready(),t,n))}function v(e={}){return i(e,async(r,t)=>c(await r.listRoutes({...e.dispatchable!==void 0?{dispatchable:e.dispatchable}:{},...e.source!==void 0?{source:e.source}:{}}),t))}function S(e,r={}){return i(r,async(t,n,a)=>{let[d,c]=await Promise.all([w(()=>t.describeRoute(e)),w(()=>t.routeHealth(e))]);if(d===void 0&&c===void 0)throw new b("absent",`No route "${e}" was readable on this instance. Either no route by that id is registered, or the introspection tier is disabled and health has nothing for it either.`);return f(d,c,n,a)})}function D(e={}){return i(e,async(r,t)=>d(await r.listDeferrals({...e.state!==void 0?{state:e.state}:{},...e.route!==void 0?{route:e.route}:{},...e.limit!==void 0?{limit:Number(e.limit)}:{},...e.after!==void 0?{after:e.after}:{}}),t))}function k(e$1,r={}){return i(r,async(t,n)=>e(await t.describeDeferral(e$1),n))}function N(e={}){return i(e,async(r,t,n)=>h((await r.health()).indicators,t,n))}function F(e,r={}){return i(r,async(t,n,a)=>i$1(await t.indicatorHealth(e),n,a))}async function w(e){try{return await e()}catch(r){if(r instanceof b&&(r.kind==="refused"||r.kind==="absent"))return;throw r}}export{k as deferralCommand,D as deferralsCommand,C as healthCommand,F as indicatorCommand,N as indicatorsCommand,P as readyCommand,S as routeCommand,v as routesCommand};//# sourceMappingURL=ops-B6N4ATXZ.js.map
|
|
2
|
+
//# sourceMappingURL=ops-B6N4ATXZ.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ops.ts"],"names":["read","overrides","run","prepared","prepare","EXEC_EXIT","error","OpsClientError","failureCode","healthCommand","client","format","view","renderReport","readyCommand","routesCommand","options","renderRoutes","routeCommand","id","definition","health","optional","renderRouteDetail","deferralsCommand","renderDeferrals","deferralCommand","renderDeferral","indicatorsCommand","renderIndicators","indicatorCommand","name","renderComponent"],"mappings":"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","file":"ops-EJMP5OLL.js","sourcesContent":["/**\n * `craft ops`: the operator-facing read commands over a running instance.\n *\n * The split across the family is by intent, not by URL. `craft exec` runs\n * work; `craft ops` inspects the instance itself. That is why `craft ops\n * health` reads `/health/**`, which is deliberately NOT under `/ops`: health\n * never walls so an orchestrator probe works without a credential, while\n * `/ops` answers by tier, and separate prefixes make \"expose health, never\n * expose ops\" a rule that is hard to get wrong at an ingress. The command\n * family and the path layout answer different questions and are allowed to\n * differ.\n */\n\nimport type { OpsDeferralFilter } from \"@routecraft/routecraft\";\nimport { OpsClientError, type OpsClient } from \"./ops-client.js\";\nimport { prepare } from \"./prepare.js\";\nimport {\n renderComponent,\n renderDeferral,\n renderDeferrals,\n renderIndicators,\n renderReport,\n renderRouteDetail,\n renderRoutes,\n type ViewNote,\n} from \"./format.js\";\nimport { EXEC_EXIT, failureCode, type ExecResult } from \"./exec.js\";\nimport type { OutputFormat, SettingsOverrides } from \"./settings.js\";\n\n/** Filters accepted by `craft ops routes`. */\nexport interface OpsRoutesOptions extends SettingsOverrides {\n dispatchable?: boolean;\n source?: string;\n}\n\n/** Filters accepted by `craft ops deferrals`. */\nexport interface OpsDeferralsOptions extends SettingsOverrides {\n state?: string;\n route?: string;\n limit?: string;\n after?: string;\n}\n\n/** Run one read and render it, turning client failures into exit codes. */\nasync function read(\n overrides: SettingsOverrides,\n run: (\n client: OpsClient,\n format: OutputFormat,\n view: ViewNote,\n ) => Promise<string>,\n): Promise<ExecResult> {\n const prepared = prepare(overrides);\n if (!prepared.ok) return { code: EXEC_EXIT.usage, error: prepared.error };\n try {\n return {\n code: EXEC_EXIT.ok,\n output: await run(prepared.client, prepared.format, prepared.view),\n };\n } catch (error: unknown) {\n if (!(error instanceof OpsClientError)) throw error;\n return { code: failureCode(error), error: error.message };\n }\n}\n\n/** `craft ops health`: the operational aggregate, never a routing signal. */\nexport function healthCommand(\n overrides: SettingsOverrides = {},\n): Promise<ExecResult> {\n return read(overrides, async (client, format, view) =>\n renderReport(await client.health(), format, view),\n );\n}\n\n/**\n * `craft ops ready`: whether this replica should receive traffic.\n *\n * Its own command rather than a flag on `health`, because it answers a\n * different question for a different consumer. The report carries `view`\n * precisely so the two are not confused, and a flag would invite reading\n * the routing signal when the operational one was meant.\n */\nexport function readyCommand(\n overrides: SettingsOverrides = {},\n): Promise<ExecResult> {\n return read(overrides, async (client, format, view) =>\n renderReport(await client.ready(), format, view),\n );\n}\n\n/** `craft ops routes`: the instance's route inventory. */\nexport function routesCommand(\n options: OpsRoutesOptions = {},\n): Promise<ExecResult> {\n return read(options, async (client, format) => {\n return renderRoutes(\n await client.listRoutes({\n ...(options.dispatchable !== undefined\n ? { dispatchable: options.dispatchable }\n : {}),\n ...(options.source !== undefined ? { source: options.source } : {}),\n }),\n format,\n );\n });\n}\n\n/**\n * `craft ops routes <id>`: one route, definition and health together.\n *\n * Merged rather than split across two subcommands, because \"tell me about\n * this route\" is one operator question and two answers would leave the\n * reader having to know which half carries the field they want. When the\n * introspection tier refuses, the health half is still served and the\n * output says the definition is missing rather than failing outright: a\n * thinner answer beats no answer for a question about a route that is\n * misbehaving right now.\n */\nexport function routeCommand(\n id: string,\n options: SettingsOverrides = {},\n): Promise<ExecResult> {\n return read(options, async (client, format, view) => {\n const [definition, health] = await Promise.all([\n optional(() => client.describeRoute(id)),\n optional(() => client.routeHealth(id)),\n ]);\n if (definition === undefined && health === undefined) {\n throw new OpsClientError(\n \"absent\",\n `No route \"${id}\" was readable on this instance. Either no route by that id is registered, or the introspection tier is disabled and health has nothing for it either.`,\n );\n }\n return renderRouteDetail(definition, health, format, view);\n });\n}\n\n/**\n * `craft ops deferrals`: what this instance is waiting on.\n *\n * One page, not the whole collection. An instance holds every exchange it\n * has ever deferred until retention takes it, so a command that walked\n * the listing would load an unbounded set to print the first screen of\n * it; the rendering names the cursor for the next page instead.\n *\n * Waiting by default, because the question this is opened with is what is\n * still owed an answer. `--state settled` asks for the history and\n * `--state all` for both.\n */\nexport function deferralsCommand(\n options: OpsDeferralsOptions = {},\n): Promise<ExecResult> {\n return read(options, async (client, format) =>\n renderDeferrals(\n await client.listDeferrals({\n // Cast rather than narrowed, with the vocabulary read off the\n // filter so there is one definition of it: the instance owns the\n // rule and refuses an unknown state naming the accepted values.\n ...(options.state !== undefined\n ? { state: options.state as NonNullable<OpsDeferralFilter[\"state\"]> }\n : {}),\n ...(options.route !== undefined ? { route: options.route } : {}),\n // Converted because the filter is typed `number`, and left\n // unvalidated for the same reason as the state: a second rule\n // here could disagree with the one the instance applies.\n ...(options.limit !== undefined\n ? { limit: Number(options.limit) }\n : {}),\n ...(options.after !== undefined ? { after: options.after } : {}),\n }),\n format,\n ),\n );\n}\n\n/** `craft ops deferrals <id>`: one deferral. */\nexport function deferralCommand(\n id: string,\n options: SettingsOverrides = {},\n): Promise<ExecResult> {\n return read(options, async (client, format) =>\n renderDeferral(await client.describeDeferral(id), format),\n );\n}\n\n/**\n * `craft ops indicators`: the indicator map, lifted off the aggregate.\n *\n * There is no indicator collection endpoint; the map on `GET /health` is\n * the source. The rendering says so rather than implying a resource that\n * does not exist.\n */\nexport function indicatorsCommand(\n overrides: SettingsOverrides = {},\n): Promise<ExecResult> {\n return read(overrides, async (client, format, view) =>\n renderIndicators((await client.health()).indicators, format, view),\n );\n}\n\n/** `craft ops indicators <name>`: one indicator's component. */\nexport function indicatorCommand(\n name: string,\n overrides: SettingsOverrides = {},\n): Promise<ExecResult> {\n return read(overrides, async (client, format, view) =>\n renderComponent(await client.indicatorHealth(name), format, view),\n );\n}\n\n/**\n * Run a read that is allowed to come back empty.\n *\n * Only a refusal or an absence degrades to `undefined`; an unreachable\n * instance still propagates, because \"half the answer\" is misleading when\n * there was never a connection to get the other half from.\n */\nasync function optional<T>(run: () => Promise<T>): Promise<T | undefined> {\n try {\n return await run();\n } catch (error: unknown) {\n if (\n error instanceof OpsClientError &&\n (error.kind === \"refused\" || error.kind === \"absent\")\n ) {\n return undefined;\n }\n throw error;\n }\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/ops.ts"],"names":["read","overrides","run","prepared","prepare","EXEC_EXIT","error","OpsClientError","failureCode","healthCommand","client","format","view","renderReport","readyCommand","routesCommand","options","renderRoutes","routeCommand","id","definition","health","optional","renderRouteDetail","deferralsCommand","renderDeferrals","deferralCommand","renderDeferral","indicatorsCommand","renderIndicators","indicatorCommand","name","renderComponent"],"mappings":"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","file":"ops-B6N4ATXZ.js","sourcesContent":["/**\n * `craft ops`: the operator-facing read commands over a running instance.\n *\n * The split across the family is by intent, not by URL. `craft exec` runs\n * work; `craft ops` inspects the instance itself. That is why `craft ops\n * health` reads `/health/**`, which is deliberately NOT under `/ops`: health\n * never walls so an orchestrator probe works without a credential, while\n * `/ops` answers by tier, and separate prefixes make \"expose health, never\n * expose ops\" a rule that is hard to get wrong at an ingress. The command\n * family and the path layout answer different questions and are allowed to\n * differ.\n */\n\nimport type { OpsDeferralFilter } from \"@routecraft/routecraft\";\nimport { OpsClientError, type OpsClient } from \"./ops-client.js\";\nimport { prepare } from \"./prepare.js\";\nimport {\n renderComponent,\n renderDeferral,\n renderDeferrals,\n renderIndicators,\n renderReport,\n renderRouteDetail,\n renderRoutes,\n type ViewNote,\n} from \"./format.js\";\nimport { EXEC_EXIT, failureCode, type ExecResult } from \"./exec.js\";\nimport type { OutputFormat, SettingsOverrides } from \"./settings.js\";\n\n/** Filters accepted by `craft ops routes`. */\nexport interface OpsRoutesOptions extends SettingsOverrides {\n dispatchable?: boolean;\n source?: string;\n}\n\n/** Filters accepted by `craft ops deferrals`. */\nexport interface OpsDeferralsOptions extends SettingsOverrides {\n state?: string;\n route?: string;\n limit?: string;\n after?: string;\n}\n\n/** Run one read and render it, turning client failures into exit codes. */\nasync function read(\n overrides: SettingsOverrides,\n run: (\n client: OpsClient,\n format: OutputFormat,\n view: ViewNote,\n ) => Promise<string>,\n): Promise<ExecResult> {\n const prepared = prepare(overrides);\n if (!prepared.ok) return { code: EXEC_EXIT.usage, error: prepared.error };\n try {\n return {\n code: EXEC_EXIT.ok,\n output: await run(prepared.client, prepared.format, prepared.view),\n };\n } catch (error: unknown) {\n if (!(error instanceof OpsClientError)) throw error;\n return { code: failureCode(error), error: error.message };\n }\n}\n\n/** `craft ops health`: the operational aggregate, never a routing signal. */\nexport function healthCommand(\n overrides: SettingsOverrides = {},\n): Promise<ExecResult> {\n return read(overrides, async (client, format, view) =>\n renderReport(await client.health(), format, view),\n );\n}\n\n/**\n * `craft ops ready`: whether this replica should receive traffic.\n *\n * Its own command rather than a flag on `health`, because it answers a\n * different question for a different consumer. The report carries `view`\n * precisely so the two are not confused, and a flag would invite reading\n * the routing signal when the operational one was meant.\n */\nexport function readyCommand(\n overrides: SettingsOverrides = {},\n): Promise<ExecResult> {\n return read(overrides, async (client, format, view) =>\n renderReport(await client.ready(), format, view),\n );\n}\n\n/** `craft ops routes`: the instance's route inventory. */\nexport function routesCommand(\n options: OpsRoutesOptions = {},\n): Promise<ExecResult> {\n return read(options, async (client, format) => {\n return renderRoutes(\n await client.listRoutes({\n ...(options.dispatchable !== undefined\n ? { dispatchable: options.dispatchable }\n : {}),\n ...(options.source !== undefined ? { source: options.source } : {}),\n }),\n format,\n );\n });\n}\n\n/**\n * `craft ops routes <id>`: one route, definition and health together.\n *\n * Merged rather than split across two subcommands, because \"tell me about\n * this route\" is one operator question and two answers would leave the\n * reader having to know which half carries the field they want. When the\n * introspection tier refuses, the health half is still served and the\n * output says the definition is missing rather than failing outright: a\n * thinner answer beats no answer for a question about a route that is\n * misbehaving right now.\n */\nexport function routeCommand(\n id: string,\n options: SettingsOverrides = {},\n): Promise<ExecResult> {\n return read(options, async (client, format, view) => {\n const [definition, health] = await Promise.all([\n optional(() => client.describeRoute(id)),\n optional(() => client.routeHealth(id)),\n ]);\n if (definition === undefined && health === undefined) {\n throw new OpsClientError(\n \"absent\",\n `No route \"${id}\" was readable on this instance. Either no route by that id is registered, or the introspection tier is disabled and health has nothing for it either.`,\n );\n }\n return renderRouteDetail(definition, health, format, view);\n });\n}\n\n/**\n * `craft ops deferrals`: what this instance is waiting on.\n *\n * One page, not the whole collection. An instance holds every exchange it\n * has ever deferred until retention takes it, so a command that walked\n * the listing would load an unbounded set to print the first screen of\n * it; the rendering names the cursor for the next page instead.\n *\n * Waiting by default, because the question this is opened with is what is\n * still owed an answer. `--state settled` asks for the history and\n * `--state all` for both.\n */\nexport function deferralsCommand(\n options: OpsDeferralsOptions = {},\n): Promise<ExecResult> {\n return read(options, async (client, format) =>\n renderDeferrals(\n await client.listDeferrals({\n // Cast rather than narrowed, with the vocabulary read off the\n // filter so there is one definition of it: the instance owns the\n // rule and refuses an unknown state naming the accepted values.\n ...(options.state !== undefined\n ? { state: options.state as NonNullable<OpsDeferralFilter[\"state\"]> }\n : {}),\n ...(options.route !== undefined ? { route: options.route } : {}),\n // Converted because the filter is typed `number`, and left\n // unvalidated for the same reason as the state: a second rule\n // here could disagree with the one the instance applies.\n ...(options.limit !== undefined\n ? { limit: Number(options.limit) }\n : {}),\n ...(options.after !== undefined ? { after: options.after } : {}),\n }),\n format,\n ),\n );\n}\n\n/** `craft ops deferrals <id>`: one deferral. */\nexport function deferralCommand(\n id: string,\n options: SettingsOverrides = {},\n): Promise<ExecResult> {\n return read(options, async (client, format) =>\n renderDeferral(await client.describeDeferral(id), format),\n );\n}\n\n/**\n * `craft ops indicators`: the indicator map, lifted off the aggregate.\n *\n * There is no indicator collection endpoint; the map on `GET /health` is\n * the source. The rendering says so rather than implying a resource that\n * does not exist.\n */\nexport function indicatorsCommand(\n overrides: SettingsOverrides = {},\n): Promise<ExecResult> {\n return read(overrides, async (client, format, view) =>\n renderIndicators((await client.health()).indicators, format, view),\n );\n}\n\n/** `craft ops indicators <name>`: one indicator's component. */\nexport function indicatorCommand(\n name: string,\n overrides: SettingsOverrides = {},\n): Promise<ExecResult> {\n return read(overrides, async (client, format, view) =>\n renderComponent(await client.indicatorHealth(name), format, view),\n );\n}\n\n/**\n * Run a read that is allowed to come back empty.\n *\n * Only a refusal or an absence degrades to `undefined`; an unreachable\n * instance still propagates, because \"half the answer\" is misleading when\n * there was never a connection to get the other half from.\n */\nasync function optional<T>(run: () => Promise<T>): Promise<T | undefined> {\n try {\n return await run();\n } catch (error: unknown) {\n if (\n error instanceof OpsClientError &&\n (error.kind === \"refused\" || error.kind === \"absent\")\n ) {\n return undefined;\n }\n throw error;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"settings-
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"settings-XW6WNPDV.js"}
|
package/dist/tui/app.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {a}from'../chunk-
|
|
1
|
+
import {a}from'../chunk-WCEUG34O.js';import {a as a$1}from'../chunk-2EEA43OX.js';import {useState,useCallback,useEffect,useMemo,Fragment as Fragment$1}from'react';import {useApp,useStdout,useInput,Box,Text,render}from'ink';import {jsx,jsxs,Fragment}from'react/jsx-runtime';var Ut=[{items:[{key:"capabilities",label:"Capabilities",shortcut:"1"}]},{items:[{key:"agents",label:"Agents",shortcut:"2"},{key:"tools",label:"Tools",shortcut:"3"}]},{items:[{key:"exchanges",label:"Exchanges",shortcut:"4"},{key:"errors",label:"Errors",shortcut:"5"},{key:"events",label:"Events",shortcut:"6"}]}],Xt=Ut.flatMap(e=>e.items);function Re(e,t){return t<=0?"":e.length>t?e.slice(0,t-1)+"\u2026":e}function M(e){return e==null||!Number.isFinite(e)||e<0?"-":e===0?"<1ms":e<1e3?`${Math.round(e)}ms`:`${(e/1e3).toFixed(1)}s`}function Z(e){switch(e){case "completed":case "started":case "finished":case "running":return "green";case "failed":case "error":return "red";case "stopped":case "dropped":return "yellow";default:return "white"}}function vo(e){return e<1e5?ee(e):e<1e6?`${Math.round(e/1e3)}k`:`${(e/1e6).toFixed(1)}M`}function Ye(e){switch(e){case "result":return "green";case "error":return "red";default:return "yellow"}}function R(e,t){return t===void 0?e:t<=0?"":e.length>t?e.slice(0,t-1)+"\u2026":e.padEnd(t)}function ln(e){try{let t=JSON.parse(e),o="exchangeId"in t?`${String(t.exchangeId).slice(0,8)}`:"",l="duration"in t?M(t.duration):"";if("operation"in t&&"routeId"in t){let s="adapter"in t?`(${t.adapter})`:"adapterId"in t?`(${t.adapterId})`:"",n="";if("metadata"in t&&typeof t.metadata=="object"&&t.metadata!==null){let f=t.metadata,m=Object.keys(f).slice(0,2);m.length>0&&(n=m.map(g=>`${g}=${f[g]}`).join(" "));}return {step:String(t.operation),adapter:s,exchange:o,duration:l,meta:n}}if("routeId"in t&&"exchangeId"in t){let s="error"in t?"(err)":"reason"in t?`(${String(t.reason).slice(0,8)})`:"";return {step:String(t.routeId),adapter:s,exchange:o,duration:l,meta:""}}if("route"in t&&typeof t.route=="object"&&t.route!==null){let s=t.route;return {step:s.routeId??s.definition?.id??"?",adapter:"",exchange:"",duration:"",meta:""}}if("pluginId"in t)return {step:`plugin=${t.pluginId}`,adapter:"",exchange:"",duration:"",meta:""};if("error"in t){let s=t.error;return {step:typeof s=="object"&&s!==null&&"message"in s?String(s.message):String(s),adapter:"",exchange:"",duration:"",meta:""}}return null}catch{return null}}function Io(e,t){let o=ln(t);return o||{step:t,adapter:"",exchange:"",duration:"",meta:""}}function ee(e){return e.toLocaleString("en-US")}function Wt(e,t,o){return o<=0?t:e<t?e:e>=t+o?e-o+1:t}function we(e=0){let[t,o]=useState(e),[l,s]=useState(0),n=useCallback((g,u,x)=>{let T=Math.max(0,Math.min(g,u-1));o(T),s(i=>Wt(T,i,x));},[]),f=useCallback((g,u,x)=>{o(T=>{let i=Math.max(0,Math.min(T+g,u-1));return s(h=>Wt(i,h,x)),i});},[]),m=useCallback(()=>{o(0),s(0);},[]);return {selectedIndex:t,scrollOffset:l,moveBy:f,moveTo:n,reset:m}}var c={accent:"#7482ff",accentSoft:"#9ea8fd",success:"green",error:"red",warn:"yellow",muted:"gray"};function _(e){return e?{color:c.accent,bold:true}:{}}function w({title:e,subtitle:t,color:o=c.muted,width:l,flexGrow:s,paddingX:n=1,children:f}){let m=l?l-2-n*2:20;return jsxs(Box,{flexDirection:"column",borderStyle:"single",borderColor:o,paddingX:n,width:l,flexGrow:s,children:[e&&jsxs(Fragment,{children:[jsxs(Text,{bold:true,dimColor:true,children:[e,t&&jsxs(Fragment,{children:[" ",t]})]}),jsx(Text,{dimColor:true,children:"\u2500".repeat(Math.max(m,1))})]}),f]})}var un=[192,36,18,9],dn=10240,ft=[{max:0,color:"gray"},{max:10,color:"green"},{max:20,color:"green"},{max:30,color:"yellow"},{max:40,color:"yellow"},{max:50,color:"red"}];function Dt({values:e,columns:t,steps:o=ft,label:l}){let s=o.length-1,n=e.length>=t?e.slice(e.length-t):[...new Array(t-e.length).fill(0),...e],f=n.map(u=>{if(u<=0)return 0;for(let x=1;x<o.length;x++)if(u<o[x].max)return x;return s}),m=Math.ceil(s/4),g=[];for(let u=m-1;u>=0;u--){let x=u*4,T=[];for(let i=0;i<n.length;i++){let h=f[i],p=0,y="";for(let D=0;D<4;D++){let ie=x+D+1;if(ie>s)break;(h>=ie||h===0&&ie===1)&&(p|=un[D],y=h===0?o[0].color:o[ie].color);}let H=String.fromCharCode(dn+p),F=T[T.length-1];F&&F.color===y?F.text+=H:T.push({text:H,color:y});}g.push(jsx(Text,{children:T.map((i,h)=>i.color?jsx(Text,{color:i.color,children:i.text},h):jsx(Text,{children:i.text},h))},u));}return jsxs(Fragment,{children:[g,l&&jsx(Text,{dimColor:true,wrap:"truncate",children:l})]})}function ko({route:e}){return jsxs(Fragment,{children:[jsxs(Text,{wrap:"truncate",children:["Capability:"," ",jsx(Text,{bold:true,color:c.accent,children:e.id})]}),jsxs(Text,{wrap:"truncate",children:["Status:"," ",jsx(Text,{bold:true,color:Z(e.status),children:e.status})," ","Exchanges: ",jsx(Text,{bold:true,children:ee(e.totalExchanges)})," ","Errors:"," ",jsx(Text,{bold:true,...e.failedExchanges>0?{color:"red"}:{},children:ee(e.failedExchanges)})," ","Dropped:"," ",jsx(Text,{bold:true,...e.droppedExchanges>0?{color:"yellow"}:{},children:ee(e.droppedExchanges)})," ","Avg: ",jsx(Text,{bold:true,children:M(e.avgDurationMs)})]})]})}function te({columns:e,data:t,rowKey:o,selectedIndex:l,scrollOffset:s,visibleRows:n,gap:f=2,emptyMessage:m="No data",renderFullRow:g}){let u=" ".repeat(f),x=jsx(Box,{children:e.map((h,p)=>{let H=p===e.length-1?"":u;if(h.width==="flex")return jsxs(Fragment$1,{children:[jsx(Box,{flexGrow:1,flexBasis:0,minWidth:0,children:jsx(Text,{bold:true,dimColor:true,wrap:"truncate",children:h.header})}),H&&jsx(Box,{flexShrink:0,children:jsx(Text,{children:H})})]},p);let F=h.align==="right"?h.header.padStart(h.width):R(h.header,h.width);return jsxs(Box,{flexShrink:0,children:[jsx(Text,{bold:true,dimColor:true,children:F}),H&&jsx(Text,{children:H})]},p)})});if(t.length===0)return jsxs(Fragment,{children:[x,jsx(Text,{dimColor:true,children:m})]});let T=t.slice(s,s+n),i=t.length-s-n;return jsxs(Fragment,{children:[x,T.map((h,p)=>{let y=s+p,H=y===l,F=g?.(h,y);return F!==void 0?jsx(Box,{children:F},o(h,y)):jsx(Box,{children:e.map((D,ie)=>{let v=ie===e.length-1?"":u,j=D.width==="flex"?void 0:D.width,rt=D.render(h,H,j);return D.width==="flex"?jsxs(Fragment$1,{children:[jsx(Box,{flexGrow:1,flexBasis:0,minWidth:0,children:jsx(Text,{wrap:"truncate",children:rt})}),v&&jsx(Box,{flexShrink:0,children:jsx(Text,{children:v})})]},ie):jsxs(Box,{flexShrink:0,children:[rt,v&&jsx(Text,{children:v})]},ie)})},o(h,y))}),jsx(Text,{dimColor:true,children:i>0?"\u2193 more":" "})]})}function kt(e,t={adapter:true,exchange:true}){let o=new WeakMap;function l(s){let n=e(s);if(!n)return;let f=o.get(n);return f||(f=Io(n.eventName,n.details),o.set(n,f)),f}return [{header:"Step",width:10,render:(s,n,f)=>{let m=l(s);return m?jsx(Text,{children:R(m.step,f)}):jsx(Text,{children:R("",f)})}},...t.adapter?[{header:"Adapter",width:10,render:(s,n,f)=>{let m=l(s);return m?jsx(Text,{children:R(m.adapter,f)}):jsx(Text,{children:R("",f)})}}]:[],...t.exchange?[{header:"Exchange",width:12,render:(s,n,f)=>{let m=l(s);return m?jsx(Text,{children:R(m.exchange,f)}):jsx(Text,{children:R("",f)})}}]:[],{header:"Duration",width:8,align:"right",render:s=>{let n=l(s);return n?jsx(Text,{children:n.duration.padStart(8)}):jsx(Text,{children:""})}}]}function oe(){return {header:"",width:2,render:(e,t)=>jsx(Text,{..._(t),children:t?"> ":" "})}}var pn=[oe(),{header:"ID",width:"flex",render:(e,t)=>jsx(Text,{..._(t),children:e.id})},{header:"Status",width:9,render:(e,t,o)=>jsx(Text,{color:Z(e.status),children:R(e.status,o)})},{header:"Duration",width:8,align:"right",render:e=>jsx(Text,{children:M(e.durationMs).padStart(8)})},{header:"Time",width:8,render:(e,t,o)=>jsx(Text,{dimColor:true,children:R(e.startedAt.replace("T"," ").slice(11,19),o)})}];function Lo({capabilityId:e,route:t,exchanges:o,selectedIndex:l,scrollOffset:s,width:n,height:f,color:m=c.muted,activity:g,title:u}){let x=Math.ceil((ft.length-1)/4),T=t?2+x+2:0,i=Math.max(f-6-T,3),h=u??(t?"EXCHANGES":`EXCHANGES: ${e}`);return jsxs(Box,{flexDirection:"column",width:n,flexGrow:1,children:[t&&jsxs(w,{width:n,children:[jsx(ko,{route:t}),jsx(Text,{children:" "}),jsx(Dt,{values:g?g.throughput:[],columns:n-4,label:"Exchanges per 5s bucket"})]}),jsx(w,{title:h,width:n,flexGrow:1,color:m,children:jsx(te,{columns:pn,data:o,rowKey:p=>`${p.id}:${p.contextId}`,selectedIndex:l,scrollOffset:s,visibleRows:i,emptyMessage:"No exchanges"})})]})}function gn(e){let t=[],o=/("(?:[^"\\]|\\.)*")\s*:|("(?:[^"\\]|\\.)*")|(-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?)|(\btrue\b|\bfalse\b)|(\bnull\b)|([{}[\],:])/g,l=0,s;for(;(s=o.exec(e))!==null;)s.index>l&&t.push({text:e.slice(l,s.index),type:"brace"}),s[1]!==void 0?(t.push({text:s[1],type:"key"}),t.push({text:":",type:"brace"})):s[2]!==void 0?t.push({text:s[2],type:"string"}):s[3]!==void 0?t.push({text:s[3],type:"number"}):s[4]!==void 0?t.push({text:s[4],type:"boolean"}):s[5]!==void 0?t.push({text:s[5],type:"null"}):s[6]!==void 0&&t.push({text:s[6],type:"brace"}),l=s.index+s[0].length;return l<e.length&&t.push({text:e.slice(l),type:"brace"}),t}var Tn={key:"white",string:c.accentSoft,number:c.warn,boolean:c.warn,null:c.error,brace:c.muted};function xe(e,t){try{let o=JSON.parse(e);return JSON.stringify(o,null,2).split(`
|
|
2
2
|
`).map(s=>{let n=Math.max(1,t);return s.length>n?s.slice(0,Math.max(0,n-1))+"\u2026":s})}catch{let o=Math.max(1,t);return e.split(`
|
|
3
3
|
`).map(l=>l.length>o?l.slice(0,Math.max(0,o-1))+"\u2026":l)}}function et({line:e}){let t=gn(e);return t.length===0?jsx(Text,{children:e}):jsx(Text,{children:t.map((o,l)=>jsx(Text,{color:Tn[o.type],children:o.text},l))})}function At(e){try{let t=JSON.parse(e);return typeof t!="object"||t===null||Array.isArray(t)?null:t}catch{return null}}function En(e,t){let o=new Map,l=0;o.set(t,{exchangeId:t,label:"parent",events:[]});for(let s of e){let n=At(s.details),f=n?String(n.exchangeId??""):"",m=!f||f===t?t:f;o.has(m)||(l++,o.set(m,{exchangeId:m,label:`child ${l}`,events:[]})),o.get(m).events.push(s);}return Array.from(o.values())}function Rn(e){return [oe(),{header:"Time",width:10,render:(t,o,l)=>{if(!t.event)return jsx(Text,{children:R("",l)});let s=" ".repeat(t.indent);return jsx(Text,{dimColor:true,children:R(s+t.event.timestamp.replace("T"," ").slice(11,19),l)})}},{header:"Event",width:"flex",render:t=>t.event?jsx(Text,{children:t.event.eventName}):jsx(Text,{})},...kt(t=>t.event,{adapter:e>=80,exchange:e>=68})]}function _o({exchange:e,events:t,width:o,height:l,scrollOffset:s,selectedIndex:n=-1,color:f=c.muted}){let m=e.error?2:0,g=Math.max(l-9-m,3),u=useMemo(()=>Rn(o-4),[o]),x=En(t,e.id),T=x.length>1,i=[];for(let p of x){T&&i.push({type:"header",text:`${p.label} (${p.exchangeId.slice(0,8)}) - ${p.events.length} events`,indent:0});for(let y of p.events)i.push({type:"event",event:y,indent:T?2:0});}let h=T?`EXCHANGE FLOW (${x.length} exchanges, ${t.length} events)`:`RELATED EVENTS (${t.length})`;return jsxs(Box,{flexDirection:"column",width:o,flexGrow:1,children:[jsxs(w,{width:o,children:[jsxs(Text,{children:["Capability:"," ",jsx(Text,{bold:true,color:c.accent,children:e.routeId})]}),jsxs(Text,{children:["Exchange:"," ",jsx(Text,{bold:true,color:c.accent,children:Re(e.id,o-14)})]}),jsxs(Text,{children:["Status:"," ",jsx(Text,{bold:true,color:Z(e.status),children:e.status}),e.durationMs!==null&&jsxs(Text,{children:[" ","Duration:"," ",jsx(Text,{bold:true,children:M(e.durationMs)})]})," ","Started: ",jsx(Text,{bold:true,children:e.startedAt}),e.completedAt&&jsxs(Text,{children:[" ","Completed: ",jsx(Text,{bold:true,children:e.completedAt})]})]}),e.error&&e.status==="failed"&&jsxs(Fragment,{children:[jsx(Text,{children:" "}),jsxs(Text,{color:"red",children:["Error: ",e.error]})]}),e.error&&e.status==="dropped"&&jsxs(Fragment,{children:[jsx(Text,{children:" "}),jsxs(Text,{color:"yellow",children:["Reason: ",e.error]})]})]}),jsx(w,{title:h,width:o,flexGrow:1,color:f,children:jsx(te,{columns:u,data:i,rowKey:(p,y)=>p.type==="header"?`h-${y}`:`${p.event?.id??p.event?.timestamp}-${y}`,selectedIndex:n,scrollOffset:s,visibleRows:g,emptyMessage:"No related events found",renderFullRow:p=>p.type==="header"?jsx(Text,{bold:true,color:c.accent,children:p.text}):void 0})})]})}function Cn(e){return [oe(),{header:"Time",width:8,render:(t,o,l)=>jsx(Text,{..._(o),children:R(t.timestamp.replace("T"," ").slice(11,19),l)})},{header:"Event",width:"flex",render:t=>jsx(Text,{children:t.eventName})},...kt(t=>t,{adapter:e>=80,exchange:e>=68})]}function Po({events:e,selectedIndex:t,scrollOffset:o,width:l,height:s,color:n=c.muted}){let f=Math.max(s-6,5),m=useMemo(()=>Cn(l-4),[l]);return jsx(w,{title:"EVENTS",subtitle:jsxs(Text,{dimColor:true,children:["(",e.length," total)"]}),width:l,flexGrow:1,color:n,children:jsx(te,{columns:m,data:e,rowKey:(g,u)=>g.id!==void 0?String(g.id):`${g.timestamp}-${u}`,selectedIndex:t,scrollOffset:o,visibleRows:f,emptyMessage:"No events recorded yet."})})}function $o({event:e,width:t,height:o,scrollOffset:l,color:s=c.accent}){let n=At(e.details),f=n&&typeof n.routeId=="string"?n.routeId:void 0,m=n&&typeof n.exchangeId=="string"?n.exchangeId:void 0,u=2+(1+(f?1:0)+(m?1:0)+2),x=5,T=Math.max(t-6,20),i=xe(e.details,T),h=Math.max(o-u-x,3),p=Math.max(0,Math.min(l,Math.max(i.length-h,0))),y=i.slice(p,p+h);return jsxs(Box,{flexDirection:"column",width:t,flexGrow:1,children:[jsxs(w,{width:t,children:[jsxs(Text,{children:["Context:"," ",jsx(Text,{bold:true,color:c.accent,children:e.contextId})]}),f&&jsxs(Text,{children:["Capability:"," ",jsx(Text,{bold:true,color:c.accent,children:f})]}),m&&jsxs(Text,{children:["Exchange:"," ",jsx(Text,{bold:true,color:c.accent,children:m})]}),jsxs(Text,{children:["Event:"," ",jsx(Text,{bold:true,color:c.accent,children:e.eventName})]}),jsxs(Text,{children:["Time: ",jsx(Text,{bold:true,children:e.timestamp.replace("T"," ")})]})]}),jsxs(w,{title:"DETAILS",subtitle:jsxs(Text,{dimColor:true,children:["(",p+1,"-",Math.min(p+h,i.length),"/",i.length," lines)"]}),width:t,flexGrow:1,color:s,children:[y.map((H,F)=>jsx(et,{line:H},p+F)),y.length<h&&Array.from({length:h-y.length}).map((H,F)=>jsx(Text,{children:" "},`pad-${F}`))]})]})}function Mn(e,t){let o=[];return o.push("HEADERS"),o.push(...xe(e.headers,t)),o.push(""),o.push("BODY"),e.body!==null?(o.push(...xe(e.body,t)),e.truncated&&(o.push(""),o.push("[Body truncated to configured limit]"))):o.push("[null]"),o}function Go({exchange:e,snapshot:t,width:o,height:l,scrollOffset:s,color:n=c.accent}){let g=Math.max(o-6,20),u=Math.max(l-5-5,3),T=t!==null?Mn(t,g):["[Snapshots not captured]","","Enable with:"," telemetry({ sqlite: { captureSnapshots: true } })"],i=Math.max(0,Math.min(s,Math.max(T.length-u,0))),h=T.slice(i,i+u);return jsxs(Box,{flexDirection:"column",width:o,flexGrow:1,children:[jsxs(w,{width:o,children:[jsxs(Text,{children:["Capability:"," ",jsx(Text,{bold:true,color:c.accent,children:e.routeId})]}),jsxs(Text,{children:["Exchange:"," ",jsx(Text,{bold:true,color:c.accent,children:Re(e.id,o-14)})]}),jsxs(Text,{children:["Status:"," ",jsx(Text,{bold:true,color:Z(e.status),children:e.status}),e.durationMs!==null&&jsxs(Text,{children:[" ","Duration:"," ",jsx(Text,{bold:true,children:M(e.durationMs)})]})]})]}),jsxs(w,{title:"EXCHANGE SNAPSHOT",subtitle:jsxs(Text,{dimColor:true,children:["(",i+1,"-",Math.min(i+u,T.length),"/",T.length," lines)"]}),width:o,flexGrow:1,color:n,children:[h.map((p,y)=>p==="HEADERS"||p==="BODY"?jsx(Text,{bold:true,color:c.accent,children:p},i+y):p.startsWith("[")?jsx(Text,{dimColor:true,children:p},i+y):jsx(et,{line:p},i+y)),h.length<u&&Array.from({length:u-h.length}).map((p,y)=>jsx(Text,{children:" "},`pad-${y}`))]})]})}function Lt({items:e,itemKey:t,label:o,dotColor:l,emptyText:s,selectedIndex:n,listOffset:f,visibleRows:m,width:g}){let u=Math.max(0,Math.min(f,Math.max(e.length-m,0)));return jsxs(Fragment,{children:[jsx(Text,{children:" "}),jsx(Text,{bold:true,dimColor:true,children:"\u2500".repeat(g+2)}),e.length===0?jsx(Text,{dimColor:true,children:s}):e.slice(u,u+m).map((x,T)=>{let h=u+T===n;return jsxs(Text,{wrap:"truncate",children:[jsx(Text,{..._(h),children:h?"> ":" "}),jsx(Text,{color:l(x),children:"\u25CF "}),jsx(Text,{..._(h),children:Re(o(x),g-2)})]},t(x))}),e.length>m&&jsxs(Text,{dimColor:true,children:[n+1,"/",e.length]})]})}function Ho({agentKey:e,runs:t,infos:o,selectedIndex:l,scrollOffset:s,width:n,height:f,color:m}){let g=Math.max(f-6,3),u=e?`RUNS: ${e}`:"RUNS",x=n-4>=66,T=[oe(),{header:"Run",width:"flex",render:(i,h)=>jsx(Text,{..._(h),children:i.id})},{header:"Status",width:9,render:(i,h,p)=>{let y=o.get(i.id)?.status??i.status;return jsx(Text,{color:Z(y),children:R(y,p)})}},{header:"Model",width:"flex",render:i=>jsx(Text,{dimColor:true,children:o.get(i.id)?.model??"-"})},{header:"Tokens",width:6,align:"right",render:i=>{let h=o.get(i.id)?.totalTokens;return jsx(Text,{children:(h!=null?vo(h):"-").padStart(6)})}},{header:"Duration",width:8,align:"right",render:i=>jsx(Text,{children:M(i.durationMs).padStart(8)})},...x?[{header:"Time",width:8,render:(i,h,p)=>jsx(Text,{dimColor:true,children:R(i.startedAt.replace("T"," ").slice(11,19),p)})}]:[]];return jsx(Box,{flexDirection:"column",width:n,flexGrow:1,children:jsx(w,{title:u,width:n,flexGrow:1,...m?{color:m}:{},children:jsx(te,{columns:T,data:t,rowKey:i=>`${i.id}:${i.contextId}`,selectedIndex:l,scrollOffset:s,visibleRows:g,emptyMessage:"No runs"})})})}var Nn=[oe(),{header:"Tool",width:"flex",render:(e,t)=>jsx(Text,{..._(t),children:e.toolName})},{header:"Status",width:8,render:(e,t,o)=>jsx(Text,{color:Ye(e.status),children:R(e.status,o)})},{header:"I/O",width:3,render:e=>jsx(Text,{dimColor:true,children:(e.hasInput?"i":"-")+(e.hasOutput?"o":"-")})},{header:"Duration",width:8,align:"right",render:e=>jsx(Text,{children:M(e.durationMs).padStart(8)})}];function Fo({agentKey:e,run:t,info:o,toolCalls:l,selectedIndex:s,scrollOffset:n,width:f,height:m,color:g=c.accent}){let x=Math.max(m-6-6,3),T=o&&(o.inputTokens!==null||o.outputTokens!==null)?`${o.inputTokens??"?"} in / ${o.outputTokens??"?"} out`+(o.totalTokens!==null?` (${o.totalTokens} total)`:""):o&&o.totalTokens!==null?`${o.totalTokens} total`:"-";return jsxs(Box,{flexDirection:"column",width:f,flexGrow:1,children:[jsxs(w,{width:f,children:[jsxs(Text,{children:["Agent:"," ",jsx(Text,{bold:true,color:c.accent,children:e})]}),jsxs(Text,{children:["Model: ",jsx(Text,{bold:true,children:o?.model??"-"})]}),jsxs(Text,{children:["Status:"," ",jsx(Text,{bold:true,color:Z(o?.status??t.status),children:o?.status??t.status}),o?.finishReason&&jsxs(Text,{children:[" ","Finish: ",jsx(Text,{bold:true,children:o.finishReason})]})]}),jsxs(Text,{children:["Tokens: ",jsx(Text,{bold:true,children:T})]})]}),jsx(w,{title:"TOOL CALLS",width:f,flexGrow:1,color:g,children:jsx(te,{columns:Nn,data:l,rowKey:i=>i.toolCallId,selectedIndex:s,scrollOffset:n,visibleRows:x,emptyMessage:"No tool calls"})})]})}function Ln(e){return [oe(),{header:"Route",width:"flex",render:(t,o)=>jsx(Text,{..._(o),children:t.routeId||"-"})},...e>=68?[{header:"Agent",width:12,render:(t,o,l)=>jsx(Text,{dimColor:true,children:R(t.agentName??"-",l)})}]:[],{header:"Status",width:8,render:(t,o,l)=>jsx(Text,{color:Ye(t.status),children:R(t.status,l)})},{header:"Exchange",width:12,render:(t,o,l)=>jsx(Text,{dimColor:true,children:R(t.exchangeId.slice(0,8),l)})},{header:"Duration",width:8,align:"right",render:t=>jsx(Text,{children:M(t.durationMs).padStart(8)})},...e>=82?[{header:"Time",width:8,render:(t,o,l)=>jsx(Text,{dimColor:true,children:R(t.timestamp.slice(11,19),l)})}]:[]]}function jo({toolName:e,calls:t,selectedIndex:o,scrollOffset:l,width:s,height:n,color:f=c.muted}){let m=Math.max(n-6,3),g=e?`TOOL CALLS: ${e}`:"TOOL CALLS";return jsx(Box,{flexDirection:"column",width:s,flexGrow:1,children:jsx(w,{title:g,width:s,flexGrow:1,color:f,children:jsx(te,{columns:Ln(s-4),data:t,rowKey:u=>u.toolCallId,selectedIndex:o,scrollOffset:l,visibleRows:m,emptyMessage:"No tool calls"})})})}function _n(e,t){let o=[];return o.push("INPUT"),e.hasInput&&e.input!==null?o.push(...xe(e.input,t)):o.push("[Not captured - enable snapshots]"),o.push(""),o.push("OUTPUT"),e.status==="invoked"?o.push("[Pending - tool still running or not recorded]"):e.hasOutput&&e.output!==null?o.push(...xe(e.output,t)):e.status==="error"?o.push("[No output - call errored]"):o.push("[Not captured - enable snapshots]"),e.status==="error"?(o.push(""),o.push("ERROR"),e.error!==null?o.push(...xe(e.error,t)):o.push(`[${e.errorName??"Error"} - enable snapshots for details]`)):e.error!==null&&(o.push(""),o.push("ERROR"),o.push(...xe(e.error,t))),o}function Jo({call:e,width:t,height:o,scrollOffset:l,color:s=c.accent}){let m=Math.max(t-6,20),g=Math.max(o-5-5,3),u=_n(e,m),x=Math.max(0,Math.min(l,Math.max(u.length-g,0))),T=u.slice(x,x+g);return jsxs(Box,{flexDirection:"column",width:t,flexGrow:1,children:[jsxs(w,{width:t,children:[jsxs(Text,{children:["Tool:"," ",jsx(Text,{bold:true,color:c.accent,children:Re(e.toolName,t-10)})]}),jsxs(Text,{children:["Exchange:"," ",jsx(Text,{bold:true,color:c.accent,children:Re(e.exchangeId,t-14)})]}),jsxs(Text,{children:["Status:"," ",jsx(Text,{bold:true,color:Ye(e.status),children:e.status}),e.durationMs!==null&&jsxs(Text,{children:[" ","Duration:"," ",jsx(Text,{bold:true,children:M(e.durationMs)})]})]})]}),jsxs(w,{title:"TOOL CALL",subtitle:jsxs(Text,{dimColor:true,children:["(",x+1,"-",Math.min(x+g,u.length),"/",u.length," lines)"]}),width:t,flexGrow:1,color:s,children:[T.map((i,h)=>i==="INPUT"||i==="OUTPUT"||i==="ERROR"?jsx(Text,{bold:true,color:c.accent,children:i},x+h):i.startsWith("[")?jsx(Text,{dimColor:true,children:i},x+h):jsx(et,{line:i},x+h)),T.length<g&&Array.from({length:g-T.length}).map((i,h)=>jsx(Text,{children:" "},`pad-${h}`))]})]})}function Jn(e){return e.failedExchanges>0?c.error:e.totalExchanges>0?c.success:c.warn}function Kn(e){return e.errorCount>0?c.error:e.runCount>0?c.success:c.warn}function Vn(e){return e.errorCount>0?c.error:e.callCount>0?c.success:c.warn}var to=[...Array.from({length:7},(e,t)=>({max:(t+1)*5,color:"green"})),...Array.from({length:7},(e,t)=>({max:35+(t+1)*10,color:"yellow"})),...Array.from({length:6},(e,t)=>({max:105+(t+1)*25,color:"red"}))];function Un(e){let t=Array.from({length:e},(o,l)=>{let s=Math.min(Math.ceil((l+1)*to.length/e)-1,to.length-1);return to[s]});return [{max:0,color:"gray"},...t]}var Ko=new Set(["event","snapshot","tool-call"]);function Uo(e,t){let o=new Map;o.set(t,[]);for(let l of e)try{let s=JSON.parse(l.details),n=String(s.exchangeId??""),f=!n||n===t?t:n;o.has(f)||o.set(f,[]),o.get(f).push(l);}catch{o.get(t).push(l);}return o}function Vo(e,t){let o=Uo(e,t);return e.length+(o.size>1?o.size:0)}function Xn({db:e}){let{exit:t}=useApp(),{stdout:o}=useStdout(),l=o?.columns??80,s=o?.rows??24,[n,f]=useState("capabilities"),[m,g]=useState([]),u=m.at(-1)??"root",[x,T]=useState([]),[i,h]=useState({totalRoutes:0,totalExchanges:0,completedExchanges:0,failedExchanges:0,droppedExchanges:0,errorRate:0,avgDurationMs:null,p90DurationMs:null,p95DurationMs:null,p99DurationMs:null}),[p,y]=useState([]),[H,F]=useState(void 0),D=we(),[ie,U]=useState([]),v=we(),[j,rt]=useState(void 0),[Bt,oo]=useState([]),[no,ro]=useState([]),pe=we(),me=we(),[xt,so]=useState(void 0),[_t,st]=useState(0),[Xo,Wo]=useState(null),[ge,lo]=useState([]),J=we(),[je,io]=useState(void 0),[qo,ao]=useState(null),[zo,co]=useState(new Map),[pt,uo]=useState([]),Te=we(),[Pt,lt]=useState(""),[$t,gt]=useState(false),[Ne,z]=useState(false),[Oe,mo]=useState([]),X=we(),[fo,Tt]=useState([]),Y=we(),[Le,bt]=useState(void 0),be=50,Yo=10,W=useCallback(r=>{g(a=>[...a,r]),st(0);},[]),yt=useCallback(()=>{g(r=>r.slice(0,-1)),st(0);},[]),Xe=Math.max(Math.min(Math.floor(l*.18),26),16),We=Math.max(Math.min(Math.floor(l*.22),30),20),ae=Math.max(l-Xe-We,30),O=Math.max(s-4,10),ye=Math.max(O-10,3),Qo=Math.max(Math.min(O-19,5),1)*4,Et=Math.max(O-6-6,3),it=m.includes("exchange")?j?.id:void 0,ho=m.includes("exchange")?j?.correlationId:void 0,at=m.includes("agent-run")?je?.id:void 0,ct=u==="tool-call"?Le?.toolCallId:void 0,Gt=u==="tool-call"?Le?.toolName:void 0,Ht=ge[J.selectedIndex]?.key,Ft=ge[J.selectedIndex]?.source,xo=Oe[X.selectedIndex]?.name,Je=useCallback((r,a)=>{if(!r){U([]),co(new Map);return}let S=a!==void 0?e.getAgentRuns(r.key,r.source,a):e.getAgentRuns(r.key,r.source);U(S),co(e.getAgentRunInfos(S.map(N=>N.id)));},[e]),jt=useCallback(()=>{try{let r=e.getRouteSummary();T(r),h(e.getMetrics());let a=We-4;y(e.getLiveTrafficBuckets(a,5));let S=ae-4,N=r[D.selectedIndex];N&&F(e.getSingleRouteActivity(N.id,S,5));let L,B;m.length===0&&(n==="agents"?(L=e.getAgents(),lo(L)):n==="tools"&&(B=e.getTools(),mo(B)));let Be=m.at(-1);if(it){let d=e.getExchangeById(it);d&&rt(d);let $=e.getEventsByExchange(it,ho??"");if(oo($),Ne&&Be==="exchange"){let Ke=d?.error?2:0,ze=Math.max(O-9-Ke,3),he=Vo($,it);me.moveTo(he-1,he,ze);}}if(at){let d=e.getExchangeById(at);d&&io(d),ao(e.getAgentRunInfo(at));let $=e.getAgentRunToolCalls(at);if(uo($),Ne&&Be==="agent-run"&&Te.moveTo($.length-1,$.length,Et),ct){let Ke=$.find(ze=>ze.toolCallId===ct);Ke&&bt(Ke);}}else if(ct&&Gt){let d=e.getToolCalls(Gt).find($=>$.toolCallId===ct);d&&bt(d);}if(m.length>0&&!(Ne&&Be==="browse"))return;if(n==="capabilities"){let d=r[D.selectedIndex];d&&U(e.getExchangesByRoute(d.id,be));}else if(n==="agents"){let d=L?L[J.selectedIndex]:Ht&&Ft?{key:Ht,source:Ft}:void 0;Je(d,be);}else if(n==="tools"){let d=B?B[X.selectedIndex]?.name:xo;Tt(d?e.getToolCalls(d):[]);}else n==="exchanges"?U(e.getAllExchanges(be)):n==="errors"?U(e.getFailedExchanges(be)):n==="events"&&ro(e.getRecentEvents({limit:200}));}catch{}},[e,n,D.selectedIndex,J.selectedIndex,X.selectedIndex,We,ae,O,Et,m,Ne,Je,it,ho,at,ct,Gt,Ht,Ft,xo,me.moveTo,Te.moveTo]);useEffect(()=>{jt();let r=setInterval(jt,2e3);return ()=>{clearInterval(r);}},[jt]);let po=useCallback(r=>{D.moveTo(r,x.length,ye),v.reset();let a=x[r];a&&U(e.getExchangesByRoute(a.id,be));},[e,x,D,v,ye]),go=useCallback(r=>{J.moveTo(r,ge.length,ye),v.reset(),Je(ge[r],be);},[ge,J,v,ye,Je]),To=useCallback(r=>{X.moveTo(r,Oe.length,ye),Y.reset();let a=Oe[r];a&&Tt(e.getToolCalls(a.name));},[e,Oe,X,Y,ye]),Zo=useCallback(r=>{if(f(r),g([]),st(0),lt(""),gt(false),z(false),v.reset(),r==="agents"){J.reset();let a=e.getAgents();lo(a),Je(a[0],be);}else if(r==="tools"){X.reset(),Y.reset();let a=e.getTools();mo(a);let S=a[0];Tt(S?e.getToolCalls(S.name):[]);}else r==="exchanges"?U(e.getAllExchanges(be)):r==="errors"?U(e.getFailedExchanges(be)):r==="events"&&(pe.reset(),ro(e.getRecentEvents({limit:200})));},[e,v,pe,J,X,Y,Je]),ut=Pt.trim().toLowerCase(),Jt=(...r)=>ut===""||r.some(a=>a!==null&&a.toLowerCase().includes(ut)),Ee=ut?ie.filter(r=>Jt(r.id,r.routeId,r.status)):ie,dt=ut?fo.filter(r=>Jt(r.toolName,r.routeId,r.exchangeId,r.status)):fo,Rt=ut?no.filter(r=>Jt(r.eventName,r.details)):no,wt=useCallback(()=>{v.reset(),Y.reset(),pe.reset();},[v,Y,pe]),qe=x[D.selectedIndex],Ct=ge[J.selectedIndex],Kt=Oe[X.selectedIndex],en=Math.ceil((ft.length-1)/4),tn=qe?2+en+2:0,bo=Math.max(O-6-tn,3),yo=Math.max(O-6,5),vt=Math.max(O-6,3),mt=useCallback(r=>{rt(r),oo(e.getEventsByExchange(r.id,r.correlationId)),me.reset(),z(r.status==="started"),W("exchange");},[e,me,W]),Eo=useCallback(r=>{if(!r.exchangeId)return;let a=e.getExchangeById(r.exchangeId)??{id:r.exchangeId,routeId:r.routeId,contextId:"",correlationId:"",status:"started",startedAt:r.timestamp,completedAt:null,durationMs:null,error:null};mt(a);},[e,mt]);useInput((r,a)=>{if($t){a.return?gt(false):a.escape?(gt(false),lt(""),wt()):a.backspace||a.delete?(lt(d=>d.slice(0,-1)),wt()):r&&!a.ctrl&&!a.meta&&(lt(d=>d+r),wt());return}if(r==="q"){e.close(),t();return}let S=Xt.find(d=>d.shortcut===r);if(S){Zo(S.key);return}let N=a.ctrl?Yo:1,L=r==="j"||a.downArrow,B=r==="k"||a.upArrow,Be=a.escape||a.backspace||a.delete;if(u==="browse"){if(r==="/"){gt(true);return}if(r==="f"){z(d=>!d);return}if((L||B)&&Ne&&z(false),Be){yt(),lt(""),z(false),wt();return}}if(u!=="root"&&Ko.has(u)){if(r==="x"&&u==="tool-call"&&Le){Eo(Le);return}L?st(d=>d+N):B?st(d=>Math.max(d-N,0)):Be&&yt();return}if(u==="agent-run"){if(r==="f"){z(d=>!d);return}if(r==="x"&&je){mt(je);return}if((L||B)&&Ne&&z(false),L)Te.moveBy(N,pt.length,Et);else if(B)Te.moveBy(-N,pt.length,Et);else if(a.return){let d=pt[Te.selectedIndex];d&&(bt(d),W("tool-call"));}else Be&&(yt(),z(false),Te.reset());return}if(u==="exchange"){if(r==="f"){z(he=>!he);return}(L||B)&&Ne&&z(false);let d=j?.error?2:0,$=Math.max(O-9-d,3),Ke=j?.id??"",ze=Vo(Bt,Ke);if(L)me.moveBy(N,ze,$);else if(B)me.moveBy(-N,ze,$);else if(a.return){let he=0,Vt,Ro=Uo(Bt,Ke),nn=Ro.size>1;for(let[,rn]of Ro){nn&&he++;for(let sn of rn)he===me.selectedIndex&&(Vt=sn),he++;}Vt&&(so(Vt),W("event"));}else if(r==="e"&&j){let he=e.getExchangeSnapshot(j.id);Wo(he),W("snapshot");}else Be&&(me.reset(),z(false),yt());return}if(n==="events"){if(u==="root"){a.return&&W("browse");return}if(L)pe.moveBy(N,Rt.length,yo);else if(B)pe.moveBy(-N,Rt.length,yo);else if(a.return){let d=Rt[pe.selectedIndex];d&&(so(d),W("event"));}return}if(n==="agents"){if(u==="root"){L?go(Math.min(J.selectedIndex+1,ge.length-1)):B?go(Math.max(J.selectedIndex-1,0)):a.return&&(W("browse"),Je(ge[J.selectedIndex]));return}if(L)v.moveBy(N,Ee.length,vt);else if(B)v.moveBy(-N,Ee.length,vt);else if(a.return){let d=Ee[v.selectedIndex];if(d){io(d);let $=e.getAgentRunInfo(d.id);ao($),uo(e.getAgentRunToolCalls(d.id)),Te.reset(),z(d.status==="started"||$?.status==="running"),W("agent-run");}}else if(r==="x"){let d=Ee[v.selectedIndex];d&&mt(d);}return}if(n==="tools"){if(u==="root"){if(L)To(Math.min(X.selectedIndex+1,Oe.length-1));else if(B)To(Math.max(X.selectedIndex-1,0));else if(a.return){W("browse");let d=Oe[X.selectedIndex];d&&Tt(e.getToolCalls(d.name));}return}if(L)Y.moveBy(N,dt.length,vt);else if(B)Y.moveBy(-N,dt.length,vt);else if(a.return){let d=dt[Y.selectedIndex];d&&(bt(d),W("tool-call"));}else if(r==="x"){let d=dt[Y.selectedIndex];d&&Eo(d);}return}if(u==="root"){if(n==="capabilities"){if(L)po(Math.min(D.selectedIndex+1,x.length-1));else if(B)po(Math.max(D.selectedIndex-1,0));else if(a.return){W("browse");let d=x[D.selectedIndex];d&&U(e.getExchangesByRoute(d.id));}}else a.return&&(W("browse"),U(n==="exchanges"?e.getAllExchanges():e.getFailedExchanges()));return}if(L)v.moveBy(N,Ee.length,bo);else if(B)v.moveBy(-N,Ee.length,bo);else if(a.return){let d=Ee[v.selectedIndex];d&&mt(d);}});let on=(n==="capabilities"||n==="agents"||n==="tools")&&u==="root",q=u==="browse",E=[];u!=="root"&&Ko.has(u)?(E.push({key:"j/k",action:"Scroll"}),E.push({key:"C-j/k",action:"Jump"}),u==="tool-call"&&E.push({key:"x",action:"Exchange"}),E.push({key:"Esc",action:"Back"})):u==="agent-run"?(E.push({key:"j/k",action:"Navigate"}),E.push({key:"Enter",action:"Tool I/O"}),E.push({key:"x",action:"Exchange"}),E.push({key:"f",action:"Follow"}),E.push({key:"Esc",action:"Back"})):u==="exchange"?(E.push({key:"j/k",action:"Navigate"}),E.push({key:"Enter",action:"Event"}),E.push({key:"e",action:"Snapshot"}),E.push({key:"f",action:"Follow"}),E.push({key:"Esc",action:"Back"})):q?(E.push({key:"j/k",action:"Navigate"}),E.push({key:"C-j/k",action:"Jump"}),E.push({key:"Enter",action:"Detail"}),(n==="agents"||n==="tools")&&E.push({key:"x",action:"Exchange"}),E.push({key:"/",action:"Filter"}),E.push({key:"f",action:"Follow"}),E.push({key:"Esc",action:"Back"})):(E.push({key:"j/k",action:"Navigate"}),n==="capabilities"?E.push({key:"Enter",action:"Exchanges"}):n==="agents"?E.push({key:"Enter",action:"Runs"}):n==="tools"?E.push({key:"Enter",action:"Calls"}):E.push({key:"Enter",action:"Browse"})),E.push({key:"1-6",action:"View"}),E.push({key:"q",action:"Quit"});let Q=[];{let r=Xt.find(a=>a.key===n)?.label??n;Q.push(r),m.length>0&&(n==="capabilities"&&qe?Q.push(qe.id):n==="agents"&&Ct?Q.push(Ct.key):n==="tools"&&Kt&&Q.push(Kt.name));for(let a of m)a==="exchange"&&j?Q.push(j.id.slice(0,8)):a==="agent-run"&&je?Q.push(`run ${je.id.slice(0,8)}`):a==="tool-call"&&Le?Q.push(Le.toolName):a==="event"&&xt?Q.push(xt.eventName):a==="snapshot"&&Q.push("snapshot");}let fe;return u==="event"&&xt?fe=jsx($o,{event:xt,width:ae,height:O,scrollOffset:_t}):u==="snapshot"&&j?fe=jsx(Go,{exchange:j,snapshot:Xo,width:ae,height:O,scrollOffset:_t}):u==="tool-call"&&Le?fe=jsx(Jo,{call:Le,width:ae,height:O,scrollOffset:_t}):u==="agent-run"&&je?fe=jsx(Fo,{agentKey:Ct?.key??"",run:je,info:qo,toolCalls:pt,selectedIndex:Te.selectedIndex,scrollOffset:Te.scrollOffset,width:ae,height:O}):u==="exchange"&&j?fe=jsx(_o,{exchange:j,events:Bt,width:ae,height:O,selectedIndex:me.selectedIndex,scrollOffset:me.scrollOffset,color:c.accent}):n==="events"?fe=jsx(Po,{events:Rt,selectedIndex:q?pe.selectedIndex:-1,scrollOffset:q?pe.scrollOffset:0,width:ae,height:O,color:q?c.accent:c.muted}):n==="agents"?fe=jsx(Ho,{agentKey:Ct?.key??"",runs:Ee,infos:zo,selectedIndex:q?v.selectedIndex:-1,scrollOffset:q?v.scrollOffset:0,width:ae,height:O,color:q?c.accent:c.muted}):n==="tools"?fe=jsx(jo,{toolName:Kt?.name??"",calls:dt,selectedIndex:q?Y.selectedIndex:-1,scrollOffset:q?Y.scrollOffset:0,width:ae,height:O,color:q?c.accent:c.muted}):fe=jsx(Lo,{capabilityId:n==="capabilities"?qe?.id??"":n==="exchanges"?"All Capabilities":"Failed Exchanges",...n==="capabilities"&&qe?{route:qe}:{},activity:n==="capabilities"?H:void 0,exchanges:Ee,selectedIndex:q?v.selectedIndex:-1,scrollOffset:q?v.scrollOffset:0,width:ae,height:O,color:q?c.accent:c.muted}),jsxs(Box,{flexDirection:"column",width:l,height:s,children:[jsxs(Box,{paddingX:1,width:l,children:[jsx(Text,{bold:true,children:"Routecraft"}),jsxs(Text,{dimColor:true,children:[" ","craft tui"," ","v",a]}),jsx(Box,{flexGrow:1,justifyContent:"flex-end",children:jsx(Text,{wrap:"truncate",children:Q.map((r,a)=>jsxs(Text,{children:[a>0&&jsx(Text,{dimColor:true,children:" \u203A "}),jsx(Text,{...a===Q.length-1&&Q.length>1?{color:c.accent}:{dimColor:true},children:r})]},`${r}-${a}`))})})]}),jsxs(Box,{flexDirection:"row",width:l,flexGrow:1,children:[jsx(Box,{flexDirection:"column",width:Xe,children:jsxs(w,{title:"NAVIGATION",color:on?c.accent:c.muted,width:Xe,flexGrow:1,children:[Ut.map((r,a)=>jsxs(Box,{flexDirection:"column",children:[a>0&&jsx(Text,{children:" "}),r.label&&jsx(Text,{dimColor:true,bold:true,children:r.label}),r.items.map(S=>jsxs(Text,{wrap:"truncate",children:[jsxs(Text,{..._(n===S.key),children:[n===S.key?"> ":" ",S.label]}),jsxs(Text,{dimColor:true,children:[" (",S.shortcut,")"]}),S.key==="errors"&&i.failedExchanges>0&&jsxs(Text,{color:c.error,children:[" ",ee(i.failedExchanges)]})]},S.key))]},r.label??a)),n==="capabilities"&&jsx(Lt,{items:x,itemKey:r=>r.id,label:r=>r.id,dotColor:Jn,emptyText:"No capabilities",selectedIndex:D.selectedIndex,listOffset:D.scrollOffset,visibleRows:ye,width:Xe-6}),n==="agents"&&jsx(Lt,{items:ge,itemKey:r=>r.key,label:r=>r.key,dotColor:Kn,emptyText:"No agents",selectedIndex:J.selectedIndex,listOffset:J.scrollOffset,visibleRows:ye,width:Xe-6}),n==="tools"&&jsx(Lt,{items:Oe,itemKey:r=>r.name,label:r=>r.name,dotColor:Vn,emptyText:"No tools",selectedIndex:X.selectedIndex,listOffset:X.scrollOffset,visibleRows:ye,width:Xe-6})]})}),fe,jsx(Box,{flexDirection:"column",width:We,children:jsxs(w,{title:"METRICS",width:We,flexGrow:1,children:[jsx(Dt,{values:p,columns:We-4,steps:Un(Qo),label:"Exchanges per 5s bucket"}),jsx(Text,{children:" "}),jsx(Text,{bold:true,dimColor:true,children:"THROUGHPUT"}),[["Exchanges",ee(i.totalExchanges),c.accent],["Completed",ee(i.completedExchanges),"green"],["Errors",ee(i.failedExchanges),i.failedExchanges>0?"red":"green"],["Dropped",ee(i.droppedExchanges),i.droppedExchanges>0?"yellow":"green"],["Error Rate",`${(i.errorRate*100).toFixed(1)}%`,i.errorRate>.1?"red":"green"],["Capabilities",ee(i.totalRoutes),""]].map(([r,a,S])=>jsxs(Box,{children:[jsx(Box,{flexGrow:1,children:jsxs(Text,{wrap:"truncate",children:[r,":"]})}),jsx(Text,{bold:true,...S?{color:S}:{},children:a})]},r)),jsx(Text,{children:" "}),jsx(Text,{bold:true,dimColor:true,children:"LATENCY (5m)"}),[["Avg",M(i.avgDurationMs),""],["p90",M(i.p90DurationMs),""],["p95",M(i.p95DurationMs),""],["p99",M(i.p99DurationMs),""]].map(([r,a,S])=>jsxs(Box,{children:[jsx(Box,{flexGrow:1,children:jsxs(Text,{wrap:"truncate",children:[r,":"]})}),jsx(Text,{bold:true,...S?{color:S}:{},children:a})]},r))]})})]}),jsx(Box,{paddingX:1,width:l,children:jsxs(Text,{wrap:"truncate",children:[($t||Pt!=="")&&jsxs(Text,{color:c.accent,children:["/",Pt,$t?"\u258F":""," "]}),Ne&&jsxs(Text,{color:c.success,children:["\u25CF follow"," "]}),E.map((r,a)=>jsxs(Text,{children:[a>0&&jsx(Text,{children:" "}),jsx(Text,{color:c.accentSoft,children:r.key}),jsxs(Text,{dimColor:true,children:[" ",r.action]})]},r.key))]})})]})}async function vl(e){let t;try{t=await a$1.open(e);}catch(l){let s=l instanceof Error?l.message:String(l);process.stderr.write(`Failed to open telemetry database: ${s}
|
|
4
4
|
`),process.stderr.write(`Path: ${e}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@routecraft/cli",
|
|
3
|
-
"version": "0.7.2
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"description": "CLI for running Routecraft capabilities",
|
|
5
5
|
"private": false,
|
|
6
6
|
"type": "module",
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"@agentclientprotocol/sdk": "^1.4.0",
|
|
26
|
-
"@routecraft/routecraft": "0.7.2
|
|
26
|
+
"@routecraft/routecraft": "^0.7.2",
|
|
27
27
|
"commander": "^14.0.3",
|
|
28
28
|
"dotenv": "^17.4.2",
|
|
29
29
|
"ink": "^7.1.1",
|
package/dist/chunk-6CUX4CM4.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../package.json"],"names":["version"],"mappings":"AAEE,IAAAA,CAAAA,CAAW","file":"chunk-6CUX4CM4.js","sourcesContent":["{\n \"name\": \"@routecraft/cli\",\n \"version\": \"0.7.2-canary-20261003210535\",\n \"description\": \"CLI for running Routecraft capabilities\",\n \"private\": false,\n \"type\": \"module\",\n \"main\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\",\n \"exports\": {\n \".\": {\n \"import\": \"./dist/index.js\",\n \"types\": \"./dist/index.d.ts\"\n }\n },\n \"files\": [\n \"dist\"\n ],\n \"scripts\": {\n \"build\": \"tsup src/index.ts src/tui/app.tsx src/tui/db.ts --format esm --dts --external react --external ink --external bun:sqlite\",\n \"test\": \"vitest\",\n \"test:coverage\": \"vitest --coverage\",\n \"prepublishOnly\": \"bun run build\"\n },\n \"dependencies\": {\n \"@agentclientprotocol/sdk\": \"^1.4.0\",\n \"@routecraft/routecraft\": \"0.7.2-canary-20261003210535\",\n \"commander\": \"^14.0.3\",\n \"dotenv\": \"^17.4.2\",\n \"ink\": \"^7.1.1\",\n \"pino-pretty\": \"^13.1.3\",\n \"react\": \"^19.2.0\",\n \"yaml\": \"^2.9.1\"\n },\n \"devDependencies\": {\n \"@types/mailparser\": \"^3.4.6\",\n \"@types/react\": \"^19.2.18\",\n \"ink-testing-library\": \"^4.0.0\",\n \"jose\": \"^6.2.12\"\n },\n \"publishConfig\": {\n \"access\": \"public\"\n },\n \"repository\": \"https://github.com/routecraftjs/routecraft\",\n \"bin\": {\n \"craft\": \"./dist/index.js\"\n },\n \"engines\": {\n \"bun\": \">=1.1.0\"\n },\n \"keywords\": [\n \"routecraft\",\n \"cli\",\n \"routes\",\n \"automation\",\n \"typescript\"\n ],\n \"author\": \"routecraftjs\",\n \"license\": \"Apache-2.0\",\n \"homepage\": \"https://routecraft.dev\"\n}\n"]}
|