@runcofactor/cli 0.52.0 → 0.53.0
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/README.md +2 -0
- package/dist/{account-3ZG24MOE.js → account-MRZ54P5P.js} +5 -5
- package/dist/{alert-5G7PTAX2.js → alert-XBHELHEI.js} +8 -8
- package/dist/{api-catalog-IBYAFKKQ.js → api-catalog-GWYRX53L.js} +5 -5
- package/dist/{api-key-UXC44BDR.js → api-key-FH6JN447.js} +5 -5
- package/dist/{attachment-T6IRFQW3.js → attachment-J7GRVT5F.js} +5 -5
- package/dist/{auth-SHOCJE6Z.js → auth-VZZQXRDR.js} +3 -3
- package/dist/{benchmark-NJ2U6VTC.js → benchmark-A3SNDARF.js} +5 -5
- package/dist/{blackcat-RQJVFGXQ.js → blackcat-UM6TBQBN.js} +3 -3
- package/dist/{chunk-DHAGRM2F.js → chunk-33U56YGD.js} +14 -5
- package/dist/{chunk-DHAGRM2F.js.map → chunk-33U56YGD.js.map} +1 -1
- package/dist/{chunk-M752EUK3.js → chunk-3JU4UYYN.js} +5 -5
- package/dist/{chunk-G6BCST3G.js → chunk-3ZOUNCA5.js} +7 -7
- package/dist/{chunk-76Z6E7XX.js → chunk-4UZN6TVT.js} +74 -131
- package/dist/chunk-4UZN6TVT.js.map +1 -0
- package/dist/{chunk-ABT3BLRC.js → chunk-5TKXHS3X.js} +3 -3
- package/dist/{chunk-QCYSONXI.js → chunk-CRYHWO4M.js} +2 -2
- package/dist/{chunk-QTYUM4ZB.js → chunk-EJ3ZPH5U.js} +23 -187
- package/dist/chunk-EJ3ZPH5U.js.map +1 -0
- package/dist/{chunk-I5RHTCPY.js → chunk-EL6KJ4PO.js} +4 -4
- package/dist/{chunk-ZL4O6C42.js → chunk-HXBK3AGD.js} +2 -2
- package/dist/{chunk-PRERH4DN.js → chunk-I2SOHQ2C.js} +3 -3
- package/dist/{chunk-CYSPCGO6.js → chunk-JEHHEMUL.js} +5 -5
- package/dist/{chunk-LIEADTEF.js → chunk-LJFVRJCA.js} +2 -2
- package/dist/{chunk-UEJ2HTKU.js → chunk-MJVUMVLO.js} +19 -1
- package/dist/chunk-MJVUMVLO.js.map +1 -0
- package/dist/chunk-N55RKCGR.js +24 -0
- package/dist/chunk-N55RKCGR.js.map +1 -0
- package/dist/{chunk-PHNH3CEU.js → chunk-O4Z44BR7.js} +5 -5
- package/dist/{chunk-QA37WVF6.js → chunk-OQFCZERZ.js} +6 -6
- package/dist/{chunk-EUVB6Y3C.js → chunk-P7L5KELH.js} +8 -8
- package/dist/chunk-P7L5KELH.js.map +1 -0
- package/dist/{chunk-Z3MDQSZG.js → chunk-PJFFGQSB.js} +2 -2
- package/dist/{chunk-IY3ZK46I.js → chunk-QOVJUSSL.js} +2 -2
- package/dist/{chunk-RPJMQBB5.js → chunk-QXU4G4YN.js} +3 -3
- package/dist/{chunk-SZSTJIYU.js → chunk-RRSUKARV.js} +4 -4
- package/dist/{chunk-775FI436.js → chunk-RVD6J6IZ.js} +2 -2
- package/dist/{chunk-5UUIBY6E.js → chunk-TAVBFLCR.js} +3 -3
- package/dist/{chunk-ROX7N3RK.js → chunk-V7HB5LAU.js} +10 -7
- package/dist/chunk-V7HB5LAU.js.map +1 -0
- package/dist/{chunk-LL6TSQWV.js → chunk-VKZOHJCE.js} +3 -3
- package/dist/chunk-VKZOHJCE.js.map +1 -0
- package/dist/{chunk-3HI6QC4V.js → chunk-WRBU6TX7.js} +2 -2
- package/dist/{proofs-TXJGAP5F.js → chunk-X7SUSIY3.js} +118 -20
- package/dist/chunk-X7SUSIY3.js.map +1 -0
- package/dist/{chunk-BF3IPGMP.js → chunk-XSSZMG65.js} +4 -4
- package/dist/{credential-TWSWV64F.js → credential-4RFRU6OH.js} +5 -5
- package/dist/{credential-template-XO5D5AI3.js → credential-template-36PFUTBN.js} +5 -5
- package/dist/{digest-SLEFOLPV.js → digest-THMKFMP7.js} +8 -8
- package/dist/{docs-IDC4V4WQ.js → docs-ZGM53L67.js} +5 -5
- package/dist/{doctor-SDAYEA6C.js → doctor-Z2XBGBM3.js} +3 -3
- package/dist/{environment-VBUIBQ6O.js → environment-5YVZXBN7.js} +7 -7
- package/dist/eval-SO5TPD37.js +1177 -0
- package/dist/eval-SO5TPD37.js.map +1 -0
- package/dist/{exploration-IREIR5PO.js → exploration-GZ4WUJJH.js} +5 -5
- package/dist/{exploratory-test-4Q7BMEFT.js → exploratory-test-Y7P4ZDLD.js} +5 -5
- package/dist/{external-run-S7LULKPT.js → external-run-IJGGZOGI.js} +7 -7
- package/dist/{feature-flag-IASHTUGU.js → feature-flag-UH6Z7774.js} +5 -5
- package/dist/{flow-IBEZFZTU.js → flow-MRWAQYZZ.js} +5 -5
- package/dist/{github-HAEZRULP.js → github-VDJU3PU3.js} +6 -6
- package/dist/index.js +101 -82
- package/dist/index.js.map +1 -1
- package/dist/{init-LT2TZMQY.js → init-CROSTPA6.js} +5 -5
- package/dist/{install-RTEYH6TK.js → install-ECR7OLAY.js} +5 -5
- package/dist/{issues-5GE277R2.js → issues-K5TL2S4Z.js} +7 -7
- package/dist/{knobs-AMIWGYUZ.js → knobs-OKQFBQLK.js} +5 -5
- package/dist/{landing-3VLVVQL5.js → landing-XANIBPVM.js} +7 -7
- package/dist/{list-GDJR6UY6.js → list-64GX47Q4.js} +5 -5
- package/dist/{local-4R6GVW7U.js → local-QMQY2ZUX.js} +7 -7
- package/dist/{login-IXVAWTLO.js → login-I7UQ3GTM.js} +5 -5
- package/dist/{mcp-BM2MJWX4.js → mcp-XZV63DX5.js} +11 -11
- package/dist/{mcp-BM2MJWX4.js.map → mcp-XZV63DX5.js.map} +1 -1
- package/dist/{metrics-SSIP5CEB.js → metrics-KBTQ3KGZ.js} +5 -5
- package/dist/{monitor-ESZYHXT2.js → monitor-UGWY43IU.js} +5 -5
- package/dist/perf-CCHWHCSR.js +961 -0
- package/dist/perf-CCHWHCSR.js.map +1 -0
- package/dist/{product-VCGUV5TH.js → product-KLG2ZTHC.js} +5 -5
- package/dist/{product-map-AXKZNQDM.js → product-map-AMEZ76EQ.js} +5 -5
- package/dist/{prompts-FVPSON2N.js → prompts-ZVQNGL7X.js} +5 -5
- package/dist/proofs-QCNSQAPX.js +20 -0
- package/dist/{property-XEPCC7KQ.js → property-PJDQFHAL.js} +6 -6
- package/dist/{psql-JKF3OYYJ.js → psql-AURAN27C.js} +5 -5
- package/dist/{record-REQ37S54.js → record-SYWBTUOB.js} +6 -6
- package/dist/{redis-WGHT2GJB.js → redis-2H752SKO.js} +5 -5
- package/dist/{release-SNDIVIA6.js → release-OSIYUXSC.js} +5 -5
- package/dist/{runbook-XFJG2LFC.js → runbook-7LVHF6KV.js} +5 -5
- package/dist/{sandbox-DYCKLCMY.js → sandbox-TJQPMRGS.js} +18 -30
- package/dist/sandbox-TJQPMRGS.js.map +1 -0
- package/dist/{scenarios-PVHCKP55.js → scenarios-P2ABU4HK.js} +5 -5
- package/dist/{schedule-DGC7CX23.js → schedule-XLS56NP5.js} +8 -8
- package/dist/{session-ERGUFDDI.js → session-ACSFC3UB.js} +8 -8
- package/dist/{skill-6QO2E3TB.js → skill-F7I5P6AI.js} +43 -28
- package/dist/{skill-6QO2E3TB.js.map → skill-F7I5P6AI.js.map} +1 -1
- package/dist/{slack-WE7THLLH.js → slack-ZEK4GRND.js} +6 -6
- package/dist/{spec-SEOY7N3L.js → spec-XPIRRSV6.js} +5 -5
- package/dist/{src-CCK3TKBX.js → src-N7ZCYCXU.js} +4 -4
- package/dist/{src-AEWV5HYH.js → src-XSBBMVGW.js} +3 -3
- package/dist/{start-EPGLHTND.js → start-DKWLOQI6.js} +5 -5
- package/dist/{status-DTE2GXM2.js → status-K7KH5DI3.js} +5 -5
- package/dist/{tag-GIFEWGBL.js → tag-2Y3OMQQC.js} +6 -6
- package/dist/{task-VLJCHSFB.js → task-4PIOC4QV.js} +6 -6
- package/dist/{teams-J2OOJBL4.js → teams-KUM56BE2.js} +83 -47
- package/dist/teams-KUM56BE2.js.map +1 -0
- package/dist/{test-suite-CTACGIAZ.js → test-suite-SW25YGJV.js} +138 -96
- package/dist/test-suite-SW25YGJV.js.map +1 -0
- package/dist/{trace-RWQDYL4K.js → trace-QPXHYBLA.js} +7 -7
- package/dist/{triage-6UAXLCGU.js → triage-EZABRZZM.js} +6 -6
- package/dist/trigger-7C7KX5KH.js +137 -0
- package/dist/trigger-7C7KX5KH.js.map +1 -0
- package/dist/{update-check-QRREAM3N.js → update-check-E3X7UIY6.js} +3 -3
- package/dist/{upgrade-5Y655TQ6.js → upgrade-EJGTMW44.js} +4 -4
- package/dist/{usage-KCXFY46V.js → usage-GZCQDULF.js} +7 -7
- package/dist/{utilities-SUON2KZK.js → utilities-RIITD53A.js} +6 -6
- package/dist/{visual-GJZVJC32.js → visual-FH67OKS2.js} +5 -5
- package/dist/{workflow-R5QAXWBX.js → workflow-34YJZ2QQ.js} +38 -86
- package/dist/workflow-34YJZ2QQ.js.map +1 -0
- package/dist/{workflow-cache-PFBTWLGM.js → workflow-cache-YQ3BGJIG.js} +17 -17
- package/dist/{workflow-cache-convergence-resolve-UZGRPC3B.js → workflow-cache-convergence-resolve-SPLBRSNK.js} +5 -5
- package/dist/{workflow-debug-RACNWWOL.js → workflow-debug-HZB7TJGK.js} +10 -10
- package/dist/workflow-debug-HZB7TJGK.js.map +1 -0
- package/dist/{workflow-feedback-RJIQ5R3R.js → workflow-feedback-6UOTIWIQ.js} +5 -5
- package/dist/{workflow-fork-LINDCYJ3.js → workflow-fork-IDYHAHCX.js} +5 -5
- package/dist/workflow-promotion-U6WYFY5U.js +62 -0
- package/dist/workflow-promotion-U6WYFY5U.js.map +1 -0
- package/dist/{workflow-proposals-E4EXKAGM.js → workflow-proposals-MMVNIQT3.js} +5 -5
- package/dist/{workflow-revisions-5M6APN6R.js → workflow-revisions-BPUOLCZB.js} +5 -5
- package/dist/{workflow-status-7KL73WS2.js → workflow-status-RA3IEMEW.js} +5 -5
- package/package.json +3 -2
- package/dist/chat-target-IZ7YLLU3.js +0 -502
- package/dist/chat-target-IZ7YLLU3.js.map +0 -1
- package/dist/chunk-76Z6E7XX.js.map +0 -1
- package/dist/chunk-EUVB6Y3C.js.map +0 -1
- package/dist/chunk-LL6TSQWV.js.map +0 -1
- package/dist/chunk-QTYUM4ZB.js.map +0 -1
- package/dist/chunk-ROX7N3RK.js.map +0 -1
- package/dist/chunk-UEJ2HTKU.js.map +0 -1
- package/dist/proofs-TXJGAP5F.js.map +0 -1
- package/dist/sandbox-DYCKLCMY.js.map +0 -1
- package/dist/teams-J2OOJBL4.js.map +0 -1
- package/dist/test-suite-CTACGIAZ.js.map +0 -1
- package/dist/workflow-R5QAXWBX.js.map +0 -1
- /package/dist/{account-3ZG24MOE.js.map → account-MRZ54P5P.js.map} +0 -0
- /package/dist/{alert-5G7PTAX2.js.map → alert-XBHELHEI.js.map} +0 -0
- /package/dist/{api-catalog-IBYAFKKQ.js.map → api-catalog-GWYRX53L.js.map} +0 -0
- /package/dist/{api-key-UXC44BDR.js.map → api-key-FH6JN447.js.map} +0 -0
- /package/dist/{attachment-T6IRFQW3.js.map → attachment-J7GRVT5F.js.map} +0 -0
- /package/dist/{auth-SHOCJE6Z.js.map → auth-VZZQXRDR.js.map} +0 -0
- /package/dist/{benchmark-NJ2U6VTC.js.map → benchmark-A3SNDARF.js.map} +0 -0
- /package/dist/{blackcat-RQJVFGXQ.js.map → blackcat-UM6TBQBN.js.map} +0 -0
- /package/dist/{chunk-M752EUK3.js.map → chunk-3JU4UYYN.js.map} +0 -0
- /package/dist/{chunk-G6BCST3G.js.map → chunk-3ZOUNCA5.js.map} +0 -0
- /package/dist/{chunk-ABT3BLRC.js.map → chunk-5TKXHS3X.js.map} +0 -0
- /package/dist/{chunk-QCYSONXI.js.map → chunk-CRYHWO4M.js.map} +0 -0
- /package/dist/{chunk-I5RHTCPY.js.map → chunk-EL6KJ4PO.js.map} +0 -0
- /package/dist/{chunk-ZL4O6C42.js.map → chunk-HXBK3AGD.js.map} +0 -0
- /package/dist/{chunk-PRERH4DN.js.map → chunk-I2SOHQ2C.js.map} +0 -0
- /package/dist/{chunk-CYSPCGO6.js.map → chunk-JEHHEMUL.js.map} +0 -0
- /package/dist/{chunk-LIEADTEF.js.map → chunk-LJFVRJCA.js.map} +0 -0
- /package/dist/{chunk-PHNH3CEU.js.map → chunk-O4Z44BR7.js.map} +0 -0
- /package/dist/{chunk-QA37WVF6.js.map → chunk-OQFCZERZ.js.map} +0 -0
- /package/dist/{chunk-Z3MDQSZG.js.map → chunk-PJFFGQSB.js.map} +0 -0
- /package/dist/{chunk-IY3ZK46I.js.map → chunk-QOVJUSSL.js.map} +0 -0
- /package/dist/{chunk-RPJMQBB5.js.map → chunk-QXU4G4YN.js.map} +0 -0
- /package/dist/{chunk-SZSTJIYU.js.map → chunk-RRSUKARV.js.map} +0 -0
- /package/dist/{chunk-775FI436.js.map → chunk-RVD6J6IZ.js.map} +0 -0
- /package/dist/{chunk-5UUIBY6E.js.map → chunk-TAVBFLCR.js.map} +0 -0
- /package/dist/{chunk-3HI6QC4V.js.map → chunk-WRBU6TX7.js.map} +0 -0
- /package/dist/{chunk-BF3IPGMP.js.map → chunk-XSSZMG65.js.map} +0 -0
- /package/dist/{credential-TWSWV64F.js.map → credential-4RFRU6OH.js.map} +0 -0
- /package/dist/{credential-template-XO5D5AI3.js.map → credential-template-36PFUTBN.js.map} +0 -0
- /package/dist/{digest-SLEFOLPV.js.map → digest-THMKFMP7.js.map} +0 -0
- /package/dist/{docs-IDC4V4WQ.js.map → docs-ZGM53L67.js.map} +0 -0
- /package/dist/{doctor-SDAYEA6C.js.map → doctor-Z2XBGBM3.js.map} +0 -0
- /package/dist/{environment-VBUIBQ6O.js.map → environment-5YVZXBN7.js.map} +0 -0
- /package/dist/{exploration-IREIR5PO.js.map → exploration-GZ4WUJJH.js.map} +0 -0
- /package/dist/{exploratory-test-4Q7BMEFT.js.map → exploratory-test-Y7P4ZDLD.js.map} +0 -0
- /package/dist/{external-run-S7LULKPT.js.map → external-run-IJGGZOGI.js.map} +0 -0
- /package/dist/{feature-flag-IASHTUGU.js.map → feature-flag-UH6Z7774.js.map} +0 -0
- /package/dist/{flow-IBEZFZTU.js.map → flow-MRWAQYZZ.js.map} +0 -0
- /package/dist/{github-HAEZRULP.js.map → github-VDJU3PU3.js.map} +0 -0
- /package/dist/{init-LT2TZMQY.js.map → init-CROSTPA6.js.map} +0 -0
- /package/dist/{install-RTEYH6TK.js.map → install-ECR7OLAY.js.map} +0 -0
- /package/dist/{issues-5GE277R2.js.map → issues-K5TL2S4Z.js.map} +0 -0
- /package/dist/{knobs-AMIWGYUZ.js.map → knobs-OKQFBQLK.js.map} +0 -0
- /package/dist/{landing-3VLVVQL5.js.map → landing-XANIBPVM.js.map} +0 -0
- /package/dist/{list-GDJR6UY6.js.map → list-64GX47Q4.js.map} +0 -0
- /package/dist/{local-4R6GVW7U.js.map → local-QMQY2ZUX.js.map} +0 -0
- /package/dist/{login-IXVAWTLO.js.map → login-I7UQ3GTM.js.map} +0 -0
- /package/dist/{metrics-SSIP5CEB.js.map → metrics-KBTQ3KGZ.js.map} +0 -0
- /package/dist/{monitor-ESZYHXT2.js.map → monitor-UGWY43IU.js.map} +0 -0
- /package/dist/{product-VCGUV5TH.js.map → product-KLG2ZTHC.js.map} +0 -0
- /package/dist/{product-map-AXKZNQDM.js.map → product-map-AMEZ76EQ.js.map} +0 -0
- /package/dist/{prompts-FVPSON2N.js.map → prompts-ZVQNGL7X.js.map} +0 -0
- /package/dist/{src-AEWV5HYH.js.map → proofs-QCNSQAPX.js.map} +0 -0
- /package/dist/{property-XEPCC7KQ.js.map → property-PJDQFHAL.js.map} +0 -0
- /package/dist/{psql-JKF3OYYJ.js.map → psql-AURAN27C.js.map} +0 -0
- /package/dist/{record-REQ37S54.js.map → record-SYWBTUOB.js.map} +0 -0
- /package/dist/{redis-WGHT2GJB.js.map → redis-2H752SKO.js.map} +0 -0
- /package/dist/{release-SNDIVIA6.js.map → release-OSIYUXSC.js.map} +0 -0
- /package/dist/{runbook-XFJG2LFC.js.map → runbook-7LVHF6KV.js.map} +0 -0
- /package/dist/{scenarios-PVHCKP55.js.map → scenarios-P2ABU4HK.js.map} +0 -0
- /package/dist/{schedule-DGC7CX23.js.map → schedule-XLS56NP5.js.map} +0 -0
- /package/dist/{session-ERGUFDDI.js.map → session-ACSFC3UB.js.map} +0 -0
- /package/dist/{slack-WE7THLLH.js.map → slack-ZEK4GRND.js.map} +0 -0
- /package/dist/{spec-SEOY7N3L.js.map → spec-XPIRRSV6.js.map} +0 -0
- /package/dist/{src-CCK3TKBX.js.map → src-N7ZCYCXU.js.map} +0 -0
- /package/dist/{tag-GIFEWGBL.js.map → src-XSBBMVGW.js.map} +0 -0
- /package/dist/{start-EPGLHTND.js.map → start-DKWLOQI6.js.map} +0 -0
- /package/dist/{status-DTE2GXM2.js.map → status-K7KH5DI3.js.map} +0 -0
- /package/dist/{trace-RWQDYL4K.js.map → tag-2Y3OMQQC.js.map} +0 -0
- /package/dist/{task-VLJCHSFB.js.map → task-4PIOC4QV.js.map} +0 -0
- /package/dist/{triage-6UAXLCGU.js.map → trace-QPXHYBLA.js.map} +0 -0
- /package/dist/{update-check-QRREAM3N.js.map → triage-EZABRZZM.js.map} +0 -0
- /package/dist/{upgrade-5Y655TQ6.js.map → update-check-E3X7UIY6.js.map} +0 -0
- /package/dist/{utilities-SUON2KZK.js.map → upgrade-EJGTMW44.js.map} +0 -0
- /package/dist/{usage-KCXFY46V.js.map → usage-GZCQDULF.js.map} +0 -0
- /package/dist/{workflow-debug-RACNWWOL.js.map → utilities-RIITD53A.js.map} +0 -0
- /package/dist/{visual-GJZVJC32.js.map → visual-FH67OKS2.js.map} +0 -0
- /package/dist/{workflow-cache-PFBTWLGM.js.map → workflow-cache-YQ3BGJIG.js.map} +0 -0
- /package/dist/{workflow-cache-convergence-resolve-UZGRPC3B.js.map → workflow-cache-convergence-resolve-SPLBRSNK.js.map} +0 -0
- /package/dist/{workflow-feedback-RJIQ5R3R.js.map → workflow-feedback-6UOTIWIQ.js.map} +0 -0
- /package/dist/{workflow-fork-LINDCYJ3.js.map → workflow-fork-IDYHAHCX.js.map} +0 -0
- /package/dist/{workflow-proposals-E4EXKAGM.js.map → workflow-proposals-MMVNIQT3.js.map} +0 -0
- /package/dist/{workflow-revisions-5M6APN6R.js.map → workflow-revisions-BPUOLCZB.js.map} +0 -0
- /package/dist/{workflow-status-7KL73WS2.js.map → workflow-status-RA3IEMEW.js.map} +0 -0
|
@@ -1,502 +0,0 @@
|
|
|
1
|
-
import { createRequire as __cr } from "module"; import { fileURLToPath as __fup } from "url"; import { dirname as __dn } from "path"; const require = __cr(import.meta.url); const __filename = __fup(import.meta.url); const __dirname = __dn(__filename);
|
|
2
|
-
import {
|
|
3
|
-
pad,
|
|
4
|
-
readFromStdin
|
|
5
|
-
} from "./chunk-2TIRL6ZK.js";
|
|
6
|
-
import {
|
|
7
|
-
apiRequest,
|
|
8
|
-
fetchProperties,
|
|
9
|
-
getApplicationArg,
|
|
10
|
-
getPositionalArg,
|
|
11
|
-
resolveCredentialId
|
|
12
|
-
} from "./chunk-LL6TSQWV.js";
|
|
13
|
-
import "./chunk-S3Q7MDCS.js";
|
|
14
|
-
import "./chunk-76Z6E7XX.js";
|
|
15
|
-
import {
|
|
16
|
-
getArgValue,
|
|
17
|
-
hasFlag,
|
|
18
|
-
resolveConfig
|
|
19
|
-
} from "./chunk-3HI6QC4V.js";
|
|
20
|
-
import {
|
|
21
|
-
writeRawOutput
|
|
22
|
-
} from "./chunk-UEJ2HTKU.js";
|
|
23
|
-
import "./chunk-TOWZAG3I.js";
|
|
24
|
-
|
|
25
|
-
// src/chat-target.ts
|
|
26
|
-
import fs from "fs/promises";
|
|
27
|
-
import process from "process";
|
|
28
|
-
var CHAT_TARGET_FLAGS = [
|
|
29
|
-
"--application",
|
|
30
|
-
"--property",
|
|
31
|
-
"--environment",
|
|
32
|
-
"--credential",
|
|
33
|
-
"--credential-template",
|
|
34
|
-
"--name",
|
|
35
|
-
"--config",
|
|
36
|
-
"--invariant",
|
|
37
|
-
"--judge-model",
|
|
38
|
-
"--message",
|
|
39
|
-
"--env",
|
|
40
|
-
"--api-url",
|
|
41
|
-
"--token",
|
|
42
|
-
"--org"
|
|
43
|
-
];
|
|
44
|
-
function parseInvariants(argv) {
|
|
45
|
-
const out = [];
|
|
46
|
-
for (let i = 0; i < argv.length; i++) {
|
|
47
|
-
if (argv[i] !== "--invariant") continue;
|
|
48
|
-
const raw = argv[i + 1];
|
|
49
|
-
if (raw === void 0 || raw.startsWith("-")) continue;
|
|
50
|
-
const eq = raw.indexOf("=");
|
|
51
|
-
if (eq <= 0) {
|
|
52
|
-
console.error(
|
|
53
|
-
`Error: --invariant "${raw}" is not in "<name>=<rubric>" form.
|
|
54
|
-
Example: --invariant "No cross-org data=Never reveals another organization's data."`
|
|
55
|
-
);
|
|
56
|
-
process.exit(1);
|
|
57
|
-
}
|
|
58
|
-
let name = raw.slice(0, eq).trim();
|
|
59
|
-
const rubric = raw.slice(eq + 1).trim();
|
|
60
|
-
let severity = "fail";
|
|
61
|
-
if (name.endsWith(":warn")) {
|
|
62
|
-
name = name.slice(0, -":warn".length).trim();
|
|
63
|
-
severity = "warn";
|
|
64
|
-
} else if (name.endsWith(":fail")) {
|
|
65
|
-
name = name.slice(0, -":fail".length).trim();
|
|
66
|
-
}
|
|
67
|
-
if (!name || !rubric) {
|
|
68
|
-
console.error(`Error: --invariant "${raw}" needs a non-empty name and rubric.`);
|
|
69
|
-
process.exit(1);
|
|
70
|
-
}
|
|
71
|
-
out.push({ id: name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, ""), name, rubric, severity });
|
|
72
|
-
}
|
|
73
|
-
return out;
|
|
74
|
-
}
|
|
75
|
-
function printChatTargetHelp() {
|
|
76
|
-
console.log(
|
|
77
|
-
[
|
|
78
|
-
"Usage: canary chat-target <sub-command> [options]",
|
|
79
|
-
"",
|
|
80
|
-
"A chat target describes how to talk to an AI chat under test: the message",
|
|
81
|
-
"request, how to read the reply, and which credential to send it as. Chat",
|
|
82
|
-
'evals (flowType "eval") point a chat_scenario node at one.',
|
|
83
|
-
"",
|
|
84
|
-
"Sub-commands:",
|
|
85
|
-
" list [options] List chat targets",
|
|
86
|
-
" get <id|name> [options] Print a target, including its full config",
|
|
87
|
-
" create [options] Create a chat target",
|
|
88
|
-
" update <id|name> [options] Update target fields",
|
|
89
|
-
" delete <id|name> [--yes] Archive a chat target",
|
|
90
|
-
" chat <id|name> --message <text> Send one real turn and print the reply",
|
|
91
|
-
"",
|
|
92
|
-
"List options:",
|
|
93
|
-
" --application <name|id> Filter by application (alias: --property)",
|
|
94
|
-
" --json Output raw JSON",
|
|
95
|
-
"",
|
|
96
|
-
"Create options:",
|
|
97
|
-
" --name <name> Target name (required)",
|
|
98
|
-
" --config <file|-> Config JSON: file path, or - for stdin (required)",
|
|
99
|
-
" --application <name|id> Application to attach to (alias: --property)",
|
|
100
|
-
" --environment <name|id> Environment to bind",
|
|
101
|
-
" --credential <name|id> Credential to authenticate turns as",
|
|
102
|
-
" --credential-template <name|id> Persona to authenticate as, resolved per",
|
|
103
|
-
" environment. Preferred over --credential for",
|
|
104
|
-
" a target used across several environments.",
|
|
105
|
-
' --invariant "<name>=<rubric>" Global invariant, judged on EVERY reply',
|
|
106
|
-
" (repeatable; append :warn to the name to soften)",
|
|
107
|
-
" --judge-model <id> Override the evals.judge routing default",
|
|
108
|
-
" --json",
|
|
109
|
-
"",
|
|
110
|
-
"Update options: same as create; only the flags you pass change.",
|
|
111
|
-
" Passing --invariant at all REPLACES the whole list. There is no way to",
|
|
112
|
-
" clear it to empty from here \u2014 edit via the app if you need that.",
|
|
113
|
-
"",
|
|
114
|
-
"Chat options:",
|
|
115
|
-
" --message <text> Message to send (required)",
|
|
116
|
-
" --application <name|id> Disambiguate when <id|name> is a name",
|
|
117
|
-
" --json Print the raw turn result",
|
|
118
|
-
"",
|
|
119
|
-
"Config shape (--config):",
|
|
120
|
-
" {",
|
|
121
|
-
' "message": { "method", "urlTemplate", "historyMode", "bodyTemplate",',
|
|
122
|
-
' "headersTemplate"? },',
|
|
123
|
-
' "response": { "transport": "ai-sdk-v5" | "sse" | "json", ... },',
|
|
124
|
-
' "timeoutSeconds"?: 120',
|
|
125
|
-
" }",
|
|
126
|
-
" Slots {{message}}, {{messages}} and {{conversationId}} are substituted per turn.",
|
|
127
|
-
"",
|
|
128
|
-
"Common options:",
|
|
129
|
-
" --env <env> Target environment (prod, dev, local)",
|
|
130
|
-
" --api-url <url> API URL override",
|
|
131
|
-
" --token <key> API token override",
|
|
132
|
-
"",
|
|
133
|
-
"Chat targets require the `evals` feature flag for the organization."
|
|
134
|
-
].join("\n")
|
|
135
|
-
);
|
|
136
|
-
}
|
|
137
|
-
async function fetchChatTargets(apiUrl, token, propertyId) {
|
|
138
|
-
const path = propertyId ? `/chat-targets?propertyId=${encodeURIComponent(propertyId)}` : "/chat-targets";
|
|
139
|
-
const res = await apiRequest(apiUrl, token, "GET", path);
|
|
140
|
-
if (!res.ok) {
|
|
141
|
-
console.error(`Error: ${res.error ?? "Failed to list chat targets"}`);
|
|
142
|
-
process.exit(1);
|
|
143
|
-
}
|
|
144
|
-
return res.data ?? [];
|
|
145
|
-
}
|
|
146
|
-
async function resolveApplicationId(arg, apiUrl, token) {
|
|
147
|
-
const properties = await fetchProperties(apiUrl, token);
|
|
148
|
-
const match = properties.find(
|
|
149
|
-
(p) => p.id === arg || p.name.toLowerCase() === arg.toLowerCase()
|
|
150
|
-
);
|
|
151
|
-
if (!match) {
|
|
152
|
-
console.error(`Error: Application "${arg}" not found.`);
|
|
153
|
-
if (properties.length > 0) {
|
|
154
|
-
console.error("Available applications:");
|
|
155
|
-
for (const p of properties) console.error(` - ${p.name} (${p.id})`);
|
|
156
|
-
}
|
|
157
|
-
process.exit(1);
|
|
158
|
-
}
|
|
159
|
-
return { id: match.id, name: match.name };
|
|
160
|
-
}
|
|
161
|
-
async function resolveEnvironmentId(arg, propertyId, apiUrl, token) {
|
|
162
|
-
if (!propertyId) {
|
|
163
|
-
if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(arg)) return arg;
|
|
164
|
-
console.error(
|
|
165
|
-
`Error: Cannot resolve environment "${arg}" by name without --application. Pass --application to narrow, or use the environment id.`
|
|
166
|
-
);
|
|
167
|
-
process.exit(1);
|
|
168
|
-
}
|
|
169
|
-
const res = await apiRequest(apiUrl, token, "GET", `/org/properties/${propertyId}/environments`);
|
|
170
|
-
if (!res.ok) {
|
|
171
|
-
console.error(`Error: ${res.error ?? "Failed to list environments"}`);
|
|
172
|
-
process.exit(1);
|
|
173
|
-
}
|
|
174
|
-
const environments = res.items ?? [];
|
|
175
|
-
const byId = environments.find((e) => e.id === arg);
|
|
176
|
-
if (byId) return byId.id;
|
|
177
|
-
const byName = environments.filter((e) => e.name.toLowerCase() === arg.toLowerCase());
|
|
178
|
-
if (byName.length === 1) return byName[0].id;
|
|
179
|
-
if (byName.length > 1) {
|
|
180
|
-
console.error(`Error: Multiple environments match "${arg}" on this application.`);
|
|
181
|
-
for (const e of byName) console.error(` - ${e.name} (${e.id})`);
|
|
182
|
-
process.exit(1);
|
|
183
|
-
}
|
|
184
|
-
console.error(`Error: Environment "${arg}" not found on this application.`);
|
|
185
|
-
if (environments.length > 0) {
|
|
186
|
-
console.error("Available environments:");
|
|
187
|
-
for (const e of environments) console.error(` - ${e.name} (${e.id})`);
|
|
188
|
-
}
|
|
189
|
-
process.exit(1);
|
|
190
|
-
}
|
|
191
|
-
async function resolveCredentialTemplate(arg, apiUrl, token) {
|
|
192
|
-
const res = await apiRequest(apiUrl, token, "GET", "/org/credential-templates");
|
|
193
|
-
if (!res.ok) {
|
|
194
|
-
console.error(`Error: ${res.error ?? "Failed to list personas"}`);
|
|
195
|
-
process.exit(1);
|
|
196
|
-
}
|
|
197
|
-
const templates = res.items ?? [];
|
|
198
|
-
const byId = templates.find((t) => t.id === arg);
|
|
199
|
-
if (byId) return byId;
|
|
200
|
-
const byName = templates.filter((t) => t.name.toLowerCase() === arg.toLowerCase());
|
|
201
|
-
if (byName.length === 1) return byName[0];
|
|
202
|
-
if (byName.length > 1) {
|
|
203
|
-
console.error(`Error: Multiple personas match "${arg}". Pass the persona id instead.`);
|
|
204
|
-
for (const t of byName) console.error(` - ${t.name} (${t.id})`);
|
|
205
|
-
process.exit(1);
|
|
206
|
-
}
|
|
207
|
-
console.error(`Error: Persona "${arg}" not found.`);
|
|
208
|
-
if (templates.length > 0) {
|
|
209
|
-
console.error("Available personas:");
|
|
210
|
-
for (const t of templates) console.error(` - ${t.name} (${t.id})`);
|
|
211
|
-
}
|
|
212
|
-
process.exit(1);
|
|
213
|
-
}
|
|
214
|
-
async function resolveTarget(arg, argv, apiUrl, token) {
|
|
215
|
-
const appArg = getApplicationArg(argv);
|
|
216
|
-
const propertyId = appArg ? (await resolveApplicationId(appArg, apiUrl, token)).id : void 0;
|
|
217
|
-
const targets = await fetchChatTargets(apiUrl, token, propertyId);
|
|
218
|
-
const byId = targets.find((t) => t.id === arg);
|
|
219
|
-
if (byId) return byId;
|
|
220
|
-
const byName = targets.filter((t) => t.name.toLowerCase() === arg.toLowerCase());
|
|
221
|
-
if (byName.length === 1) return byName[0];
|
|
222
|
-
if (byName.length > 1) {
|
|
223
|
-
console.error(
|
|
224
|
-
`Error: Multiple chat targets match "${arg}". Pass --application to disambiguate.`
|
|
225
|
-
);
|
|
226
|
-
for (const t of byName) console.error(` - ${t.name} (${t.id}) application=${t.propertyId}`);
|
|
227
|
-
process.exit(1);
|
|
228
|
-
}
|
|
229
|
-
console.error(`Error: No chat target matching "${arg}".`);
|
|
230
|
-
if (targets.length > 0) {
|
|
231
|
-
console.error("Available chat targets:");
|
|
232
|
-
for (const t of targets) console.error(` - ${t.name} (${t.id})`);
|
|
233
|
-
}
|
|
234
|
-
process.exit(1);
|
|
235
|
-
}
|
|
236
|
-
async function readConfig(source) {
|
|
237
|
-
const raw = source === "-" ? await readFromStdin() : await fs.readFile(source, "utf-8");
|
|
238
|
-
let parsed;
|
|
239
|
-
try {
|
|
240
|
-
parsed = JSON.parse(raw);
|
|
241
|
-
} catch {
|
|
242
|
-
console.error(`Error: --config ${source} is not valid JSON.`);
|
|
243
|
-
process.exit(1);
|
|
244
|
-
}
|
|
245
|
-
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
246
|
-
console.error("Error: chat target config must be a JSON object.");
|
|
247
|
-
process.exit(1);
|
|
248
|
-
}
|
|
249
|
-
const obj = parsed;
|
|
250
|
-
for (const key of ["message", "response"]) {
|
|
251
|
-
if (!obj[key]) {
|
|
252
|
-
console.error(`Error: chat target config is missing "${key}".`);
|
|
253
|
-
console.error("Run `canary chat-target --help` for the expected shape.");
|
|
254
|
-
process.exit(1);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
return obj;
|
|
258
|
-
}
|
|
259
|
-
function transportOf(target) {
|
|
260
|
-
const response = target.configJson?.response;
|
|
261
|
-
if (response && typeof response === "object" && "transport" in response) {
|
|
262
|
-
return String(response.transport);
|
|
263
|
-
}
|
|
264
|
-
return "";
|
|
265
|
-
}
|
|
266
|
-
async function handleList(argv, apiUrl, token) {
|
|
267
|
-
const json = hasFlag(argv, "--json");
|
|
268
|
-
const appArg = getApplicationArg(argv);
|
|
269
|
-
const propertyId = appArg ? (await resolveApplicationId(appArg, apiUrl, token)).id : void 0;
|
|
270
|
-
const targets = await fetchChatTargets(apiUrl, token, propertyId);
|
|
271
|
-
if (json) {
|
|
272
|
-
writeRawOutput(JSON.stringify({ data: targets }, null, 2));
|
|
273
|
-
return;
|
|
274
|
-
}
|
|
275
|
-
if (targets.length === 0) {
|
|
276
|
-
console.log("No chat targets found.");
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
console.log(
|
|
280
|
-
`${pad("ID", 28)} ${pad("Name", 32)} ${pad("Transport", 10)} ${pad("Invariants", 10)} Credential`
|
|
281
|
-
);
|
|
282
|
-
for (const t of targets) {
|
|
283
|
-
const credential = t.credentialTemplateName ?? t.credentialId ?? "(none)";
|
|
284
|
-
console.log(
|
|
285
|
-
`${pad(t.id, 28)} ${pad(t.name, 32)} ${pad(transportOf(t), 10)} ${pad(String(t.globalInvariants?.length ?? 0), 10)} ${credential}`
|
|
286
|
-
);
|
|
287
|
-
}
|
|
288
|
-
}
|
|
289
|
-
async function handleGet(argv, apiUrl, token) {
|
|
290
|
-
const arg = getPositionalArg(argv, CHAT_TARGET_FLAGS);
|
|
291
|
-
if (!arg) {
|
|
292
|
-
console.error("Usage: canary chat-target get <id|name> [--application <name|id>] [--json]");
|
|
293
|
-
process.exit(1);
|
|
294
|
-
}
|
|
295
|
-
const target = await resolveTarget(arg, argv, apiUrl, token);
|
|
296
|
-
if (hasFlag(argv, "--json")) {
|
|
297
|
-
writeRawOutput(JSON.stringify(target, null, 2));
|
|
298
|
-
return;
|
|
299
|
-
}
|
|
300
|
-
console.log(`${target.name} (${target.id})`);
|
|
301
|
-
console.log(` Application: ${target.propertyId ?? "(none)"}`);
|
|
302
|
-
console.log(` Environment: ${target.environmentId ?? "(none)"}`);
|
|
303
|
-
console.log(` Credential: ${target.credentialTemplateName ?? target.credentialId ?? "(none)"}`);
|
|
304
|
-
console.log(` Judge model: ${target.judgeModelId ?? "(routing default)"}`);
|
|
305
|
-
const invariants = target.globalInvariants ?? [];
|
|
306
|
-
console.log(` Invariants: ${invariants.length}`);
|
|
307
|
-
for (const inv of invariants) {
|
|
308
|
-
console.log(` [${inv.severity}] ${inv.name}: ${inv.rubric}`);
|
|
309
|
-
}
|
|
310
|
-
console.log(" Config:");
|
|
311
|
-
writeRawOutput(
|
|
312
|
-
JSON.stringify(target.configJson, null, 2).split("\n").map((l) => ` ${l}`).join("\n")
|
|
313
|
-
);
|
|
314
|
-
}
|
|
315
|
-
async function buildWriteBody(argv, apiUrl, token) {
|
|
316
|
-
const body = {};
|
|
317
|
-
const name = getArgValue(argv, "--name");
|
|
318
|
-
if (name !== void 0) body.name = name;
|
|
319
|
-
const appArg = getApplicationArg(argv);
|
|
320
|
-
if (appArg !== void 0) {
|
|
321
|
-
body.propertyId = (await resolveApplicationId(appArg, apiUrl, token)).id;
|
|
322
|
-
}
|
|
323
|
-
const scopePropertyId = typeof body.propertyId === "string" ? body.propertyId : void 0;
|
|
324
|
-
const environment = getArgValue(argv, "--environment");
|
|
325
|
-
if (environment !== void 0) {
|
|
326
|
-
body.environmentId = await resolveEnvironmentId(environment, scopePropertyId, apiUrl, token);
|
|
327
|
-
}
|
|
328
|
-
const credential = getArgValue(argv, "--credential");
|
|
329
|
-
if (credential !== void 0) {
|
|
330
|
-
body.credentialId = await resolveCredentialId(credential, scopePropertyId, apiUrl, token);
|
|
331
|
-
}
|
|
332
|
-
const credentialTemplate = getArgValue(argv, "--credential-template");
|
|
333
|
-
if (credentialTemplate !== void 0) {
|
|
334
|
-
const template = await resolveCredentialTemplate(credentialTemplate, apiUrl, token);
|
|
335
|
-
body.credentialTemplateId = template.id;
|
|
336
|
-
body.credentialTemplateName = template.name;
|
|
337
|
-
}
|
|
338
|
-
const judgeModel = getArgValue(argv, "--judge-model");
|
|
339
|
-
if (judgeModel !== void 0) body.judgeModelId = judgeModel;
|
|
340
|
-
const configSource = getArgValue(argv, "--config");
|
|
341
|
-
if (configSource !== void 0) body.configJson = await readConfig(configSource);
|
|
342
|
-
const invariants = parseInvariants(argv);
|
|
343
|
-
if (invariants.length > 0) body.globalInvariants = invariants;
|
|
344
|
-
return body;
|
|
345
|
-
}
|
|
346
|
-
async function handleCreate(argv, apiUrl, token) {
|
|
347
|
-
const json = hasFlag(argv, "--json");
|
|
348
|
-
const body = await buildWriteBody(argv, apiUrl, token);
|
|
349
|
-
if (!body.name || !body.configJson) {
|
|
350
|
-
console.error("Error: --name and --config are required.");
|
|
351
|
-
console.error(
|
|
352
|
-
"Usage: canary chat-target create --name <name> --config <file|-> [--application <name|id>] [options]"
|
|
353
|
-
);
|
|
354
|
-
process.exit(1);
|
|
355
|
-
}
|
|
356
|
-
const res = await apiRequest(apiUrl, token, "POST", "/chat-targets", body);
|
|
357
|
-
if (!res.ok || !res.data) {
|
|
358
|
-
console.error(`Error: ${res.error ?? "Failed to create chat target"}`);
|
|
359
|
-
process.exit(1);
|
|
360
|
-
}
|
|
361
|
-
if (json) {
|
|
362
|
-
writeRawOutput(JSON.stringify(res.data, null, 2));
|
|
363
|
-
return;
|
|
364
|
-
}
|
|
365
|
-
console.log(`\u2713 Created chat target "${res.data.name}" (${res.data.id})`);
|
|
366
|
-
console.log(` Transport: ${transportOf(res.data)}`);
|
|
367
|
-
console.log(` Invariants: ${res.data.globalInvariants?.length ?? 0}`);
|
|
368
|
-
console.log("");
|
|
369
|
-
console.log("Next:");
|
|
370
|
-
console.log(
|
|
371
|
-
` canary chat-target chat ${res.data.id} --message "What can you help me with?"`
|
|
372
|
-
);
|
|
373
|
-
}
|
|
374
|
-
async function handleUpdate(argv, apiUrl, token) {
|
|
375
|
-
const arg = getPositionalArg(argv, CHAT_TARGET_FLAGS);
|
|
376
|
-
if (!arg) {
|
|
377
|
-
console.error("Usage: canary chat-target update <id|name> [options]");
|
|
378
|
-
process.exit(1);
|
|
379
|
-
}
|
|
380
|
-
const target = await resolveTarget(arg, argv, apiUrl, token);
|
|
381
|
-
const body = await buildWriteBody(argv, apiUrl, token);
|
|
382
|
-
if (Object.keys(body).length === 0) {
|
|
383
|
-
console.error(
|
|
384
|
-
"Error: No fields to update. Provide at least one of: --name, --config, --application, --environment, --credential, --credential-template, --invariant, --judge-model"
|
|
385
|
-
);
|
|
386
|
-
process.exit(1);
|
|
387
|
-
}
|
|
388
|
-
const res = await apiRequest(
|
|
389
|
-
apiUrl,
|
|
390
|
-
token,
|
|
391
|
-
"PATCH",
|
|
392
|
-
`/chat-targets/${target.id}`,
|
|
393
|
-
body
|
|
394
|
-
);
|
|
395
|
-
if (!res.ok || !res.data) {
|
|
396
|
-
console.error(`Error: ${res.error ?? "Failed to update chat target"}`);
|
|
397
|
-
process.exit(1);
|
|
398
|
-
}
|
|
399
|
-
if (hasFlag(argv, "--json")) {
|
|
400
|
-
writeRawOutput(JSON.stringify(res.data, null, 2));
|
|
401
|
-
return;
|
|
402
|
-
}
|
|
403
|
-
console.log(`\u2713 Updated chat target "${res.data.name}" (${res.data.id})`);
|
|
404
|
-
}
|
|
405
|
-
async function handleDelete(argv, apiUrl, token) {
|
|
406
|
-
const arg = getPositionalArg(argv, CHAT_TARGET_FLAGS);
|
|
407
|
-
if (!arg) {
|
|
408
|
-
console.error("Usage: canary chat-target delete <id|name> [--yes]");
|
|
409
|
-
process.exit(1);
|
|
410
|
-
}
|
|
411
|
-
const target = await resolveTarget(arg, argv, apiUrl, token);
|
|
412
|
-
if (!hasFlag(argv, "--yes")) {
|
|
413
|
-
console.error(`Refusing to archive "${target.name}" (${target.id}) without --yes.`);
|
|
414
|
-
console.error("Evals pointing at this target will fail to run once it is archived.");
|
|
415
|
-
process.exit(1);
|
|
416
|
-
}
|
|
417
|
-
const res = await apiRequest(
|
|
418
|
-
apiUrl,
|
|
419
|
-
token,
|
|
420
|
-
"DELETE",
|
|
421
|
-
`/chat-targets/${target.id}`
|
|
422
|
-
);
|
|
423
|
-
if (!res.ok) {
|
|
424
|
-
console.error(`Error: ${res.error ?? "Failed to archive chat target"}`);
|
|
425
|
-
process.exit(1);
|
|
426
|
-
}
|
|
427
|
-
console.log(`\u2713 Archived chat target "${target.name}" (${target.id})`);
|
|
428
|
-
}
|
|
429
|
-
async function handleChat(argv, apiUrl, token) {
|
|
430
|
-
const arg = getPositionalArg(argv, CHAT_TARGET_FLAGS);
|
|
431
|
-
const message = getArgValue(argv, "--message");
|
|
432
|
-
if (!arg || !message) {
|
|
433
|
-
console.error("Usage: canary chat-target chat <id|name> --message <text> [--json]");
|
|
434
|
-
process.exit(1);
|
|
435
|
-
}
|
|
436
|
-
const target = await resolveTarget(arg, argv, apiUrl, token);
|
|
437
|
-
const configured = target.configJson?.timeoutSeconds;
|
|
438
|
-
const targetSeconds = typeof configured === "number" && configured > 0 ? configured : 120;
|
|
439
|
-
const res = await apiRequest(
|
|
440
|
-
apiUrl,
|
|
441
|
-
token,
|
|
442
|
-
"POST",
|
|
443
|
-
`/chat-targets/${target.id}/chat`,
|
|
444
|
-
{ message },
|
|
445
|
-
{ timeoutMs: (targetSeconds + 60) * 1e3 }
|
|
446
|
-
);
|
|
447
|
-
if (!res.ok || !res.data) {
|
|
448
|
-
console.error(`Error: ${res.error ?? "Failed to send message"}`);
|
|
449
|
-
process.exit(1);
|
|
450
|
-
}
|
|
451
|
-
if (hasFlag(argv, "--json")) {
|
|
452
|
-
writeRawOutput(JSON.stringify(res.data, null, 2));
|
|
453
|
-
}
|
|
454
|
-
if (!res.data.ok) {
|
|
455
|
-
if (!hasFlag(argv, "--json")) {
|
|
456
|
-
console.error(`Turn failed: ${res.data.error}`);
|
|
457
|
-
}
|
|
458
|
-
process.exit(1);
|
|
459
|
-
}
|
|
460
|
-
if (!hasFlag(argv, "--json")) {
|
|
461
|
-
console.log(`> ${res.data.sentMessage}`);
|
|
462
|
-
console.log("");
|
|
463
|
-
console.log(res.data.parsedText);
|
|
464
|
-
}
|
|
465
|
-
}
|
|
466
|
-
async function runChatTarget(argv) {
|
|
467
|
-
const [subCommand, ...rest] = argv;
|
|
468
|
-
if (!subCommand || subCommand === "help" || hasFlag(argv, "--help", "-h")) {
|
|
469
|
-
printChatTargetHelp();
|
|
470
|
-
return;
|
|
471
|
-
}
|
|
472
|
-
const { apiUrl, token } = await resolveConfig(argv);
|
|
473
|
-
switch (subCommand) {
|
|
474
|
-
case "list":
|
|
475
|
-
await handleList(rest, apiUrl, token);
|
|
476
|
-
return;
|
|
477
|
-
case "get":
|
|
478
|
-
await handleGet(rest, apiUrl, token);
|
|
479
|
-
return;
|
|
480
|
-
case "create":
|
|
481
|
-
await handleCreate(rest, apiUrl, token);
|
|
482
|
-
return;
|
|
483
|
-
case "update":
|
|
484
|
-
await handleUpdate(rest, apiUrl, token);
|
|
485
|
-
return;
|
|
486
|
-
case "delete":
|
|
487
|
-
await handleDelete(rest, apiUrl, token);
|
|
488
|
-
return;
|
|
489
|
-
case "chat":
|
|
490
|
-
await handleChat(rest, apiUrl, token);
|
|
491
|
-
return;
|
|
492
|
-
default:
|
|
493
|
-
console.error(`Unknown chat-target sub-command: ${subCommand}`);
|
|
494
|
-
printChatTargetHelp();
|
|
495
|
-
process.exit(1);
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
export {
|
|
499
|
-
parseInvariants,
|
|
500
|
-
runChatTarget
|
|
501
|
-
};
|
|
502
|
-
//# sourceMappingURL=chat-target-IZ7YLLU3.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/chat-target.ts"],"sourcesContent":["/**\n * CLI Chat Target Commands\n *\n * Manage chat targets — the saved description of how to talk to an AI chat\n * under test — and send a single live turn against one.\n *\n * Mirrors `credential`: application-scoped, `<id|name>` resolution, and a\n * `chat` verb playing the role `credential test` plays.\n *\n * @module chat-target\n */\n\nimport fs from 'node:fs/promises';\nimport process from 'node:process';\nimport { resolveConfig, getArgValue, hasFlag } from './auth.js';\nimport { apiRequest, fetchProperties, getApplicationArg, getPositionalArg, resolveCredentialId } from './cli-helpers.js';\nimport { pad, readFromStdin } from './cli-format.js';\nimport { writeRawOutput } from './brand.js';\n\n/** Severity of a global invariant. Mirrors GlobalInvariantSchema in @chatsdet/types. */\ntype InvariantSeverity = 'warn' | 'fail';\n\ntype GlobalInvariant = {\n id: string;\n name: string;\n rubric: string;\n severity: InvariantSeverity;\n};\n\ntype ChatTarget = {\n id: string;\n name: string;\n propertyId: string | null;\n environmentId: string | null;\n credentialId: string | null;\n credentialTemplateId: string | null;\n credentialTemplateName: string | null;\n configJson: Record<string, unknown>;\n globalInvariants: GlobalInvariant[] | null;\n judgeModelId: string | null;\n createdAt: string;\n updatedAt: string;\n};\n\ntype ListResponse = { ok: boolean; error?: string; data?: ChatTarget[] };\ntype OneResponse = { ok: boolean; error?: string; data?: ChatTarget };\ntype OkResponse = { ok: boolean; error?: string };\n\n/**\n * The live-turn route always answers HTTP 200 and reports a failed turn INSIDE\n * the envelope, so `data.ok` is the real outcome. Treating the envelope as the\n * result would report a broken target as a success — the exact thing this\n * command exists to catch.\n */\ntype ChatTurnResult =\n | { ok: true; sentMessage: string; parsedText: string; conversation: unknown }\n | { ok: false; error: string };\ntype ChatResponse = { ok: boolean; error?: string; data?: ChatTurnResult };\n\n/** Flags that consume the following argv entry, so positional scanning skips both. */\nconst CHAT_TARGET_FLAGS = [\n '--application',\n '--property',\n '--environment',\n '--credential',\n '--credential-template',\n '--name',\n '--config',\n '--invariant',\n '--judge-model',\n '--message',\n '--env',\n '--api-url',\n '--token',\n '--org',\n];\n\n/**\n * Parse repeatable `--invariant \"<name>=<rubric>\"` flags.\n *\n * Severity defaults to `fail`; one that only warned by default would quietly\n * stop gating. Only the first `=` separates name from rubric, so a rubric may\n * contain `=` — comparing against `$var` is the motivating case.\n */\nexport function parseInvariants(argv: string[]): GlobalInvariant[] {\n const out: GlobalInvariant[] = [];\n for (let i = 0; i < argv.length; i++) {\n if (argv[i] !== '--invariant') continue;\n const raw = argv[i + 1];\n if (raw === undefined || raw.startsWith('-')) continue;\n const eq = raw.indexOf('=');\n if (eq <= 0) {\n console.error(\n `Error: --invariant \"${raw}\" is not in \"<name>=<rubric>\" form.\\n` +\n ' Example: --invariant \"No cross-org data=Never reveals another organization\\'s data.\"'\n );\n process.exit(1);\n }\n let name = raw.slice(0, eq).trim();\n const rubric = raw.slice(eq + 1).trim();\n let severity: InvariantSeverity = 'fail';\n if (name.endsWith(':warn')) {\n name = name.slice(0, -':warn'.length).trim();\n severity = 'warn';\n } else if (name.endsWith(':fail')) {\n name = name.slice(0, -':fail'.length).trim();\n }\n if (!name || !rubric) {\n console.error(`Error: --invariant \"${raw}\" needs a non-empty name and rubric.`);\n process.exit(1);\n }\n out.push({ id: name.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, ''), name, rubric, severity });\n }\n return out;\n}\n\nfunction printChatTargetHelp(): void {\n console.log(\n [\n 'Usage: canary chat-target <sub-command> [options]',\n '',\n 'A chat target describes how to talk to an AI chat under test: the message',\n 'request, how to read the reply, and which credential to send it as. Chat',\n 'evals (flowType \"eval\") point a chat_scenario node at one.',\n '',\n 'Sub-commands:',\n ' list [options] List chat targets',\n ' get <id|name> [options] Print a target, including its full config',\n ' create [options] Create a chat target',\n ' update <id|name> [options] Update target fields',\n ' delete <id|name> [--yes] Archive a chat target',\n ' chat <id|name> --message <text> Send one real turn and print the reply',\n '',\n 'List options:',\n ' --application <name|id> Filter by application (alias: --property)',\n ' --json Output raw JSON',\n '',\n 'Create options:',\n ' --name <name> Target name (required)',\n ' --config <file|-> Config JSON: file path, or - for stdin (required)',\n ' --application <name|id> Application to attach to (alias: --property)',\n ' --environment <name|id> Environment to bind',\n ' --credential <name|id> Credential to authenticate turns as',\n ' --credential-template <name|id> Persona to authenticate as, resolved per',\n ' environment. Preferred over --credential for',\n ' a target used across several environments.',\n ' --invariant \"<name>=<rubric>\" Global invariant, judged on EVERY reply',\n ' (repeatable; append :warn to the name to soften)',\n ' --judge-model <id> Override the evals.judge routing default',\n ' --json',\n '',\n 'Update options: same as create; only the flags you pass change.',\n ' Passing --invariant at all REPLACES the whole list. There is no way to',\n ' clear it to empty from here — edit via the app if you need that.',\n '',\n 'Chat options:',\n ' --message <text> Message to send (required)',\n ' --application <name|id> Disambiguate when <id|name> is a name',\n ' --json Print the raw turn result',\n '',\n 'Config shape (--config):',\n ' {',\n ' \"message\": { \"method\", \"urlTemplate\", \"historyMode\", \"bodyTemplate\",',\n ' \"headersTemplate\"? },',\n ' \"response\": { \"transport\": \"ai-sdk-v5\" | \"sse\" | \"json\", ... },',\n ' \"timeoutSeconds\"?: 120',\n ' }',\n ' Slots {{message}}, {{messages}} and {{conversationId}} are substituted per turn.',\n '',\n 'Common options:',\n ' --env <env> Target environment (prod, dev, local)',\n ' --api-url <url> API URL override',\n ' --token <key> API token override',\n '',\n 'Chat targets require the `evals` feature flag for the organization.',\n ].join('\\n')\n );\n}\n\nasync function fetchChatTargets(\n apiUrl: string,\n token: string,\n propertyId?: string\n): Promise<ChatTarget[]> {\n const path = propertyId\n ? `/chat-targets?propertyId=${encodeURIComponent(propertyId)}`\n : '/chat-targets';\n const res = await apiRequest<ListResponse>(apiUrl, token, 'GET', path);\n if (!res.ok) {\n console.error(`Error: ${res.error ?? 'Failed to list chat targets'}`);\n process.exit(1);\n }\n return res.data ?? [];\n}\n\n/**\n * Resolve an application name or id to its id, listing the alternatives when the\n * lookup misses rather than failing with a bare \"not found\".\n */\nasync function resolveApplicationId(\n arg: string,\n apiUrl: string,\n token: string\n): Promise<{ id: string; name: string }> {\n const properties = await fetchProperties(apiUrl, token);\n const match = properties.find(\n (p) => p.id === arg || p.name.toLowerCase() === arg.toLowerCase()\n );\n if (!match) {\n console.error(`Error: Application \"${arg}\" not found.`);\n if (properties.length > 0) {\n console.error('Available applications:');\n for (const p of properties) console.error(` - ${p.name} (${p.id})`);\n }\n process.exit(1);\n }\n return { id: match.id, name: match.name };\n}\n\n\n/**\n * Resolve a persona (credential template) name or id, org-wide.\n *\n * Both the id AND the name must be written. The live-turn route branches on\n * `credentialTemplateId` alone; `credentialTemplateName` is a display label the\n * repo stores verbatim. Setting only the name produces a target that reads as\n * bound in `get`/`list` while turns go out under no session at all.\n *\n * Listed org-wide rather than per-application so `update` can change a persona\n * without re-stating an application the target already has.\n */\n/**\n * Resolve a `--environment` argument (id or case-insensitive name) to an\n * environment id. Mirrors `resolveCredentialId`'s scoping: environments are\n * only listable per-application (`/org/properties/:id/environments` — there\n * is no org-wide environment listing the way `/org/credentials` is), so a\n * name can only be resolved when `--application` narrowed this invocation to\n * a raw property uuid. A bare id is passed through — the server remains the\n * authority on whether it is valid.\n */\nasync function resolveEnvironmentId(\n arg: string,\n propertyId: string | undefined,\n apiUrl: string,\n token: string\n): Promise<string> {\n if (!propertyId) {\n if (/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(arg)) return arg;\n console.error(\n `Error: Cannot resolve environment \"${arg}\" by name without --application. Pass --application to narrow, or use the environment id.`\n );\n process.exit(1);\n }\n\n const res = await apiRequest<{\n ok: boolean;\n error?: string;\n items?: Array<{ id: string; name: string }>;\n }>(apiUrl, token, 'GET', `/org/properties/${propertyId}/environments`);\n if (!res.ok) {\n console.error(`Error: ${res.error ?? 'Failed to list environments'}`);\n process.exit(1);\n }\n const environments = res.items ?? [];\n\n const byId = environments.find((e) => e.id === arg);\n if (byId) return byId.id;\n\n const byName = environments.filter((e) => e.name.toLowerCase() === arg.toLowerCase());\n if (byName.length === 1) return byName[0]!.id;\n if (byName.length > 1) {\n console.error(`Error: Multiple environments match \"${arg}\" on this application.`);\n for (const e of byName) console.error(` - ${e.name} (${e.id})`);\n process.exit(1);\n }\n\n console.error(`Error: Environment \"${arg}\" not found on this application.`);\n if (environments.length > 0) {\n console.error('Available environments:');\n for (const e of environments) console.error(` - ${e.name} (${e.id})`);\n }\n process.exit(1);\n}\n\nasync function resolveCredentialTemplate(\n arg: string,\n apiUrl: string,\n token: string\n): Promise<{ id: string; name: string }> {\n const res = await apiRequest<{\n ok: boolean;\n error?: string;\n items?: Array<{ id: string; name: string }>;\n }>(apiUrl, token, 'GET', '/org/credential-templates');\n if (!res.ok) {\n console.error(`Error: ${res.error ?? 'Failed to list personas'}`);\n process.exit(1);\n }\n const templates = res.items ?? [];\n\n const byId = templates.find((t) => t.id === arg);\n if (byId) return byId;\n\n const byName = templates.filter((t) => t.name.toLowerCase() === arg.toLowerCase());\n if (byName.length === 1) return byName[0]!;\n if (byName.length > 1) {\n console.error(`Error: Multiple personas match \"${arg}\". Pass the persona id instead.`);\n for (const t of byName) console.error(` - ${t.name} (${t.id})`);\n process.exit(1);\n }\n\n console.error(`Error: Persona \"${arg}\" not found.`);\n if (templates.length > 0) {\n console.error('Available personas:');\n for (const t of templates) console.error(` - ${t.name} (${t.id})`);\n }\n process.exit(1);\n}\n\n/**\n * Resolve a chat target by id or name. An ambiguous name is an explicit error\n * rather than a silent first-match — two targets on different applications\n * routinely share a name, and picking one would send a live message to the\n * wrong endpoint.\n */\nasync function resolveTarget(\n arg: string,\n argv: string[],\n apiUrl: string,\n token: string\n): Promise<ChatTarget> {\n const appArg = getApplicationArg(argv);\n const propertyId = appArg ? (await resolveApplicationId(appArg, apiUrl, token)).id : undefined;\n const targets = await fetchChatTargets(apiUrl, token, propertyId);\n\n const byId = targets.find((t) => t.id === arg);\n if (byId) return byId;\n\n const byName = targets.filter((t) => t.name.toLowerCase() === arg.toLowerCase());\n if (byName.length === 1) return byName[0]!;\n if (byName.length > 1) {\n console.error(\n `Error: Multiple chat targets match \"${arg}\". Pass --application to disambiguate.`\n );\n for (const t of byName) console.error(` - ${t.name} (${t.id}) application=${t.propertyId}`);\n process.exit(1);\n }\n\n console.error(`Error: No chat target matching \"${arg}\".`);\n if (targets.length > 0) {\n console.error('Available chat targets:');\n for (const t of targets) console.error(` - ${t.name} (${t.id})`);\n }\n process.exit(1);\n}\n\nasync function readConfig(source: string): Promise<Record<string, unknown>> {\n const raw = source === '-' ? await readFromStdin() : await fs.readFile(source, 'utf-8');\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n console.error(`Error: --config ${source} is not valid JSON.`);\n process.exit(1);\n }\n if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {\n console.error('Error: chat target config must be a JSON object.');\n process.exit(1);\n }\n // Shape is validated server-side by ChatTargetConfigSchema. Check only the two\n // keys whose absence produces a confusing server error, so the fix is obvious\n // from the CLI rather than from a zod path.\n const obj = parsed as Record<string, unknown>;\n for (const key of ['message', 'response']) {\n if (!obj[key]) {\n console.error(`Error: chat target config is missing \"${key}\".`);\n console.error('Run `canary chat-target --help` for the expected shape.');\n process.exit(1);\n }\n }\n return obj;\n}\n\nfunction transportOf(target: ChatTarget): string {\n const response = target.configJson?.response;\n if (response && typeof response === 'object' && 'transport' in response) {\n return String((response as { transport: unknown }).transport);\n }\n return '';\n}\n\nasync function handleList(argv: string[], apiUrl: string, token: string): Promise<void> {\n const json = hasFlag(argv, '--json');\n const appArg = getApplicationArg(argv);\n const propertyId = appArg ? (await resolveApplicationId(appArg, apiUrl, token)).id : undefined;\n const targets = await fetchChatTargets(apiUrl, token, propertyId);\n\n if (json) {\n writeRawOutput(JSON.stringify({ data: targets }, null, 2));\n return;\n }\n if (targets.length === 0) {\n console.log('No chat targets found.');\n return;\n }\n\n // Prefixed ids (`chtg_` + 22 chars) are 27 wide; a narrower column bleeds into\n // the next one and misaligns every row.\n console.log(\n `${pad('ID', 28)} ${pad('Name', 32)} ${pad('Transport', 10)} ${pad('Invariants', 10)} Credential`\n );\n for (const t of targets) {\n const credential = t.credentialTemplateName ?? t.credentialId ?? '(none)';\n console.log(\n `${pad(t.id, 28)} ${pad(t.name, 32)} ${pad(transportOf(t), 10)} ` +\n `${pad(String(t.globalInvariants?.length ?? 0), 10)} ${credential}`\n );\n }\n}\n\nasync function handleGet(argv: string[], apiUrl: string, token: string): Promise<void> {\n const arg = getPositionalArg(argv, CHAT_TARGET_FLAGS);\n if (!arg) {\n console.error('Usage: canary chat-target get <id|name> [--application <name|id>] [--json]');\n process.exit(1);\n }\n const target = await resolveTarget(arg, argv, apiUrl, token);\n\n if (hasFlag(argv, '--json')) {\n writeRawOutput(JSON.stringify(target, null, 2));\n return;\n }\n console.log(`${target.name} (${target.id})`);\n console.log(` Application: ${target.propertyId ?? '(none)'}`);\n console.log(` Environment: ${target.environmentId ?? '(none)'}`);\n console.log(` Credential: ${target.credentialTemplateName ?? target.credentialId ?? '(none)'}`);\n console.log(` Judge model: ${target.judgeModelId ?? '(routing default)'}`);\n const invariants = target.globalInvariants ?? [];\n console.log(` Invariants: ${invariants.length}`);\n for (const inv of invariants) {\n console.log(` [${inv.severity}] ${inv.name}: ${inv.rubric}`);\n }\n console.log(' Config:');\n writeRawOutput(JSON.stringify(target.configJson, null, 2)\n .split('\\n')\n .map((l) => ` ${l}`)\n .join('\\n')\n );\n}\n\n/**\n * Build the create/update body from flags. Returns only the keys actually\n * supplied, so `update` patches rather than blanking every omitted field.\n */\nasync function buildWriteBody(\n argv: string[],\n apiUrl: string,\n token: string\n): Promise<Record<string, unknown>> {\n const body: Record<string, unknown> = {};\n\n const name = getArgValue(argv, '--name');\n if (name !== undefined) body.name = name;\n\n const appArg = getApplicationArg(argv);\n if (appArg !== undefined) {\n body.propertyId = (await resolveApplicationId(appArg, apiUrl, token)).id;\n }\n\n // Only an application resolved on THIS invocation is usable for narrowing:\n // it is a raw uuid, whereas an id read back off an existing target is\n // prefixed, and comparing the two forms would silently match nothing.\n const scopePropertyId = typeof body.propertyId === 'string' ? body.propertyId : undefined;\n\n const environment = getArgValue(argv, '--environment');\n if (environment !== undefined) {\n body.environmentId = await resolveEnvironmentId(environment, scopePropertyId, apiUrl, token);\n }\n\n const credential = getArgValue(argv, '--credential');\n if (credential !== undefined) {\n body.credentialId = await resolveCredentialId(credential, scopePropertyId, apiUrl, token);\n }\n\n const credentialTemplate = getArgValue(argv, '--credential-template');\n if (credentialTemplate !== undefined) {\n const template = await resolveCredentialTemplate(credentialTemplate, apiUrl, token);\n body.credentialTemplateId = template.id;\n body.credentialTemplateName = template.name;\n }\n\n const judgeModel = getArgValue(argv, '--judge-model');\n if (judgeModel !== undefined) body.judgeModelId = judgeModel;\n\n const configSource = getArgValue(argv, '--config');\n if (configSource !== undefined) body.configJson = await readConfig(configSource);\n\n const invariants = parseInvariants(argv);\n if (invariants.length > 0) body.globalInvariants = invariants;\n\n return body;\n}\n\nasync function handleCreate(argv: string[], apiUrl: string, token: string): Promise<void> {\n const json = hasFlag(argv, '--json');\n const body = await buildWriteBody(argv, apiUrl, token);\n\n if (!body.name || !body.configJson) {\n console.error('Error: --name and --config are required.');\n console.error(\n 'Usage: canary chat-target create --name <name> --config <file|-> [--application <name|id>] [options]'\n );\n process.exit(1);\n }\n\n const res = await apiRequest<OneResponse>(apiUrl, token, 'POST', '/chat-targets', body);\n if (!res.ok || !res.data) {\n console.error(`Error: ${res.error ?? 'Failed to create chat target'}`);\n process.exit(1);\n }\n if (json) {\n writeRawOutput(JSON.stringify(res.data, null, 2));\n return;\n }\n console.log(`✓ Created chat target \"${res.data.name}\" (${res.data.id})`);\n console.log(` Transport: ${transportOf(res.data)}`);\n console.log(` Invariants: ${res.data.globalInvariants?.length ?? 0}`);\n console.log('');\n console.log('Next:');\n console.log(\n ` canary chat-target chat ${res.data.id} --message \"What can you help me with?\"`\n );\n}\n\nasync function handleUpdate(argv: string[], apiUrl: string, token: string): Promise<void> {\n const arg = getPositionalArg(argv, CHAT_TARGET_FLAGS);\n if (!arg) {\n console.error('Usage: canary chat-target update <id|name> [options]');\n process.exit(1);\n }\n const target = await resolveTarget(arg, argv, apiUrl, token);\n const body = await buildWriteBody(argv, apiUrl, token);\n\n if (Object.keys(body).length === 0) {\n console.error(\n 'Error: No fields to update. Provide at least one of: --name, --config, --application, ' +\n '--environment, --credential, --credential-template, --invariant, --judge-model'\n );\n process.exit(1);\n }\n\n const res = await apiRequest<OneResponse>(\n apiUrl,\n token,\n 'PATCH',\n `/chat-targets/${target.id}`,\n body\n );\n if (!res.ok || !res.data) {\n console.error(`Error: ${res.error ?? 'Failed to update chat target'}`);\n process.exit(1);\n }\n if (hasFlag(argv, '--json')) {\n writeRawOutput(JSON.stringify(res.data, null, 2));\n return;\n }\n console.log(`✓ Updated chat target \"${res.data.name}\" (${res.data.id})`);\n}\n\nasync function handleDelete(argv: string[], apiUrl: string, token: string): Promise<void> {\n const arg = getPositionalArg(argv, CHAT_TARGET_FLAGS);\n if (!arg) {\n console.error('Usage: canary chat-target delete <id|name> [--yes]');\n process.exit(1);\n }\n const target = await resolveTarget(arg, argv, apiUrl, token);\n\n if (!hasFlag(argv, '--yes')) {\n console.error(`Refusing to archive \"${target.name}\" (${target.id}) without --yes.`);\n console.error('Evals pointing at this target will fail to run once it is archived.');\n process.exit(1);\n }\n\n const res = await apiRequest<OkResponse>(\n apiUrl,\n token,\n 'DELETE',\n `/chat-targets/${target.id}`\n );\n if (!res.ok) {\n console.error(`Error: ${res.error ?? 'Failed to archive chat target'}`);\n process.exit(1);\n }\n console.log(`✓ Archived chat target \"${target.name}\" (${target.id})`);\n}\n\nasync function handleChat(argv: string[], apiUrl: string, token: string): Promise<void> {\n const arg = getPositionalArg(argv, CHAT_TARGET_FLAGS);\n const message = getArgValue(argv, '--message');\n if (!arg || !message) {\n console.error('Usage: canary chat-target chat <id|name> --message <text> [--json]');\n process.exit(1);\n }\n const target = await resolveTarget(arg, argv, apiUrl, token);\n\n // Derive the client budget from the target's own, rather than a flat\n // constant: `timeoutSeconds` has no upper bound, so a fixed ceiling would cut\n // off a legitimately slow target and report a client timeout as a target\n // failure. The extra 60s covers resolving an authenticated session\n // server-side, which routinely takes 10-30s on a credentialed target.\n const configured = target.configJson?.timeoutSeconds;\n const targetSeconds = typeof configured === 'number' && configured > 0 ? configured : 120;\n const res = await apiRequest<ChatResponse>(\n apiUrl,\n token,\n 'POST',\n `/chat-targets/${target.id}/chat`,\n { message },\n { timeoutMs: (targetSeconds + 60) * 1000 }\n );\n\n if (!res.ok || !res.data) {\n console.error(`Error: ${res.error ?? 'Failed to send message'}`);\n process.exit(1);\n }\n\n if (hasFlag(argv, '--json')) {\n writeRawOutput(JSON.stringify(res.data, null, 2));\n }\n\n // The turn's own outcome rides inside a 200 envelope. Exiting 0 here would\n // report a target that never answered as working.\n if (!res.data.ok) {\n if (!hasFlag(argv, '--json')) {\n console.error(`Turn failed: ${res.data.error}`);\n }\n process.exit(1);\n }\n\n if (!hasFlag(argv, '--json')) {\n console.log(`> ${res.data.sentMessage}`);\n console.log('');\n console.log(res.data.parsedText);\n }\n}\n\nexport async function runChatTarget(argv: string[]): Promise<void> {\n const [subCommand, ...rest] = argv;\n\n if (!subCommand || subCommand === 'help' || hasFlag(argv, '--help', '-h')) {\n printChatTargetHelp();\n return;\n }\n\n const { apiUrl, token } = await resolveConfig(argv);\n\n switch (subCommand) {\n case 'list':\n await handleList(rest, apiUrl, token);\n return;\n case 'get':\n await handleGet(rest, apiUrl, token);\n return;\n case 'create':\n await handleCreate(rest, apiUrl, token);\n return;\n case 'update':\n await handleUpdate(rest, apiUrl, token);\n return;\n case 'delete':\n await handleDelete(rest, apiUrl, token);\n return;\n case 'chat':\n await handleChat(rest, apiUrl, token);\n return;\n default:\n console.error(`Unknown chat-target sub-command: ${subCommand}`);\n printChatTargetHelp();\n process.exit(1);\n }\n}\n"],"mappings":"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","names":[]}
|