@rulemetric/cli 0.7.2 → 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 -309
- 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 -781
- 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 -46
- 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 -15
- 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 -14
- 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 -11
- 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 -17
- package/dist/lib/manual-tasks-meta.js +1 -8
- package/dist/lib/manual-tasks.js +1 -79
- 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 +8 -7
- 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-7DULPSFU.js +0 -299
- package/dist/chunk-7DULPSFU.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-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-FZKLLNDS.js +0 -228
- package/dist/chunk-FZKLLNDS.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-OK3I555A.js +0 -243
- package/dist/chunk-OK3I555A.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-PMI56ED5.js +0 -167
- package/dist/chunk-PMI56ED5.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-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-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-YOBA3NAM.js +0 -55
- package/dist/chunk-YOBA3NAM.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-Y4BJXXYV.js
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
worktreePathFor
|
|
3
|
-
} from "./chunk-F5N6CLJJ.js";
|
|
4
|
-
import {
|
|
5
|
-
tmuxSpawnEnv
|
|
6
|
-
} from "./chunk-KRBQLMOP.js";
|
|
7
|
-
|
|
8
|
-
// src/lib/worktree.ts
|
|
9
|
-
import { spawn } from "node:child_process";
|
|
10
|
-
import fs from "node:fs";
|
|
11
|
-
import path from "node:path";
|
|
12
|
-
function runGit(args, cwd) {
|
|
13
|
-
return new Promise((resolve, reject) => {
|
|
14
|
-
const proc = spawn("git", args, {
|
|
15
|
-
cwd,
|
|
16
|
-
stdio: ["ignore", "pipe", "pipe"],
|
|
17
|
-
env: tmuxSpawnEnv()
|
|
18
|
-
});
|
|
19
|
-
let stdout = "";
|
|
20
|
-
let stderr = "";
|
|
21
|
-
proc.stdout.on("data", (d) => {
|
|
22
|
-
stdout += d.toString();
|
|
23
|
-
});
|
|
24
|
-
proc.stderr.on("data", (d) => {
|
|
25
|
-
stderr += d.toString();
|
|
26
|
-
});
|
|
27
|
-
proc.on(
|
|
28
|
-
"error",
|
|
29
|
-
(err) => reject(new Error(`git ${args.join(" ")} failed to spawn: ${err.message}`))
|
|
30
|
-
);
|
|
31
|
-
proc.on("close", (code) => {
|
|
32
|
-
if (code === 0) {
|
|
33
|
-
resolve({ code, stdout, stderr });
|
|
34
|
-
} else {
|
|
35
|
-
reject(
|
|
36
|
-
new Error(`git ${args.join(" ")} exited ${code}: ${stderr.trim() || stdout.trim()}`)
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
});
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
async function assertValidBranch(repoRoot, branch) {
|
|
43
|
-
if (!branch || !branch.trim()) {
|
|
44
|
-
throw new Error('invalid branch name "": branch must be a non-empty git refname');
|
|
45
|
-
}
|
|
46
|
-
if (branch.startsWith("-")) {
|
|
47
|
-
throw new Error(
|
|
48
|
-
`invalid branch name "${branch}": must not start with "-" (git would parse it as an option)`
|
|
49
|
-
);
|
|
50
|
-
}
|
|
51
|
-
if (/\s/.test(branch)) {
|
|
52
|
-
throw new Error(`invalid branch name "${branch}": must not contain whitespace`);
|
|
53
|
-
}
|
|
54
|
-
try {
|
|
55
|
-
await runGit(["check-ref-format", "--branch", branch], repoRoot);
|
|
56
|
-
} catch {
|
|
57
|
-
throw new Error(`invalid branch name "${branch}": not a valid git refname`);
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
function canonical(p) {
|
|
61
|
-
const resolved = path.resolve(p);
|
|
62
|
-
try {
|
|
63
|
-
return fs.realpathSync(resolved);
|
|
64
|
-
} catch {
|
|
65
|
-
return resolved;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
function parseWorktreeList(porcelain) {
|
|
69
|
-
const entries = [];
|
|
70
|
-
let current = null;
|
|
71
|
-
for (const line of porcelain.split("\n")) {
|
|
72
|
-
if (line.startsWith("worktree ")) {
|
|
73
|
-
if (current) entries.push(current);
|
|
74
|
-
current = { path: line.slice("worktree ".length).trim() };
|
|
75
|
-
} else if (line.startsWith("branch ") && current) {
|
|
76
|
-
current.branch = line.slice("branch ".length).trim().replace(/^refs\/heads\//, "");
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
if (current) entries.push(current);
|
|
80
|
-
return entries;
|
|
81
|
-
}
|
|
82
|
-
async function branchExists(repoRoot, branch) {
|
|
83
|
-
try {
|
|
84
|
-
await runGit(["show-ref", "--verify", "--quiet", `refs/heads/${branch}`], repoRoot);
|
|
85
|
-
return true;
|
|
86
|
-
} catch {
|
|
87
|
-
return false;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
async function ensureWorktree(options) {
|
|
91
|
-
const { repoRoot, branch, baseRef, allowExistingBranch = false } = options;
|
|
92
|
-
await assertValidBranch(repoRoot, branch);
|
|
93
|
-
const targetPath = worktreePathFor({ repoRoot, branch, basePath: options.basePath });
|
|
94
|
-
const listed = await runGit(["worktree", "list", "--porcelain"], repoRoot);
|
|
95
|
-
const existing = parseWorktreeList(listed.stdout);
|
|
96
|
-
const byBranch = existing.find((e) => e.branch === branch);
|
|
97
|
-
if (byBranch) {
|
|
98
|
-
return { path: canonical(byBranch.path), branch, created: false };
|
|
99
|
-
}
|
|
100
|
-
const byPath = existing.find((e) => canonical(e.path) === targetPath);
|
|
101
|
-
if (byPath) {
|
|
102
|
-
return { path: canonical(byPath.path), branch: byPath.branch ?? branch, created: false };
|
|
103
|
-
}
|
|
104
|
-
if (await branchExists(repoRoot, branch)) {
|
|
105
|
-
if (!allowExistingBranch) {
|
|
106
|
-
throw new Error(
|
|
107
|
-
`branch "${branch}" already exists with no worktree; refusing to clobber (pass allowExistingBranch:true to attach a worktree onto it)`
|
|
108
|
-
);
|
|
109
|
-
}
|
|
110
|
-
await runGit(["worktree", "add", targetPath, branch], repoRoot);
|
|
111
|
-
return { path: canonical(targetPath), branch, created: true };
|
|
112
|
-
}
|
|
113
|
-
await runGit(["worktree", "add", targetPath, "-b", branch, baseRef], repoRoot);
|
|
114
|
-
return { path: canonical(targetPath), branch, created: true };
|
|
115
|
-
}
|
|
116
|
-
async function removeWorktree(options) {
|
|
117
|
-
const { repoRoot, worktreePath } = options;
|
|
118
|
-
if (!fs.existsSync(worktreePath)) {
|
|
119
|
-
return { removed: false, reason: "absent" };
|
|
120
|
-
}
|
|
121
|
-
let dirty = false;
|
|
122
|
-
try {
|
|
123
|
-
const status = await runGit(["status", "--porcelain"], worktreePath);
|
|
124
|
-
dirty = status.stdout.trim().length > 0;
|
|
125
|
-
} catch {
|
|
126
|
-
dirty = false;
|
|
127
|
-
}
|
|
128
|
-
if (dirty) {
|
|
129
|
-
return { removed: false, reason: "dirty" };
|
|
130
|
-
}
|
|
131
|
-
try {
|
|
132
|
-
await runGit(["worktree", "remove", worktreePath], repoRoot);
|
|
133
|
-
return { removed: true };
|
|
134
|
-
} catch (err) {
|
|
135
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
136
|
-
if (/not a working tree|No such file or directory|not a valid path|is not a working tree/i.test(message)) {
|
|
137
|
-
return { removed: false, reason: "absent" };
|
|
138
|
-
}
|
|
139
|
-
throw err;
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
export {
|
|
144
|
-
runGit,
|
|
145
|
-
ensureWorktree,
|
|
146
|
-
removeWorktree
|
|
147
|
-
};
|
|
148
|
-
//# sourceMappingURL=chunk-Y4BJXXYV.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/lib/worktree.ts"],
|
|
4
|
-
"sourcesContent": ["import { spawn } from 'node:child_process';\nimport fs from 'node:fs';\nimport path from 'node:path';\n\nimport { worktreePathFor } from '@rulemetric/session';\n\nimport { tmuxSpawnEnv } from './tmux.js';\n\n// Re-export so existing importers (and the API reconcile path) share ONE\n// sanitizer. The implementation lives in @rulemetric/session/worktree-path so\n// the API process \u2014 which can't import @rulemetric/cli \u2014 can derive the same\n// path without duplicating the logic.\nexport { sanitizeBranch } from '@rulemetric/session';\n\nexport interface EnsureWorktreeOptions {\n /** Absolute path to the root of the source git repository. */\n repoRoot: string;\n /** Branch name to give the worktree (e.g. `rm/run-abc/s0`). */\n branch: string;\n /** Commit-ish the new branch is created from (e.g. `HEAD`, `main`, a SHA). */\n baseRef: string;\n /**\n * Where to put the worktree. Defaults to a SIBLING of `repoRoot`:\n * `<repoRoot>/../.rulemetric-worktrees/<sanitized-branch>`. Never placed\n * inside `repoRoot` \u2014 a nested worktree would be tracked by the parent repo.\n */\n basePath?: string;\n /**\n * If the branch already exists (but has no worktree), `false` (default)\n * throws \u2014 this is the caller's \"make sure it doesn't exist first\" guard.\n * `true` attaches a worktree onto the existing branch (no `-b`).\n */\n allowExistingBranch?: boolean;\n}\n\nexport interface EnsureWorktreeResult {\n /** Absolute filesystem path of the worktree. */\n path: string;\n /** The branch the worktree is checked out on. */\n branch: string;\n /** `true` if this call created the worktree; `false` if it already existed. */\n created: boolean;\n}\n\ninterface GitRunResult {\n code: number | null;\n stdout: string;\n stderr: string;\n}\n\n/**\n * Spawn `git` with a PATH-augmented env. The launchd worker's minimal PATH\n * omits Homebrew dirs, so a bare `spawn('git')` ENOENTs under launchd (same\n * failure mode as tmux \u2014 see the `launchd-worker-path-homebrew` incident).\n * We reuse `tmuxSpawnEnv()` (apps/cli/src/lib/tmux.ts), which appends\n * `/opt/homebrew/bin` + `/usr/local/bin` to PATH when missing. Rejects on a\n * nonzero exit (or spawn error) with stderr included for diagnosis.\n */\nexport function runGit(args: string[], cwd?: string): Promise<GitRunResult> {\n return new Promise((resolve, reject) => {\n const proc = spawn('git', args, {\n cwd,\n stdio: ['ignore', 'pipe', 'pipe'],\n env: tmuxSpawnEnv(),\n });\n let stdout = '';\n let stderr = '';\n proc.stdout.on('data', (d: Buffer) => {\n stdout += d.toString();\n });\n proc.stderr.on('data', (d: Buffer) => {\n stderr += d.toString();\n });\n proc.on('error', (err) =>\n reject(new Error(`git ${args.join(' ')} failed to spawn: ${err.message}`)),\n );\n proc.on('close', (code) => {\n if (code === 0) {\n resolve({ code, stdout, stderr });\n } else {\n reject(\n new Error(`git ${args.join(' ')} exited ${code}: ${stderr.trim() || stdout.trim()}`),\n );\n }\n });\n });\n}\n\n/**\n * Reject branch names that git would misparse or refuse, BEFORE any git call.\n *\n * `branch` is interpolated into argv for `git worktree add ... -b <branch>`.\n * Argv-array spawn already blocks shell injection, but a name that starts with\n * `-` (e.g. `--help`) is parsed by git as an OPTION, not a ref \u2014 a defense-in-\n * depth gap for this exported helper. We catch the obvious cases up-front with\n * clear errors (empty / whitespace / leading `-`), then defer to git's own\n * `check-ref-format --branch`, which exits nonzero for any otherwise-invalid\n * refname (`..`, trailing `.lock`, control chars, etc.). `runGit` rejects on a\n * nonzero exit, so we catch and rethrow as a uniform message.\n */\nasync function assertValidBranch(repoRoot: string, branch: string): Promise<void> {\n if (!branch || !branch.trim()) {\n throw new Error('invalid branch name \"\": branch must be a non-empty git refname');\n }\n if (branch.startsWith('-')) {\n throw new Error(\n `invalid branch name \"${branch}\": must not start with \"-\" (git would parse it as an option)`,\n );\n }\n if (/\\s/.test(branch)) {\n throw new Error(`invalid branch name \"${branch}\": must not contain whitespace`);\n }\n try {\n await runGit(['check-ref-format', '--branch', branch], repoRoot);\n } catch {\n throw new Error(`invalid branch name \"${branch}\": not a valid git refname`);\n }\n}\n\n/**\n * Canonicalize a path so values are comparable across calls. `git worktree\n * list --porcelain` reports realpath-resolved paths (e.g. macOS `/var` \u2192\n * `/private/var`), so we resolve symlinks when the path exists. Falls back to\n * `path.resolve` for not-yet-created paths.\n */\nfunction canonical(p: string): string {\n const resolved = path.resolve(p);\n try {\n return fs.realpathSync(resolved);\n } catch {\n return resolved;\n }\n}\n\ninterface WorktreeEntry {\n path: string;\n branch?: string;\n}\n\n/** Parse `git worktree list --porcelain` output into structured entries. */\nfunction parseWorktreeList(porcelain: string): WorktreeEntry[] {\n const entries: WorktreeEntry[] = [];\n let current: WorktreeEntry | null = null;\n for (const line of porcelain.split('\\n')) {\n if (line.startsWith('worktree ')) {\n if (current) entries.push(current);\n current = { path: line.slice('worktree '.length).trim() };\n } else if (line.startsWith('branch ') && current) {\n // e.g. \"branch refs/heads/rm/run-abc/s0\" \u2192 \"rm/run-abc/s0\"\n current.branch = line.slice('branch '.length).trim().replace(/^refs\\/heads\\//, '');\n }\n }\n if (current) entries.push(current);\n return entries;\n}\n\n/** Does a local branch with this exact name exist? */\nasync function branchExists(repoRoot: string, branch: string): Promise<boolean> {\n try {\n await runGit(['show-ref', '--verify', '--quiet', `refs/heads/${branch}`], repoRoot);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * Ensure an isolated git worktree + branch exists for a launched session.\n *\n * Pure/idempotent: takes `repoRoot` as input, holds no global state, and is\n * safe to call repeatedly \u2014 a pre-existence guard returns the existing\n * worktree with `created: false` instead of erroring.\n */\nexport async function ensureWorktree(\n options: EnsureWorktreeOptions,\n): Promise<EnsureWorktreeResult> {\n const { repoRoot, branch, baseRef, allowExistingBranch = false } = options;\n\n // 0. Reject git-flag / invalid branch names BEFORE any git call. Guards the\n // raw `-b <branch>` interpolation (e.g. `--help` would be read as a git\n // option, not a ref). sanitizeBranch below only protects the FS path.\n await assertValidBranch(repoRoot, branch);\n\n // Shared with the API reconcile fallback via @rulemetric/session \u2014 see\n // worktree-path.ts. `sanitizeBranch` is referenced through it.\n const targetPath = worktreePathFor({ repoRoot, branch, basePath: options.basePath });\n\n // 1. Pre-existence guard \u2014 reuse an existing worktree for this branch/path.\n const listed = await runGit(['worktree', 'list', '--porcelain'], repoRoot);\n const existing = parseWorktreeList(listed.stdout);\n const byBranch = existing.find((e) => e.branch === branch);\n if (byBranch) {\n return { path: canonical(byBranch.path), branch, created: false };\n }\n // Assumes the naming convention makes targetPath \u21D2 branch 1:1 (one branch\n // per worktree path), so a path hit implies the same logical branch and\n // returning created:false here is safe.\n const byPath = existing.find((e) => canonical(e.path) === targetPath);\n if (byPath) {\n return { path: canonical(byPath.path), branch: byPath.branch ?? branch, created: false };\n }\n\n // 2. Branch exists but has no worktree \u2192 honor allowExistingBranch.\n if (await branchExists(repoRoot, branch)) {\n if (!allowExistingBranch) {\n throw new Error(\n `branch \"${branch}\" already exists with no worktree; refusing to clobber ` +\n `(pass allowExistingBranch:true to attach a worktree onto it)`,\n );\n }\n // Attach a worktree onto the existing branch (no -b, no baseRef).\n await runGit(['worktree', 'add', targetPath, branch], repoRoot);\n return { path: canonical(targetPath), branch, created: true };\n }\n\n // 3. Fresh worktree on a brand-new branch off baseRef.\n await runGit(['worktree', 'add', targetPath, '-b', branch, baseRef], repoRoot);\n return { path: canonical(targetPath), branch, created: true };\n}\n\nexport interface RemoveWorktreeOptions {\n /** Absolute path to the root of the source git repository. */\n repoRoot: string;\n /** Absolute path of the worktree to remove (e.g. the value returned by `ensureWorktree`). */\n worktreePath: string;\n}\n\nexport interface RemoveWorktreeResult {\n /** `true` if this call removed the worktree; `false` if it refused or was a no-op. */\n removed: boolean;\n /**\n * Why the worktree was NOT removed (only set when `removed: false`):\n * - `'dirty'` \u2014 the worktree has uncommitted changes; refusing to clobber.\n * - `'absent'` \u2014 there was no worktree at that path (already removed / never existed).\n */\n reason?: 'dirty' | 'absent';\n}\n\n/**\n * Remove a session's git worktree, GUARDING against destroying uncommitted work.\n *\n * Load-bearing safety contract (research \"merge-review bottleneck\" / Prime\n * Directive: never silently discard work):\n * 1. Run `git -C <worktreePath> status --porcelain`. If the output is\n * non-empty the worktree has uncommitted changes (modified/untracked/\n * staged) \u2014 DO NOT remove it. Return `{ removed: false, reason: 'dirty' }`\n * and leave the directory on disk untouched. The caller surfaces this so\n * the user can review/commit before cleanup.\n * 2. If clean, run `git -C <repoRoot> worktree remove <worktreePath>`.\n * Idempotent: a missing worktree (already removed, or its dir was deleted\n * out from under git) is treated as a no-op \u2192 `{ removed: false,\n * reason: 'absent' }` rather than an error.\n *\n * Uses the PATH-augmented `runGit` (the launchd worker's minimal PATH omits\n * Homebrew, so a bare `git` spawn ENOENTs \u2014 same incident as `ensureWorktree`).\n */\nexport async function removeWorktree(\n options: RemoveWorktreeOptions,\n): Promise<RemoveWorktreeResult> {\n const { repoRoot, worktreePath } = options;\n\n // 0. If nothing is on disk at the path, it's already gone \u2014 idempotent no-op.\n // (git status below would error with a confusing message on a missing cwd.)\n if (!fs.existsSync(worktreePath)) {\n return { removed: false, reason: 'absent' };\n }\n\n // 1. Dirty-guard. A non-empty `status --porcelain` means uncommitted work\n // (staged, unstaged, OR untracked files). Refuse \u2014 never clobber.\n let dirty = false;\n try {\n const status = await runGit(['status', '--porcelain'], worktreePath);\n dirty = status.stdout.trim().length > 0;\n } catch {\n // The path exists but isn't (or is no longer) a valid worktree checkout \u2014\n // e.g. its `.git` link is broken. Fall through to the remove step, which\n // handles \"not a working tree\" idempotently as `absent`.\n dirty = false;\n }\n if (dirty) {\n return { removed: false, reason: 'dirty' };\n }\n\n // 2. Clean \u2192 remove. Treat \"not a working tree / already removed\" as a no-op.\n try {\n await runGit(['worktree', 'remove', worktreePath], repoRoot);\n return { removed: true };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n // git's messages for an already-absent worktree vary by version:\n // \"is not a working tree\", \"No such file or directory\", \"not a valid\n // path\". Match the common phrases \u2192 idempotent absent. Anything else is\n // a real error and rethrows.\n if (/not a working tree|No such file or directory|not a valid path|is not a working tree/i.test(message)) {\n return { removed: false, reason: 'absent' };\n }\n throw err;\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
package/dist/chunk-YNIH3KMU.js
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
executeEval
|
|
3
|
-
} from "./chunk-QN34TGD3.js";
|
|
4
|
-
|
|
5
|
-
// src/lib/eval-grader.ts
|
|
6
|
-
var GRADER_SYSTEM_PROMPT = `You are a rigorous eval grader. Your job is to evaluate whether an AI assistant's output meets a set of expectations.
|
|
7
|
-
|
|
8
|
-
You will receive:
|
|
9
|
-
1. The original prompt that was given to the AI
|
|
10
|
-
2. The AI's output/response
|
|
11
|
-
3. A list of expectations (assertions) to evaluate
|
|
12
|
-
|
|
13
|
-
For each expectation:
|
|
14
|
-
- Search the output for evidence that the expectation is met
|
|
15
|
-
- Determine PASS or FAIL (no partial credit)
|
|
16
|
-
- Cite specific evidence (quote or description)
|
|
17
|
-
|
|
18
|
-
PASS criteria:
|
|
19
|
-
- Clear evidence the assertion is true
|
|
20
|
-
- Evidence reflects genuine completion, not surface compliance
|
|
21
|
-
|
|
22
|
-
FAIL criteria:
|
|
23
|
-
- No evidence found
|
|
24
|
-
- Evidence contradicts the expectation
|
|
25
|
-
- Cannot verify from available information
|
|
26
|
-
|
|
27
|
-
Beyond the predefined expectations, extract implicit claims from the output:
|
|
28
|
-
- Factual claims ("uses TypeScript", "has 3 parameters")
|
|
29
|
-
- Process claims ("used async/await pattern")
|
|
30
|
-
- Quality claims ("handles edge cases")
|
|
31
|
-
|
|
32
|
-
Verify each claim against the actual output.
|
|
33
|
-
|
|
34
|
-
Finally, critique the eval itself \u2014 identify assertions that are too weak (pass for wrong outputs) or important outcomes that no assertion covers.
|
|
35
|
-
|
|
36
|
-
You MUST respond with ONLY a valid JSON object matching this exact structure (no markdown, no explanation, just JSON):
|
|
37
|
-
|
|
38
|
-
{
|
|
39
|
-
"expectations": [
|
|
40
|
-
{ "text": "assertion text", "passed": true, "evidence": "specific quote or description" }
|
|
41
|
-
],
|
|
42
|
-
"summary": { "passed": 2, "failed": 1, "total": 3, "pass_rate": 0.67 },
|
|
43
|
-
"claims": [
|
|
44
|
-
{ "claim": "statement", "type": "factual", "verified": true, "evidence": "..." }
|
|
45
|
-
],
|
|
46
|
-
"eval_feedback": {
|
|
47
|
-
"suggestions": [{ "assertion": "suggested new assertion", "reason": "why it matters" }],
|
|
48
|
-
"overall": "brief summary assessment"
|
|
49
|
-
}
|
|
50
|
-
}`;
|
|
51
|
-
async function gradeEvalOutput(options) {
|
|
52
|
-
const { prompt, output, expectations, model, timeout = 12e4 } = options;
|
|
53
|
-
const graderPrompt = `## Original Prompt
|
|
54
|
-
|
|
55
|
-
${prompt}
|
|
56
|
-
|
|
57
|
-
## AI Output
|
|
58
|
-
|
|
59
|
-
${output}
|
|
60
|
-
|
|
61
|
-
## Expectations to Evaluate
|
|
62
|
-
|
|
63
|
-
${expectations.map((e, i) => `${i + 1}. ${e}`).join("\n")}
|
|
64
|
-
|
|
65
|
-
Grade the output against each expectation. Respond with ONLY valid JSON.`;
|
|
66
|
-
const result = await executeEval({
|
|
67
|
-
prompt: graderPrompt,
|
|
68
|
-
targetContent: GRADER_SYSTEM_PROMPT,
|
|
69
|
-
timeout,
|
|
70
|
-
model
|
|
71
|
-
});
|
|
72
|
-
if (result.error) {
|
|
73
|
-
return {
|
|
74
|
-
expectations: expectations.map((e) => ({
|
|
75
|
-
text: e,
|
|
76
|
-
passed: false,
|
|
77
|
-
evidence: `Grader error: ${result.error}`
|
|
78
|
-
})),
|
|
79
|
-
summary: { passed: 0, failed: expectations.length, total: expectations.length, pass_rate: 0 },
|
|
80
|
-
claims: [],
|
|
81
|
-
eval_feedback: { suggestions: [], overall: `Grading failed: ${result.error}` }
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
try {
|
|
85
|
-
let jsonStr = result.output.trim();
|
|
86
|
-
const jsonMatch = jsonStr.match(/```(?:json)?\s*([\s\S]*?)```/);
|
|
87
|
-
if (jsonMatch) {
|
|
88
|
-
jsonStr = jsonMatch[1].trim();
|
|
89
|
-
}
|
|
90
|
-
const objMatch = jsonStr.match(/\{[\s\S]*\}/);
|
|
91
|
-
if (objMatch) {
|
|
92
|
-
jsonStr = objMatch[0];
|
|
93
|
-
}
|
|
94
|
-
const parsed = JSON.parse(jsonStr);
|
|
95
|
-
const passed = parsed.expectations.filter((e) => e.passed).length;
|
|
96
|
-
const total = parsed.expectations.length;
|
|
97
|
-
parsed.summary = {
|
|
98
|
-
passed,
|
|
99
|
-
failed: total - passed,
|
|
100
|
-
total,
|
|
101
|
-
pass_rate: total > 0 ? passed / total : 0
|
|
102
|
-
};
|
|
103
|
-
return parsed;
|
|
104
|
-
} catch {
|
|
105
|
-
return {
|
|
106
|
-
expectations: expectations.map((e) => ({
|
|
107
|
-
text: e,
|
|
108
|
-
passed: false,
|
|
109
|
-
evidence: "Grader output was not valid JSON"
|
|
110
|
-
})),
|
|
111
|
-
summary: { passed: 0, failed: expectations.length, total: expectations.length, pass_rate: 0 },
|
|
112
|
-
claims: [],
|
|
113
|
-
eval_feedback: { suggestions: [], overall: `Grader returned unparseable output: ${result.output.slice(0, 200)}` }
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
export {
|
|
119
|
-
gradeEvalOutput
|
|
120
|
-
};
|
|
121
|
-
//# sourceMappingURL=chunk-YNIH3KMU.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/lib/eval-grader.ts"],
|
|
4
|
-
"sourcesContent": ["import { executeEval } from './eval-executor.js';\n\nexport interface GradingExpectation {\n text: string;\n passed: boolean;\n evidence: string;\n}\n\nexport interface GradingResult {\n expectations: GradingExpectation[];\n summary: {\n passed: number;\n failed: number;\n total: number;\n pass_rate: number;\n };\n claims: Array<{\n claim: string;\n type: 'factual' | 'process' | 'quality';\n verified: boolean;\n evidence: string;\n }>;\n eval_feedback: {\n suggestions: Array<{ assertion?: string; reason: string }>;\n overall: string;\n };\n}\n\nconst GRADER_SYSTEM_PROMPT = `You are a rigorous eval grader. Your job is to evaluate whether an AI assistant's output meets a set of expectations.\n\nYou will receive:\n1. The original prompt that was given to the AI\n2. The AI's output/response\n3. A list of expectations (assertions) to evaluate\n\nFor each expectation:\n- Search the output for evidence that the expectation is met\n- Determine PASS or FAIL (no partial credit)\n- Cite specific evidence (quote or description)\n\nPASS criteria:\n- Clear evidence the assertion is true\n- Evidence reflects genuine completion, not surface compliance\n\nFAIL criteria:\n- No evidence found\n- Evidence contradicts the expectation\n- Cannot verify from available information\n\nBeyond the predefined expectations, extract implicit claims from the output:\n- Factual claims (\"uses TypeScript\", \"has 3 parameters\")\n- Process claims (\"used async/await pattern\")\n- Quality claims (\"handles edge cases\")\n\nVerify each claim against the actual output.\n\nFinally, critique the eval itself \u2014 identify assertions that are too weak (pass for wrong outputs) or important outcomes that no assertion covers.\n\nYou MUST respond with ONLY a valid JSON object matching this exact structure (no markdown, no explanation, just JSON):\n\n{\n \"expectations\": [\n { \"text\": \"assertion text\", \"passed\": true, \"evidence\": \"specific quote or description\" }\n ],\n \"summary\": { \"passed\": 2, \"failed\": 1, \"total\": 3, \"pass_rate\": 0.67 },\n \"claims\": [\n { \"claim\": \"statement\", \"type\": \"factual\", \"verified\": true, \"evidence\": \"...\" }\n ],\n \"eval_feedback\": {\n \"suggestions\": [{ \"assertion\": \"suggested new assertion\", \"reason\": \"why it matters\" }],\n \"overall\": \"brief summary assessment\"\n }\n}`;\n\n/**\n * Grades an eval output against expectations using an LLM grader.\n */\nexport async function gradeEvalOutput(options: {\n prompt: string;\n output: string;\n expectations: string[];\n model?: string;\n timeout?: number;\n}): Promise<GradingResult> {\n const { prompt, output, expectations, model, timeout = 120_000 } = options;\n\n const graderPrompt = `## Original Prompt\n\n${prompt}\n\n## AI Output\n\n${output}\n\n## Expectations to Evaluate\n\n${expectations.map((e, i) => `${i + 1}. ${e}`).join('\\n')}\n\nGrade the output against each expectation. Respond with ONLY valid JSON.`;\n\n const result = await executeEval({\n prompt: graderPrompt,\n targetContent: GRADER_SYSTEM_PROMPT,\n timeout,\n model,\n });\n\n if (result.error) {\n // Return a failed grading if the grader itself errors\n return {\n expectations: expectations.map((e) => ({\n text: e,\n passed: false,\n evidence: `Grader error: ${result.error}`,\n })),\n summary: { passed: 0, failed: expectations.length, total: expectations.length, pass_rate: 0 },\n claims: [],\n eval_feedback: { suggestions: [], overall: `Grading failed: ${result.error}` },\n };\n }\n\n // Parse the grader's JSON response\n try {\n // Extract JSON from the output (handle potential markdown wrapping)\n let jsonStr = result.output.trim();\n const jsonMatch = jsonStr.match(/```(?:json)?\\s*([\\s\\S]*?)```/);\n if (jsonMatch) {\n jsonStr = jsonMatch[1].trim();\n }\n // Also try to find JSON object directly\n const objMatch = jsonStr.match(/\\{[\\s\\S]*\\}/);\n if (objMatch) {\n jsonStr = objMatch[0];\n }\n\n const parsed = JSON.parse(jsonStr) as GradingResult;\n\n // Validate and ensure summary is correct\n const passed = parsed.expectations.filter((e) => e.passed).length;\n const total = parsed.expectations.length;\n parsed.summary = {\n passed,\n failed: total - passed,\n total,\n pass_rate: total > 0 ? passed / total : 0,\n };\n\n return parsed;\n } catch {\n // If we can't parse, return a best-effort result\n return {\n expectations: expectations.map((e) => ({\n text: e,\n passed: false,\n evidence: 'Grader output was not valid JSON',\n })),\n summary: { passed: 0, failed: expectations.length, total: expectations.length, pass_rate: 0 },\n claims: [],\n eval_feedback: { suggestions: [], overall: `Grader returned unparseable output: ${result.output.slice(0, 200)}` },\n };\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;;AA4BA,IAAM,uBAAuB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiD7B,eAAsB,gBAAgB,SAMX;AACzB,QAAM,EAAE,QAAQ,QAAQ,cAAc,OAAO,UAAU,KAAQ,IAAI;AAEnE,QAAM,eAAe;AAAA;AAAA,EAErB,MAAM;AAAA;AAAA;AAAA;AAAA,EAIN,MAAM;AAAA;AAAA;AAAA;AAAA,EAIN,aAAa,IAAI,CAAC,GAAG,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA;AAAA;AAIvD,QAAM,SAAS,MAAM,YAAY;AAAA,IAC/B,QAAQ;AAAA,IACR,eAAe;AAAA,IACf;AAAA,IACA;AAAA,EACF,CAAC;AAED,MAAI,OAAO,OAAO;AAEhB,WAAO;AAAA,MACL,cAAc,aAAa,IAAI,CAAC,OAAO;AAAA,QACrC,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,UAAU,iBAAiB,OAAO,KAAK;AAAA,MACzC,EAAE;AAAA,MACF,SAAS,EAAE,QAAQ,GAAG,QAAQ,aAAa,QAAQ,OAAO,aAAa,QAAQ,WAAW,EAAE;AAAA,MAC5F,QAAQ,CAAC;AAAA,MACT,eAAe,EAAE,aAAa,CAAC,GAAG,SAAS,mBAAmB,OAAO,KAAK,GAAG;AAAA,IAC/E;AAAA,EACF;AAGA,MAAI;AAEF,QAAI,UAAU,OAAO,OAAO,KAAK;AACjC,UAAM,YAAY,QAAQ,MAAM,8BAA8B;AAC9D,QAAI,WAAW;AACb,gBAAU,UAAU,CAAC,EAAE,KAAK;AAAA,IAC9B;AAEA,UAAM,WAAW,QAAQ,MAAM,aAAa;AAC5C,QAAI,UAAU;AACZ,gBAAU,SAAS,CAAC;AAAA,IACtB;AAEA,UAAM,SAAS,KAAK,MAAM,OAAO;AAGjC,UAAM,SAAS,OAAO,aAAa,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE;AAC3D,UAAM,QAAQ,OAAO,aAAa;AAClC,WAAO,UAAU;AAAA,MACf;AAAA,MACA,QAAQ,QAAQ;AAAA,MAChB;AAAA,MACA,WAAW,QAAQ,IAAI,SAAS,QAAQ;AAAA,IAC1C;AAEA,WAAO;AAAA,EACT,QAAQ;AAEN,WAAO;AAAA,MACL,cAAc,aAAa,IAAI,CAAC,OAAO;AAAA,QACrC,MAAM;AAAA,QACN,QAAQ;AAAA,QACR,UAAU;AAAA,MACZ,EAAE;AAAA,MACF,SAAS,EAAE,QAAQ,GAAG,QAAQ,aAAa,QAAQ,OAAO,aAAa,QAAQ,WAAW,EAAE;AAAA,MAC5F,QAAQ,CAAC;AAAA,MACT,eAAe,EAAE,aAAa,CAAC,GAAG,SAAS,uCAAuC,OAAO,OAAO,MAAM,GAAG,GAAG,CAAC,GAAG;AAAA,IAClH;AAAA,EACF;AACF;",
|
|
6
|
-
"names": []
|
|
7
|
-
}
|
package/dist/chunk-YOBA3NAM.js
DELETED
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getDb,
|
|
3
|
-
sessionEvents,
|
|
4
|
-
sessions
|
|
5
|
-
} from "./chunk-EI5BHWXA.js";
|
|
6
|
-
import {
|
|
7
|
-
runLlmPrompt
|
|
8
|
-
} from "./chunk-FZKLLNDS.js";
|
|
9
|
-
|
|
10
|
-
// src/lib/handlers/process-session-goal.ts
|
|
11
|
-
import { eq, asc, sql } from "drizzle-orm";
|
|
12
|
-
var ACTIVE_WINDOW_MS = 30 * 60 * 1e3;
|
|
13
|
-
var RECENT_WINDOW_MS = 5 * 60 * 1e3;
|
|
14
|
-
var MAX_TURNS = 10;
|
|
15
|
-
var PROMPT = `Given these messages from an AI coding session, write a 1-2 sentence summary of what the user is trying to accomplish. Focus on the goal, not the steps. No preamble.
|
|
16
|
-
|
|
17
|
-
Return strict JSON in the form: {"goalSummary": "..."}`;
|
|
18
|
-
async function processSessionGoal(payload, deps = {}) {
|
|
19
|
-
const db = deps.db ?? getDb();
|
|
20
|
-
const llm = deps.llm ?? runLlmPrompt;
|
|
21
|
-
const now = deps.now ?? Date.now;
|
|
22
|
-
const [s] = await db.select().from(sessions).where(eq(sessions.id, payload.sessionId)).limit(1);
|
|
23
|
-
if (!s) return { skipped: "not_found" };
|
|
24
|
-
const lastAtRows = await db.execute(
|
|
25
|
-
sql`SELECT MAX(timestamp) AS last_at FROM session_events WHERE session_id = ${payload.sessionId}`
|
|
26
|
-
);
|
|
27
|
-
const lastAtRaw = lastAtRows?.[0]?.last_at ?? s.startedAt;
|
|
28
|
-
const lastAt = new Date(lastAtRaw).getTime();
|
|
29
|
-
if (now() - lastAt > ACTIVE_WINDOW_MS) return { skipped: "stale" };
|
|
30
|
-
const analysis = s.analysis ?? {};
|
|
31
|
-
const lastGoalAt = analysis.goalSummaryAt ? new Date(analysis.goalSummaryAt).getTime() : 0;
|
|
32
|
-
if (lastGoalAt && now() - lastGoalAt < RECENT_WINDOW_MS) {
|
|
33
|
-
return { skipped: "recent" };
|
|
34
|
-
}
|
|
35
|
-
const events = await db.select().from(sessionEvents).where(eq(sessionEvents.sessionId, payload.sessionId)).orderBy(asc(sessionEvents.timestamp)).limit(MAX_TURNS * 2);
|
|
36
|
-
const turns = events.filter(
|
|
37
|
-
(e) => e.content && (e.eventType === "user_message" || e.eventType === "assistant_response")
|
|
38
|
-
).map(
|
|
39
|
-
(e) => `${e.eventType === "user_message" ? "USER" : "ASSISTANT"}: ${e.content}`
|
|
40
|
-
).join("\n\n");
|
|
41
|
-
if (!turns) return { skipped: "no_content" };
|
|
42
|
-
const parsed = await llm(PROMPT, turns, 200);
|
|
43
|
-
const summary = typeof parsed?.goalSummary === "string" ? parsed.goalSummary.trim() : "";
|
|
44
|
-
if (!summary) return { skipped: "llm_empty" };
|
|
45
|
-
const goalSummaryAt = new Date(now()).toISOString();
|
|
46
|
-
await db.update(sessions).set({
|
|
47
|
-
analysis: { ...analysis, goalSummary: summary, goalSummaryAt }
|
|
48
|
-
}).where(eq(sessions.id, payload.sessionId));
|
|
49
|
-
return { goalSummary: summary };
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export {
|
|
53
|
-
processSessionGoal
|
|
54
|
-
};
|
|
55
|
-
//# sourceMappingURL=chunk-YOBA3NAM.js.map
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/lib/handlers/process-session-goal.ts"],
|
|
4
|
-
"sourcesContent": ["import { eq, asc, sql } from 'drizzle-orm';\nimport { sessions, sessionEvents, getDb } from '@rulemetric/db';\nimport { runLlmPrompt } from '../llm-client.js';\n\nconst ACTIVE_WINDOW_MS = 30 * 60 * 1000;\nconst RECENT_WINDOW_MS = 5 * 60 * 1000;\nconst MAX_TURNS = 10;\n\nconst PROMPT = `Given these messages from an AI coding session, write a 1-2 sentence summary of what the user is trying to accomplish. Focus on the goal, not the steps. No preamble.\n\nReturn strict JSON in the form: {\"goalSummary\": \"...\"}`;\n\nexport interface ProcessSessionGoalPayload {\n sessionId: string;\n milestone: 5 | 20 | 50;\n}\n\nexport interface ProcessSessionGoalResult {\n skipped?: 'not_found' | 'stale' | 'recent' | 'no_content' | 'llm_empty';\n goalSummary?: string;\n}\n\nexport interface ProcessSessionGoalDeps {\n db?: any;\n llm?: typeof runLlmPrompt;\n now?: () => number;\n}\n\n/**\n * Fire-and-forget background job triggered at event milestones (5/20/50).\n * Generates a short \"what is the user trying to do\" summary and writes it\n * to `sessions.analysis.goalSummary` + `goalSummaryAt`, preserving any\n * existing analysis keys.\n *\n * Guards:\n * - stale: skip if no activity in last 30 min (session is dead, don't waste an LLM call)\n * - recent: skip if we already generated a summary in the last 5 min (dedup milestone burst)\n *\n * No mirror table \u2014 this is fire-and-forget, similar to crons. Errors\n * propagate so Graphile retries.\n */\nexport async function processSessionGoal(\n payload: ProcessSessionGoalPayload,\n deps: ProcessSessionGoalDeps = {},\n): Promise<ProcessSessionGoalResult> {\n const db = deps.db ?? getDb();\n const llm = deps.llm ?? runLlmPrompt;\n const now = deps.now ?? Date.now;\n\n const [s] = await db\n .select()\n .from(sessions)\n .where(eq(sessions.id, payload.sessionId))\n .limit(1);\n if (!s) return { skipped: 'not_found' };\n\n // Single-roundtrip MAX(timestamp) \u2014 fall back to startedAt if no events yet.\n const lastAtRows = await db.execute(\n sql`SELECT MAX(timestamp) AS last_at FROM session_events WHERE session_id = ${payload.sessionId}`,\n );\n const lastAtRaw = lastAtRows?.[0]?.last_at ?? s.startedAt;\n const lastAt = new Date(lastAtRaw as string | Date).getTime();\n if (now() - lastAt > ACTIVE_WINDOW_MS) return { skipped: 'stale' };\n\n const analysis = (s.analysis ?? {}) as Record<string, unknown>;\n const lastGoalAt = analysis.goalSummaryAt\n ? new Date(analysis.goalSummaryAt as string).getTime()\n : 0;\n if (lastGoalAt && now() - lastGoalAt < RECENT_WINDOW_MS) {\n return { skipped: 'recent' };\n }\n\n const events = await db\n .select()\n .from(sessionEvents)\n .where(eq(sessionEvents.sessionId, payload.sessionId))\n .orderBy(asc(sessionEvents.timestamp))\n .limit(MAX_TURNS * 2);\n\n const turns = (events as Array<{ eventType: string; content: string | null }>)\n .filter(\n (e) =>\n e.content &&\n (e.eventType === 'user_message' || e.eventType === 'assistant_response'),\n )\n .map(\n (e) =>\n `${e.eventType === 'user_message' ? 'USER' : 'ASSISTANT'}: ${e.content}`,\n )\n .join('\\n\\n');\n\n if (!turns) return { skipped: 'no_content' };\n\n // Let LLM errors throw \u2014 Graphile will retry.\n const parsed = await llm(PROMPT, turns, 200);\n const summary =\n typeof parsed?.goalSummary === 'string' ? parsed.goalSummary.trim() : '';\n if (!summary) return { skipped: 'llm_empty' };\n\n const goalSummaryAt = new Date(now()).toISOString();\n await db\n .update(sessions)\n .set({\n analysis: { ...analysis, goalSummary: summary, goalSummaryAt },\n })\n .where(eq(sessions.id, payload.sessionId));\n\n return { goalSummary: summary };\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;AAAA,SAAS,IAAI,KAAK,WAAW;AAI7B,IAAM,mBAAmB,KAAK,KAAK;AACnC,IAAM,mBAAmB,IAAI,KAAK;AAClC,IAAM,YAAY;AAElB,IAAM,SAAS;AAAA;AAAA;AAiCf,eAAsB,mBACpB,SACA,OAA+B,CAAC,GACG;AACnC,QAAM,KAAK,KAAK,MAAM,MAAM;AAC5B,QAAM,MAAM,KAAK,OAAO;AACxB,QAAM,MAAM,KAAK,OAAO,KAAK;AAE7B,QAAM,CAAC,CAAC,IAAI,MAAM,GACf,OAAO,EACP,KAAK,QAAQ,EACb,MAAM,GAAG,SAAS,IAAI,QAAQ,SAAS,CAAC,EACxC,MAAM,CAAC;AACV,MAAI,CAAC,EAAG,QAAO,EAAE,SAAS,YAAY;AAGtC,QAAM,aAAa,MAAM,GAAG;AAAA,IAC1B,8EAA8E,QAAQ,SAAS;AAAA,EACjG;AACA,QAAM,YAAY,aAAa,CAAC,GAAG,WAAW,EAAE;AAChD,QAAM,SAAS,IAAI,KAAK,SAA0B,EAAE,QAAQ;AAC5D,MAAI,IAAI,IAAI,SAAS,iBAAkB,QAAO,EAAE,SAAS,QAAQ;AAEjE,QAAM,WAAY,EAAE,YAAY,CAAC;AACjC,QAAM,aAAa,SAAS,gBACxB,IAAI,KAAK,SAAS,aAAuB,EAAE,QAAQ,IACnD;AACJ,MAAI,cAAc,IAAI,IAAI,aAAa,kBAAkB;AACvD,WAAO,EAAE,SAAS,SAAS;AAAA,EAC7B;AAEA,QAAM,SAAS,MAAM,GAClB,OAAO,EACP,KAAK,aAAa,EAClB,MAAM,GAAG,cAAc,WAAW,QAAQ,SAAS,CAAC,EACpD,QAAQ,IAAI,cAAc,SAAS,CAAC,EACpC,MAAM,YAAY,CAAC;AAEtB,QAAM,QAAS,OACZ;AAAA,IACC,CAAC,MACC,EAAE,YACD,EAAE,cAAc,kBAAkB,EAAE,cAAc;AAAA,EACvD,EACC;AAAA,IACC,CAAC,MACC,GAAG,EAAE,cAAc,iBAAiB,SAAS,WAAW,KAAK,EAAE,OAAO;AAAA,EAC1E,EACC,KAAK,MAAM;AAEd,MAAI,CAAC,MAAO,QAAO,EAAE,SAAS,aAAa;AAG3C,QAAM,SAAS,MAAM,IAAI,QAAQ,OAAO,GAAG;AAC3C,QAAM,UACJ,OAAO,QAAQ,gBAAgB,WAAW,OAAO,YAAY,KAAK,IAAI;AACxE,MAAI,CAAC,QAAS,QAAO,EAAE,SAAS,YAAY;AAE5C,QAAM,gBAAgB,IAAI,KAAK,IAAI,CAAC,EAAE,YAAY;AAClD,QAAM,GACH,OAAO,QAAQ,EACf,IAAI;AAAA,IACH,UAAU,EAAE,GAAG,UAAU,aAAa,SAAS,cAAc;AAAA,EAC/D,CAAC,EACA,MAAM,GAAG,SAAS,IAAI,QAAQ,SAAS,CAAC;AAE3C,SAAO,EAAE,aAAa,QAAQ;AAChC;",
|
|
6
|
-
"names": []
|
|
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
|
-
}
|