@rulemetric/cli 0.7.3 → 0.7.4
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/base-command.js +1 -14
- package/dist/chunk-2TC6WCUT.js +34 -0
- package/dist/chunk-2UC3ULIG.js +1 -0
- package/dist/chunk-3AV3GTMP.js +1 -0
- package/dist/chunk-4Z5ECCJE.js +1 -0
- package/dist/chunk-5RBLIVBF.js +1 -0
- package/dist/chunk-67QCYUJU.js +1 -0
- package/dist/chunk-6QKI756T.js +2 -0
- package/dist/chunk-6V4WM73L.js +1 -0
- package/dist/chunk-6XEC6474.js +1 -0
- package/dist/chunk-72XLQE3X.js +2 -0
- package/dist/chunk-7DFNBRLY.js +61 -0
- package/dist/chunk-7XQ4VPLC.js +2 -0
- package/dist/chunk-AHRHCERJ.js +1 -0
- package/dist/chunk-ARNZQBMX.js +1 -0
- package/dist/chunk-CADKBP3D.js +58 -0
- package/dist/chunk-CDI5CCHU.js +1 -0
- package/dist/chunk-CNQ5DTNC.js +1 -0
- package/dist/chunk-CRAKDQ4H.js +1 -0
- package/dist/chunk-DNF4HDI6.js +14 -0
- package/dist/chunk-DSO2U4Y6.js +56 -0
- package/dist/chunk-DT4GKEP5.js +5 -0
- package/dist/chunk-DVN7GFJG.js +1 -0
- package/dist/chunk-E4SFUPYR.js +15 -0
- package/dist/chunk-EUHNCVJQ.js +33 -0
- package/dist/chunk-F2VP4B4J.js +1 -0
- package/dist/chunk-FEHM5OKW.js +1 -0
- package/dist/chunk-FHVBTDBM.js +69 -0
- package/dist/chunk-GBMF3TP6.js +1 -0
- package/dist/chunk-GY5IJ4RS.js +1 -0
- package/dist/chunk-HOHD5HY2.js +5 -0
- package/dist/chunk-HP2BUPGS.js +24 -0
- package/dist/{chunk-OQBBVTDG.js → chunk-I2DZGJRR.js} +6 -71
- package/dist/chunk-I4YJ7NTX.js +1 -0
- package/dist/chunk-IY5NXR3N.js +1 -0
- package/dist/chunk-IZTIYR5Q.js +2 -0
- package/dist/chunk-KKDHD4XA.js +2 -0
- package/dist/chunk-LQRYQE6Q.js +4 -0
- package/dist/chunk-M6AJDVCL.js +5 -0
- package/dist/chunk-MGHFDHHM.js +1 -0
- package/dist/chunk-ML36XQW7.js +1 -0
- package/dist/chunk-MODXEGCU.js +1 -0
- package/dist/chunk-MVM6OGAF.js +4 -0
- package/dist/chunk-N7ODX6PO.js +1 -0
- package/dist/chunk-NBTC5FNV.js +1 -0
- package/dist/chunk-NJ5UED3H.js +1 -0
- package/dist/chunk-NVKX36YN.js +3 -0
- package/dist/chunk-NVOTOQBA.js +1 -0
- package/dist/chunk-O7ZMHCMG.js +31 -0
- package/dist/chunk-OMXUK4M6.js +1 -0
- package/dist/chunk-PZS2KOU7.js +1 -0
- package/dist/chunk-RSKQRVPJ.js +1 -0
- package/dist/chunk-RTEATXTP.js +1 -0
- package/dist/chunk-RTWRHIKY.js +7 -0
- package/dist/chunk-RVO4HV3M.js +1 -0
- package/dist/chunk-SBILN45P.js +1 -0
- package/dist/chunk-SZ62CP55.js +1 -0
- package/dist/chunk-T3W5N3BP.js +2 -0
- package/dist/chunk-TDD7IOV2.js +1 -0
- package/dist/chunk-TIQ7DQ3M.js +1 -0
- package/dist/chunk-TU2AR6XO.js +1 -0
- package/dist/chunk-UF6US7VU.js +1 -0
- package/dist/chunk-V5QFOF4F.js +9 -0
- package/dist/chunk-V5U3E4BZ.js +1 -0
- package/dist/chunk-VAFAH6QL.js +1 -0
- package/dist/chunk-VMWY7KHH.js +1 -0
- package/dist/chunk-VUGRXM7R.js +1 -0
- package/dist/{chunk-XZXS2W24.js → chunk-VWEXKDWG.js} +10 -56
- package/dist/chunk-W2MV25SB.js +1 -0
- package/dist/chunk-WJ3H73G6.js +1 -0
- package/dist/chunk-WJUQBMTF.js +9 -0
- package/dist/chunk-WLVQJH4E.js +1 -0
- package/dist/chunk-WPJ2BND4.js +1 -0
- package/dist/chunk-WSCK4WNK.js +1 -0
- package/dist/chunk-Y65CSJFF.js +3 -0
- package/dist/chunk-ZL4MZMUK.js +34 -0
- package/dist/chunk-ZLLER3HP.js +1 -0
- package/dist/chunk-ZXF5NE54.js +1 -0
- package/dist/commands/antigravity/backfill.js +2 -136
- package/dist/commands/auth/create-key.js +1 -52
- package/dist/commands/auth/login.js +1 -85
- package/dist/commands/auth/logout.js +1 -29
- package/dist/commands/auth/revoke-key.js +1 -33
- package/dist/commands/auth/signup.js +1 -89
- package/dist/commands/auth/status.js +1 -42
- package/dist/commands/catalog/index.js +2 -52
- package/dist/commands/catalog/recommend.js +3 -43
- package/dist/commands/convert.js +1 -75
- package/dist/commands/converters.js +1 -54
- package/dist/commands/crons/list.js +1 -41
- package/dist/commands/crons/run.js +2 -76
- package/dist/commands/dashboard.js +1 -46
- package/dist/commands/diagnostics.js +1 -117
- package/dist/commands/eval-targets/create.js +1 -53
- package/dist/commands/eval-targets/list.js +1 -54
- package/dist/commands/evals/agent.js +3 -310
- package/dist/commands/evals/benchmark.js +6 -73
- package/dist/commands/evals/compare.js +13 -96
- package/dist/commands/evals/create.js +1 -67
- package/dist/commands/evals/optimize-description.js +25 -239
- package/dist/commands/evals/optimize.js +5 -211
- package/dist/commands/evals/run.js +3 -183
- package/dist/commands/gateway/ensure.js +1 -104
- package/dist/commands/hooks/emit-instructions.js +1 -25
- package/dist/commands/hooks/install.js +1 -442
- package/dist/commands/hooks/run.js +3 -81
- package/dist/commands/hooks/uninstall.js +2 -156
- package/dist/commands/import.js +1 -66
- package/dist/commands/instructions/create.js +1 -74
- package/dist/commands/instructions/delete.js +1 -55
- package/dist/commands/instructions/fork.js +1 -34
- package/dist/commands/instructions/get.js +1 -68
- package/dist/commands/instructions/list.js +1 -65
- package/dist/commands/instructions/promote.js +1 -42
- package/dist/commands/instructions/pull.js +1 -39
- package/dist/commands/instructions/upstream.js +1 -38
- package/dist/commands/instructions/versions.js +1 -53
- package/dist/commands/launcher.js +1 -40
- package/dist/commands/org/current.js +1 -77
- package/dist/commands/org/list.js +1 -52
- package/dist/commands/org/switch.js +1 -71
- package/dist/commands/packs/add-instruction.js +1 -37
- package/dist/commands/packs/apply.js +1 -39
- package/dist/commands/packs/create.js +1 -50
- package/dist/commands/packs/fork.js +1 -34
- package/dist/commands/packs/get.js +3 -56
- package/dist/commands/packs/list.js +1 -66
- package/dist/commands/packs/remove-instruction.js +1 -35
- package/dist/commands/proxy/env.js +3 -131
- package/dist/commands/proxy/logs.js +3 -85
- package/dist/commands/proxy/restart.js +1 -35
- package/dist/commands/proxy/setup.js +15 -454
- package/dist/commands/proxy/start.js +10 -333
- package/dist/commands/proxy/status.js +1 -78
- package/dist/commands/proxy/stop.js +1 -94
- package/dist/commands/research/backfill.js +1 -59
- package/dist/commands/research/tail-transcript.js +1 -70
- package/dist/commands/service/install.js +57 -796
- package/dist/commands/service/status.js +1 -180
- package/dist/commands/service/uninstall.js +1 -119
- package/dist/commands/sessions/analyze.js +3 -48
- package/dist/commands/sessions/end.js +2 -85
- package/dist/commands/sessions/import.js +1 -46
- package/dist/commands/sessions/list.js +1 -48
- package/dist/commands/sessions/start.js +3 -90
- package/dist/commands/setup.js +3 -150
- package/dist/commands/skills/export-approved.js +1 -46
- package/dist/commands/skills/install.js +4 -107
- package/dist/commands/skills/list.js +4 -65
- package/dist/commands/skills/publish.js +2 -98
- package/dist/commands/skills/search.js +3 -72
- package/dist/commands/skills/update.js +3 -55
- package/dist/commands/suggestions/accept.js +8 -84
- package/dist/commands/suggestions/dismiss.js +1 -45
- package/dist/commands/suggestions/list.js +1 -61
- package/dist/commands/suggestions/refresh.js +1 -27
- package/dist/cursor-T7AMCMKS.js +13 -0
- package/dist/dashboard/Dashboard.js +1 -243
- package/dist/dashboard/data.js +1 -15
- package/dist/dashboard/launcher/ActiveJobsList.js +1 -10
- package/dist/dashboard/launcher/LauncherOverlay.js +1 -16
- package/dist/dashboard/launcher/NewLaunchForm.js +1 -10
- package/dist/dashboard/launcher/api.js +1 -16
- package/dist/dashboard/launcher/tool-labels.js +1 -10
- package/dist/dashboard/launcher/types.js +0 -1
- package/dist/dashboard/launcher/useLaunchJobs.js +1 -11
- package/dist/dashboard/panels/friction.js +1 -10
- package/dist/dashboard/panels/insights.js +1 -10
- package/dist/dashboard/panels/instructions.js +1 -10
- package/dist/dashboard/panels/outcomes.js +1 -10
- package/dist/dashboard/panels/overview.js +1 -10
- package/dist/dashboard/panels/shared.js +1 -19
- package/dist/dashboard/types.js +1 -24
- package/dist/dist-FAVALJ5C.js +1 -0
- package/dist/index.js +1 -8
- package/dist/lib/active-org-refresh.js +1 -15
- package/dist/lib/active-org.js +1 -16
- package/dist/lib/agent-loop.js +1 -47
- package/dist/lib/antigravity-transcript.js +1 -22
- package/dist/lib/api-client.js +1 -23
- package/dist/lib/auth.js +1 -30
- package/dist/lib/capture-hosts.js +1 -8
- package/dist/lib/detect-languages.js +1 -8
- package/dist/lib/detect-tmux.js +1 -9
- package/dist/lib/diagnostics.js +1 -12
- package/dist/lib/editor-proxy-pins.js +1 -14
- package/dist/lib/ensure-api-key.js +1 -11
- package/dist/lib/eval-analyzer.js +1 -9
- package/dist/lib/eval-benchmark.js +1 -12
- package/dist/lib/eval-conversation-handler.js +1 -13
- package/dist/lib/eval-executor.js +1 -8
- package/dist/lib/eval-grader.js +1 -9
- package/dist/lib/eval-meta-judge.js +1 -9
- package/dist/lib/eval-trigger-tester.js +1 -11
- package/dist/lib/eval-worktree.js +1 -8
- package/dist/lib/gateway-entry.js +1 -61
- package/dist/lib/gateway-identity.js +1 -16
- package/dist/lib/gateway-lifecycle.js +1 -32
- package/dist/lib/gateway.js +1 -14
- package/dist/lib/handlers/cron-refresh-pricing.js +1 -0
- package/dist/lib/handlers/cron-refresh-skills.js +1 -8
- package/dist/lib/handlers/cron-suggest-instructions.js +1 -16
- package/dist/lib/handlers/process-announcement.js +1 -11
- package/dist/lib/handlers/process-changelog.js +1 -11
- package/dist/lib/handlers/process-conversation.js +1 -14
- package/dist/lib/handlers/process-eval.js +1 -15
- package/dist/lib/handlers/process-insights.js +1 -15
- package/dist/lib/handlers/process-launch.js +1 -16
- package/dist/lib/handlers/process-run-cleanup.js +1 -13
- package/dist/lib/handlers/process-send-message.js +1 -10
- package/dist/lib/handlers/process-session-goal.js +1 -12
- package/dist/lib/hooks-config.js +1 -81
- package/dist/lib/insights-prompts.js +1 -12
- package/dist/lib/instruction-snapshot.js +1 -8
- package/dist/lib/job-helpers.js +0 -1
- package/dist/lib/llm-client.js +1 -20
- package/dist/lib/manual-tasks-meta.js +1 -8
- package/dist/lib/manual-tasks.js +1 -80
- package/dist/lib/output.js +1 -12
- package/dist/lib/permanent-job-error.js +1 -10
- package/dist/lib/pid-identity.js +1 -14
- package/dist/lib/proxy-respawn.js +1 -12
- package/dist/lib/research-client.js +1 -12
- package/dist/lib/setup-steps.js +1 -33
- package/dist/lib/skills-loader.js +1 -8
- package/dist/lib/statusline-shim.js +1 -20
- package/dist/lib/telemetry.js +1 -16
- package/dist/lib/terminal-target-heartbeat.js +1 -15
- package/dist/lib/tmux.js +1 -16
- package/dist/lib/transcript-rate-limit-watcher.js +1 -22
- package/dist/lib/types.js +1 -8
- package/dist/lib/version-check.js +1 -12
- package/dist/lib/which.js +1 -8
- package/dist/lib/worktree.js +1 -17
- package/dist/opencode-QRJ3BH23.js +1 -0
- package/oclif.manifest.json +135 -135
- package/package.json +9 -8
- package/dist/base-command.js.map +0 -7
- package/dist/chunk-2HK7RGZB.js +0 -82
- package/dist/chunk-2HK7RGZB.js.map +0 -7
- package/dist/chunk-2ORJWTNZ.js +0 -307
- package/dist/chunk-2ORJWTNZ.js.map +0 -7
- package/dist/chunk-37LN5O7M.js +0 -59
- package/dist/chunk-37LN5O7M.js.map +0 -7
- package/dist/chunk-3S7223UR.js +0 -81
- package/dist/chunk-3S7223UR.js.map +0 -7
- package/dist/chunk-3TIMQ3O6.js +0 -96
- package/dist/chunk-3TIMQ3O6.js.map +0 -7
- package/dist/chunk-42GFSAJP.js +0 -32
- package/dist/chunk-42GFSAJP.js.map +0 -7
- package/dist/chunk-4BHDHHKL.js +0 -48
- package/dist/chunk-4BHDHHKL.js.map +0 -7
- package/dist/chunk-4D537GXE.js +0 -99
- package/dist/chunk-4D537GXE.js.map +0 -7
- package/dist/chunk-4LYCDS2N.js +0 -139
- package/dist/chunk-4LYCDS2N.js.map +0 -7
- package/dist/chunk-4SCZK7AL.js +0 -129
- package/dist/chunk-4SCZK7AL.js.map +0 -7
- package/dist/chunk-4XAWK6S2.js +0 -161
- package/dist/chunk-4XAWK6S2.js.map +0 -7
- package/dist/chunk-52WIYRZH.js +0 -73
- package/dist/chunk-52WIYRZH.js.map +0 -7
- package/dist/chunk-5BAOGNUH.js +0 -79
- package/dist/chunk-5BAOGNUH.js.map +0 -7
- package/dist/chunk-5EDMGK3W.js +0 -39
- package/dist/chunk-5EDMGK3W.js.map +0 -7
- package/dist/chunk-6NBS5XFS.js +0 -99
- package/dist/chunk-6NBS5XFS.js.map +0 -7
- package/dist/chunk-7LVVKQMZ.js +0 -98
- package/dist/chunk-7LVVKQMZ.js.map +0 -7
- package/dist/chunk-7NNFYWKK.js +0 -243
- package/dist/chunk-7NNFYWKK.js.map +0 -7
- package/dist/chunk-7NYKWN7U.js +0 -12
- package/dist/chunk-7NYKWN7U.js.map +0 -7
- package/dist/chunk-BO76WKJR.js +0 -42
- package/dist/chunk-BO76WKJR.js.map +0 -7
- package/dist/chunk-BRD5RUGM.js +0 -53
- package/dist/chunk-BRD5RUGM.js.map +0 -7
- package/dist/chunk-BT6Z6545.js +0 -43
- package/dist/chunk-BT6Z6545.js.map +0 -7
- package/dist/chunk-BZDKEQKU.js +0 -39
- package/dist/chunk-BZDKEQKU.js.map +0 -7
- package/dist/chunk-DGHWRQXL.js +0 -17
- package/dist/chunk-DGHWRQXL.js.map +0 -7
- package/dist/chunk-DIQUV5FR.js +0 -257
- package/dist/chunk-DIQUV5FR.js.map +0 -7
- package/dist/chunk-DMX5YOTM.js +0 -167
- package/dist/chunk-DMX5YOTM.js.map +0 -7
- package/dist/chunk-DNKSVWMD.js +0 -108
- package/dist/chunk-DNKSVWMD.js.map +0 -7
- package/dist/chunk-DQ3KELXD.js +0 -74
- package/dist/chunk-DQ3KELXD.js.map +0 -7
- package/dist/chunk-DUJSRBLP.js +0 -122
- package/dist/chunk-DUJSRBLP.js.map +0 -7
- package/dist/chunk-E3BIT53W.js +0 -154
- package/dist/chunk-E3BIT53W.js.map +0 -7
- package/dist/chunk-EARWG4EV.js +0 -22
- package/dist/chunk-EARWG4EV.js.map +0 -7
- package/dist/chunk-EI5BHWXA.js +0 -1662
- package/dist/chunk-EI5BHWXA.js.map +0 -7
- package/dist/chunk-EJ3YAFDP.js +0 -37
- package/dist/chunk-EJ3YAFDP.js.map +0 -7
- package/dist/chunk-EKJ2CABV.js +0 -76
- package/dist/chunk-EKJ2CABV.js.map +0 -7
- package/dist/chunk-EKP32DLN.js +0 -16
- package/dist/chunk-EKP32DLN.js.map +0 -7
- package/dist/chunk-EYPAAGN5.js +0 -51
- package/dist/chunk-EYPAAGN5.js.map +0 -7
- package/dist/chunk-F5N6CLJJ.js +0 -1995
- package/dist/chunk-F5N6CLJJ.js.map +0 -7
- package/dist/chunk-GIUBARWS.js +0 -99
- package/dist/chunk-GIUBARWS.js.map +0 -7
- package/dist/chunk-GQNJO2P2.js +0 -102
- package/dist/chunk-GQNJO2P2.js.map +0 -7
- package/dist/chunk-IJGF2ETG.js +0 -68
- package/dist/chunk-IJGF2ETG.js.map +0 -7
- package/dist/chunk-ILYDELUE.js +0 -46
- package/dist/chunk-ILYDELUE.js.map +0 -7
- package/dist/chunk-J6QFW4LD.js +0 -55
- package/dist/chunk-J6QFW4LD.js.map +0 -7
- package/dist/chunk-J7N3DLH6.js +0 -117
- package/dist/chunk-J7N3DLH6.js.map +0 -7
- package/dist/chunk-JFDWKLQC.js +0 -23
- package/dist/chunk-JFDWKLQC.js.map +0 -7
- package/dist/chunk-JULOLTZS.js +0 -61
- package/dist/chunk-JULOLTZS.js.map +0 -7
- package/dist/chunk-KJKBDQ4D.js +0 -220
- package/dist/chunk-KJKBDQ4D.js.map +0 -7
- package/dist/chunk-KRBQLMOP.js +0 -41
- package/dist/chunk-KRBQLMOP.js.map +0 -7
- package/dist/chunk-LXKPNATC.js +0 -624
- package/dist/chunk-LXKPNATC.js.map +0 -7
- package/dist/chunk-NSBPE2FW.js +0 -17
- package/dist/chunk-NSBPE2FW.js.map +0 -7
- package/dist/chunk-OCKHW72U.js +0 -55
- package/dist/chunk-OCKHW72U.js.map +0 -7
- package/dist/chunk-OKWCKCPE.js +0 -414
- package/dist/chunk-OKWCKCPE.js.map +0 -7
- package/dist/chunk-OO7JDFS4.js +0 -157
- package/dist/chunk-OO7JDFS4.js.map +0 -7
- package/dist/chunk-OQBBVTDG.js.map +0 -7
- package/dist/chunk-OQSQC7VB.js +0 -77
- package/dist/chunk-OQSQC7VB.js.map +0 -7
- package/dist/chunk-PED7L5GX.js +0 -92
- package/dist/chunk-PED7L5GX.js.map +0 -7
- package/dist/chunk-QJQS6TUN.js +0 -44
- package/dist/chunk-QJQS6TUN.js.map +0 -7
- package/dist/chunk-QN34TGD3.js +0 -83
- package/dist/chunk-QN34TGD3.js.map +0 -7
- package/dist/chunk-QSN77T7C.js +0 -250
- package/dist/chunk-QSN77T7C.js.map +0 -7
- package/dist/chunk-R56PH7YE.js +0 -78
- package/dist/chunk-R56PH7YE.js.map +0 -7
- package/dist/chunk-RAXRZYOB.js +0 -299
- package/dist/chunk-RAXRZYOB.js.map +0 -7
- package/dist/chunk-RH7NHVSK.js +0 -16
- package/dist/chunk-RH7NHVSK.js.map +0 -7
- package/dist/chunk-RMTT4KDY.js +0 -191
- package/dist/chunk-RMTT4KDY.js.map +0 -7
- package/dist/chunk-RQ2TMLKG.js +0 -142
- package/dist/chunk-RQ2TMLKG.js.map +0 -7
- package/dist/chunk-SO3T35U7.js +0 -80
- package/dist/chunk-SO3T35U7.js.map +0 -7
- package/dist/chunk-UKMLICWS.js +0 -51
- package/dist/chunk-UKMLICWS.js.map +0 -7
- package/dist/chunk-VA5FFOS7.js +0 -243
- package/dist/chunk-VA5FFOS7.js.map +0 -7
- package/dist/chunk-W2YERO7E.js +0 -170
- package/dist/chunk-W2YERO7E.js.map +0 -7
- package/dist/chunk-W53GKIZQ.js +0 -50
- package/dist/chunk-W53GKIZQ.js.map +0 -7
- package/dist/chunk-WA4MWYRW.js +0 -254
- package/dist/chunk-WA4MWYRW.js.map +0 -7
- package/dist/chunk-XC6M4CSW.js +0 -44
- package/dist/chunk-XC6M4CSW.js.map +0 -7
- package/dist/chunk-XK42ZBDE.js +0 -23
- package/dist/chunk-XK42ZBDE.js.map +0 -7
- package/dist/chunk-XUV6DDBF.js +0 -124
- package/dist/chunk-XUV6DDBF.js.map +0 -7
- package/dist/chunk-XZXS2W24.js.map +0 -7
- package/dist/chunk-Y3WD5CSW.js +0 -49
- package/dist/chunk-Y3WD5CSW.js.map +0 -7
- package/dist/chunk-Y4BJXXYV.js +0 -148
- package/dist/chunk-Y4BJXXYV.js.map +0 -7
- package/dist/chunk-YNIH3KMU.js +0 -121
- package/dist/chunk-YNIH3KMU.js.map +0 -7
- package/dist/chunk-ZUJBM6HE.js +0 -125
- package/dist/chunk-ZUJBM6HE.js.map +0 -7
- package/dist/commands/antigravity/backfill.js.map +0 -7
- package/dist/commands/auth/create-key.js.map +0 -7
- package/dist/commands/auth/login.js.map +0 -7
- package/dist/commands/auth/logout.js.map +0 -7
- package/dist/commands/auth/revoke-key.js.map +0 -7
- package/dist/commands/auth/signup.js.map +0 -7
- package/dist/commands/auth/status.js.map +0 -7
- package/dist/commands/catalog/index.js.map +0 -7
- package/dist/commands/catalog/recommend.js.map +0 -7
- package/dist/commands/convert.js.map +0 -7
- package/dist/commands/converters.js.map +0 -7
- package/dist/commands/crons/list.js.map +0 -7
- package/dist/commands/crons/run.js.map +0 -7
- package/dist/commands/dashboard.js.map +0 -7
- package/dist/commands/diagnostics.js.map +0 -7
- package/dist/commands/eval-targets/create.js.map +0 -7
- package/dist/commands/eval-targets/list.js.map +0 -7
- package/dist/commands/evals/agent.js.map +0 -7
- package/dist/commands/evals/benchmark.js.map +0 -7
- package/dist/commands/evals/compare.js.map +0 -7
- package/dist/commands/evals/create.js.map +0 -7
- package/dist/commands/evals/optimize-description.js.map +0 -7
- package/dist/commands/evals/optimize.js.map +0 -7
- package/dist/commands/evals/run.js.map +0 -7
- package/dist/commands/gateway/ensure.js.map +0 -7
- package/dist/commands/hooks/emit-instructions.js.map +0 -7
- package/dist/commands/hooks/install.js.map +0 -7
- package/dist/commands/hooks/run.js.map +0 -7
- package/dist/commands/hooks/uninstall.js.map +0 -7
- package/dist/commands/import.js.map +0 -7
- package/dist/commands/instructions/create.js.map +0 -7
- package/dist/commands/instructions/delete.js.map +0 -7
- package/dist/commands/instructions/fork.js.map +0 -7
- package/dist/commands/instructions/get.js.map +0 -7
- package/dist/commands/instructions/list.js.map +0 -7
- package/dist/commands/instructions/promote.js.map +0 -7
- package/dist/commands/instructions/pull.js.map +0 -7
- package/dist/commands/instructions/upstream.js.map +0 -7
- package/dist/commands/instructions/versions.js.map +0 -7
- package/dist/commands/launcher.js.map +0 -7
- package/dist/commands/org/current.js.map +0 -7
- package/dist/commands/org/list.js.map +0 -7
- package/dist/commands/org/switch.js.map +0 -7
- package/dist/commands/packs/add-instruction.js.map +0 -7
- package/dist/commands/packs/apply.js.map +0 -7
- package/dist/commands/packs/create.js.map +0 -7
- package/dist/commands/packs/fork.js.map +0 -7
- package/dist/commands/packs/get.js.map +0 -7
- package/dist/commands/packs/list.js.map +0 -7
- package/dist/commands/packs/remove-instruction.js.map +0 -7
- package/dist/commands/proxy/env.js.map +0 -7
- package/dist/commands/proxy/logs.js.map +0 -7
- package/dist/commands/proxy/restart.js.map +0 -7
- package/dist/commands/proxy/setup.js.map +0 -7
- package/dist/commands/proxy/start.js.map +0 -7
- package/dist/commands/proxy/status.js.map +0 -7
- package/dist/commands/proxy/stop.js.map +0 -7
- package/dist/commands/research/backfill.js.map +0 -7
- package/dist/commands/research/tail-transcript.js.map +0 -7
- package/dist/commands/service/install.js.map +0 -7
- package/dist/commands/service/status.js.map +0 -7
- package/dist/commands/service/uninstall.js.map +0 -7
- package/dist/commands/sessions/analyze.js.map +0 -7
- package/dist/commands/sessions/end.js.map +0 -7
- package/dist/commands/sessions/import.js.map +0 -7
- package/dist/commands/sessions/list.js.map +0 -7
- package/dist/commands/sessions/start.js.map +0 -7
- package/dist/commands/setup.js.map +0 -7
- package/dist/commands/skills/export-approved.js.map +0 -7
- package/dist/commands/skills/install.js.map +0 -7
- package/dist/commands/skills/list.js.map +0 -7
- package/dist/commands/skills/publish.js.map +0 -7
- package/dist/commands/skills/search.js.map +0 -7
- package/dist/commands/skills/update.js.map +0 -7
- package/dist/commands/suggestions/accept.js.map +0 -7
- package/dist/commands/suggestions/dismiss.js.map +0 -7
- package/dist/commands/suggestions/list.js.map +0 -7
- package/dist/commands/suggestions/refresh.js.map +0 -7
- package/dist/cursor-BGQJ4CWI.js +0 -134
- package/dist/cursor-BGQJ4CWI.js.map +0 -7
- package/dist/dashboard/Dashboard.js.map +0 -7
- package/dist/dashboard/data.js.map +0 -7
- package/dist/dashboard/launcher/ActiveJobsList.js.map +0 -7
- package/dist/dashboard/launcher/LauncherOverlay.js.map +0 -7
- package/dist/dashboard/launcher/NewLaunchForm.js.map +0 -7
- package/dist/dashboard/launcher/api.js.map +0 -7
- package/dist/dashboard/launcher/tool-labels.js.map +0 -7
- package/dist/dashboard/launcher/types.js.map +0 -7
- package/dist/dashboard/launcher/useLaunchJobs.js.map +0 -7
- package/dist/dashboard/panels/friction.js.map +0 -7
- package/dist/dashboard/panels/insights.js.map +0 -7
- package/dist/dashboard/panels/instructions.js.map +0 -7
- package/dist/dashboard/panels/outcomes.js.map +0 -7
- package/dist/dashboard/panels/overview.js.map +0 -7
- package/dist/dashboard/panels/shared.js.map +0 -7
- package/dist/dashboard/types.js.map +0 -7
- package/dist/dist-UNYP5PJR.js +0 -56
- package/dist/dist-UNYP5PJR.js.map +0 -7
- package/dist/index.js.map +0 -7
- package/dist/lib/active-org-refresh.js.map +0 -7
- package/dist/lib/active-org.js.map +0 -7
- package/dist/lib/agent-loop.js.map +0 -7
- package/dist/lib/antigravity-transcript.js.map +0 -7
- package/dist/lib/api-client.js.map +0 -7
- package/dist/lib/auth.js.map +0 -7
- package/dist/lib/capture-hosts.js.map +0 -7
- package/dist/lib/detect-languages.js.map +0 -7
- package/dist/lib/detect-tmux.js.map +0 -7
- package/dist/lib/diagnostics.js.map +0 -7
- package/dist/lib/editor-proxy-pins.js.map +0 -7
- package/dist/lib/ensure-api-key.js.map +0 -7
- package/dist/lib/eval-analyzer.js.map +0 -7
- package/dist/lib/eval-benchmark.js.map +0 -7
- package/dist/lib/eval-conversation-handler.js.map +0 -7
- package/dist/lib/eval-executor.js.map +0 -7
- package/dist/lib/eval-grader.js.map +0 -7
- package/dist/lib/eval-meta-judge.js.map +0 -7
- package/dist/lib/eval-trigger-tester.js.map +0 -7
- package/dist/lib/eval-worktree.js.map +0 -7
- package/dist/lib/gateway-entry.js.map +0 -7
- package/dist/lib/gateway-identity.js.map +0 -7
- package/dist/lib/gateway-lifecycle.js.map +0 -7
- package/dist/lib/gateway.js.map +0 -7
- package/dist/lib/handlers/cron-refresh-skills.js.map +0 -7
- package/dist/lib/handlers/cron-suggest-instructions.js.map +0 -7
- package/dist/lib/handlers/process-announcement.js.map +0 -7
- package/dist/lib/handlers/process-changelog.js.map +0 -7
- package/dist/lib/handlers/process-conversation.js.map +0 -7
- package/dist/lib/handlers/process-eval.js.map +0 -7
- package/dist/lib/handlers/process-insights.js.map +0 -7
- package/dist/lib/handlers/process-launch.js.map +0 -7
- package/dist/lib/handlers/process-run-cleanup.js.map +0 -7
- package/dist/lib/handlers/process-send-message.js.map +0 -7
- package/dist/lib/handlers/process-session-goal.js.map +0 -7
- package/dist/lib/hooks-config.js.map +0 -7
- package/dist/lib/insights-prompts.js.map +0 -7
- package/dist/lib/instruction-snapshot.js.map +0 -7
- package/dist/lib/job-helpers.js.map +0 -7
- package/dist/lib/llm-client.js.map +0 -7
- package/dist/lib/manual-tasks-meta.js.map +0 -7
- package/dist/lib/manual-tasks.js.map +0 -7
- package/dist/lib/output.js.map +0 -7
- package/dist/lib/permanent-job-error.js.map +0 -7
- package/dist/lib/pid-identity.js.map +0 -7
- package/dist/lib/proxy-respawn.js.map +0 -7
- package/dist/lib/research-client.js.map +0 -7
- package/dist/lib/setup-steps.js.map +0 -7
- package/dist/lib/skills-loader.js.map +0 -7
- package/dist/lib/statusline-shim.js.map +0 -7
- package/dist/lib/telemetry.js.map +0 -7
- package/dist/lib/terminal-target-heartbeat.js.map +0 -7
- package/dist/lib/tmux.js.map +0 -7
- package/dist/lib/transcript-rate-limit-watcher.js.map +0 -7
- package/dist/lib/types.js.map +0 -7
- package/dist/lib/version-check.js.map +0 -7
- package/dist/lib/which.js.map +0 -7
- package/dist/lib/worktree.js.map +0 -7
- package/dist/opencode-IQ7X5YMJ.js +0 -190
- package/dist/opencode-IQ7X5YMJ.js.map +0 -7
package/dist/chunk-ZUJBM6HE.js
DELETED
|
@@ -1,125 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
loadEnvFileAuth,
|
|
3
|
-
loadToken
|
|
4
|
-
} from "./chunk-W2YERO7E.js";
|
|
5
|
-
|
|
6
|
-
// src/lib/api-client.ts
|
|
7
|
-
import { fileURLToPath } from "node:url";
|
|
8
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
9
|
-
import { dirname, join } from "node:path";
|
|
10
|
-
function readCliVersion() {
|
|
11
|
-
let dir = dirname(fileURLToPath(import.meta.url));
|
|
12
|
-
for (let i = 0; i < 8; i++) {
|
|
13
|
-
const pj = join(dir, "package.json");
|
|
14
|
-
if (existsSync(pj)) {
|
|
15
|
-
try {
|
|
16
|
-
const parsed = JSON.parse(readFileSync(pj, "utf8"));
|
|
17
|
-
if (parsed.name === "@rulemetric/cli" && parsed.version) return parsed.version;
|
|
18
|
-
} catch {
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
const parent = dirname(dir);
|
|
22
|
-
if (parent === dir) break;
|
|
23
|
-
dir = parent;
|
|
24
|
-
}
|
|
25
|
-
return "0.0.0";
|
|
26
|
-
}
|
|
27
|
-
var version = readCliVersion();
|
|
28
|
-
var DEFAULT_API_URL = "https://rulemetric.com";
|
|
29
|
-
var ApiError = class extends Error {
|
|
30
|
-
constructor(statusCode, message) {
|
|
31
|
-
super(message);
|
|
32
|
-
this.statusCode = statusCode;
|
|
33
|
-
this.name = "ApiError";
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
function getBaseUrl() {
|
|
37
|
-
const url = process.env.RULEMETRIC_API_URL ?? loadEnvFileAuth().apiUrl ?? DEFAULT_API_URL;
|
|
38
|
-
const parsed = new URL(url);
|
|
39
|
-
if (parsed.protocol === "http:" && parsed.hostname !== "localhost" && parsed.hostname !== "127.0.0.1") {
|
|
40
|
-
throw new Error(`API URL must use HTTPS for non-localhost hosts: ${url}`);
|
|
41
|
-
}
|
|
42
|
-
return url;
|
|
43
|
-
}
|
|
44
|
-
async function api(path, options = {}) {
|
|
45
|
-
const baseUrl = getBaseUrl();
|
|
46
|
-
const url = `${baseUrl}${path}`;
|
|
47
|
-
const headers = {
|
|
48
|
-
"Content-Type": "application/json",
|
|
49
|
-
"User-Agent": `rulemetric-cli/${version}`,
|
|
50
|
-
...options.headers
|
|
51
|
-
};
|
|
52
|
-
const envAuth = loadEnvFileAuth();
|
|
53
|
-
const bearer = process.env.RULEMETRIC_API_KEY || envAuth.apiKey || loadToken()?.accessToken || envAuth.accessToken;
|
|
54
|
-
if (bearer) {
|
|
55
|
-
headers["Authorization"] = `Bearer ${bearer}`;
|
|
56
|
-
}
|
|
57
|
-
const parsed = new URL(url);
|
|
58
|
-
const isLocalhost = parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1";
|
|
59
|
-
const savedProxy = process.env.HTTPS_PROXY;
|
|
60
|
-
const savedHttpProxy = process.env.HTTP_PROXY;
|
|
61
|
-
if (isLocalhost) {
|
|
62
|
-
delete process.env.HTTPS_PROXY;
|
|
63
|
-
delete process.env.HTTP_PROXY;
|
|
64
|
-
}
|
|
65
|
-
const controller = options.timeoutMs ? new AbortController() : void 0;
|
|
66
|
-
let timedOut = false;
|
|
67
|
-
const timer = controller ? setTimeout(() => {
|
|
68
|
-
timedOut = true;
|
|
69
|
-
controller.abort();
|
|
70
|
-
}, options.timeoutMs) : void 0;
|
|
71
|
-
let response;
|
|
72
|
-
try {
|
|
73
|
-
response = await fetch(url, {
|
|
74
|
-
method: options.method ?? "GET",
|
|
75
|
-
headers,
|
|
76
|
-
body: options.body ? JSON.stringify(options.body) : void 0,
|
|
77
|
-
signal: controller?.signal
|
|
78
|
-
});
|
|
79
|
-
} catch (err) {
|
|
80
|
-
if (timedOut) {
|
|
81
|
-
const host = new URL(url).host;
|
|
82
|
-
const secs = Math.round(options.timeoutMs / 1e3);
|
|
83
|
-
throw new ApiError(
|
|
84
|
-
408,
|
|
85
|
-
`Request to ${host} timed out after ${secs}s. This is usually transient or a local proxy/gateway issue \u2014 retry, and if it persists check HTTPS_PROXY / the RuleMetric gateway (:8787).`
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
throw err;
|
|
89
|
-
} finally {
|
|
90
|
-
if (timer) clearTimeout(timer);
|
|
91
|
-
if (isLocalhost) {
|
|
92
|
-
if (savedProxy !== void 0) process.env.HTTPS_PROXY = savedProxy;
|
|
93
|
-
if (savedHttpProxy !== void 0) process.env.HTTP_PROXY = savedHttpProxy;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
let responseBody;
|
|
97
|
-
const contentType = response.headers.get("content-type");
|
|
98
|
-
if (contentType?.includes("application/json")) {
|
|
99
|
-
responseBody = await response.json();
|
|
100
|
-
} else {
|
|
101
|
-
responseBody = await response.text();
|
|
102
|
-
}
|
|
103
|
-
if (!response.ok) {
|
|
104
|
-
const message = responseBody && typeof responseBody === "object" && "error" in responseBody ? String(responseBody.error) : `HTTP ${response.status}`;
|
|
105
|
-
throw new ApiError(response.status, message);
|
|
106
|
-
}
|
|
107
|
-
return responseBody;
|
|
108
|
-
}
|
|
109
|
-
var apiGet = (path) => api(path);
|
|
110
|
-
var apiPost = (path, body) => api(path, { method: "POST", body });
|
|
111
|
-
var apiPut = (path, body) => api(path, { method: "PUT", body });
|
|
112
|
-
var apiPatch = (path, body) => api(path, { method: "PATCH", body });
|
|
113
|
-
var apiDelete = (path) => api(path, { method: "DELETE" });
|
|
114
|
-
|
|
115
|
-
export {
|
|
116
|
-
DEFAULT_API_URL,
|
|
117
|
-
ApiError,
|
|
118
|
-
api,
|
|
119
|
-
apiGet,
|
|
120
|
-
apiPost,
|
|
121
|
-
apiPut,
|
|
122
|
-
apiPatch,
|
|
123
|
-
apiDelete
|
|
124
|
-
};
|
|
125
|
-
//# sourceMappingURL=chunk-ZUJBM6HE.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/lib/api-client.ts"],
|
|
4
|
-
"sourcesContent": ["import { fileURLToPath } from 'node:url';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { loadToken, loadEnvFileAuth } from './auth.js';\n\n/**\n * Read the CLI's own version. Walks up from this module's location to find\n * `@rulemetric/cli`'s package.json \u2014 robust whether running unbundled from\n * `src/lib/` (dev) or from a bundled chunk at a different `dist/` depth (prod),\n * where a fixed relative `../../package.json` would resolve to the wrong file.\n */\nfunction readCliVersion(): string {\n let dir = dirname(fileURLToPath(import.meta.url));\n for (let i = 0; i < 8; i++) {\n const pj = join(dir, 'package.json');\n if (existsSync(pj)) {\n try {\n const parsed = JSON.parse(readFileSync(pj, 'utf8')) as { name?: string; version?: string };\n if (parsed.name === '@rulemetric/cli' && parsed.version) return parsed.version;\n } catch {\n /* unreadable/parse error \u2014 keep walking up */\n }\n }\n const parent = dirname(dir);\n if (parent === dir) break;\n dir = parent;\n }\n return '0.0.0';\n}\n\nconst version = readCliVersion();\n\n/**\n * Default API base URL for the CLI. Points at PRODUCTION so a fresh `npm i -g\n * @rulemetric/cli` (no config, no env vars) can `auth login` out of the box.\n * Dev opts into localhost by setting `RULEMETRIC_API_URL` \u2014 `bin/dev.js` sets\n * it to `http://localhost:3000` automatically, and `scripts/start.sh` exports\n * it for the launchd services.\n */\nexport const DEFAULT_API_URL = 'https://rulemetric.com';\n\nexport class ApiError extends Error {\n constructor(\n public statusCode: number,\n message: string,\n ) {\n super(message);\n this.name = 'ApiError';\n }\n}\n\ninterface ApiOptions {\n method?: string;\n body?: unknown;\n headers?: Record<string, string>;\n /**\n * Client-side timeout in ms. OPT-IN: when unset there is NO timeout, so the\n * worker's ~30s `/api/work/next` long-poll and slow imports (which share this\n * client) are never aborted. Interactive onboarding calls (auth login/signup)\n * pass a short budget so a held/502'd connection or a broken local proxy\n * fails fast + retryable instead of appearing frozen for minutes.\n */\n timeoutMs?: number;\n}\n\nfunction getBaseUrl(): string {\n // Additive fallback to the env file's URL so a key/token read from that same\n // file (see the auth header below) is sent to the SERVER it belongs to,\n // not the localhost default.\n const url = process.env.RULEMETRIC_API_URL ?? loadEnvFileAuth().apiUrl ?? DEFAULT_API_URL;\n\n // Enforce HTTPS for non-localhost URLs\n const parsed = new URL(url);\n if (parsed.protocol === 'http:' && parsed.hostname !== 'localhost' && parsed.hostname !== '127.0.0.1') {\n throw new Error(`API URL must use HTTPS for non-localhost hosts: ${url}`);\n }\n\n return url;\n}\n\nexport async function api<T>(path: string, options: ApiOptions = {}): Promise<T> {\n const baseUrl = getBaseUrl();\n const url = `${baseUrl}${path}`;\n\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n 'User-Agent': `rulemetric-cli/${version}`,\n ...options.headers,\n };\n\n // Auth header resolution, first match wins:\n // 1. process.env.RULEMETRIC_API_KEY \u2014 exported long-lived key\n // 2. env-file RULEMETRIC_API_KEY \u2014 long-lived key on disk (create-key)\n // 3. auth.json OAuth accessToken \u2014 fresh right after `auth login`\n // 4. env-file RULEMETRIC_ACCESS_TOKEN \u2014 token persisted by login\n // The long-lived API key is preferred over the OAuth token because the latter\n // EXPIRES \u2014 auth.json can hold a stale token, so trying it first would 401\n // (\"Session expired\") even when a valid key sits right there in the env file.\n const envAuth = loadEnvFileAuth();\n const bearer =\n process.env.RULEMETRIC_API_KEY ||\n envAuth.apiKey ||\n loadToken()?.accessToken ||\n envAuth.accessToken;\n if (bearer) {\n headers['Authorization'] = `Bearer ${bearer}`;\n }\n\n // Bypass proxy for localhost API calls \u2014 HTTPS_PROXY is for Claude Code \u2192 Anthropic,\n // not for CLI \u2192 local API. Node.js fetch doesn't respect NO_PROXY reliably, so we\n // temporarily unset the proxy env vars for localhost calls.\n const parsed = new URL(url);\n const isLocalhost = parsed.hostname === 'localhost' || parsed.hostname === '127.0.0.1';\n const savedProxy = process.env.HTTPS_PROXY;\n const savedHttpProxy = process.env.HTTP_PROXY;\n if (isLocalhost) {\n delete process.env.HTTPS_PROXY;\n delete process.env.HTTP_PROXY;\n }\n\n // Opt-in client-side timeout (see ApiOptions.timeoutMs). Without it, no signal\n // is attached and behavior is unchanged (long-poll / import safe).\n const controller = options.timeoutMs ? new AbortController() : undefined;\n let timedOut = false;\n const timer = controller\n ? setTimeout(() => {\n timedOut = true;\n controller.abort();\n }, options.timeoutMs)\n : undefined;\n\n let response: Response;\n try {\n response = await fetch(url, {\n method: options.method ?? 'GET',\n headers,\n body: options.body ? JSON.stringify(options.body) : undefined,\n signal: controller?.signal,\n });\n } catch (err) {\n // A timeout abort surfaces as an AbortError. Translate it into a clear,\n // actionable ApiError \u2014 base-command otherwise maps a raw network failure to\n // \"Could not connect to the API server. Is it running?\", which is misleading\n // when the server IS up but a held connection or a broken local proxy/gateway\n // (HTTPS_PROXY \u2192 :8787) is eating the request.\n if (timedOut) {\n const host = new URL(url).host;\n const secs = Math.round((options.timeoutMs as number) / 1000);\n throw new ApiError(\n 408,\n `Request to ${host} timed out after ${secs}s. This is usually transient or a ` +\n `local proxy/gateway issue \u2014 retry, and if it persists check HTTPS_PROXY / the ` +\n `RuleMetric gateway (:8787).`,\n );\n }\n throw err;\n } finally {\n if (timer) clearTimeout(timer);\n // Restore proxy vars so claude -p calls still route through the proxy\n if (isLocalhost) {\n if (savedProxy !== undefined) process.env.HTTPS_PROXY = savedProxy;\n if (savedHttpProxy !== undefined) process.env.HTTP_PROXY = savedHttpProxy;\n }\n }\n\n let responseBody: unknown;\n const contentType = response.headers.get('content-type');\n if (contentType?.includes('application/json')) {\n responseBody = await response.json();\n } else {\n responseBody = await response.text();\n }\n\n if (!response.ok) {\n // Extract only the error message, not the full response body\n const message =\n responseBody && typeof responseBody === 'object' && 'error' in responseBody\n ? String((responseBody as { error: string }).error)\n : `HTTP ${response.status}`;\n throw new ApiError(response.status, message);\n }\n\n return responseBody as T;\n}\n\nexport const apiGet = <T>(path: string): Promise<T> => api<T>(path);\nexport const apiPost = <T>(path: string, body: unknown): Promise<T> => api<T>(path, { method: 'POST', body });\nexport const apiPut = <T>(path: string, body: unknown): Promise<T> => api<T>(path, { method: 'PUT', body });\nexport const apiPatch = <T>(path: string, body: unknown): Promise<T> => api<T>(path, { method: 'PATCH', body });\nexport const apiDelete = <T>(path: string): Promise<T> => api<T>(path, { method: 'DELETE' });\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/commands/antigravity/backfill.ts"],
|
|
4
|
-
"sourcesContent": ["import { Args, Flags } from '@oclif/core';\nimport { existsSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { BaseCommand } from '../../base-command.js';\nimport {\n emitRecordsAsEvents,\n findMaxStepIndex,\n readNewRecords,\n stateApi,\n} from '../../lib/antigravity-transcript.js';\n\nconst TRANSCRIPT_BRAIN_DIR = join(homedir(), '.gemini', 'antigravity-ide', 'brain');\n\nexport default class AntigravityBackfill extends BaseCommand {\n static override description =\n 'Backfill historical events from an Antigravity conversation transcript into a RuleMetric session. Useful for seeding a conversation that existed before hooks were installed \u2014 the live hook intentionally only captures forward.';\n\n static override examples = [\n '<%= config.bin %> antigravity backfill 26fd215d-f43b-4ea5-b177-dc2c0e696f97 --session 158db9aa-68ee-43fc-961b-f3a180578694',\n '<%= config.bin %> antigravity backfill 26fd215d-f43b-4ea5-b177-dc2c0e696f97 --dry-run',\n ];\n\n static override args = {\n conversationId: Args.string({\n description: 'Antigravity conversationId (UUID) \u2014 the directory name under ~/.gemini/antigravity-ide/brain/',\n required: true,\n }),\n };\n\n static override flags = {\n session: Flags.string({\n char: 's',\n description:\n 'RuleMetric session UUID to POST events into. If omitted, resolved from the hook tmp file ($TMPDIR/rulemetric/<conversationId>) \u2014 fails if neither is present.',\n }),\n transcript: Flags.string({\n description:\n 'Path to the transcript.jsonl file. Defaults to ~/.gemini/antigravity-ide/brain/<conversationId>/.system_generated/logs/transcript.jsonl',\n }),\n 'after-step': Flags.integer({\n description:\n 'Only emit records with step_index > this value. Default: read from existing state file, else -1 (everything).',\n }),\n limit: Flags.integer({\n description: 'Cap on the number of records to process this run.',\n }),\n 'dry-run': Flags.boolean({\n default: false,\n description: 'Classify records without POSTing. Reports counts only.',\n }),\n 'save-state': Flags.boolean({\n default: true,\n allowNo: true,\n description: 'After backfill, persist the highest step_index so the live hook resumes from there.',\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(AntigravityBackfill);\n const conversationId = args.conversationId;\n\n stateApi.loadEnvFile();\n if (!process.env.RULEMETRIC_API_URL) {\n this.error('RULEMETRIC_API_URL is not set. Configure it via env or ~/.config/rulemetric/env.');\n }\n\n const transcriptPath =\n flags.transcript ??\n join(TRANSCRIPT_BRAIN_DIR, conversationId, '.system_generated', 'logs', 'transcript.jsonl');\n if (!existsSync(transcriptPath)) {\n this.error(`Transcript not found: ${transcriptPath}`);\n }\n\n const rwSessionId = flags.session ?? stateApi.resolveRwSessionId(conversationId);\n if (!rwSessionId) {\n this.error(\n `No RuleMetric session resolved. Pass --session <uuid>, or run the Antigravity hook at least once so $TMPDIR/rulemetric/${conversationId} is populated.`,\n );\n }\n\n let after = flags['after-step'];\n if (after === undefined) {\n const existing = stateApi.load(conversationId);\n after = existing?.lastStepIdx ?? -1;\n }\n\n let records = readNewRecords(transcriptPath, after);\n if (flags.limit !== undefined && records.length > flags.limit) {\n records = records.slice(0, flags.limit);\n }\n\n const max = findMaxStepIndex(transcriptPath);\n this.log(\n `Conversation ${conversationId}: transcript max step = ${max}, after-step = ${after}, records to process = ${records.length}`,\n );\n if (records.length === 0) {\n this.log('Nothing to backfill.');\n return;\n }\n\n if (flags['dry-run']) {\n // Count classification outcomes without POSTing.\n let wouldEmit = 0;\n let wouldSkip = 0;\n const byEventType: Record<string, number> = {};\n for (const record of records) {\n // Use a stable fake sequence \u2014 classification doesn't care about its value.\n const classified = (await import('../../lib/antigravity-transcript.js')).classifyRecord(record, 0);\n if (classified) {\n wouldEmit++;\n byEventType[classified.eventType] = (byEventType[classified.eventType] ?? 0) + 1;\n } else {\n wouldSkip++;\n }\n }\n this.log(\n `Dry run: would emit ${wouldEmit}, skip ${wouldSkip}. By eventType: ${JSON.stringify(byEventType)}`,\n );\n return;\n }\n\n const start = Date.now();\n const result = await emitRecordsAsEvents(records, rwSessionId, conversationId, after, {\n onProgress: ({ attempted, total }) => {\n if (attempted % 100 === 0 || attempted === total) {\n process.stderr.write(` \u2026${attempted}/${total}\\n`);\n }\n },\n });\n const elapsedSec = ((Date.now() - start) / 1000).toFixed(1);\n\n this.log(\n `Backfill complete in ${elapsedSec}s. attempted=${result.attempted} emitted=${result.emitted} skipped=${result.skipped} failed=${result.failed} highestStepIdx=${result.highestStepIdx}`,\n );\n\n if (flags['save-state']) {\n stateApi.save(conversationId, { lastStepIdx: result.highestStepIdx });\n this.log(`State saved \u2192 live hook will resume from step_index > ${result.highestStepIdx}.`);\n } else {\n this.log('State NOT saved (--no-save-state). Live hook will re-emit any new records from after-step.');\n }\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/commands/auth/create-key.ts"],
|
|
4
|
-
"sourcesContent": ["import * as path from 'node:path';\nimport { Flags } from '@oclif/core';\nimport { BaseCommand } from '../../base-command.js';\nimport { apiPost } from '../../lib/api-client.js';\nimport { saveApiKey, getDefaultConfigDir } from '../../lib/auth.js';\n\ninterface CreateKeyResponse {\n id: string;\n name: string;\n key: string;\n keyPrefix: string;\n createdAt: string;\n}\n\nexport default class AuthCreateKey extends BaseCommand {\n static override description = 'Create a long-lived API key for CLI and proxy authentication';\n\n static override examples = [\n '<%= config.bin %> auth create-key --name \"laptop\"',\n '<%= config.bin %> auth create-key --name \"work proxy\" --save',\n ];\n\n static override flags = {\n name: Flags.string({ char: 'n', description: 'Name for this key', required: true }),\n save: Flags.boolean({ char: 's', description: 'Save key to ~/.config/rulemetric/env for hooks/proxy', default: true }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(AuthCreateKey);\n\n const data = await apiPost<CreateKeyResponse>('/api/auth/api-keys', { name: flags.name });\n\n this.log('');\n this.log('API key created successfully:');\n this.log('');\n this.log(` Name: ${data.name}`);\n this.log(` Key: ${data.key}`);\n this.log(` Prefix: ${data.keyPrefix}`);\n this.log('');\n this.warn('Save this key now \u2014 it will not be shown again.');\n\n if (flags.save) {\n saveApiKey(data.key, process.env.RULEMETRIC_API_URL);\n this.log('');\n this.log(`Key saved to ${path.join(getDefaultConfigDir(), 'env')} (RULEMETRIC_API_KEY)`);\n this.log('Hooks and proxy will use this key automatically.');\n }\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;AAAA,YAAY,UAAU;AACtB,SAAS,aAAa;AAatB,IAAqB,gBAArB,MAAqB,uBAAsB,YAAY;AAAA,EACrD,OAAgB,cAAc;AAAA,EAE9B,OAAgB,WAAW;AAAA,IACzB;AAAA,IACA;AAAA,EACF;AAAA,EAEA,OAAgB,QAAQ;AAAA,IACtB,MAAM,MAAM,OAAO,EAAE,MAAM,KAAK,aAAa,qBAAqB,UAAU,KAAK,CAAC;AAAA,IAClF,MAAM,MAAM,QAAQ,EAAE,MAAM,KAAK,aAAa,wDAAwD,SAAS,KAAK,CAAC;AAAA,EACvH;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,cAAa;AAEhD,UAAM,OAAO,MAAM,QAA2B,sBAAsB,EAAE,MAAM,MAAM,KAAK,CAAC;AAExF,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,+BAA+B;AACxC,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,aAAa,KAAK,IAAI,EAAE;AACjC,SAAK,IAAI,aAAa,KAAK,GAAG,EAAE;AAChC,SAAK,IAAI,aAAa,KAAK,SAAS,EAAE;AACtC,SAAK,IAAI,EAAE;AACX,SAAK,KAAK,sDAAiD;AAE3D,QAAI,MAAM,MAAM;AACd,iBAAW,KAAK,KAAK,QAAQ,IAAI,kBAAkB;AACnD,WAAK,IAAI,EAAE;AACX,WAAK,IAAI,gBAAqB,UAAK,oBAAoB,GAAG,KAAK,CAAC,uBAAuB;AACvF,WAAK,IAAI,kDAAkD;AAAA,IAC7D;AAAA,EACF;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/commands/auth/login.ts"],
|
|
4
|
-
"sourcesContent": ["import { Flags } from '@oclif/core';\nimport { BaseCommand } from '../../base-command.js';\nimport { saveToken, saveEnvFile } from '../../lib/auth.js';\nimport { api, ApiError } from '../../lib/api-client.js';\nimport { bootstrapActiveOrg } from '../../lib/active-org-refresh.js';\nimport { ensureDeviceApiKey } from '../../lib/ensure-api-key.js';\nimport { emitSetupEvent } from '../../lib/telemetry.js';\n\ninterface LoginResponse {\n accessToken: string;\n refreshToken: string;\n expiresAt: string | null;\n email: string;\n}\n\nexport default class AuthLogin extends BaseCommand {\n static override description = 'Log in to RuleMetric';\n\n static override examples = [\n '<%= config.bin %> auth login',\n '<%= config.bin %> auth login -e user@example.com',\n ];\n\n static override flags = {\n email: Flags.string({ char: 'e', description: 'Email address' }),\n password: Flags.string({ char: 'p', description: 'Password (for non-interactive use)' }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(AuthLogin);\n\n let email = flags.email;\n let password = flags.password;\n\n if (!email || !password) {\n // Interactive prompts hang forever with no output in a non-TTY (CI, SSH\n // pipe, an agent driving the CLI). Fail fast with actionable guidance\n // instead of appearing to freeze.\n if (!process.stdin.isTTY) {\n this.error(\n 'Missing credentials in a non-interactive shell. Pass --email/-e and --password/-p, ' +\n 'or set RULEMETRIC_API_KEY (create a key at https://rulemetric.com/settings).',\n );\n }\n const { input, password: passwordPrompt } = await import('@inquirer/prompts');\n\n if (!email) {\n email = await input({ message: 'Email:' });\n }\n\n if (!password) {\n password = await passwordPrompt({ message: 'Password:' });\n }\n }\n\n let data: LoginResponse;\n try {\n // Bounded so the first onboarding step fails fast + retryable instead of\n // hanging for minutes on a held/502'd connection or a broken local proxy.\n data = await api<LoginResponse>('/auth/login', {\n method: 'POST',\n body: { email, password },\n timeoutMs: 20_000,\n });\n } catch (err) {\n // A 401 HERE means the email/password were rejected \u2014 not that a prior\n // session expired. base-command's generic catch maps every 401 to\n // \"Session expired. Run auth login\", which is nonsensical mid-login and\n // loops the user. Give the real reason.\n if (err instanceof ApiError && err.statusCode === 401) {\n this.error('Invalid email or password.');\n }\n throw err;\n }\n\n const expiresAt = data.expiresAt ?? new Date(Date.now() + 3600 * 1000).toISOString();\n\n saveToken({\n accessToken: data.accessToken,\n refreshToken: data.refreshToken,\n expiresAt,\n email: data.email,\n });\n\n saveEnvFile(data.accessToken, process.env.RULEMETRIC_API_URL);\n\n // Bootstrap the active-org cache now that auth is available. BaseCommand\n // fired the guarded refresh BEFORE login completed (no creds \u2192 401 \u2192\n // swallowed); without this explicit retry, the cache stays empty until\n // the user runs another CLI command, and any Claude Code session that\n // fires in the meantime lands with org_id = NULL.\n await bootstrapActiveOrg();\n\n // Auto-mint a hooks/proxy API key so create-key isn't a separate manual\n // step (best-effort; no-ops if a key already exists, never fails login).\n await ensureDeviceApiKey(this.log.bind(this), this.warn.bind(this), this.config.version);\n\n // Onboarding telemetry (disclosed + opt-outable) \u2014 first authenticated\n // event, so a remote install becomes visible from here on.\n void emitSetupEvent('auth_login', {}, this.config.version);\n\n this.log(`Logged in as ${data.email}`);\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,aAAa;AAetB,IAAqB,YAArB,MAAqB,mBAAkB,YAAY;AAAA,EACjD,OAAgB,cAAc;AAAA,EAE9B,OAAgB,WAAW;AAAA,IACzB;AAAA,IACA;AAAA,EACF;AAAA,EAEA,OAAgB,QAAQ;AAAA,IACtB,OAAO,MAAM,OAAO,EAAE,MAAM,KAAK,aAAa,gBAAgB,CAAC;AAAA,IAC/D,UAAU,MAAM,OAAO,EAAE,MAAM,KAAK,aAAa,qCAAqC,CAAC;AAAA,EACzF;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,UAAS;AAE5C,QAAI,QAAQ,MAAM;AAClB,QAAI,WAAW,MAAM;AAErB,QAAI,CAAC,SAAS,CAAC,UAAU;AAIvB,UAAI,CAAC,QAAQ,MAAM,OAAO;AACxB,aAAK;AAAA,UACH;AAAA,QAEF;AAAA,MACF;AACA,YAAM,EAAE,OAAO,UAAU,eAAe,IAAI,MAAM,OAAO,mBAAmB;AAE5E,UAAI,CAAC,OAAO;AACV,gBAAQ,MAAM,MAAM,EAAE,SAAS,SAAS,CAAC;AAAA,MAC3C;AAEA,UAAI,CAAC,UAAU;AACb,mBAAW,MAAM,eAAe,EAAE,SAAS,YAAY,CAAC;AAAA,MAC1D;AAAA,IACF;AAEA,QAAI;AACJ,QAAI;AAGF,aAAO,MAAM,IAAmB,eAAe;AAAA,QAC7C,QAAQ;AAAA,QACR,MAAM,EAAE,OAAO,SAAS;AAAA,QACxB,WAAW;AAAA,MACb,CAAC;AAAA,IACH,SAAS,KAAK;AAKZ,UAAI,eAAe,YAAY,IAAI,eAAe,KAAK;AACrD,aAAK,MAAM,4BAA4B;AAAA,MACzC;AACA,YAAM;AAAA,IACR;AAEA,UAAM,YAAY,KAAK,aAAa,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,GAAI,EAAE,YAAY;AAEnF,cAAU;AAAA,MACR,aAAa,KAAK;AAAA,MAClB,cAAc,KAAK;AAAA,MACnB;AAAA,MACA,OAAO,KAAK;AAAA,IACd,CAAC;AAED,gBAAY,KAAK,aAAa,QAAQ,IAAI,kBAAkB;AAO5D,UAAM,mBAAmB;AAIzB,UAAM,mBAAmB,KAAK,IAAI,KAAK,IAAI,GAAG,KAAK,KAAK,KAAK,IAAI,GAAG,KAAK,OAAO,OAAO;AAIvF,SAAK,eAAe,cAAc,CAAC,GAAG,KAAK,OAAO,OAAO;AAEzD,SAAK,IAAI,gBAAgB,KAAK,KAAK,EAAE;AAAA,EACvC;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/commands/auth/logout.ts"],
|
|
4
|
-
"sourcesContent": ["import { BaseCommand } from '../../base-command.js';\nimport { clearToken, clearEnvFile } from '../../lib/auth.js';\n\nexport default class AuthLogout extends BaseCommand {\n static override description = 'Log out of RuleMetric';\n\n static override examples = ['<%= config.bin %> auth logout'];\n\n async run(): Promise<void> {\n await this.parse(AuthLogout);\n clearToken();\n clearEnvFile();\n this.log('Logged out successfully.');\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;AAGA,IAAqB,aAArB,MAAqB,oBAAmB,YAAY;AAAA,EAClD,OAAgB,cAAc;AAAA,EAE9B,OAAgB,WAAW,CAAC,+BAA+B;AAAA,EAE3D,MAAM,MAAqB;AACzB,UAAM,KAAK,MAAM,WAAU;AAC3B,eAAW;AACX,iBAAa;AACb,SAAK,IAAI,0BAA0B;AAAA,EACrC;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/commands/auth/revoke-key.ts"],
|
|
4
|
-
"sourcesContent": ["import { Args } from '@oclif/core';\nimport { BaseCommand } from '../../base-command.js';\nimport { apiDelete } from '../../lib/api-client.js';\n\nexport default class AuthRevokeKey extends BaseCommand {\n static override description = 'Revoke an API key';\n\n static override examples = [\n '<%= config.bin %> auth revoke-key <key-id>',\n ];\n\n static override args = {\n id: Args.string({ description: 'API key ID to revoke', required: true }),\n };\n\n async run(): Promise<void> {\n const { args } = await this.parse(AuthRevokeKey);\n\n await apiDelete(`/api/auth/api-keys/${args.id}`);\n this.log(`API key ${args.id} revoked.`);\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;AAAA,SAAS,YAAY;AAIrB,IAAqB,gBAArB,MAAqB,uBAAsB,YAAY;AAAA,EACrD,OAAgB,cAAc;AAAA,EAE9B,OAAgB,WAAW;AAAA,IACzB;AAAA,EACF;AAAA,EAEA,OAAgB,OAAO;AAAA,IACrB,IAAI,KAAK,OAAO,EAAE,aAAa,wBAAwB,UAAU,KAAK,CAAC;AAAA,EACzE;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,cAAa;AAE/C,UAAM,UAAU,sBAAsB,KAAK,EAAE,EAAE;AAC/C,SAAK,IAAI,WAAW,KAAK,EAAE,WAAW;AAAA,EACxC;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/commands/auth/signup.ts"],
|
|
4
|
-
"sourcesContent": ["import { Flags } from '@oclif/core';\nimport { BaseCommand } from '../../base-command.js';\nimport { saveToken, saveEnvFile } from '../../lib/auth.js';\nimport { api, ApiError } from '../../lib/api-client.js';\nimport { bootstrapActiveOrg } from '../../lib/active-org-refresh.js';\nimport { ensureDeviceApiKey } from '../../lib/ensure-api-key.js';\nimport { emitSetupEvent } from '../../lib/telemetry.js';\n\ninterface SignupResponse {\n confirmationRequired: boolean;\n accessToken?: string;\n refreshToken?: string;\n expiresAt?: string | null;\n email: string;\n}\n\nexport default class AuthSignup extends BaseCommand {\n static override description = 'Create a RuleMetric account from the CLI';\n\n static override examples = [\n '<%= config.bin %> auth signup',\n '<%= config.bin %> auth signup -e user@example.com',\n ];\n\n static override flags = {\n email: Flags.string({ char: 'e', description: 'Email address' }),\n password: Flags.string({ char: 'p', description: 'Password (min 8 chars; for non-interactive use)' }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(AuthSignup);\n\n let email = flags.email;\n let password = flags.password;\n\n if (!email || !password) {\n // Interactive prompts hang forever with no output in a non-TTY (CI, SSH\n // pipe, an agent driving the CLI). Fail fast with actionable guidance.\n if (!process.stdin.isTTY) {\n this.error('Missing credentials in a non-interactive shell. Pass --email/-e and --password/-p.');\n }\n const { input, password: passwordPrompt } = await import('@inquirer/prompts');\n\n if (!email) {\n email = await input({ message: 'Email:' });\n }\n if (!password) {\n password = await passwordPrompt({ message: 'Password (min 8 chars):' });\n }\n }\n\n let data: SignupResponse;\n try {\n // Bounded so the first onboarding step fails fast + retryable instead of\n // hanging for minutes on a held/502'd connection or a broken local proxy.\n data = await api<SignupResponse>('/auth/signup', {\n method: 'POST',\n body: { email, password },\n timeoutMs: 20_000,\n });\n } catch (err) {\n // 409 = the email is already registered \u2014 steer to login, not a retry loop.\n if (err instanceof ApiError && err.statusCode === 409) {\n this.error(`An account with ${email} already exists. Run: rulemetric auth login -e ${email}`);\n }\n throw err;\n }\n\n // Email confirmation is ON: no session yet. Tell the user exactly what to do\n // next instead of leaving them at a dead end.\n if (data.confirmationRequired || !data.accessToken || !data.refreshToken) {\n this.log(`Account created for ${data.email}.`);\n this.log('Check your email and click the confirmation link, then run:');\n this.log(` rulemetric auth login -e ${data.email}`);\n return;\n }\n\n // Confirmation OFF: a session came back \u2014 log in immediately.\n const expiresAt = data.expiresAt ?? new Date(Date.now() + 3600 * 1000).toISOString();\n saveToken({\n accessToken: data.accessToken,\n refreshToken: data.refreshToken,\n expiresAt,\n email: data.email,\n });\n saveEnvFile(data.accessToken, process.env.RULEMETRIC_API_URL);\n\n await bootstrapActiveOrg();\n await ensureDeviceApiKey(this.log.bind(this), this.warn.bind(this), this.config.version);\n void emitSetupEvent('auth_signup', {}, this.config.version);\n\n this.log(`Signed up and logged in as ${data.email}`);\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;AAAA,SAAS,aAAa;AAgBtB,IAAqB,aAArB,MAAqB,oBAAmB,YAAY;AAAA,EAClD,OAAgB,cAAc;AAAA,EAE9B,OAAgB,WAAW;AAAA,IACzB;AAAA,IACA;AAAA,EACF;AAAA,EAEA,OAAgB,QAAQ;AAAA,IACtB,OAAO,MAAM,OAAO,EAAE,MAAM,KAAK,aAAa,gBAAgB,CAAC;AAAA,IAC/D,UAAU,MAAM,OAAO,EAAE,MAAM,KAAK,aAAa,kDAAkD,CAAC;AAAA,EACtG;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,WAAU;AAE7C,QAAI,QAAQ,MAAM;AAClB,QAAI,WAAW,MAAM;AAErB,QAAI,CAAC,SAAS,CAAC,UAAU;AAGvB,UAAI,CAAC,QAAQ,MAAM,OAAO;AACxB,aAAK,MAAM,oFAAoF;AAAA,MACjG;AACA,YAAM,EAAE,OAAO,UAAU,eAAe,IAAI,MAAM,OAAO,mBAAmB;AAE5E,UAAI,CAAC,OAAO;AACV,gBAAQ,MAAM,MAAM,EAAE,SAAS,SAAS,CAAC;AAAA,MAC3C;AACA,UAAI,CAAC,UAAU;AACb,mBAAW,MAAM,eAAe,EAAE,SAAS,0BAA0B,CAAC;AAAA,MACxE;AAAA,IACF;AAEA,QAAI;AACJ,QAAI;AAGF,aAAO,MAAM,IAAoB,gBAAgB;AAAA,QAC/C,QAAQ;AAAA,QACR,MAAM,EAAE,OAAO,SAAS;AAAA,QACxB,WAAW;AAAA,MACb,CAAC;AAAA,IACH,SAAS,KAAK;AAEZ,UAAI,eAAe,YAAY,IAAI,eAAe,KAAK;AACrD,aAAK,MAAM,mBAAmB,KAAK,kDAAkD,KAAK,EAAE;AAAA,MAC9F;AACA,YAAM;AAAA,IACR;AAIA,QAAI,KAAK,wBAAwB,CAAC,KAAK,eAAe,CAAC,KAAK,cAAc;AACxE,WAAK,IAAI,uBAAuB,KAAK,KAAK,GAAG;AAC7C,WAAK,IAAI,6DAA6D;AACtE,WAAK,IAAI,8BAA8B,KAAK,KAAK,EAAE;AACnD;AAAA,IACF;AAGA,UAAM,YAAY,KAAK,aAAa,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,GAAI,EAAE,YAAY;AACnF,cAAU;AAAA,MACR,aAAa,KAAK;AAAA,MAClB,cAAc,KAAK;AAAA,MACnB;AAAA,MACA,OAAO,KAAK;AAAA,IACd,CAAC;AACD,gBAAY,KAAK,aAAa,QAAQ,IAAI,kBAAkB;AAE5D,UAAM,mBAAmB;AACzB,UAAM,mBAAmB,KAAK,IAAI,KAAK,IAAI,GAAG,KAAK,KAAK,KAAK,IAAI,GAAG,KAAK,OAAO,OAAO;AACvF,SAAK,eAAe,eAAe,CAAC,GAAG,KAAK,OAAO,OAAO;AAE1D,SAAK,IAAI,8BAA8B,KAAK,KAAK,EAAE;AAAA,EACrD;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/commands/auth/status.ts"],
|
|
4
|
-
"sourcesContent": ["import { BaseCommand } from '../../base-command.js';\nimport { loadToken, isAuthenticated, getDefaultConfigDir } from '../../lib/auth.js';\nimport { formatDate } from '../../lib/output.js';\n\nexport default class AuthStatus extends BaseCommand {\n static override description = 'Show current authentication status';\n\n static override examples = ['<%= config.bin %> auth status'];\n\n async run(): Promise<void> {\n await this.parse(AuthStatus);\n const token = loadToken();\n\n if (!token) {\n this.log('Not logged in. Run `rulemetric auth login` to authenticate.');\n return;\n }\n\n if (!isAuthenticated()) {\n this.log('Session expired. Run `rulemetric auth login` to re-authenticate.');\n return;\n }\n\n this.log(`Logged in as: ${token.email}`);\n this.log(`Session expires: ${formatDate(token.expiresAt)}`);\n this.log(`Config: ${getDefaultConfigDir()}`);\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;AAIA,IAAqB,aAArB,MAAqB,oBAAmB,YAAY;AAAA,EAClD,OAAgB,cAAc;AAAA,EAE9B,OAAgB,WAAW,CAAC,+BAA+B;AAAA,EAE3D,MAAM,MAAqB;AACzB,UAAM,KAAK,MAAM,WAAU;AAC3B,UAAM,QAAQ,UAAU;AAExB,QAAI,CAAC,OAAO;AACV,WAAK,IAAI,6DAA6D;AACtE;AAAA,IACF;AAEA,QAAI,CAAC,gBAAgB,GAAG;AACtB,WAAK,IAAI,kEAAkE;AAC3E;AAAA,IACF;AAEA,SAAK,IAAI,iBAAiB,MAAM,KAAK,EAAE;AACvC,SAAK,IAAI,oBAAoB,WAAW,MAAM,SAAS,CAAC,EAAE;AAC1D,SAAK,IAAI,WAAW,oBAAoB,CAAC,EAAE;AAAA,EAC7C;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/commands/catalog/index.ts"],
|
|
4
|
-
"sourcesContent": ["import { Flags } from '@oclif/core';\nimport { BaseCommand } from '../../base-command.js';\nimport { apiGet } from '../../lib/api-client.js';\nimport { formatDate, truncate, formatScope } from '../../lib/output.js';\n\ninterface CatalogInstruction {\n id: string;\n name: string;\n scope: string;\n badge: string | null;\n tags: string[];\n version: string;\n updatedAt: string;\n}\n\nexport default class Catalog extends BaseCommand {\n static override description = 'Browse the org instruction catalog';\n\n static override flags = {\n badge: Flags.string({ description: 'Filter by badge', options: ['recommended', 'required'] }),\n scope: Flags.string({ description: 'Filter by scope', options: ['org', 'team'] }),\n search: Flags.string({ description: 'Search by name or description' }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Catalog);\n this.requireAuth();\n\n const params = new URLSearchParams();\n if (flags.badge) params.set('badge', flags.badge);\n if (flags.scope) params.set('scope', flags.scope);\n if (flags.search) params.set('search', flags.search);\n\n const results = await apiGet<CatalogInstruction[]>(`/api/catalog?${params.toString()}`);\n\n if (results.length === 0) {\n this.log('No instructions found in catalog.');\n return;\n }\n\n for (const item of results) {\n const badgeStr = item.badge ? ` [${item.badge}]` : '';\n const tags = item.tags?.length ? ` (${item.tags.join(', ')})` : '';\n this.log(` ${truncate(item.name, 40)} \u2014 ${formatScope(item.scope)}${badgeStr} v${item.version}${tags} ${formatDate(item.updatedAt)}`);\n }\n\n this.log(`\\n${results.length} instruction(s) found.`);\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;AAAA,SAAS,aAAa;AAetB,IAAqB,UAArB,MAAqB,iBAAgB,YAAY;AAAA,EAC7C,OAAgB,cAAc;AAAA,EAE9B,OAAgB,QAAQ;AAAA,IACpB,OAAO,MAAM,OAAO,EAAE,aAAa,mBAAmB,SAAS,CAAC,eAAe,UAAU,EAAE,CAAC;AAAA,IAC5F,OAAO,MAAM,OAAO,EAAE,aAAa,mBAAmB,SAAS,CAAC,OAAO,MAAM,EAAE,CAAC;AAAA,IAChF,QAAQ,MAAM,OAAO,EAAE,aAAa,gCAAgC,CAAC;AAAA,EACzE;AAAA,EAEA,MAAM,MAAqB;AACvB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,QAAO;AAC1C,SAAK,YAAY;AAEjB,UAAM,SAAS,IAAI,gBAAgB;AACnC,QAAI,MAAM,MAAO,QAAO,IAAI,SAAS,MAAM,KAAK;AAChD,QAAI,MAAM,MAAO,QAAO,IAAI,SAAS,MAAM,KAAK;AAChD,QAAI,MAAM,OAAQ,QAAO,IAAI,UAAU,MAAM,MAAM;AAEnD,UAAM,UAAU,MAAM,OAA6B,gBAAgB,OAAO,SAAS,CAAC,EAAE;AAEtF,QAAI,QAAQ,WAAW,GAAG;AACtB,WAAK,IAAI,mCAAmC;AAC5C;AAAA,IACJ;AAEA,eAAW,QAAQ,SAAS;AACxB,YAAM,WAAW,KAAK,QAAQ,KAAK,KAAK,KAAK,MAAM;AACnD,YAAM,OAAO,KAAK,MAAM,SAAS,KAAK,KAAK,KAAK,KAAK,IAAI,CAAC,MAAM;AAChE,WAAK,IAAI,KAAK,SAAS,KAAK,MAAM,EAAE,CAAC,WAAM,YAAY,KAAK,KAAK,CAAC,GAAG,QAAQ,KAAK,KAAK,OAAO,GAAG,IAAI,KAAK,WAAW,KAAK,SAAS,CAAC,EAAE;AAAA,IAC1I;AAEA,SAAK,IAAI;AAAA,EAAK,QAAQ,MAAM,wBAAwB;AAAA,EACxD;AACJ;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/commands/catalog/recommend.ts"],
|
|
4
|
-
"sourcesContent": ["import { Args } from '@oclif/core';\nimport { BaseCommand } from '../../base-command.js';\nimport { apiPost } from '../../lib/api-client.js';\n\ninterface RecommendationResult {\n recommendations: Array<{ instructionId: string; score: number; reason: string }>;\n error: string | null;\n}\n\nexport default class CatalogRecommend extends BaseCommand {\n static override description = 'Get AI-powered instruction recommendations for a project';\n\n static override args = {\n projectId: Args.string({ description: 'ID of the project', required: true }),\n };\n\n async run(): Promise<void> {\n const { args } = await this.parse(CatalogRecommend);\n this.requireAuth();\n\n this.log('Analyzing project and generating recommendations...\\n');\n\n const result = await apiPost<RecommendationResult>(`/api/projects/${args.projectId}/recommendations`, {});\n\n if (result.error) {\n this.warn(`Note: ${result.error}`);\n }\n\n if (result.recommendations.length === 0) {\n this.log('No recommendations found.');\n return;\n }\n\n for (const rec of result.recommendations) {\n this.log(` ${(rec.score * 100).toFixed(0)}% \u2014 ${rec.instructionId}`);\n this.log(` ${rec.reason}\\n`);\n }\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;AAAA,SAAS,YAAY;AASrB,IAAqB,mBAArB,MAAqB,0BAAyB,YAAY;AAAA,EACtD,OAAgB,cAAc;AAAA,EAE9B,OAAgB,OAAO;AAAA,IACnB,WAAW,KAAK,OAAO,EAAE,aAAa,qBAAqB,UAAU,KAAK,CAAC;AAAA,EAC/E;AAAA,EAEA,MAAM,MAAqB;AACvB,UAAM,EAAE,KAAK,IAAI,MAAM,KAAK,MAAM,iBAAgB;AAClD,SAAK,YAAY;AAEjB,SAAK,IAAI,uDAAuD;AAEhE,UAAM,SAAS,MAAM,QAA8B,iBAAiB,KAAK,SAAS,oBAAoB,CAAC,CAAC;AAExG,QAAI,OAAO,OAAO;AACd,WAAK,KAAK,SAAS,OAAO,KAAK,EAAE;AAAA,IACrC;AAEA,QAAI,OAAO,gBAAgB,WAAW,GAAG;AACrC,WAAK,IAAI,2BAA2B;AACpC;AAAA,IACJ;AAEA,eAAW,OAAO,OAAO,iBAAiB;AACtC,WAAK,IAAI,MAAM,IAAI,QAAQ,KAAK,QAAQ,CAAC,CAAC,YAAO,IAAI,aAAa,EAAE;AACpE,WAAK,IAAI,UAAU,IAAI,MAAM;AAAA,CAAI;AAAA,IACrC;AAAA,EACJ;AACJ;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/commands/convert.ts"],
|
|
4
|
-
"sourcesContent": ["import * as fs from 'node:fs';\nimport { Args, Flags } from '@oclif/core';\nimport { BaseCommand } from '../base-command.js';\nimport { apiPost, DEFAULT_API_URL } from '../lib/api-client.js';\nimport { validateUuid } from '../lib/types.js';\nimport type { ConvertResult } from '../lib/types.js';\n\nexport default class Convert extends BaseCommand {\n static override description = 'Convert an instruction to a target format';\n\n static override examples = [\n '<%= config.bin %> convert <id> --format claude-md',\n '<%= config.bin %> convert <id> -f cursorrules --score',\n '<%= config.bin %> convert <id> -f copilot -o .github/copilot-instructions.md',\n ];\n\n static override args = {\n id: Args.string({ description: 'Instruction ID', required: true }),\n };\n\n static override flags = {\n format: Flags.string({\n char: 'f',\n description: 'Target format (e.g., claude-md, cursorrules)',\n required: true,\n }),\n score: Flags.boolean({\n description: 'Include quality score',\n default: false,\n }),\n output: Flags.string({\n char: 'o',\n description: 'Write output to file',\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(Convert);\n this.requireAuth();\n validateUuid(args.id, 'instruction ID');\n\n const url = new URL(`${process.env.RULEMETRIC_API_URL ?? DEFAULT_API_URL}/api/instructions/${encodeURIComponent(args.id)}/convert`);\n url.searchParams.set('format', flags.format);\n url.searchParams.set('score', String(flags.score));\n\n const result = await apiPost<ConvertResult>(\n `${url.pathname}${url.search}`,\n {},\n );\n\n if (flags.output) {\n fs.writeFileSync(flags.output, result.output, 'utf-8');\n this.log(`Written to ${flags.output}`);\n } else {\n this.log(result.output);\n }\n\n if (flags.score && result.score) {\n this.log('');\n this.log(`Quality Score: ${result.score.overall}/100`);\n }\n\n if (result.warnings.length > 0) {\n this.warn(`Warnings: ${result.warnings.join(', ')}`);\n }\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA,YAAY,QAAQ;AACpB,SAAS,MAAM,aAAa;AAM5B,IAAqB,UAArB,MAAqB,iBAAgB,YAAY;AAAA,EAC/C,OAAgB,cAAc;AAAA,EAE9B,OAAgB,WAAW;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EAEA,OAAgB,OAAO;AAAA,IACrB,IAAI,KAAK,OAAO,EAAE,aAAa,kBAAkB,UAAU,KAAK,CAAC;AAAA,EACnE;AAAA,EAEA,OAAgB,QAAQ;AAAA,IACtB,QAAQ,MAAM,OAAO;AAAA,MACnB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,UAAU;AAAA,IACZ,CAAC;AAAA,IACD,OAAO,MAAM,QAAQ;AAAA,MACnB,aAAa;AAAA,MACb,SAAS;AAAA,IACX,CAAC;AAAA,IACD,QAAQ,MAAM,OAAO;AAAA,MACnB,MAAM;AAAA,MACN,aAAa;AAAA,IACf,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,KAAK,MAAM,QAAO;AAChD,SAAK,YAAY;AACjB,iBAAa,KAAK,IAAI,gBAAgB;AAEtC,UAAM,MAAM,IAAI,IAAI,GAAG,QAAQ,IAAI,sBAAsB,eAAe,qBAAqB,mBAAmB,KAAK,EAAE,CAAC,UAAU;AAClI,QAAI,aAAa,IAAI,UAAU,MAAM,MAAM;AAC3C,QAAI,aAAa,IAAI,SAAS,OAAO,MAAM,KAAK,CAAC;AAEjD,UAAM,SAAS,MAAM;AAAA,MACnB,GAAG,IAAI,QAAQ,GAAG,IAAI,MAAM;AAAA,MAC5B,CAAC;AAAA,IACH;AAEA,QAAI,MAAM,QAAQ;AAChB,MAAG,iBAAc,MAAM,QAAQ,OAAO,QAAQ,OAAO;AACrD,WAAK,IAAI,cAAc,MAAM,MAAM,EAAE;AAAA,IACvC,OAAO;AACL,WAAK,IAAI,OAAO,MAAM;AAAA,IACxB;AAEA,QAAI,MAAM,SAAS,OAAO,OAAO;AAC/B,WAAK,IAAI,EAAE;AACX,WAAK,IAAI,kBAAkB,OAAO,MAAM,OAAO,MAAM;AAAA,IACvD;AAEA,QAAI,OAAO,SAAS,SAAS,GAAG;AAC9B,WAAK,KAAK,aAAa,OAAO,SAAS,KAAK,IAAI,CAAC,EAAE;AAAA,IACrD;AAAA,EACF;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/commands/converters.ts"],
|
|
4
|
-
"sourcesContent": ["import { Flags } from '@oclif/core';\nimport { printTable } from '@oclif/table';\nimport { BaseCommand } from '../base-command.js';\nimport { apiGet } from '../lib/api-client.js';\nimport type { ConverterEntry } from '../lib/types.js';\n\nexport default class Converters extends BaseCommand {\n static override description = 'List all supported conversion formats';\n\n static override examples = [\n '<%= config.bin %> converters',\n '<%= config.bin %> converters --tier 1',\n ];\n\n static override enableJsonFlag = true;\n\n static override flags = {\n tier: Flags.string({\n char: 't',\n description: 'Filter by tier',\n options: ['1', '2', '3'],\n }),\n };\n\n async run(): Promise<ConverterEntry[]> {\n const { flags } = await this.parse(Converters);\n this.requireAuth();\n\n let entries = await apiGet<ConverterEntry[]>('/api/converters');\n\n if (flags.tier) {\n const tierNum = Number.parseInt(flags.tier, 10);\n entries = entries.filter((e) => e.tier === tierNum);\n }\n\n printTable({\n data: entries.map((e) => ({\n ID: e.id,\n Name: e.name,\n Tier: String(e.tier),\n 'Output Path': e.outputPath,\n })),\n columns: ['ID', 'Name', 'Tier', 'Output Path'],\n });\n\n return entries;\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;AAAA,SAAS,aAAa;AACtB,SAAS,kBAAkB;AAK3B,IAAqB,aAArB,MAAqB,oBAAmB,YAAY;AAAA,EAClD,OAAgB,cAAc;AAAA,EAE9B,OAAgB,WAAW;AAAA,IACzB;AAAA,IACA;AAAA,EACF;AAAA,EAEA,OAAgB,iBAAiB;AAAA,EAEjC,OAAgB,QAAQ;AAAA,IACtB,MAAM,MAAM,OAAO;AAAA,MACjB,MAAM;AAAA,MACN,aAAa;AAAA,MACb,SAAS,CAAC,KAAK,KAAK,GAAG;AAAA,IACzB,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,MAAiC;AACrC,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,WAAU;AAC7C,SAAK,YAAY;AAEjB,QAAI,UAAU,MAAM,OAAyB,iBAAiB;AAE9D,QAAI,MAAM,MAAM;AACd,YAAM,UAAU,OAAO,SAAS,MAAM,MAAM,EAAE;AAC9C,gBAAU,QAAQ,OAAO,CAAC,MAAM,EAAE,SAAS,OAAO;AAAA,IACpD;AAEA,eAAW;AAAA,MACT,MAAM,QAAQ,IAAI,CAAC,OAAO;AAAA,QACxB,IAAI,EAAE;AAAA,QACN,MAAM,EAAE;AAAA,QACR,MAAM,OAAO,EAAE,IAAI;AAAA,QACnB,eAAe,EAAE;AAAA,MACnB,EAAE;AAAA,MACF,SAAS,CAAC,MAAM,QAAQ,QAAQ,aAAa;AAAA,IAC/C,CAAC;AAED,WAAO;AAAA,EACT;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/commands/crons/list.ts"],
|
|
4
|
-
"sourcesContent": ["import { printTable } from '@oclif/table';\nimport { BaseCommand } from '../../base-command.js';\n// Metadata-only import: pulling the full manual-tasks module here would drag the\n// heavy worker handlers (postgres/OTel/Sentry) into this command's bundle chunk\n// and crash a standalone npm install at load. See manual-tasks-meta.ts.\nimport { MANUAL_TASK_META } from '../../lib/manual-tasks-meta.js';\n\nexport default class CronsList extends BaseCommand {\n static override description = 'List manually-runnable maintenance tasks';\n\n static override examples = [\n '<%= config.bin %> crons list',\n ];\n\n async run(): Promise<void> {\n await this.parse(CronsList);\n printTable({\n data: MANUAL_TASK_META.map((t) => ({\n Name: t.name,\n 'Scheduled by': t.scheduledBy,\n Description: t.description,\n })),\n columns: ['Name', 'Scheduled by', 'Description'],\n });\n this.log('');\n this.log('Scheduled crons run in Supabase pg_cron \u2014 audit them with:');\n this.log(\" psql \\\"$DATABASE_URL\\\" -c 'select jobname, schedule, active from cron.job;'\");\n this.log('Run any task above on demand with: rulemetric crons run <name>');\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;AAAA,SAAS,kBAAkB;AAO3B,IAAqB,YAArB,MAAqB,mBAAkB,YAAY;AAAA,EAC/C,OAAgB,cAAc;AAAA,EAE9B,OAAgB,WAAW;AAAA,IACvB;AAAA,EACJ;AAAA,EAEA,MAAM,MAAqB;AACvB,UAAM,KAAK,MAAM,UAAS;AAC1B,eAAW;AAAA,MACP,MAAM,iBAAiB,IAAI,CAAC,OAAO;AAAA,QAC/B,MAAM,EAAE;AAAA,QACR,gBAAgB,EAAE;AAAA,QAClB,aAAa,EAAE;AAAA,MACnB,EAAE;AAAA,MACF,SAAS,CAAC,QAAQ,gBAAgB,aAAa;AAAA,IACnD,CAAC;AACD,SAAK,IAAI,EAAE;AACX,SAAK,IAAI,iEAA4D;AACrE,SAAK,IAAI,6EAA+E;AACxF,SAAK,IAAI,gEAAgE;AAAA,EAC7E;AACJ;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/commands/crons/run.ts"],
|
|
4
|
-
"sourcesContent": ["import { Args, Flags } from '@oclif/core';\nimport { BaseCommand } from '../../base-command.js';\n// Metadata-only static import (dependency-free). The executor (runManualTask) and\n// its heavy db/OTel/Sentry handlers are lazy-imported inside run(), so loading\n// this command never pulls `postgres` into its bundle chunk and a standalone\n// npm install no longer crashes at module-load. See manual-tasks-meta.ts.\nimport { MANUAL_TASK_META } from '../../lib/manual-tasks-meta.js';\n\nexport default class CronsRun extends BaseCommand {\n static override description = 'Run a maintenance task synchronously, right now';\n\n static override examples = [\n '<%= config.bin %> crons run cron_check_changelog',\n '<%= config.bin %> crons run cron_suggest_instructions --quiet',\n ];\n\n static override args = {\n name: Args.string({\n description: 'Task name (run `rulemetric crons list` to see all)',\n required: true,\n }),\n };\n\n static override flags = {\n quiet: Flags.boolean({\n char: 'q',\n description: 'Suppress per-line log output; print summary only',\n }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(CronsRun);\n this.requireAuth();\n\n // Validate against the dependency-free metadata first, so an unknown task\n // never triggers the lazy load of the heavy executor below.\n const def = MANUAL_TASK_META.find((t) => t.name === args.name);\n if (!def) {\n this.error(`Unknown task: ${args.name}\\nRun \\`rulemetric crons list\\` to see available tasks.`);\n }\n\n // Lazy-load the executor only when a task is actually run. This keeps the\n // heavy handler chunk (postgres/OTel/Sentry) out of this command's static\n // import graph. Executing a task still needs the worker runtime\n // (DATABASE_URL + those deps); a standalone npm install lacks them, so\n // turn the raw MODULE_NOT_FOUND into an actionable message.\n let runManualTask: typeof import('../../lib/manual-tasks.js').runManualTask;\n try {\n ({ runManualTask } = await import('../../lib/manual-tasks.js'));\n } catch (err) {\n const code = (err as { code?: string } | null)?.code;\n if (code === 'ERR_MODULE_NOT_FOUND' || code === 'MODULE_NOT_FOUND') {\n this.error(\n `\\`crons run\\` needs the worker runtime, which isn't available in this install.\\n` +\n `These maintenance tasks connect to the database directly \u2014 run them from a full ` +\n `RuleMetric checkout with DATABASE_URL and the worker dependencies installed.`,\n );\n }\n throw err;\n }\n\n this.log(`\u25B6 Running ${def.name} \u2026`);\n const startedAt = Date.now();\n const result = await runManualTask(args.name);\n\n if (!flags.quiet) {\n for (const line of result.logs) {\n const prefix = line.level === 'error' || line.level === 'warn' ? `[${line.level}]` : '';\n this.log(` ${prefix} ${line.message}`);\n }\n }\n\n const seconds = ((result.durationMs ?? Date.now() - startedAt) / 1000).toFixed(1);\n if (result.ok) {\n this.log(`\u2713 ${def.name} completed in ${seconds}s (${result.logs.length} log line${result.logs.length === 1 ? '' : 's'})`);\n } else {\n this.error(`\u2717 ${def.name} failed after ${seconds}s: ${result.error}`);\n }\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;AAAA,SAAS,MAAM,aAAa;AAQ5B,IAAqB,WAArB,MAAqB,kBAAiB,YAAY;AAAA,EAC9C,OAAgB,cAAc;AAAA,EAE9B,OAAgB,WAAW;AAAA,IACvB;AAAA,IACA;AAAA,EACJ;AAAA,EAEA,OAAgB,OAAO;AAAA,IACnB,MAAM,KAAK,OAAO;AAAA,MACd,aAAa;AAAA,MACb,UAAU;AAAA,IACd,CAAC;AAAA,EACL;AAAA,EAEA,OAAgB,QAAQ;AAAA,IACpB,OAAO,MAAM,QAAQ;AAAA,MACjB,MAAM;AAAA,MACN,aAAa;AAAA,IACjB,CAAC;AAAA,EACL;AAAA,EAEA,MAAM,MAAqB;AACvB,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,KAAK,MAAM,SAAQ;AACjD,SAAK,YAAY;AAIjB,UAAM,MAAM,iBAAiB,KAAK,CAAC,MAAM,EAAE,SAAS,KAAK,IAAI;AAC7D,QAAI,CAAC,KAAK;AACN,WAAK,MAAM,iBAAiB,KAAK,IAAI;AAAA,sDAAyD;AAAA,IAClG;AAOA,QAAI;AACJ,QAAI;AACA,OAAC,EAAE,cAAc,IAAI,MAAM,OAAO,2BAA2B;AAAA,IACjE,SAAS,KAAK;AACV,YAAM,OAAQ,KAAkC;AAChD,UAAI,SAAS,0BAA0B,SAAS,oBAAoB;AAChE,aAAK;AAAA,UACD;AAAA;AAAA,QAGJ;AAAA,MACJ;AACA,YAAM;AAAA,IACV;AAEA,SAAK,IAAI,kBAAa,IAAI,IAAI,SAAI;AAClC,UAAM,YAAY,KAAK,IAAI;AAC3B,UAAM,SAAS,MAAM,cAAc,KAAK,IAAI;AAE5C,QAAI,CAAC,MAAM,OAAO;AACd,iBAAW,QAAQ,OAAO,MAAM;AAC5B,cAAM,SAAS,KAAK,UAAU,WAAW,KAAK,UAAU,SAAS,IAAI,KAAK,KAAK,MAAM;AACrF,aAAK,IAAI,KAAK,MAAM,IAAI,KAAK,OAAO,EAAE;AAAA,MAC1C;AAAA,IACJ;AAEA,UAAM,YAAY,OAAO,cAAc,KAAK,IAAI,IAAI,aAAa,KAAM,QAAQ,CAAC;AAChF,QAAI,OAAO,IAAI;AACX,WAAK,IAAI,UAAK,IAAI,IAAI,iBAAiB,OAAO,MAAM,OAAO,KAAK,MAAM,YAAY,OAAO,KAAK,WAAW,IAAI,KAAK,GAAG,GAAG;AAAA,IAC5H,OAAO;AACH,WAAK,MAAM,UAAK,IAAI,IAAI,iBAAiB,OAAO,MAAM,OAAO,KAAK,EAAE;AAAA,IACxE;AAAA,EACJ;AACJ;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/commands/dashboard.ts"],
|
|
4
|
-
"sourcesContent": ["import { Flags } from '@oclif/core';\nimport { BaseCommand } from '../base-command.js';\n\nexport default class Dashboard extends BaseCommand {\n static override description = 'Interactive TUI dashboard showing session analytics, outcomes, friction, and insights';\n\n static override examples = [\n '<%= config.bin %> dashboard',\n '<%= config.bin %> dashboard --period 30days',\n '<%= config.bin %> dashboard --launcher',\n ];\n\n static override flags = {\n period: Flags.string({\n char: 'p',\n default: 'week',\n options: ['today', 'week', '30days', 'month', 'all'],\n description: 'Initial time period',\n }),\n launcher: Flags.boolean({\n char: 'l',\n default: false,\n description: 'Open the launcher overlay immediately',\n }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(Dashboard);\n const { renderDashboard } = await import('../dashboard/Dashboard.js');\n await renderDashboard(\n flags.period as 'today' | 'week' | '30days' | 'month' | 'all',\n { openLauncher: flags.launcher }\n );\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;AAAA,SAAS,aAAa;AAGtB,IAAqB,YAArB,MAAqB,mBAAkB,YAAY;AAAA,EACjD,OAAgB,cAAc;AAAA,EAE9B,OAAgB,WAAW;AAAA,IACzB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EAEA,OAAgB,QAAQ;AAAA,IACtB,QAAQ,MAAM,OAAO;AAAA,MACnB,MAAM;AAAA,MACN,SAAS;AAAA,MACT,SAAS,CAAC,SAAS,QAAQ,UAAU,SAAS,KAAK;AAAA,MACnD,aAAa;AAAA,IACf,CAAC;AAAA,IACD,UAAU,MAAM,QAAQ;AAAA,MACtB,MAAM;AAAA,MACN,SAAS;AAAA,MACT,aAAa;AAAA,IACf,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,UAAS;AAC5C,UAAM,EAAE,gBAAgB,IAAI,MAAM,OAAO,2BAA2B;AACpE,UAAM;AAAA,MACJ,MAAM;AAAA,MACN,EAAE,cAAc,MAAM,SAAS;AAAA,IACjC;AAAA,EACF;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../src/commands/diagnostics.ts"],
|
|
4
|
-
"sourcesContent": ["import { spawnSync } from 'node:child_process';\nimport { existsSync, readFileSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { BaseCommand } from '../base-command.js';\nimport { DEFAULT_API_URL } from '../lib/api-client.js';\nimport { loadEnvFileAuth, isAuthenticated } from '../lib/auth.js';\nimport { isGatewayListening, GATEWAY_PORT, MITMPROXY_PORT } from '../lib/gateway-lifecycle.js';\nimport { diagnose, isProxyBreakingNode } from '../lib/diagnostics.js';\n\n/**\n * `rulemetric diagnostics` \u2014 a doctor for the \"capture isn't working / API\n * returns 502\" class. Its core move is comparing DIRECT reachability against\n * reachability THROUGH the local proxy: when direct works but the proxy path\n * fails, the user's own gateway (:8787) is producing the 502, not production.\n */\nexport default class Diagnostics extends BaseCommand {\n static override description =\n 'Diagnose capture / proxy / connectivity problems (e.g. a client-side \"502 Bad Gateway\")';\n\n static override examples = ['<%= config.bin %> diagnostics'];\n\n private baseUrl(): string {\n return process.env.RULEMETRIC_API_URL ?? loadEnvFileAuth().apiUrl ?? DEFAULT_API_URL;\n }\n\n /** GET /health with the proxy bypassed \u2014 \"is production reachable at all?\" */\n private async checkDirect(): Promise<boolean> {\n const savedHttps = process.env.HTTPS_PROXY;\n const savedHttp = process.env.HTTP_PROXY;\n delete process.env.HTTPS_PROXY;\n delete process.env.HTTP_PROXY;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), 8000);\n try {\n const res = await globalThis.fetch(`${this.baseUrl()}/health`, { signal: controller.signal });\n return res.ok;\n } catch {\n return false;\n } finally {\n clearTimeout(timer);\n if (savedHttps !== undefined) process.env.HTTPS_PROXY = savedHttps;\n if (savedHttp !== undefined) process.env.HTTP_PROXY = savedHttp;\n }\n }\n\n /** Resolve the configured proxy: env HTTPS_PROXY, else the project settings files. */\n private configuredProxy(): string | null {\n if (process.env.HTTPS_PROXY) return process.env.HTTPS_PROXY;\n // settings.local.json (machine-local, where current installs write the\n // proxy env) wins over the shared settings.json (legacy installs) \u2014\n // mirrors Claude Code's merge order.\n for (const fileName of ['settings.local.json', 'settings.json']) {\n const settingsPath = join(process.cwd(), '.claude', fileName);\n if (!existsSync(settingsPath)) continue;\n try {\n const parsed = JSON.parse(readFileSync(settingsPath, 'utf8')) as {\n env?: { HTTPS_PROXY?: string };\n };\n if (parsed.env?.HTTPS_PROXY) return parsed.env.HTTPS_PROXY;\n } catch {\n /* ignore malformed settings */\n }\n }\n return null;\n }\n\n /** GET /health THROUGH the proxy via curl (Node fetch won't honor HTTPS_PROXY). */\n private checkThroughProxy(proxyUrl: string): boolean | null {\n const res = spawnSync(\n 'curl',\n ['-sS', '-x', proxyUrl, '--max-time', '8', '-o', '/dev/null', '-w', '%{http_code}', `${this.baseUrl()}/health`],\n { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] },\n );\n if (res.error || typeof res.stdout !== 'string') return null; // curl missing \u2192 inconclusive\n return res.stdout.trim() === '200';\n }\n\n async run(): Promise<void> {\n await this.parse(Diagnostics);\n\n const nodeVersion = process.version;\n const proxyUrl = this.configuredProxy();\n const httpsProxySet = proxyUrl != null;\n\n const [directApiOk, gatewayAlive, mitmproxyAlive] = await Promise.all([\n this.checkDirect(),\n isGatewayListening(GATEWAY_PORT),\n isGatewayListening(MITMPROXY_PORT),\n ]);\n const proxyPathOk = httpsProxySet && proxyUrl ? this.checkThroughProxy(proxyUrl) : null;\n\n const line = (label: string, ok: boolean | null, detail: string) => {\n const mark = ok === null ? '\u2013' : ok ? '[OK]' : '[!!]';\n this.log(` ${mark} ${label.padEnd(22)} ${detail}`);\n };\n\n this.log('RuleMetric diagnostics');\n this.log('');\n line('Node', !isProxyBreakingNode(nodeVersion), `${nodeVersion}${isProxyBreakingNode(nodeVersion) ? ' (< 20.11 \u2014 breaks the bundled proxy)' : ''}`);\n line('API (direct)', directApiOk, `${this.baseUrl()}/health ${directApiOk ? 'reachable' : 'UNREACHABLE'}`);\n line('Authenticated', isAuthenticated(), isAuthenticated() ? 'yes' : 'no \u2014 run `rulemetric auth login`');\n line('Proxy configured', httpsProxySet ? true : null, httpsProxySet ? (proxyUrl as string) : 'no HTTPS_PROXY set');\n if (httpsProxySet) {\n line('Gateway :' + GATEWAY_PORT, gatewayAlive, gatewayAlive ? 'listening' : 'NOT listening');\n line('mitmproxy :' + MITMPROXY_PORT, mitmproxyAlive, mitmproxyAlive ? 'listening' : 'not listening (gateway should route direct)');\n line('API (via proxy)', proxyPathOk, proxyPathOk === null ? 'inconclusive (curl unavailable)' : proxyPathOk ? 'reachable' : 'FAILED \u2014 502/blocked through your proxy');\n }\n\n const d = diagnose({ nodeVersion, directApiOk, httpsProxySet, gatewayAlive, mitmproxyAlive, proxyPathOk });\n this.log('');\n const badge = d.severity === 'ok' ? '[OK]' : d.severity === 'warn' ? '[!!]' : '[XX]';\n this.log(`${badge} ${d.headline}`);\n for (const h of d.hints) this.log(` \u2022 ${h}`);\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/commands/eval-targets/create.ts"],
|
|
4
|
-
"sourcesContent": ["import { Flags } from '@oclif/core';\nimport { readFileSync } from 'node:fs';\nimport { BaseCommand } from '../../base-command.js';\nimport { apiPost } from '../../lib/api-client.js';\n\nexport default class EvalTargetCreate extends BaseCommand {\n static override description = 'Create an eval target (instruction, skill, prompt, or plan to test)';\n\n static override examples = [\n '<%= config.bin %> eval-targets create --name my-rules --type instruction --file ./CLAUDE.md',\n '<%= config.bin %> eval-targets create --name my-prompt --type prompt --content \"Always use TypeScript\"',\n ];\n\n static override flags = {\n name: Flags.string({ char: 'n', description: 'Name for the eval target', required: true }),\n type: Flags.string({ char: 't', description: 'Target type', options: ['instruction', 'skill', 'prompt', 'plan'], required: true }),\n file: Flags.string({ char: 'f', description: 'Path to content file' }),\n content: Flags.string({ char: 'c', description: 'Content string (alternative to --file)' }),\n description: Flags.string({ char: 'd', description: 'Description of the target', default: '' }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(EvalTargetCreate);\n this.requireAuth();\n\n let content: string;\n if (flags.file) {\n content = readFileSync(flags.file, 'utf-8');\n } else if (flags.content) {\n content = flags.content;\n } else {\n this.error('Provide either --file or --content');\n }\n\n const result = await apiPost<{ id: string; name: string; version: number }>('/api/eval-targets', {\n name: flags.name,\n type: flags.type,\n content,\n description: flags.description,\n });\n\n this.log(`Created eval target: ${result.name} (${result.id}) v${result.version}`);\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;AAAA,SAAS,aAAa;AACtB,SAAS,oBAAoB;AAI7B,IAAqB,mBAArB,MAAqB,0BAAyB,YAAY;AAAA,EACxD,OAAgB,cAAc;AAAA,EAE9B,OAAgB,WAAW;AAAA,IACzB;AAAA,IACA;AAAA,EACF;AAAA,EAEA,OAAgB,QAAQ;AAAA,IACtB,MAAM,MAAM,OAAO,EAAE,MAAM,KAAK,aAAa,4BAA4B,UAAU,KAAK,CAAC;AAAA,IACzF,MAAM,MAAM,OAAO,EAAE,MAAM,KAAK,aAAa,eAAe,SAAS,CAAC,eAAe,SAAS,UAAU,MAAM,GAAG,UAAU,KAAK,CAAC;AAAA,IACjI,MAAM,MAAM,OAAO,EAAE,MAAM,KAAK,aAAa,uBAAuB,CAAC;AAAA,IACrE,SAAS,MAAM,OAAO,EAAE,MAAM,KAAK,aAAa,yCAAyC,CAAC;AAAA,IAC1F,aAAa,MAAM,OAAO,EAAE,MAAM,KAAK,aAAa,6BAA6B,SAAS,GAAG,CAAC;AAAA,EAChG;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,iBAAgB;AACnD,SAAK,YAAY;AAEjB,QAAI;AACJ,QAAI,MAAM,MAAM;AACd,gBAAU,aAAa,MAAM,MAAM,OAAO;AAAA,IAC5C,WAAW,MAAM,SAAS;AACxB,gBAAU,MAAM;AAAA,IAClB,OAAO;AACL,WAAK,MAAM,oCAAoC;AAAA,IACjD;AAEA,UAAM,SAAS,MAAM,QAAuD,qBAAqB;AAAA,MAC/F,MAAM,MAAM;AAAA,MACZ,MAAM,MAAM;AAAA,MACZ;AAAA,MACA,aAAa,MAAM;AAAA,IACrB,CAAC;AAED,SAAK,IAAI,wBAAwB,OAAO,IAAI,KAAK,OAAO,EAAE,MAAM,OAAO,OAAO,EAAE;AAAA,EAClF;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/commands/eval-targets/list.ts"],
|
|
4
|
-
"sourcesContent": ["import { Flags } from '@oclif/core';\nimport { printTable } from '@oclif/table';\nimport { BaseCommand } from '../../base-command.js';\nimport { apiGet } from '../../lib/api-client.js';\nimport { formatDate, truncate } from '../../lib/output.js';\n\ninterface EvalTarget {\n id: string;\n name: string;\n type: string;\n version: number;\n description: string;\n updatedAt: string;\n}\n\nexport default class EvalTargetList extends BaseCommand {\n static override description = 'List eval targets';\n\n static override examples = [\n '<%= config.bin %> eval-targets list',\n '<%= config.bin %> eval-targets list --type instruction',\n ];\n\n static override flags = {\n type: Flags.string({ char: 't', description: 'Filter by type', options: ['instruction', 'skill', 'prompt', 'plan'] }),\n };\n\n async run(): Promise<void> {\n const { flags } = await this.parse(EvalTargetList);\n this.requireAuth();\n\n const query = flags.type ? `?type=${flags.type}` : '';\n const results = await apiGet<EvalTarget[]>(`/api/eval-targets${query}`);\n\n if (results.length === 0) {\n this.log('No eval targets found. Create one with `rulemetric eval-targets create`.');\n return;\n }\n\n printTable({\n data: results.map((t) => ({\n Name: truncate(t.name, 30),\n Type: t.type,\n Version: `v${t.version}`,\n Description: truncate(t.description, 40),\n Updated: formatDate(t.updatedAt),\n })),\n columns: ['Name', 'Type', 'Version', 'Description', 'Updated'],\n });\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA,SAAS,aAAa;AACtB,SAAS,kBAAkB;AAc3B,IAAqB,iBAArB,MAAqB,wBAAuB,YAAY;AAAA,EACtD,OAAgB,cAAc;AAAA,EAE9B,OAAgB,WAAW;AAAA,IACzB;AAAA,IACA;AAAA,EACF;AAAA,EAEA,OAAgB,QAAQ;AAAA,IACtB,MAAM,MAAM,OAAO,EAAE,MAAM,KAAK,aAAa,kBAAkB,SAAS,CAAC,eAAe,SAAS,UAAU,MAAM,EAAE,CAAC;AAAA,EACtH;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,IAAI,MAAM,KAAK,MAAM,eAAc;AACjD,SAAK,YAAY;AAEjB,UAAM,QAAQ,MAAM,OAAO,SAAS,MAAM,IAAI,KAAK;AACnD,UAAM,UAAU,MAAM,OAAqB,oBAAoB,KAAK,EAAE;AAEtE,QAAI,QAAQ,WAAW,GAAG;AACxB,WAAK,IAAI,0EAA0E;AACnF;AAAA,IACF;AAEA,eAAW;AAAA,MACT,MAAM,QAAQ,IAAI,CAAC,OAAO;AAAA,QACxB,MAAM,SAAS,EAAE,MAAM,EAAE;AAAA,QACzB,MAAM,EAAE;AAAA,QACR,SAAS,IAAI,EAAE,OAAO;AAAA,QACtB,aAAa,SAAS,EAAE,aAAa,EAAE;AAAA,QACvC,SAAS,WAAW,EAAE,SAAS;AAAA,MACjC,EAAE;AAAA,MACF,SAAS,CAAC,QAAQ,QAAQ,WAAW,eAAe,SAAS;AAAA,IAC/D,CAAC;AAAA,EACH;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../../../packages/telemetry/src/init.ts", "../../../../../packages/telemetry/src/otlp-headers.ts", "../../../../../packages/telemetry/src/hono-middleware.ts", "../../../../../packages/telemetry/src/span-attributes.ts", "../../../../../packages/telemetry/src/sentry.ts", "../../../src/commands/evals/agent.ts"],
|
|
4
|
-
"sourcesContent": ["import { trace, context, type Tracer } from '@opentelemetry/api';\nimport { NodeSDK } from '@opentelemetry/sdk-node';\nimport { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';\nimport {\n BatchSpanProcessor,\n ConsoleSpanExporter,\n SimpleSpanProcessor,\n} from '@opentelemetry/sdk-trace-node';\nimport { Resource } from '@opentelemetry/resources';\nimport { ATTR_SERVICE_NAME, ATTR_SERVICE_VERSION } from '@opentelemetry/semantic-conventions';\nimport { parseOtlpHeaders } from './otlp-headers.js';\n\nlet sdk: NodeSDK | null = null;\n\nexport interface TelemetryConfig {\n serviceName: string;\n serviceVersion?: string;\n}\n\n/**\n * Boot states for `initTelemetry`. Returned discriminator lets callers\n * emit a precise boot log:\n * - 'otlp' \u2014 spans ship over OTLP to a real backend (Honeycomb etc.)\n * - 'console' \u2014 spans print to stdout as JSON (Fly logs ingest them);\n * the \"open + zero third-party\" default\n * - 'off' \u2014 telemetry globally disabled (TELEMETRY_ENABLED=false)\n * OR a prior `initTelemetry()` already booted the SDK\n * in this process (idempotent skip)\n */\nexport type TelemetryBootState = 'otlp' | 'console' | 'silent' | 'off';\n\nexport function isTelemetryEnabled(): boolean {\n return process.env.TELEMETRY_ENABLED !== 'false';\n}\n\n/**\n * Initialize OpenTelemetry tracing. Two transport modes, both built on\n * the same OTel SDK \u2014 only the exporter changes:\n *\n * - OTLP backend \u2192 set `OTEL_EXPORTER_OTLP_ENDPOINT` (+ optional\n * `OTEL_EXPORTER_OTLP_HEADERS` for vendor auth)\n * - Console (stdout) \u2192 the default when no endpoint is set\n *\n * The console path is intentionally on-by-default. Without a real backend\n * configured, spans are written to stdout as JSON and end up in Fly's log\n * stream alongside everything else \u2014 searchable, structured, and you\n * stay inside the open OpenTelemetry spec without paying a third party.\n * Swap to OTLP later by setting one env var; no code change needed.\n *\n * Returns `'off'` when:\n * - TELEMETRY_ENABLED=false (operator kill switch \u2014 beats any config)\n * - The SDK was already started in this process (idempotent skip)\n *\n * See packages/telemetry/src/init.test.ts for the full state table.\n */\nexport function initTelemetry(config: TelemetryConfig): TelemetryBootState {\n if (!isTelemetryEnabled()) {\n return 'off';\n }\n if (sdk !== null) {\n // OTel's global tracer provider gets set on first start(); calling\n // start() twice triggers an SDK warning. Treat second-call as a no-op.\n return 'off';\n }\n\n const resource = new Resource({\n [ATTR_SERVICE_NAME]: config.serviceName,\n [ATTR_SERVICE_VERSION]: config.serviceVersion ?? '0.1.0',\n });\n\n const endpoint = process.env.OTEL_EXPORTER_OTLP_ENDPOINT;\n let mode: TelemetryBootState;\n let spanProcessor: BatchSpanProcessor | SimpleSpanProcessor | undefined;\n\n if (endpoint) {\n // OTLP path. Headers via OTEL_EXPORTER_OTLP_HEADERS (W3C convention,\n // comma-separated key=value pairs). Parsed explicitly rather than\n // relying on SDK-version-specific auto-discovery \u2014 predictable boot\n // matters more than tracking whatever the current default is.\n // Honeycomb: x-honeycomb-team=hcaik_xxx (plus optional dataset)\n // Grafana Cloud: authorization=Basic <base64creds>\n const headers = parseOtlpHeaders(process.env.OTEL_EXPORTER_OTLP_HEADERS);\n const exporter = new OTLPTraceExporter({\n url: `${endpoint}/v1/traces`,\n headers,\n });\n spanProcessor = new BatchSpanProcessor(exporter);\n mode = 'otlp';\n } else if (process.env.OTEL_SPAN_EXPORT === 'none') {\n // Silent path: trace context still propagates (so trace IDs are available\n // for correlation and an OTLP endpoint can be added later with zero code\n // change), but NO span processor is registered \u2014 nothing is written to\n // stdout. This exists because the ConsoleSpanExporter below writes one\n // JSON span per ended span, and on the local launchd API (no OTLP\n // endpoint, fixed log file, no Fly-managed rotation) that grew api-stdout\n // to 370MB / ~400k spans. Set OTEL_SPAN_EXPORT=none on that process; Fly\n // leaves it unset so console spans stay grep-able in its managed log stream.\n spanProcessor = undefined;\n mode = 'silent';\n } else {\n // Console (stdout) path. SimpleSpanProcessor \u2014 not batched \u2014 so spans\n // appear in chronological order in the log stream. Acceptable cost for\n // tracing: a span is written per ended span, vs. a batched POST for OTLP.\n // Logs that would otherwise need a UI to make sense (trace tree\n // visualization) are still queryable via `flyctl logs | grep traceId=...`\n // or any log-aggregator that ingests Fly's stream.\n const exporter = new ConsoleSpanExporter();\n spanProcessor = new SimpleSpanProcessor(exporter);\n mode = 'console';\n }\n\n sdk = new NodeSDK({\n resource,\n spanProcessors: spanProcessor ? [spanProcessor] : [],\n });\n\n sdk.start();\n return mode;\n}\n\nexport async function shutdownTelemetry(): Promise<void> {\n if (sdk) {\n await sdk.shutdown();\n sdk = null;\n }\n}\n\nexport function getTracer(name?: string): Tracer {\n return trace.getTracer(name ?? 'rulemetric');\n}\n\nexport function getTraceId(): string | undefined {\n const span = trace.getSpan(context.active());\n return span?.spanContext().traceId;\n}\n", "// Parse the `OTEL_EXPORTER_OTLP_HEADERS` env var into a plain headers object\n// that the OTLP exporter constructor accepts.\n//\n// OpenTelemetry SDK env-vars spec (\u00A710) defines this as a comma-separated list\n// of `key=value` pairs. We parse it ourselves rather than relying on the\n// `@opentelemetry/exporter-trace-otlp-http` package's auto-discovery, because\n// that auto-discovery has shifted between SDK versions and we want predictable\n// behaviour at boot.\n//\n// Real-world usage:\n// - Honeycomb: `x-honeycomb-team=hcaik_xxx` (and optionally `,x-honeycomb-dataset=...`)\n// - Grafana Cloud: `authorization=Basic <base64>` (note: base64 padding can be `==`)\n//\n// Edge cases (covered by `otlp-headers.test.ts`):\n// - undefined or empty \u2192 {} (caller will get a no-headers exporter)\n// - whitespace around `=` and `,` is trimmed (operator-friendly)\n// - only the first `=` is the separator, so base64 padding (==) survives in\n// values\n// - malformed entries (no `=`) are skipped silently\n// - empty keys are dropped (never inject a \"\" header)\n// - duplicate keys: last value wins, matching URL search-params semantics\n\nexport function parseOtlpHeaders(raw: string | undefined): Record<string, string> {\n if (!raw) return {};\n const out: Record<string, string> = {};\n for (const entry of raw.split(',')) {\n const eq = entry.indexOf('=');\n if (eq === -1) continue;\n const key = entry.slice(0, eq).trim();\n const value = entry.slice(eq + 1).trim();\n if (!key) continue;\n out[key] = value;\n }\n return out;\n}\n", "import { SpanKind, SpanStatusCode } from '@opentelemetry/api';\nimport type { MiddlewareHandler } from 'hono';\nimport { getTracer, isTelemetryEnabled } from './init.js';\n\nexport function telemetryMiddleware(): MiddlewareHandler {\n return async (c, next) => {\n if (!isTelemetryEnabled()) {\n await next();\n return;\n }\n\n const tracer = getTracer();\n const method = c.req.method;\n const path = c.req.path;\n\n await tracer.startActiveSpan(\n `${method} ${path}`,\n {\n kind: SpanKind.SERVER,\n attributes: {\n 'http.method': method,\n 'http.url': c.req.url,\n 'http.route': path,\n },\n },\n async (span) => {\n try {\n await next();\n\n span.setAttribute('http.status_code', c.res.status);\n\n const userId = c.get('userId' as never);\n if (userId) {\n span.setAttribute('rulemetric.user_id', userId as string);\n }\n\n if (c.res.status >= 400) {\n span.setStatus({ code: SpanStatusCode.ERROR });\n }\n } catch (err) {\n span.setStatus({ code: SpanStatusCode.ERROR });\n span.recordException(err as Error);\n throw err;\n } finally {\n span.end();\n }\n },\n );\n };\n}\n", "import { trace, context as otelContext } from '@opentelemetry/api';\n\n/**\n * Set attributes on the currently-active span, if one exists. Safe no-op\n * when no span is active (e.g. running outside of a Hono request handler,\n * or with telemetry disabled).\n *\n * Use this from business-logic code that wants to expose a discriminator\n * for telemetry queries \u2014 e.g. \"which branch did `resolveCallerOrgId` take\"\n * in `apps/api/src/routes/sessions.ts`. Span attributes are searchable in\n * any OpenTelemetry backend (Honeycomb, Grafana Cloud, ...) and in\n * `flyctl logs` when the console exporter is active.\n *\n * Keeping this thin wrapper in the telemetry package means application\n * code never imports `@opentelemetry/api` directly \u2014 the package boundary\n * stays the only place that knows about the OTel SDK shape.\n */\nexport function setSpanAttributes(\n attributes: Record<string, string | number | boolean>,\n): void {\n const span = trace.getSpan(otelContext.active());\n if (!span) return;\n for (const [key, value] of Object.entries(attributes)) {\n span.setAttribute(key, value);\n }\n}\n", "// Thin wrapper around @sentry/node so callers don't have to guard every\n// captureException with `if (process.env.SENTRY_DSN)`. The wrapper handles\n// three concerns:\n//\n// 1. Init only when SENTRY_DSN is set. Otherwise every entry point becomes\n// a silent no-op \u2014 never throws, never logs noise, never opens a\n// network transport.\n// 2. Idempotent init. Double-init is a Sentry SDK foot-gun (the second\n// call wins, but the warning lands at runtime). The module-level\n// `enabled` flag short-circuits the second call.\n// 3. tracesSampleRate = 0 by default. We already have OpenTelemetry\n// shipping spans to a tracing backend; paying Sentry's quota for the\n// same data isn't useful. Sentry's job here is errors-only.\n//\n// Wiring:\n// - `apps/api/src/index.ts` \u2192 initSentry({ serviceName: 'rulemetric-api' })\n// - `apps/api/src/middleware/auth.ts` \u2192 setSentryUser(userId) after JWT verify\n// - `apps/cli/src/commands/evals/agent.ts` \u2192 initSentry({ serviceName: 'rulemetric-agent' })\n// (the thin-agent worker \u2014 Phase 4c moved the init here from the old\n// graphile `listen.ts`; that path no longer inits Sentry)\n//\n// All four hooks are no-op-safe when DSN is unset, so the wiring doesn't\n// require feature-flag plumbing.\n\nimport * as Sentry from '@sentry/node';\n\nlet enabled = false;\n\nexport interface InitSentryConfig {\n serviceName: string;\n}\n\n/**\n * Initialize Sentry if SENTRY_DSN is set. Presence of the DSN is now the\n * single switch: set it (incl. as a Fly secret in prod) to enable error\n * capture, leave it unset for a silent no-op.\n *\n * Previously gated to non-production by policy; that gate was dropped so\n * production errors actually get reported. Errors-only (`tracesSampleRate:\n * 0`) keeps Sentry quota bounded \u2014 OpenTelemetry still owns tracing.\n *\n * Returns true when init actually ran, false when it was skipped (DSN unset\n * or a prior call already initialized). Idempotent.\n */\nexport function initSentry(config: InitSentryConfig): boolean {\n if (enabled) return false;\n const dsn = process.env.SENTRY_DSN;\n if (!dsn) return false;\n\n Sentry.init({\n dsn,\n serverName: config.serviceName,\n environment: process.env.NODE_ENV ?? 'development',\n // We rely on OpenTelemetry for tracing \u2014 Sentry stays errors-only here.\n // Override at the env-var level if you ever want Sentry performance too:\n // `SENTRY_TRACES_SAMPLE_RATE=0.05` (Sentry SDK reads it natively).\n tracesSampleRate: 0,\n });\n\n enabled = true;\n return true;\n}\n\n/**\n * Report an exception. Coerces non-Error throws to Error so Sentry's\n * grouping/stack-trace logic has something to work with. Silent no-op when\n * SENTRY_DSN is unset.\n */\nexport function captureException(\n err: unknown,\n context?: { extra?: Record<string, unknown>; tags?: Record<string, string> },\n): void {\n if (!enabled) return;\n const e = err instanceof Error ? err : new Error(typeof err === 'string' ? err : JSON.stringify(err));\n Sentry.captureException(e, context);\n}\n\n/**\n * Attach (or clear, with null) the active user on the Sentry scope. Called\n * from the API auth middleware so any captured exception during the request\n * carries `user.id`. Silent no-op when SENTRY_DSN is unset.\n */\nexport function setSentryUser(userId: string | null): void {\n if (!enabled) return;\n if (userId === null) {\n Sentry.setUser(null);\n return;\n }\n Sentry.setUser({ id: userId });\n}\n\n/**\n * Flush any queued events with a timeout. Critical to call before\n * `process.exit()` in worker shutdown \u2014 Sentry batches events and the SIGTERM\n * path was previously dropping the final exception (the one we'd most want\n * to see). Resolves immediately when SENTRY_DSN is unset.\n */\nexport async function flushSentry(timeoutMs: number): Promise<void> {\n if (!enabled) return;\n await Sentry.flush(timeoutMs);\n}\n\n/**\n * Reset the module-level state. Test-only \u2014 exported so test suites can\n * unwind the singleton between cases without `vi.resetModules` plumbing in\n * every block.\n */\nexport function _resetSentryForTests(): void {\n enabled = false;\n}\n", "import { initSentry, flushSentry, initTelemetry, shutdownTelemetry } from '@rulemetric/telemetry';\nimport { BaseCommand } from '../../base-command.js';\nimport { loadToken, getDefaultConfigDir } from '../../lib/auth.js';\nimport { runAgentLoop } from '../../lib/agent-loop.js';\nimport { closeDb } from '@rulemetric/db';\nimport { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';\nimport { dirname, join } from 'node:path';\nimport { execFileSync } from 'node:child_process';\n\n// Anchored under the config dir (honors RULEMETRIC_CONFIG_DIR; default\n// ~/.config/rulemetric, like gateway.pid), NOT os.tmpdir(), to avoid\n// launch-context TMPDIR divergence (launchd vs SSH/sudo/CI). Config-dir-scoped\n// so an isolated config (e.g. a cold-start test harness) can run its own agent\n// without colliding with the machine's real launchd-worker lock; two agents\n// sharing one config dir \u2014 the orphaned-fleet case this guard exists for \u2014 are\n// still refused.\nconst AGENT_LOCK_PATH = join(getDefaultConfigDir(), 'evals-agent.lock');\n\nfunction pidAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch (e) {\n // ESRCH = no such process (stale); EPERM = exists but owned by another user\n return (e as { code?: string }).code === 'EPERM';\n }\n}\n\n// Defends against PID reuse: a SIGKILL/OOM leaves the lock behind and the OS may\n// later assign that PID to an unrelated process \u2014 `pidAlive` alone would then\n// wedge `evals agent` (refuse to start forever). Confirm the holder is actually\n// an evals-agent before treating the lock as held; otherwise it's reclaimable.\nfunction isLiveAgent(pid: number): boolean {\n if (!pidAlive(pid)) return false;\n try {\n const cmd = execFileSync('ps', ['-p', String(pid), '-o', 'command='], {\n encoding: 'utf-8',\n stdio: ['ignore', 'pipe', 'ignore'],\n });\n return /run\\.js\\s+evals\\s+agent|evals\\s+agent/.test(cmd);\n } catch {\n // ps unavailable/failed \u2014 fall back to liveness only (conservative: held)\n return true;\n }\n}\n\n// Single-instance guard. Each `evals agent` daemon holds its own postgres-js\n// pool; an orphaned, unsupervised fleet (4 stale agents found alive 3+ days on\n// 2026-06-21) was a confirmed driver of the recurring Supavisor 200-client\n// saturation. ATOMIC acquire via O_EXCL (flag 'wx') closes the TOCTOU window\n// where two simultaneously-starting agents could both acquire. On EEXIST the\n// holder is liveness-checked; a stale lock (holder gone) is reclaimed once.\n// See docs/incidents/2026-06-21-pool-exhaustion.md.\nfunction acquireAgentLock(): { ok: true } | { ok: false; holder: number } {\n try {\n mkdirSync(dirname(AGENT_LOCK_PATH), { recursive: true });\n } catch {\n /* ignore \u2014 writeFileSync will surface a real problem */\n }\n for (let attempt = 0; attempt < 2; attempt++) {\n try {\n // 'wx' = O_CREAT | O_EXCL: fails atomically with EEXIST if it exists.\n writeFileSync(AGENT_LOCK_PATH, String(process.pid), { flag: 'wx' });\n return { ok: true };\n } catch (e) {\n if ((e as { code?: string }).code !== 'EEXIST') throw e;\n let holder = 0;\n try {\n holder = Number(readFileSync(AGENT_LOCK_PATH, 'utf-8').trim());\n } catch {\n /* unreadable \u2014 treat as stale */\n }\n if (holder && holder !== process.pid && isLiveAgent(holder)) {\n return { ok: false, holder };\n }\n // stale (holder gone) / ours / unreadable \u2014 drop it and retry the atomic create once\n try { unlinkSync(AGENT_LOCK_PATH); } catch { /* raced with another reclaimer */ }\n }\n }\n // Last resort after a reclaim race \u2014 best-effort non-exclusive write.\n try { writeFileSync(AGENT_LOCK_PATH, String(process.pid)); } catch { /* ignore */ }\n return { ok: true };\n}\n\nfunction releaseAgentLock(): void {\n try {\n if (\n existsSync(AGENT_LOCK_PATH) &&\n Number(readFileSync(AGENT_LOCK_PATH, 'utf-8').trim()) === process.pid\n ) {\n unlinkSync(AGENT_LOCK_PATH);\n }\n } catch {\n /* best-effort */\n }\n}\n\n/**\n * `rulemetric evals agent` \u2014 Phase 4b parallel-run thin agent.\n *\n * Polls the /api/work endpoints (Phase 4a) instead of binding a Postgres\n * LISTEN/NOTIFY connection. This is the scaffold for the cutover described\n * in docs/plans/2026-05-25-thin-agent-migration.md; the default worker is\n * the sole worker mode since Phase 4c deleted the graphile path.\n *\n * Both commands can run side-by-side on the same user during the cutover \u2014\n * the API's atomic SKIP-LOCKED claim guarantees a job is handed to exactly\n * one agent. Picking which one runs is a launchd / shell choice.\n */\nexport default class EvalAgentCommand extends BaseCommand {\n static override description =\n 'The worker daemon: long-polls /api/work/next, claims jobs, and runs them locally. Installed as a launchd service by `rulemetric service install`.';\n\n static override examples = [\n '<%= config.bin %> evals agent',\n ];\n\n async run(): Promise<void> {\n await this.parse(EvalAgentCommand);\n this.requireAuth();\n\n // Single-instance guard \u2014 refuse to start a second agent. Each extra agent\n // holds its own DB pool; an orphaned fleet was a confirmed cause of pooler\n // saturation (pool-exhaustion RCA 2026-06-21).\n const lock = acquireAgentLock();\n if (!lock.ok) {\n this.log(\n `Another rulemetric evals agent is already running (pid ${lock.holder}). ` +\n 'Refusing to start a second instance.',\n );\n return;\n }\n\n process.env.PG_APPLICATION_NAME ||= 'rulemetric-agent';\n\n const sentryEnabled = initSentry({ serviceName: 'rulemetric-agent' });\n if (sentryEnabled) this.log('[sentry] error capture enabled');\n\n const otelMode = initTelemetry({ serviceName: 'rulemetric-agent' });\n if (otelMode === 'otlp') {\n this.log(`[otel] traces exporting to ${process.env.OTEL_EXPORTER_OTLP_ENDPOINT}`);\n } else if (otelMode === 'console') {\n this.log('[otel] cron spans printing to stdout (set OTEL_EXPORTER_OTLP_ENDPOINT to ship to a backend)');\n } else {\n this.log('[otel] disabled (TELEMETRY_ENABLED=false)');\n }\n\n // Early auth sanity check \u2014 the agent loop also reads the token on every\n // request via api-client, but failing here gives a friendlier error than\n // a 401 thirty seconds into the first long-poll.\n const token = loadToken();\n if (!token && !process.env.RULEMETRIC_API_KEY) {\n this.error('No auth token found. Run `rulemetric auth login` first.');\n }\n\n this.log('Starting thin agent (Phase 4b parallel-run)...');\n this.log('Long-polling /api/work/next. Press Ctrl+C to stop.\\n');\n\n const controller = new AbortController();\n\n const shutdown = async (signal: string) => {\n this.log(`\\n[${signal}] shutting down agent...`);\n controller.abort();\n // Flush telemetry + drain the pool on the way out. All members run\n // concurrently under Promise.allSettled (flushSentry 2s, closeDb 5s), so\n // the total stays well under launchd's ~20s shutdown grace.\n await Promise.allSettled([\n flushSentry(2_000),\n shutdownTelemetry(),\n // Drain the postgres-js pool so this agent's Supavisor client sessions\n // are released (Terminate) instead of orphaned as ghosts on every\n // launchd bounce. Pool-exhaustion RCA 2026-06-21.\n closeDb(),\n ]);\n releaseAgentLock();\n process.exit(0);\n };\n process.on('SIGINT', () => { void shutdown('SIGINT'); });\n process.on('SIGTERM', () => { void shutdown('SIGTERM'); });\n\n // Set when the loop stops because `npm i -g` replaced the CLI under this\n // running process \u2014 exit NON-ZERO after cleanup so the supervisor respawns\n // onto the new code (systemd is Restart=on-failure; launchd KeepAlive\n // restarts on any exit). Without this, a remote worker keeps executing the\n // old code until someone manually restarts the unit.\n let restartForUpgrade = false;\n try {\n await runAgentLoop({\n signal: controller.signal,\n log: (msg) => this.log(msg),\n version: this.config.version,\n readInstalledVersion: () => {\n try {\n const pkg = JSON.parse(\n readFileSync(join(this.config.root, 'package.json'), 'utf-8'),\n ) as { version?: string };\n return pkg.version ?? null;\n } catch {\n return null;\n }\n },\n onVersionDrift: () => {\n restartForUpgrade = true;\n },\n });\n if (restartForUpgrade) {\n this.log('[upgrade] Installed CLI version changed \u2014 restarting worker onto the new code.');\n await Promise.allSettled([flushSentry(2_000), shutdownTelemetry(), closeDb()]);\n releaseAgentLock();\n process.exit(1);\n }\n } finally {\n releaseAgentLock();\n // Drain on the throw path too (defense-in-depth). The signal-handler drain\n // covers normal shutdown; a thrown runAgentLoop must not skip it. closeDb\n // is idempotent, so the happy-path SIGTERM drain stays a no-op.\n await closeDb();\n }\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["trace"]
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/commands/evals/benchmark.ts"],
|
|
4
|
-
"sourcesContent": ["import { Args, Flags } from '@oclif/core';\nimport { BaseCommand } from '../../base-command.js';\nimport { apiGet } from '../../lib/api-client.js';\nimport { aggregateBenchmark, postBenchmark } from '../../lib/eval-benchmark.js';\n\nexport default class EvalBenchmarkCommand extends BaseCommand {\n static override description = 'Aggregate eval runs into a benchmark for a target';\n\n static override examples = [\n '<%= config.bin %> evals benchmark <target-id>',\n '<%= config.bin %> evals benchmark <target-id> --iteration 2',\n ];\n\n static override args = {\n targetId: Args.string({ description: 'Eval target ID', required: true }),\n };\n\n static override flags = {\n iteration: Flags.integer({ description: 'Filter runs by iteration', default: 1 }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(EvalBenchmarkCommand);\n this.requireAuth();\n\n const target = await apiGet<{ name: string; version: number }>(`/api/eval-targets/${args.targetId}`);\n this.log(`Aggregating benchmark for \"${target.name}\" v${target.version}, iteration ${flags.iteration}`);\n\n const result = await aggregateBenchmark(args.targetId, flags.iteration);\n\n if (result.totalRuns === 0) {\n this.error('No completed runs found. Run evals first with `rulemetric evals run`.');\n }\n\n this.log(`\\nAggregated ${result.totalRuns} runs\\n`);\n\n // Display summary\n for (const [config, stats] of Object.entries(result.runSummary)) {\n if (config === 'delta') {\n this.log(`\\nDelta (with_target - without_target):`);\n for (const [metric, value] of Object.entries(stats as unknown as Record<string, string>)) {\n this.log(` ${metric}: ${value}`);\n }\n continue;\n }\n this.log(`${config}:`);\n for (const [metric, stat] of Object.entries(stats)) {\n const s = stat as { mean: number; stddev: number; min: number; max: number };\n this.log(` ${metric}: mean=${s.mean} stddev=${s.stddev} [${s.min}, ${s.max}]`);\n }\n }\n\n if (result.notes.length > 0) {\n this.log('\\nNotes:');\n for (const note of result.notes) {\n this.log(` - ${note}`);\n }\n }\n\n // Post to API\n const benchmark = await postBenchmark(args.targetId, flags.iteration, result);\n this.log(`\\nBenchmark saved: ${benchmark.id}`);\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;AAAA,SAAS,MAAM,aAAa;AAK5B,IAAqB,uBAArB,MAAqB,8BAA6B,YAAY;AAAA,EAC5D,OAAgB,cAAc;AAAA,EAE9B,OAAgB,WAAW;AAAA,IACzB;AAAA,IACA;AAAA,EACF;AAAA,EAEA,OAAgB,OAAO;AAAA,IACrB,UAAU,KAAK,OAAO,EAAE,aAAa,kBAAkB,UAAU,KAAK,CAAC;AAAA,EACzE;AAAA,EAEA,OAAgB,QAAQ;AAAA,IACtB,WAAW,MAAM,QAAQ,EAAE,aAAa,4BAA4B,SAAS,EAAE,CAAC;AAAA,EAClF;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,KAAK,MAAM,qBAAoB;AAC7D,SAAK,YAAY;AAEjB,UAAM,SAAS,MAAM,OAA0C,qBAAqB,KAAK,QAAQ,EAAE;AACnG,SAAK,IAAI,8BAA8B,OAAO,IAAI,MAAM,OAAO,OAAO,eAAe,MAAM,SAAS,EAAE;AAEtG,UAAM,SAAS,MAAM,mBAAmB,KAAK,UAAU,MAAM,SAAS;AAEtE,QAAI,OAAO,cAAc,GAAG;AAC1B,WAAK,MAAM,uEAAuE;AAAA,IACpF;AAEA,SAAK,IAAI;AAAA,aAAgB,OAAO,SAAS;AAAA,CAAS;AAGlD,eAAW,CAAC,QAAQ,KAAK,KAAK,OAAO,QAAQ,OAAO,UAAU,GAAG;AAC/D,UAAI,WAAW,SAAS;AACtB,aAAK,IAAI;AAAA,sCAAyC;AAClD,mBAAW,CAAC,QAAQ,KAAK,KAAK,OAAO,QAAQ,KAA0C,GAAG;AACxF,eAAK,IAAI,KAAK,MAAM,KAAK,KAAK,EAAE;AAAA,QAClC;AACA;AAAA,MACF;AACA,WAAK,IAAI,GAAG,MAAM,GAAG;AACrB,iBAAW,CAAC,QAAQ,IAAI,KAAK,OAAO,QAAQ,KAAK,GAAG;AAClD,cAAM,IAAI;AACV,aAAK,IAAI,KAAK,MAAM,UAAU,EAAE,IAAI,WAAW,EAAE,MAAM,KAAK,EAAE,GAAG,KAAK,EAAE,GAAG,GAAG;AAAA,MAChF;AAAA,IACF;AAEA,QAAI,OAAO,MAAM,SAAS,GAAG;AAC3B,WAAK,IAAI,UAAU;AACnB,iBAAW,QAAQ,OAAO,OAAO;AAC/B,aAAK,IAAI,OAAO,IAAI,EAAE;AAAA,MACxB;AAAA,IACF;AAGA,UAAM,YAAY,MAAM,cAAc,KAAK,UAAU,MAAM,WAAW,MAAM;AAC5E,SAAK,IAAI;AAAA,mBAAsB,UAAU,EAAE,EAAE;AAAA,EAC/C;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/commands/evals/compare.ts"],
|
|
4
|
-
"sourcesContent": ["import { Args, Flags } from '@oclif/core';\nimport { BaseCommand } from '../../base-command.js';\nimport { apiGet } from '../../lib/api-client.js';\nimport { executeEval } from '../../lib/eval-executor.js';\n\ninterface EvalTarget {\n id: string;\n name: string;\n content: string;\n version: number;\n}\n\ninterface Eval {\n id: string;\n name: string;\n prompt: string;\n expectations: string[];\n}\n\nexport default class EvalCompareCommand extends BaseCommand {\n static override description = 'Blind A/B comparison between two eval target versions';\n\n static override examples = [\n '<%= config.bin %> evals compare <target-a> <target-b>',\n ];\n\n static override args = {\n targetA: Args.string({ description: 'First eval target ID', required: true }),\n targetB: Args.string({ description: 'Second eval target ID', required: true }),\n };\n\n static override flags = {\n model: Flags.string({ description: 'Model for execution and comparison' }),\n timeout: Flags.integer({ description: 'Timeout per eval in ms', default: 120_000 }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(EvalCompareCommand);\n this.requireAuth();\n\n const [targetA, targetB] = await Promise.all([\n apiGet<EvalTarget>(`/api/eval-targets/${args.targetA}`),\n apiGet<EvalTarget>(`/api/eval-targets/${args.targetB}`),\n ]);\n\n // Use evals from target A (they should be testing the same thing)\n const evals = await apiGet<Eval[]>(`/api/eval-targets/${args.targetA}/evals`);\n if (evals.length === 0) {\n this.error('No evals found for target A. Create some first.');\n }\n\n this.log(`Comparing \"${targetA.name}\" v${targetA.version} vs \"${targetB.name}\" v${targetB.version}`);\n this.log(`Running ${evals.length} eval(s)...\\n`);\n\n // Randomize A/B assignment for blindness\n const isSwapped = Math.random() > 0.5;\n const contentA = isSwapped ? targetB.content : targetA.content;\n const contentB = isSwapped ? targetA.content : targetB.content;\n const labelA = isSwapped ? targetB.name : targetA.name;\n const labelB = isSwapped ? targetA.name : targetB.name;\n\n const comparisons: Array<{\n evalName: string;\n outputA: string;\n outputB: string;\n }> = [];\n\n for (const eval_ of evals) {\n this.log(`[${eval_.name}] Running A...`);\n const resultA = await executeEval({\n prompt: eval_.prompt,\n targetContent: contentA,\n timeout: flags.timeout,\n model: flags.model,\n });\n\n this.log(`[${eval_.name}] Running B...`);\n const resultB = await executeEval({\n prompt: eval_.prompt,\n targetContent: contentB,\n timeout: flags.timeout,\n model: flags.model,\n });\n\n comparisons.push({\n evalName: eval_.name,\n outputA: resultA.output,\n outputB: resultB.output,\n });\n }\n\n // Run blind comparison via LLM\n this.log('\\nRunning blind comparison...');\n\n const comparisonPrompt = comparisons.map((c) => `\n## Eval: ${c.evalName}\n\n### Output A\n${c.outputA}\n\n### Output B\n${c.outputB}\n`).join('\\n---\\n');\n\n const comparatorResult = await executeEval({\n prompt: `Compare these two sets of outputs. For each eval, determine which output (A or B) is better.\nThen provide an overall winner with reasoning.\n\n${comparisonPrompt}\n\nRespond with JSON:\n{\n \"per_eval\": [\n { \"eval_name\": \"...\", \"winner\": \"A|B|TIE\", \"reasoning\": \"...\" }\n ],\n \"overall\": {\n \"winner\": \"A|B|TIE\",\n \"reasoning\": \"...\",\n \"strengths_winner\": [\"...\"],\n \"weaknesses_loser\": [\"...\"]\n }\n}`,\n timeout: flags.timeout,\n model: flags.model,\n });\n\n // Unblind and display results\n this.log('\\n=== Comparison Results ===\\n');\n this.log(`A = \"${labelA}\" | B = \"${labelB}\"`);\n if (isSwapped) this.log('(Labels were swapped for blind comparison)');\n this.log('');\n this.log(comparatorResult.output);\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/commands/evals/create.ts"],
|
|
4
|
-
"sourcesContent": ["import { Args, Flags } from '@oclif/core';\nimport { readFileSync } from 'node:fs';\nimport { BaseCommand } from '../../base-command.js';\nimport { apiPost } from '../../lib/api-client.js';\n\ninterface EvalInput {\n name: string;\n prompt: string;\n expectedOutput?: string;\n expectations?: string[];\n files?: unknown[];\n}\n\nexport default class EvalCreate extends BaseCommand {\n static override description = 'Create test cases (evals) for an eval target';\n\n static override examples = [\n '<%= config.bin %> evals create <target-id> --name \"ts-check\" --prompt \"Write a function to add two numbers\"',\n '<%= config.bin %> evals create <target-id> --from-file evals.json',\n ];\n\n static override args = {\n targetId: Args.string({ description: 'Eval target ID', required: true }),\n };\n\n static override flags = {\n name: Flags.string({ char: 'n', description: 'Eval name' }),\n prompt: Flags.string({ char: 'p', description: 'Test prompt' }),\n 'expected-output': Flags.string({ description: 'Expected output description' }),\n expectations: Flags.string({ char: 'e', description: 'Assertion (repeatable)', multiple: true }),\n 'from-file': Flags.string({ description: 'Bulk create from JSON file' }),\n };\n\n async run(): Promise<void> {\n const { args, flags } = await this.parse(EvalCreate);\n this.requireAuth();\n\n if (flags['from-file']) {\n const data = JSON.parse(readFileSync(flags['from-file'], 'utf-8'));\n const evalsArray: EvalInput[] = Array.isArray(data) ? data : data.evals;\n\n for (const evalItem of evalsArray) {\n const result = await apiPost<{ id: string; name: string }>(`/api/eval-targets/${args.targetId}/evals`, {\n name: evalItem.name,\n prompt: evalItem.prompt,\n expectedOutput: evalItem.expectedOutput ?? '',\n expectations: evalItem.expectations ?? [],\n files: evalItem.files ?? [],\n });\n this.log(`Created eval: ${result.name} (${result.id})`);\n }\n\n this.log(`Created ${evalsArray.length} evals.`);\n return;\n }\n\n if (!flags.name || !flags.prompt) {\n this.error('Provide --name and --prompt, or use --from-file for bulk creation');\n }\n\n const result = await apiPost<{ id: string; name: string }>(`/api/eval-targets/${args.targetId}/evals`, {\n name: flags.name,\n prompt: flags.prompt,\n expectedOutput: flags['expected-output'] ?? '',\n expectations: flags.expectations ?? [],\n });\n\n this.log(`Created eval: ${result.name} (${result.id})`);\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;AAAA,SAAS,MAAM,aAAa;AAC5B,SAAS,oBAAoB;AAY7B,IAAqB,aAArB,MAAqB,oBAAmB,YAAY;AAAA,EAClD,OAAgB,cAAc;AAAA,EAE9B,OAAgB,WAAW;AAAA,IACzB;AAAA,IACA;AAAA,EACF;AAAA,EAEA,OAAgB,OAAO;AAAA,IACrB,UAAU,KAAK,OAAO,EAAE,aAAa,kBAAkB,UAAU,KAAK,CAAC;AAAA,EACzE;AAAA,EAEA,OAAgB,QAAQ;AAAA,IACtB,MAAM,MAAM,OAAO,EAAE,MAAM,KAAK,aAAa,YAAY,CAAC;AAAA,IAC1D,QAAQ,MAAM,OAAO,EAAE,MAAM,KAAK,aAAa,cAAc,CAAC;AAAA,IAC9D,mBAAmB,MAAM,OAAO,EAAE,aAAa,8BAA8B,CAAC;AAAA,IAC9E,cAAc,MAAM,OAAO,EAAE,MAAM,KAAK,aAAa,0BAA0B,UAAU,KAAK,CAAC;AAAA,IAC/F,aAAa,MAAM,OAAO,EAAE,aAAa,6BAA6B,CAAC;AAAA,EACzE;AAAA,EAEA,MAAM,MAAqB;AACzB,UAAM,EAAE,MAAM,MAAM,IAAI,MAAM,KAAK,MAAM,WAAU;AACnD,SAAK,YAAY;AAEjB,QAAI,MAAM,WAAW,GAAG;AACtB,YAAM,OAAO,KAAK,MAAM,aAAa,MAAM,WAAW,GAAG,OAAO,CAAC;AACjE,YAAM,aAA0B,MAAM,QAAQ,IAAI,IAAI,OAAO,KAAK;AAElE,iBAAW,YAAY,YAAY;AACjC,cAAMA,UAAS,MAAM,QAAsC,qBAAqB,KAAK,QAAQ,UAAU;AAAA,UACrG,MAAM,SAAS;AAAA,UACf,QAAQ,SAAS;AAAA,UACjB,gBAAgB,SAAS,kBAAkB;AAAA,UAC3C,cAAc,SAAS,gBAAgB,CAAC;AAAA,UACxC,OAAO,SAAS,SAAS,CAAC;AAAA,QAC5B,CAAC;AACD,aAAK,IAAI,iBAAiBA,QAAO,IAAI,KAAKA,QAAO,EAAE,GAAG;AAAA,MACxD;AAEA,WAAK,IAAI,WAAW,WAAW,MAAM,SAAS;AAC9C;AAAA,IACF;AAEA,QAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,QAAQ;AAChC,WAAK,MAAM,mEAAmE;AAAA,IAChF;AAEA,UAAM,SAAS,MAAM,QAAsC,qBAAqB,KAAK,QAAQ,UAAU;AAAA,MACrG,MAAM,MAAM;AAAA,MACZ,QAAQ,MAAM;AAAA,MACd,gBAAgB,MAAM,iBAAiB,KAAK;AAAA,MAC5C,cAAc,MAAM,gBAAgB,CAAC;AAAA,IACvC,CAAC;AAED,SAAK,IAAI,iBAAiB,OAAO,IAAI,KAAK,OAAO,EAAE,GAAG;AAAA,EACxD;AACF;",
|
|
6
|
-
"names": ["result"]
|
|
7
|
-
}
|