@rulemetric/cli 0.18.1 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/base-command.js +1 -1
- package/dist/{chunk-WLLIFRRE.js → chunk-2EXQM3UF.js} +1 -1
- package/dist/chunk-2RZDFKX4.js +1 -0
- package/dist/{chunk-NSO2EBYE.js → chunk-2WRP6ZJF.js} +1 -1
- package/dist/chunk-35NZJWFC.js +4 -0
- package/dist/{chunk-3ZHBOILE.js → chunk-45CCW25C.js} +1 -1
- package/dist/{chunk-NMCQ7JZZ.js → chunk-52RILE5M.js} +1 -1
- package/dist/{chunk-O7ZQEKND.js → chunk-5O62P6KC.js} +1 -1
- package/dist/chunk-6WX3AXMI.js +1 -0
- package/dist/{chunk-ENW5SUQJ.js → chunk-6XCD343D.js} +1 -1
- package/dist/chunk-6Z4JNHBO.js +1 -0
- package/dist/{chunk-MJLW5KN2.js → chunk-75H3CKWA.js} +1 -1
- package/dist/{chunk-XAGNGQL3.js → chunk-7CQBFCHP.js} +1 -1
- package/dist/{chunk-ZFEDOPRU.js → chunk-AEIKPNLG.js} +1 -1
- package/dist/{chunk-XCN2YPWI.js → chunk-ANPGOUIO.js} +1 -1
- package/dist/chunk-B56GMANB.js +1 -0
- package/dist/{chunk-CXENLSMR.js → chunk-B5FBLLKT.js} +1 -1
- package/dist/{chunk-KIQK7NVF.js → chunk-CLPIN7TY.js} +1 -1
- package/dist/{chunk-4LVSD2XZ.js → chunk-DRX65ZLX.js} +1 -1
- package/dist/{chunk-5VWVQCNR.js → chunk-E5FI5YHO.js} +1 -1
- package/dist/{chunk-7MQZPDDZ.js → chunk-E6O2IFOK.js} +1 -1
- package/dist/{chunk-BOYWPUV2.js → chunk-EA3X4TAE.js} +1 -1
- package/dist/{chunk-AZWY2DOT.js → chunk-EBGVDX3Z.js} +1 -1
- package/dist/{chunk-FGGESTXG.js → chunk-EYRM7BT4.js} +1 -1
- package/dist/chunk-FD272ZXG.js +2 -0
- package/dist/chunk-FKUFJWII.js +1 -0
- package/dist/chunk-G2MRNA45.js +1 -0
- package/dist/{chunk-C3XWDYZJ.js → chunk-G2UGWEMO.js} +1 -1
- package/dist/chunk-GRTEWHXU.js +5 -0
- package/dist/{chunk-RRBFKVCI.js → chunk-HEO56SKT.js} +1 -1
- package/dist/chunk-HRU6WGCG.js +1 -0
- package/dist/{chunk-MHLHLJ5T.js → chunk-I2U5GNNM.js} +2 -2
- package/dist/{chunk-AZRGURHR.js → chunk-ICULHHNZ.js} +1 -1
- package/dist/{chunk-BRYURAUN.js → chunk-ID47WFUP.js} +1 -1
- package/dist/chunk-IQOBKWVY.js +5 -0
- package/dist/chunk-JE2JX7IJ.js +4 -0
- package/dist/chunk-JVTSJFFI.js +1 -0
- package/dist/{chunk-D7L7IMJQ.js → chunk-K2PI3OGV.js} +1 -1
- package/dist/chunk-K4LO27GG.js +1 -0
- package/dist/chunk-KCX2YDC3.js +1 -0
- package/dist/{chunk-5LTJNYCP.js → chunk-KTLRSRHF.js} +1 -1
- package/dist/{chunk-K65DDLTZ.js → chunk-LKOUL3IF.js} +1 -1
- package/dist/{chunk-GWQ24FQP.js → chunk-LQRXWLFJ.js} +1 -1
- package/dist/{chunk-A2JFQUDW.js → chunk-NI6RDOZ5.js} +1 -1
- package/dist/{chunk-JCZOEIL7.js → chunk-NJKPUZNM.js} +1 -1
- package/dist/{chunk-PPQFN62M.js → chunk-NN4M476J.js} +1 -1
- package/dist/chunk-NX3PF3EQ.js +1 -0
- package/dist/{chunk-7J7H7YFQ.js → chunk-O662MWOR.js} +1 -1
- package/dist/{chunk-UROUVE3D.js → chunk-OHMVGDWQ.js} +1 -1
- package/dist/{chunk-RQBN7WNS.js → chunk-OLOECA5V.js} +7 -7
- package/dist/{chunk-IYX65N6T.js → chunk-ONDOPTSL.js} +1 -1
- package/dist/chunk-ONSRPEUQ.js +7 -0
- package/dist/{chunk-UQJNUESP.js → chunk-OT7ZUHJF.js} +1 -1
- package/dist/{chunk-CAQLSYOK.js → chunk-PCSSIYH6.js} +1 -1
- package/dist/chunk-PD4BUQ2X.js +1 -0
- package/dist/{chunk-WSUKOU3X.js → chunk-PRC5N4NB.js} +1 -1
- package/dist/chunk-Q37D6V2G.js +2 -0
- package/dist/chunk-Q42RXJ4R.js +1 -0
- package/dist/{chunk-3EZZGA72.js → chunk-RFLO7L5X.js} +1 -1
- package/dist/{chunk-QRKMRG6W.js → chunk-RR5EE23Q.js} +1 -1
- package/dist/{chunk-5U5SHJJA.js → chunk-RYMQMJ7O.js} +1 -1
- package/dist/chunk-S7ZQTZNB.js +3 -0
- package/dist/{chunk-LELSVLNK.js → chunk-SFZSHNZZ.js} +1 -1
- package/dist/{chunk-7N55TWYQ.js → chunk-T7DAU6DV.js} +1 -1
- package/dist/{chunk-HNPC5U3C.js → chunk-TUSFCQBL.js} +1 -1
- package/dist/chunk-UFRJ75FW.js +1 -0
- package/dist/{chunk-I2FPXRA6.js → chunk-VGBATQZ3.js} +1 -1
- package/dist/{chunk-NAS7FIGM.js → chunk-WLLSWFAJ.js} +1 -1
- package/dist/chunk-WUDHDZOG.js +1 -0
- package/dist/{chunk-A6JUIZ3H.js → chunk-WYDRKFXO.js} +1 -1
- package/dist/{chunk-LSZ32DUR.js → chunk-XPVI6H2L.js} +1 -1
- package/dist/{chunk-IPNBW7ZW.js → chunk-XQEI7NOC.js} +1 -1
- package/dist/{chunk-EKTNI6RV.js → chunk-Y6VBAURK.js} +1 -1
- package/dist/chunk-YMIO3CVV.js +2 -0
- package/dist/{chunk-RAMQVEJB.js → chunk-YRGNBYZZ.js} +1 -1
- package/dist/{chunk-TQFHRD5B.js → chunk-Z7LBSVG3.js} +1 -1
- package/dist/{chunk-ANLPPIMS.js → chunk-ZFIGOHQ6.js} +1 -1
- package/dist/chunk-ZVCKDNBT.js +1 -0
- package/dist/commands/antigravity/backfill.js +1 -1
- package/dist/commands/auth/create-key.js +1 -1
- package/dist/commands/auth/login.js +1 -1
- package/dist/commands/auth/logout.js +1 -1
- package/dist/commands/auth/revoke-key.js +1 -1
- package/dist/commands/auth/signup.js +1 -1
- package/dist/commands/auth/status.js +1 -1
- package/dist/commands/capture/scope.js +1 -1
- package/dist/commands/catalog/index.js +1 -1
- package/dist/commands/catalog/recommend.js +1 -1
- package/dist/commands/crons/list.js +1 -1
- package/dist/commands/crons/run.js +1 -1
- package/dist/commands/dashboard.js +1 -1
- package/dist/commands/diagnostics.js +1 -1
- package/dist/commands/eval-targets/create.js +1 -1
- package/dist/commands/eval-targets/list.js +1 -1
- package/dist/commands/evals/agent.js +3 -3
- package/dist/commands/evals/auto-run.js +1 -5
- package/dist/commands/evals/benchmark.js +1 -1
- package/dist/commands/evals/compare.js +1 -31
- package/dist/commands/evals/create.js +1 -1
- package/dist/commands/evals/optimize-description.js +1 -59
- package/dist/commands/evals/optimize.js +1 -5
- package/dist/commands/evals/refine-cases.js +1 -1
- package/dist/commands/evals/run.js +1 -3
- package/dist/commands/evals/validate-judge.js +1 -1
- package/dist/commands/experiments/enroll.js +1 -0
- package/dist/commands/experiments/list.js +1 -1
- package/dist/commands/gateway/ensure.js +1 -1
- package/dist/commands/hooks/install.js +1 -1
- package/dist/commands/hooks/run.js +1 -1
- package/dist/commands/hooks/uninstall.js +1 -1
- package/dist/commands/instructions/create.js +1 -1
- package/dist/commands/instructions/dedupe.js +1 -1
- package/dist/commands/instructions/delete.js +1 -1
- package/dist/commands/instructions/fork.js +1 -1
- package/dist/commands/instructions/get.js +1 -1
- package/dist/commands/instructions/list.js +1 -1
- package/dist/commands/instructions/promote.js +1 -1
- package/dist/commands/instructions/pull.js +1 -1
- package/dist/commands/instructions/restore.js +1 -1
- package/dist/commands/instructions/retract.js +1 -1
- package/dist/commands/instructions/upstream.js +1 -1
- package/dist/commands/instructions/versions.js +1 -1
- package/dist/commands/launcher.js +1 -1
- package/dist/commands/local/down.js +1 -1
- package/dist/commands/local/up.js +1 -1
- package/dist/commands/org/current.js +1 -1
- package/dist/commands/org/list.js +1 -1
- package/dist/commands/org/switch.js +1 -1
- package/dist/commands/packs/add-instruction.js +1 -1
- package/dist/commands/packs/apply.js +1 -1
- package/dist/commands/packs/create.js +1 -1
- package/dist/commands/packs/fork.js +1 -1
- package/dist/commands/packs/get.js +1 -1
- package/dist/commands/packs/list.js +1 -1
- package/dist/commands/packs/remove-instruction.js +1 -1
- package/dist/commands/proxy/env.js +1 -1
- package/dist/commands/proxy/logs.js +1 -1
- package/dist/commands/proxy/restart.js +1 -1
- package/dist/commands/proxy/setup.js +1 -1
- package/dist/commands/proxy/start.js +1 -1
- package/dist/commands/proxy/status.js +1 -1
- package/dist/commands/proxy/stop.js +1 -1
- package/dist/commands/research/backfill.js +1 -1
- package/dist/commands/research/resume-scoped-outcomes.js +1 -1
- package/dist/commands/research/tail-transcript.js +1 -1
- package/dist/commands/service/install.js +37 -37
- package/dist/commands/service/status.js +1 -1
- package/dist/commands/service/uninstall.js +1 -1
- package/dist/commands/service/updates.js +1 -0
- package/dist/commands/sessions/analyze.js +1 -1
- package/dist/commands/sessions/delete.js +1 -1
- package/dist/commands/sessions/end.js +1 -1
- package/dist/commands/sessions/import.js +1 -1
- package/dist/commands/sessions/list.js +1 -1
- package/dist/commands/sessions/start.js +1 -1
- package/dist/commands/setup.js +1 -1
- package/dist/commands/skills/export-approved.js +1 -1
- package/dist/commands/skills/install.js +1 -1
- package/dist/commands/skills/list.js +1 -1
- package/dist/commands/skills/publish.js +1 -1
- package/dist/commands/skills/search.js +1 -1
- package/dist/commands/skills/update.js +1 -1
- package/dist/commands/suggestions/accept.js +1 -1
- package/dist/commands/suggestions/auto.js +1 -1
- package/dist/commands/suggestions/dismiss.js +1 -1
- package/dist/commands/suggestions/list.js +1 -1
- package/dist/commands/suggestions/refresh.js +1 -1
- package/dist/commands/suggestions/undo.js +1 -1
- package/dist/dashboard/Dashboard.js +1 -1
- package/dist/dashboard/data.js +1 -1
- package/dist/dashboard/launcher/LauncherOverlay.js +1 -1
- package/dist/dashboard/launcher/api.js +1 -1
- package/dist/dashboard/launcher/useLaunchJobs.js +1 -1
- package/dist/dashboard/panels/measurement.js +1 -1
- package/dist/dashboard/telemetry.js +1 -1
- package/dist/{dist-ZJY72TUD.js → dist-TNM2RNPT.js} +1 -1
- package/dist/lib/active-org-refresh.js +1 -1
- package/dist/lib/agent-loop.js +1 -1
- package/dist/lib/agent-presence.js +1 -1
- package/dist/lib/antigravity-transcript.js +1 -1
- package/dist/lib/api-client.js +1 -1
- package/dist/lib/case-refinement-policy.js +1 -0
- package/dist/lib/discovery-evidence.js +1 -0
- package/dist/lib/discovery-repository.js +1 -0
- package/dist/lib/ensure-api-key.js +1 -1
- package/dist/lib/ensure-fresh-token.js +1 -1
- package/dist/lib/eval-benchmark.js +1 -1
- package/dist/lib/eval-candidate-run.js +1 -1
- package/dist/lib/eval-case-generator.js +1 -1
- package/dist/lib/eval-compare.js +1 -1
- package/dist/lib/eval-conversation-handler.js +1 -1
- package/dist/lib/eval-quota-gate.js +1 -1
- package/dist/lib/eval-resume.js +1 -1
- package/dist/lib/eval-run-batch.js +1 -1
- package/dist/lib/eval-trigger-tester.js +8 -1
- package/dist/lib/insights/generation/installed-asks.js +1 -1
- package/dist/lib/insights/generation/project-evidence.js +1 -1
- package/dist/lib/insights/generation/quality-review.js +1 -1
- package/dist/lib/insights/nomination/nominate.js +1 -1
- package/dist/lib/instruction-proposer.js +16 -1
- package/dist/lib/instruction-restoration.js +1 -1
- package/dist/lib/instructions/acceptance/accept-events.js +1 -1
- package/dist/lib/instructions/acceptance/accept-hook.js +1 -1
- package/dist/lib/instructions/acceptance/hook-install.js +1 -1
- package/dist/lib/instructions/acceptance/reverse-applications.js +1 -1
- package/dist/lib/instructions/acceptance/suggestion-accept.js +1 -1
- package/dist/lib/jobs/handlers/cron-auto-accept-suggestions.js +1 -1
- package/dist/lib/jobs/handlers/cron-eval-autorun.js +1 -1
- package/dist/lib/jobs/handlers/cron-instruction-training.js +1 -1
- package/dist/lib/jobs/handlers/cron-reconcile-attribution.js +1 -1
- package/dist/lib/jobs/handlers/cron-refine-cases.js +1 -1
- package/dist/lib/jobs/handlers/cron-refresh-pricing.js +1 -1
- package/dist/lib/jobs/handlers/cron-retire-unused-skills.js +1 -1
- package/dist/lib/jobs/handlers/cron-suggest-instructions.js +1 -1
- package/dist/lib/jobs/handlers/distill-memories.js +1 -1
- package/dist/lib/jobs/handlers/finalize-scoped-launch.js +1 -1
- package/dist/lib/jobs/handlers/harbor-ab.js +1 -1
- package/dist/lib/jobs/handlers/prepare-isolated-launch.js +1 -0
- package/dist/lib/jobs/handlers/prepare-suggestion-live.js +1 -1
- package/dist/lib/jobs/handlers/process-changelog.js +1 -1
- package/dist/lib/jobs/handlers/process-conversation.js +1 -1
- package/dist/lib/jobs/handlers/process-eval.js +1 -1
- package/dist/lib/jobs/handlers/process-insights.js +1 -1
- package/dist/lib/jobs/handlers/process-judge-review.js +1 -1
- package/dist/lib/jobs/handlers/process-launch.js +1 -1
- package/dist/lib/jobs/handlers/process-run-cleanup.js +1 -1
- package/dist/lib/jobs/handlers/process-session-goal.js +1 -1
- package/dist/lib/jobs/handlers/process-suggestion-adoption.js +1 -1
- package/dist/lib/jobs/handlers/process-suggestion-discovery.js +1 -1
- package/dist/lib/jobs/handlers/process-suggestion-eval.js +1 -1
- package/dist/lib/jobs/handlers/restore-instruction.js +1 -0
- package/dist/lib/jobs/shed-retry.js +1 -1
- package/dist/lib/judge-review-runner.js +1 -1
- package/dist/lib/llm-client.js +1 -1
- package/dist/lib/manual-tasks.js +1 -1
- package/dist/lib/projects/workspace/worktree.js +1 -1
- package/dist/lib/refine-cases.js +1 -1
- package/dist/lib/research-client.js +1 -1
- package/dist/lib/retraction.js +1 -1
- package/dist/lib/session-updates.js +1 -1
- package/dist/lib/setup-steps.js +1 -1
- package/dist/lib/study-result-store.js +1 -0
- package/dist/lib/suggestion-discovery.js +1 -1
- package/dist/lib/telemetry.js +1 -1
- package/dist/lib/terminal-target-heartbeat.js +1 -1
- package/dist/lib/transcript-sync.js +1 -1
- package/dist/lib/work-report.js +1 -1
- package/dist/lib/worker-updates.js +1 -0
- package/oclif.manifest.json +322 -199
- package/package.json +7 -7
- package/dist/chunk-2C7CFCMM.js +0 -1
- package/dist/chunk-647M2I2Y.js +0 -1
- package/dist/chunk-7OTOAC6C.js +0 -8
- package/dist/chunk-A6XQSO62.js +0 -4
- package/dist/chunk-AHLVY52I.js +0 -1
- package/dist/chunk-BDWQ6J4V.js +0 -1
- package/dist/chunk-BU3ZGLQG.js +0 -1
- package/dist/chunk-CJ2WSSHD.js +0 -1
- package/dist/chunk-DTTR4EUJ.js +0 -1
- package/dist/chunk-DZRBB34J.js +0 -16
- package/dist/chunk-FLJTAD2R.js +0 -1
- package/dist/chunk-G7V4ZZZ3.js +0 -1
- package/dist/chunk-GHUW7P55.js +0 -2
- package/dist/chunk-GYKYJJNF.js +0 -1
- package/dist/chunk-KFNFLMUR.js +0 -3
- package/dist/chunk-KOIFFSYW.js +0 -2
- package/dist/chunk-KR32Y5Q5.js +0 -1
- package/dist/chunk-L5ILEWHH.js +0 -1
- package/dist/chunk-LZPE6424.js +0 -5
- package/dist/chunk-MRQIYIQE.js +0 -1
- package/dist/chunk-NLUHMHPM.js +0 -1
- package/dist/chunk-NVOYP4HX.js +0 -1
- package/dist/chunk-P577DWWL.js +0 -1
- package/dist/chunk-PMMHMRFS.js +0 -1
- package/dist/chunk-R26SQ3BE.js +0 -5
- package/dist/chunk-RITL4NU3.js +0 -1
- package/dist/chunk-RWQG25JU.js +0 -1
- package/dist/chunk-YZQZD2E6.js +0 -1
- package/dist/chunk-ZJABRHIP.js +0 -1
- package/dist/lib/eval-accumulation.js +0 -1
- package/dist/lib/evolution-cost.js +0 -1
- package/dist/lib/evolution-enrolment.js +0 -1
- package/dist/lib/jobs/handlers/cron-instruction-evolution.js +0 -1
- package/dist/lib/jobs/handlers/process-memory-ab.js +0 -1
- package/dist/lib/optimize-compare.js +0 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{b as a,c as r}from"../../chunk-W2MV25SB.js";import{a as o}from"../../chunk-
|
|
1
|
+
import{b as a,c as r}from"../../chunk-W2MV25SB.js";import{a as o}from"../../chunk-Z7LBSVG3.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-RFLO7L5X.js";import"../../chunk-KTLRSRHF.js";import"../../chunk-7CQBFCHP.js";import"../../chunk-3AV3GTMP.js";import{e}from"../../chunk-E5FI5YHO.js";import"../../chunk-I2U5GNNM.js";import"../../chunk-XQYAVSUQ.js";import"../../chunk-PZNWH4VQ.js";import{a as n}from"../../chunk-ZLLER3HP.js";import{Args as g}from"@oclif/core";import{printTable as m}from"@oclif/table";var s=class c extends o{static{n(this,"PacksGet")}static description="Get pack detail with instruction list";static examples=["<%= config.bin %> packs get <pack-id>"];static args={id:g.string({description:"Pack ID",required:!0})};async run(){let{args:p}=await this.parse(c);this.requireAuth();let i=await e(`/api/packs/${p.id}`);this.log(`
|
|
2
2
|
Pack: ${i.name}`),this.log(`Description: ${i.description}`),this.log(`Scope: ${r(i.scope)} | Version: ${i.version} | Tier: ${i.tier}`),this.log(`Tags: ${(i.tags??[]).join(", ")||"(none)"}`),this.log(`Instructions: ${i.instructionCount}
|
|
3
3
|
`),i.instructions.length>0&&m({data:i.instructions.map(t=>({"#":String(t.position),Name:a(t.name,40),Scope:r(t.scope),Version:t.version})),columns:["#","Name","Scope","Version"]})}};export{s as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as o,b as n,c}from"../../chunk-W2MV25SB.js";import{a as s}from"../../chunk-
|
|
1
|
+
import{a as o,b as n,c}from"../../chunk-W2MV25SB.js";import{a as s}from"../../chunk-Z7LBSVG3.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-RFLO7L5X.js";import"../../chunk-KTLRSRHF.js";import"../../chunk-7CQBFCHP.js";import"../../chunk-3AV3GTMP.js";import{e as a}from"../../chunk-E5FI5YHO.js";import"../../chunk-I2U5GNNM.js";import"../../chunk-XQYAVSUQ.js";import"../../chunk-PZNWH4VQ.js";import{a as i}from"../../chunk-ZLLER3HP.js";import{Flags as p}from"@oclif/core";import{printTable as g}from"@oclif/table";var e=class m extends s{static{i(this,"PacksList")}static description="List your instruction packs";static examples=["<%= config.bin %> packs list","<%= config.bin %> packs list --json"];static enableJsonFlag=!0;static flags={format:p.string({char:"f",description:"Output format",options:["table","json"],default:"table"})};async run(){let{flags:u}=await this.parse(m);this.requireAuth();let r=await a("/api/packs");return r.length===0?(this.log("No packs found. Create one with `rulemetric packs create`."),r):(u.format==="json"?this.log(JSON.stringify(r,null,2)):g({data:r.map(t=>({Name:n(t.name,40),Scope:c(t.scope),Tier:t.tier,Count:String(t.instructionCount),Tags:(t.tags??[]).join(", "),Updated:o(t.updatedAt)})),columns:["Name","Scope","Tier","Count","Tags","Updated"]}),r)}};export{e as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as s}from"../../chunk-
|
|
1
|
+
import{a as s}from"../../chunk-Z7LBSVG3.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-RFLO7L5X.js";import"../../chunk-KTLRSRHF.js";import"../../chunk-7CQBFCHP.js";import"../../chunk-3AV3GTMP.js";import{i as e}from"../../chunk-E5FI5YHO.js";import"../../chunk-I2U5GNNM.js";import"../../chunk-XQYAVSUQ.js";import"../../chunk-PZNWH4VQ.js";import{a as t}from"../../chunk-ZLLER3HP.js";import{Args as o}from"@oclif/core";var i=class a extends s{static{t(this,"PacksRemoveInstruction")}static description="Remove an instruction from a pack";static examples=["<%= config.bin %> packs remove-instruction <pack-id> <instruction-id>"];static args={packId:o.string({description:"Pack ID",required:!0}),instructionId:o.string({description:"Instruction ID",required:!0})};async run(){let{args:r}=await this.parse(a);this.requireAuth(),await e(`/api/packs/${r.packId}/instructions/${r.instructionId}`),this.log("Instruction removed from pack.")}};export{i as default};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{e as f}from"../../chunk-QWCEZEDO.js";import"../../chunk-KKDHD4XA.js";import"../../chunk-SZ62CP55.js";import{a as h}from"../../chunk-
|
|
1
|
+
import{e as f}from"../../chunk-QWCEZEDO.js";import"../../chunk-KKDHD4XA.js";import"../../chunk-SZ62CP55.js";import{a as h}from"../../chunk-Z7LBSVG3.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-RFLO7L5X.js";import"../../chunk-KTLRSRHF.js";import"../../chunk-7CQBFCHP.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-E5FI5YHO.js";import"../../chunk-I2U5GNNM.js";import"../../chunk-XQYAVSUQ.js";import"../../chunk-PZNWH4VQ.js";import{a as m}from"../../chunk-ZLLER3HP.js";import{Flags as i}from"@oclif/core";import{existsSync as v}from"node:fs";import{homedir as x}from"node:os";import{join as g}from"node:path";var o=g(x(),".mitmproxy","mitmproxy-ca-cert.pem"),l=class d extends h{static{m(this,"ProxyEnv")}static description="Print shell env vars to route any client through the RuleMetric proxy";static examples=["<%= config.bin %> proxy env","<%= config.bin %> proxy env --shell fish",'eval "$(rulemetric proxy env)"',"rulemetric proxy env --python"];static flags={shell:i.string({char:"s",default:"posix",description:"Shell format (posix, fish, powershell)",options:["posix","fish","powershell"]}),python:i.boolean({default:!1,description:"Include Python-specific env vars (REQUESTS_CA_BUNDLE, SSL_CERT_FILE)"}),node:i.boolean({default:!1,description:"Include Node.js-specific env vars (NODE_EXTRA_CA_CERTS)"}),all:i.boolean({default:!1,description:"Include env vars for all runtimes"}),vscode:i.boolean({default:!1,description:"Output VS Code settings.json snippet for Copilot proxy"})};async run(){let{flags:s}=await this.parse(d),y=s.shell,c=s.all,a=s.python||c,p=s.node||c,u=v(o),n=`http://localhost:${f}`;if(u||(this.warn(`CA certificate not found at ${o}
|
|
2
2
|
Run 'rulemetric hooks install' or 'rulemetric proxy setup' to generate it.`),this.exit(1)),s.vscode){let e={"http.proxy":n,"http.proxyStrictSSL":u,"github.copilot.advanced":{"debug.overrideProxyUrl":n}};this.log(JSON.stringify(e,null,2));return}let r=[{key:"HTTPS_PROXY",value:n,comment:"Route HTTPS through RuleMetric gateway"},{key:"HTTP_PROXY",value:n,comment:"Route HTTP through RuleMetric gateway"}];r.push({key:"SSL_CERT_FILE",value:o,comment:"Trust mitmproxy CA (generic \u2014 works with most libraries)"}),(p||!a&&!p)&&r.push({key:"NODE_EXTRA_CA_CERTS",value:o,comment:"Trust mitmproxy CA (Node.js)"}),a&&(r.push({key:"REQUESTS_CA_BUNDLE",value:o,comment:"Trust mitmproxy CA (Python requests / httpx)"}),r.push({key:"CURL_CA_BUNDLE",value:o,comment:"Trust mitmproxy CA (curl / libcurl)"}));let t=[];for(let e of r)switch(y){case"fish":e.comment&&t.push(`# ${e.comment}`),t.push(`set -gx ${e.key} "${e.value}"`);break;case"powershell":e.comment&&t.push(`# ${e.comment}`),t.push(`$env:${e.key} = "${e.value}"`);break;default:e.comment&&t.push(`# ${e.comment}`),t.push(`export ${e.key}="${e.value}"`)}this.log(t.join(`
|
|
3
3
|
`))}};export{l as default};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import{a as c}from"../../chunk-
|
|
1
|
+
import{a as c}from"../../chunk-Z7LBSVG3.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-RFLO7L5X.js";import"../../chunk-KTLRSRHF.js";import"../../chunk-7CQBFCHP.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-E5FI5YHO.js";import"../../chunk-I2U5GNNM.js";import"../../chunk-XQYAVSUQ.js";import"../../chunk-PZNWH4VQ.js";import{a as l}from"../../chunk-ZLLER3HP.js";import{Flags as a}from"@oclif/core";import{existsSync as f,readFileSync as p}from"node:fs";import{homedir as x}from"node:os";import{join as n}from"node:path";import{spawn as m}from"node:child_process";var g=n(x(),".config","rulemetric"),s=n(g,"proxy.log"),d=n(g,"proxy.pid"),h="rulemetric-proxy",r=class u extends c{static{l(this,"ProxyLogs")}static description="View context capture proxy logs";static examples=["<%= config.bin %> proxy logs","<%= config.bin %> proxy logs --follow","<%= config.bin %> proxy logs --lines 50"];static flags={follow:a.boolean({char:"f",default:!1,description:"Follow log output (like tail -f)"}),lines:a.integer({char:"n",default:30,description:"Number of lines to show"})};async run(){let{flags:i}=await this.parse(u);if(f(d)&&p(d,"utf-8").trim().startsWith("docker:")){let o=["logs"];i.follow&&o.push("-f"),o.push("--tail",String(i.lines),h);let t=m("docker",o,{stdio:"inherit"});process.on("SIGINT",()=>{t.kill(),process.exit(0)}),await new Promise(e=>{t.on("exit",()=>e())});return}if(!f(s)){this.log(`No proxy log file found at ${s}`),this.log("Start the proxy first: rulemetric proxy start");return}if(i.follow){let o=m("tail",["-f","-n",String(i.lines),s],{stdio:"inherit"});process.on("SIGINT",()=>{o.kill(),process.exit(0)}),await new Promise(t=>{o.on("exit",()=>t())})}else{let e=p(s,"utf-8").split(`
|
|
2
2
|
`).slice(-i.lines).join(`
|
|
3
3
|
`);this.log(e)}}};export{r as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as s}from"../../chunk-
|
|
1
|
+
import{a as s}from"../../chunk-Z7LBSVG3.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-RFLO7L5X.js";import"../../chunk-KTLRSRHF.js";import"../../chunk-7CQBFCHP.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-E5FI5YHO.js";import"../../chunk-I2U5GNNM.js";import"../../chunk-XQYAVSUQ.js";import"../../chunk-PZNWH4VQ.js";import{a as e}from"../../chunk-ZLLER3HP.js";import{Flags as i}from"@oclif/core";import{setTimeout as p}from"node:timers/promises";var o=class a extends s{static{e(this,"ProxyRestart")}static description="Restart the context capture proxy (stop + start)";static examples=["<%= config.bin %> proxy restart"];static flags={port:i.integer({char:"p",description:"Proxy listen port"}),docker:i.boolean({char:"d",default:!1,description:"Run in Docker mode"})};async run(){let{flags:t}=await this.parse(a);await this.config.runCommand("proxy:stop",[]),await p(500);let r=["--skip-checks"];t.docker&&r.push("--docker"),t.port&&r.push("--port",String(t.port)),await this.config.runCommand("proxy:start",r)}};export{o as default};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as g}from"../../chunk-PJ3WHQ67.js";import{a as S}from"../../chunk-
|
|
1
|
+
import{a as g}from"../../chunk-PJ3WHQ67.js";import{a as S}from"../../chunk-Z7LBSVG3.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-RFLO7L5X.js";import"../../chunk-KTLRSRHF.js";import"../../chunk-7CQBFCHP.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-E5FI5YHO.js";import"../../chunk-I2U5GNNM.js";import"../../chunk-XQYAVSUQ.js";import{g as x}from"../../chunk-PZNWH4VQ.js";import{a as h}from"../../chunk-ZLLER3HP.js";import{Flags as _}from"@oclif/core";import{execSync as P,spawnSync as m}from"node:child_process";import{existsSync as f,readFileSync as y,appendFileSync as T,writeFileSync as k,mkdirSync as v}from"node:fs";import{homedir as d}from"node:os";import{dirname as E,join as u}from"node:path";var c=u(d(),".mitmproxy","mitmproxy-ca-cert.pem"),$=u(d(),".config","rulemetric"),A=8787,R=class C extends S{static{h(this,"ProxySetup")}static description="Set up context capture proxy (installs mitmproxy, configures shell)";static examples=["<%= config.bin %> proxy setup","<%= config.bin %> proxy setup --shell zsh","<%= config.bin %> proxy setup --check"];static flags={shell:_.string({description:"Shell to configure (auto-detected if omitted)",options:["zsh","bash","fish","powershell"]}),port:_.integer({char:"p",default:A,description:"Proxy listen port"}),check:_.boolean({description:"Only check prerequisites, do not install anything",default:!1})};async run(){let{flags:e}=await this.parse(C),i=e.check,t=e.port;this.log("RuleMetric Proxy Setup"),this.log(`=====================
|
|
2
2
|
`);let l=[await this.checkAuth(),await this.checkMitmproxy(),await this.checkCACert(),await this.checkHooks(),this.checkShellEnv(t)],r=!0;for(let n of l){let p=n.ok?"[OK]":"[!!]";this.log(`${p} ${n.name}: ${n.message}`),n.ok||(r=!1)}if(r){this.log("\nAll checks passed. Run `rulemetric proxy start` to begin capturing.");return}if(i){this.log("\nSome checks failed. Run `rulemetric proxy setup` (without --check) to fix.");return}this.log(`
|
|
3
3
|
Fixing issues...
|
|
4
4
|
`);for(let n of l){if(n.ok||!n.fix)continue;this.log(`Fixing: ${n.name}...`),await n.fix()?this.log(` Fixed.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{a as K}from"../../chunk-OMXUK4M6.js";import{b as F,d as N}from"../../chunk-SZ62CP55.js";import{a as U}from"../../chunk-PJ3WHQ67.js";import{a as M}from"../../chunk-
|
|
1
|
+
import{a as K}from"../../chunk-OMXUK4M6.js";import{b as F,d as N}from"../../chunk-SZ62CP55.js";import{a as U}from"../../chunk-PJ3WHQ67.js";import{a as M}from"../../chunk-Z7LBSVG3.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-RFLO7L5X.js";import"../../chunk-KTLRSRHF.js";import"../../chunk-7CQBFCHP.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-E5FI5YHO.js";import"../../chunk-I2U5GNNM.js";import"../../chunk-XQYAVSUQ.js";import{g as $}from"../../chunk-PZNWH4VQ.js";import{a as u}from"../../chunk-ZLLER3HP.js";import{Flags as _}from"@oclif/core";import{execSync as H,spawn as q,spawnSync as m}from"node:child_process";import{appendFileSync as G,existsSync as l,mkdirSync as P,openSync as V,readFileSync as b,writeFileSync as Y}from"node:fs";import{createRequire as W}from"node:module";import{homedir as x}from"node:os";import{dirname as A,join as c,resolve as f}from"node:path";import{fileURLToPath as X}from"node:url";var g=A(X(import.meta.url)),J=8788,S=c(x(),".config","rulemetric"),T=c(S,"proxy.pid"),D=c(S,"proxy.log"),w="rulemetric/proxy",v="rulemetric-proxy";function j(s,o){try{let d=W(import.meta.url).resolve(`@rulemetric/proxy/${s}`);if(l(d))return d}catch{}for(let t of o)if(l(t))return t;return null}u(j,"resolveProxyFile");function B(){let s=[f(g,"../../../../../packages/proxy/addon/rulemetric_addon.py"),f(g,"../../../node_modules/@rulemetric/proxy/addon/rulemetric_addon.py"),f(g,"../../../../../node_modules/@rulemetric/proxy/addon/rulemetric_addon.py")],o=j("addon/rulemetric_addon.py",s);if(o)return o;throw new Error(`Could not find rulemetric_addon.py. Is @rulemetric/proxy installed?
|
|
2
2
|
Searched (after module resolution):
|
|
3
3
|
`+s.map(t=>` ${t}`).join(`
|
|
4
4
|
`))}u(B,"findAddonPath");function z(){let s=[f(g,"../../../../../packages/proxy/Dockerfile"),f(g,"../../../node_modules/@rulemetric/proxy/Dockerfile"),f(g,"../../../../../node_modules/@rulemetric/proxy/Dockerfile")],o=j("Dockerfile",s);if(o)return A(o);throw new Error("Could not find proxy Dockerfile. Is @rulemetric/proxy installed?")}u(z,"findDockerfilePath");function Q(){return m("docker",["image","inspect",w],{stdio:"ignore"}).status===0}u(Q,"dockerImageExists");function Z(){let s=m("docker",["container","inspect","-f","{{.State.Running}}",v],{encoding:"utf-8",stdio:["ignore","pipe","ignore"]});return s.status===0&&s.stdout?.trim()==="true"}u(Z,"dockerContainerRunning");var L=class s extends M{static{u(this,"ProxyStart")}static description="Start context capture proxy";static examples=["<%= config.bin %> proxy start","<%= config.bin %> proxy start --docker","<%= config.bin %> proxy start --port 9090","<%= config.bin %> proxy start --web"];static flags={port:_.integer({char:"p",default:J,description:"Proxy listen port"}),docker:_.boolean({char:"d",default:!1,description:"Run proxy in Docker (no local mitmproxy needed)"}),web:_.boolean({default:!1,description:"Launch mitmweb debug UI instead of mitmdump (local mode only)"}),"skip-checks":_.boolean({default:!1,description:"Skip prerequisite checks"}),build:_.boolean({default:!1,description:"Force rebuild Docker image"})};async run(){let{flags:o}=await this.parse(s),t=o.port;o.docker?await this.startDocker(t,o.build):await this.startLocal(t,o.web,o["skip-checks"])}async startDocker(o,t){try{H("docker info",{stdio:"ignore"})}catch{this.error("Docker is not running. Start Docker Desktop and try again.")}Z()&&this.error("Proxy container already running. Stop it first: rulemetric proxy stop");let d=this.findComposeFile(),k=c(x(),".mitmproxy");P(k,{recursive:!0});let E=process.env.TMPDIR||"/tmp";P(c(E,"rulemetric"),{recursive:!0});let y={PROXY_PORT:String(o),RULEMETRIC_PROJECT_PATH:process.cwd()};if(!process.env.RULEMETRIC_API_KEY&&!process.env.RULEMETRIC_ACCESS_TOKEN){let n=c(x(),".config","rulemetric","env");if(l(n))for(let h of b(n,"utf-8").split(`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{e as m,f as o,k as l,l as d}from"../../chunk-QWCEZEDO.js";import"../../chunk-KKDHD4XA.js";import{b as p,c as u,d as g}from"../../chunk-SZ62CP55.js";import{a as c}from"../../chunk-
|
|
1
|
+
import{e as m,f as o,k as l,l as d}from"../../chunk-QWCEZEDO.js";import"../../chunk-KKDHD4XA.js";import{b as p,c as u,d as g}from"../../chunk-SZ62CP55.js";import{a as c}from"../../chunk-Z7LBSVG3.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-RFLO7L5X.js";import"../../chunk-KTLRSRHF.js";import"../../chunk-7CQBFCHP.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-E5FI5YHO.js";import"../../chunk-I2U5GNNM.js";import"../../chunk-XQYAVSUQ.js";import"../../chunk-PZNWH4VQ.js";import{a}from"../../chunk-ZLLER3HP.js";import{spawnSync as x}from"node:child_process";import{existsSync as M,readFileSync as P}from"node:fs";import{homedir as I}from"node:os";import{join as y}from"node:path";var D=y(I(),".config","rulemetric"),f=y(D,"proxy.pid"),e=class h extends c{static{a(this,"ProxyStatus")}static description="Check gateway and context capture proxy status";static examples=["<%= config.bin %> proxy status"];async run(){if(await this.parse(h),l()){let n=d();this.log(`Gateway: running (PID ${n}) on :${m}`)}else this.log("Gateway: not running");if(!M(f)){this.log("Mitmproxy: not running \u2014 routing direct (no capture)");return}let i=P(f,"utf-8").trim();if(i.startsWith("docker:")){let n=i.slice(7),r=x("docker",["container","inspect","-f","{{.State.Status}}",n],{encoding:"utf-8",stdio:["ignore","pipe","ignore"]}),s=r.stdout?.trim();r.status===0&&s==="running"?this.log(`Mitmproxy: running in Docker (container: ${n}) on :${o} \u2014 capturing context`):this.log(`Mitmproxy: container ${s||"not running"} (stale)`);return}let t=Number.parseInt(i,10);if(Number.isNaN(t)){this.log("Mitmproxy: not running (invalid PID file)");return}g(t,p)?this.log(`Mitmproxy: running (PID ${t}) on :${o} \u2014 capturing context`):u(t)?this.log(`Mitmproxy: not running (PID ${t} was reused by another process \u2014 stale PID file)`):this.log("Mitmproxy: not running (stale PID file)")}};export{e as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as m,d as a}from"../../chunk-SZ62CP55.js";import{a as d}from"../../chunk-
|
|
1
|
+
import{b as m,d as a}from"../../chunk-SZ62CP55.js";import{a as d}from"../../chunk-Z7LBSVG3.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-RFLO7L5X.js";import"../../chunk-KTLRSRHF.js";import"../../chunk-7CQBFCHP.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-E5FI5YHO.js";import"../../chunk-I2U5GNNM.js";import"../../chunk-XQYAVSUQ.js";import"../../chunk-PZNWH4VQ.js";import{a as l}from"../../chunk-ZLLER3HP.js";import{spawnSync as s}from"node:child_process";import{existsSync as f,readFileSync as y,unlinkSync as n}from"node:fs";import{homedir as h}from"node:os";import{dirname as g,join as p,resolve as x}from"node:path";import{fileURLToPath as I}from"node:url";var P=g(I(import.meta.url)),k=p(h(),".config","rulemetric"),t=p(k,"proxy.pid"),c=class u extends d{static{l(this,"ProxyStop")}static description="Stop the context capture proxy";static examples=["<%= config.bin %> proxy stop"];async run(){if(await this.parse(u),!f(t)){this.log("No proxy process found (no PID file).");return}let e=y(t,"utf-8").trim();if(e.startsWith("docker:")){let r=e.slice(7),i=this.findComposeFile();i?(s("docker",["compose","-f",i,"stop","proxy"],{stdio:"inherit"}),s("docker",["compose","-f",i,"rm","-f","proxy"],{stdio:"ignore"})):(s("docker",["stop",r],{stdio:"ignore"}),s("docker",["rm",r],{stdio:"ignore"})),this.log("Proxy container stopped.");try{n(t)}catch{}return}let o=Number.parseInt(e,10);if(Number.isNaN(o)){n(t),this.log("Invalid PID file removed.");return}if(a(o,m))try{process.kill(o,"SIGTERM"),this.log(`Proxy stopped (PID ${o}).`)}catch(r){r.code==="ESRCH"?this.log("Proxy process not running (stale PID file removed)."):this.error(`Failed to stop proxy: ${r.message}`)}else this.log("Proxy process not running (stale PID file removed).");try{n(t)}catch{}this.log(""),this.log("Gateway is still running \u2014 Claude Code will route direct until proxy restarts.")}findComposeFile(){let e=[p(process.cwd(),"docker-compose.yml"),x(P,"../../../../../docker-compose.yml")];for(let o of e)if(f(o))return o;return null}};export{c as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{e as s}from"../../chunk-NVKX36YN.js";import{b as n}from"../../chunk-
|
|
1
|
+
import{e as s}from"../../chunk-NVKX36YN.js";import{b as n}from"../../chunk-O662MWOR.js";import{a}from"../../chunk-Z7LBSVG3.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-RFLO7L5X.js";import"../../chunk-KTLRSRHF.js";import"../../chunk-7CQBFCHP.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-E5FI5YHO.js";import"../../chunk-I2U5GNNM.js";import"../../chunk-XQYAVSUQ.js";import"../../chunk-PZNWH4VQ.js";import{a as o}from"../../chunk-ZLLER3HP.js";import{Flags as d}from"@oclif/core";import l from"node:path";import f from"node:os";var i=class c extends a{static{o(this,"ResearchBackfill")}static description="Scan every ~/.claude/projects transcript for past rate-limit (429) events and POST them as observations. Opt-in seed for the usage-research dataset \u2014 forward-only tail is the default capture path.";static examples=["<%= config.bin %> research backfill","<%= config.bin %> research backfill --claude-dir /custom/.claude --dry-run"];static flags={"claude-dir":d.string({description:"Override the Claude Code projects directory (defaults to ~/.claude)",default:l.join(f.homedir(),".claude"),noCacheDefault:!0}),"dry-run":d.boolean({description:"Print observation count without POSTing",default:!1})};async run(){let{flags:e}=await this.parse(c);this.requireAuth(),this.log(`Scanning ${l.join(e["claude-dir"],"projects")} for rate-limit events...`);let r=await s(e["claude-dir"]);if(this.log(`Found ${r.length} rate-limit observation(s).`),r.length===0)return;if(e["dry-run"]){this.log("Dry run \u2014 nothing posted.");return}let t=await n(r);if(this.log(`Posted ${t.posted} observation(s); ${t.failed} failed.`),t.failed>0)for(let u of t.errors)this.warn(u)}};export{i as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{h as d}from"../../chunk-
|
|
1
|
+
import{h as d}from"../../chunk-WUDHDZOG.js";import{c as i,s as a}from"../../chunk-XFOG2PDJ.js";import"../../chunk-SIGZEQ3K.js";import{a as s}from"../../chunk-Z7LBSVG3.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-RFLO7L5X.js";import"../../chunk-KTLRSRHF.js";import"../../chunk-7CQBFCHP.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-E5FI5YHO.js";import"../../chunk-I2U5GNNM.js";import"../../chunk-XQYAVSUQ.js";import"../../chunk-PZNWH4VQ.js";import{a as o}from"../../chunk-ZLLER3HP.js";import{Flags as p}from"@oclif/core";var r=class n extends s{static{o(this,"ResearchResumeScopedOutcomes")}static description="Finish uploading scoped headless outcomes whose receipt was preserved locally after the actor exited but whose capture or verification upload failed. Never re-runs the actor or re-measures the repository; ships the stored receipt and exact transcript only.";static hidden=!0;static examples=["<%= config.bin %> research resume-scoped-outcomes","<%= config.bin %> research resume-scoped-outcomes --list"];static flags={list:p.boolean({description:"Show the outcome store without uploading anything",default:!1})};async run(){let{flags:l}=await this.parse(n);if(this.log(`Outcome store: ${i()}`),l.list){for(let e of a()){let c=e.ledger?.completedAt?"delivered":e.receipt?`pending (${e.ledger?.completed.join(",")||"nothing"} done${e.ledger?.lastError?`; last error at ${e.ledger.lastError.step}: ${e.ledger.lastError.message}`:""})`:"unmeasured (no receipt)";this.log(`${e.confirmationId}/${e.externalSessionId}: ${c}`)}return}this.requireAuth();let t=await d(e=>this.log(e));this.log(`scanned=${t.scanned} delivered=${t.delivered} failed=${t.failed} unmeasured=${t.unmeasured}`),t.failed>0&&this.exit(1)}};export{r as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{d,g as c,h as p}from"../../chunk-NVKX36YN.js";import{b as l}from"../../chunk-
|
|
1
|
+
import{d,g as c,h as p}from"../../chunk-NVKX36YN.js";import{b as l}from"../../chunk-O662MWOR.js";import{a as f}from"../../chunk-Z7LBSVG3.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-RFLO7L5X.js";import"../../chunk-KTLRSRHF.js";import"../../chunk-7CQBFCHP.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-E5FI5YHO.js";import"../../chunk-I2U5GNNM.js";import"../../chunk-XQYAVSUQ.js";import"../../chunk-PZNWH4VQ.js";import{a as n}from"../../chunk-ZLLER3HP.js";import{Args as v,Flags as g}from"@oclif/core";import w from"node:path";var r=class h extends f{static{n(this,"ResearchTailTranscript")}static description="Read new lines from a Claude Code transcript since the last cached offset, POST any 429 events, and persist the new offset. Invoked by the session-end hook \u2014 safe to re-run.";static hidden=!0;static args={transcript:v.string({description:"Absolute path to a Claude Code .jsonl transcript",required:!0})};static flags={"no-post":g.boolean({description:"Parse and advance the offset without POSTing (debug)",default:!1})};async run(){let{args:u,flags:m}=await this.parse(h),e=w.resolve(u.transcript);try{this.requireAuth()}catch{return}let s=await c(),o=s[e]??0,{observations:a,newOffset:i}=await d(e,o);if(a.length>0&&!m["no-post"])try{let t=await l(a);process.env.RULEMETRIC_DEBUG&&this.log(`tail-transcript: posted ${t.posted}, failed ${t.failed}`)}catch(t){process.env.RULEMETRIC_DEBUG&&this.warn(`tail-transcript POST error: ${String(t)}`)}i!==o&&(s[e]=i,await p(s))}};export{r as default};
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import{a as
|
|
2
|
-
Or skip the capture proxy with --no-proxy.`)),e)this.log("[..] Skipping pre-install build (--skip-build)");else{this.log("[..] Building workspace artifacts (api, web, cli) via turbo...");let R=
|
|
3
|
-
`)){let s=e.trim();if(!s||s.startsWith("#"))continue;let
|
|
1
|
+
import{a as x}from"../../chunk-MMM4B3KH.js";import{a as G}from"../../chunk-6XEC6474.js";import{c as N,g as K}from"../../chunk-YMIO3CVV.js";import"../../chunk-N7ODX6PO.js";import{a as B}from"../../chunk-Z7LBSVG3.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-RFLO7L5X.js";import{c as M}from"../../chunk-KTLRSRHF.js";import{b as $}from"../../chunk-7CQBFCHP.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-E5FI5YHO.js";import"../../chunk-I2U5GNNM.js";import"../../chunk-XQYAVSUQ.js";import{l as U}from"../../chunk-PZNWH4VQ.js";import{a as _}from"../../chunk-ZLLER3HP.js";import{Flags as v}from"@oclif/core";import{existsSync as u,mkdirSync as E,readFileSync as I,writeFileSync as V}from"node:fs";import{execSync as Y,execFileSync as p,spawnSync as D}from"node:child_process";import{homedir as y,userInfo as rt}from"node:os";import{dirname as P,join as n}from"node:path";var q="com.rulemetric.api",L=n(y(),"Library","LaunchAgents",`${q}.plist`),J="com.rulemetric.worker",w=n(y(),"Library","LaunchAgents",`${J}.plist`),z="com.rulemetric.gateway",H=n(y(),"Library","LaunchAgents",`${z}.plist`),Q="com.rulemetric.proxy",F=n(y(),"Library","LaunchAgents",`${Q}.plist`),it="com.rulemetric.worker.restart",C=n(y(),"Library","LaunchAgents",`${it}.plist`),T=n(y(),".config","rulemetric"),h=n(T,"logs"),st=8787,X=8788,Z=n(y(),".config","systemd","user"),A="rulemetric-worker.service",W=n(Z,A),j=class O extends B{static{_(this,"ServiceInstall")}static description="Install RuleMetric services. Default (in a repo checkout): API + worker + gateway + capture proxy as launchd agents. With --worker-only: just the job worker, targeting the globally-installed CLI \u2014 no repo, no build (works from `npm i -g @rulemetric/cli`, macOS launchd or Linux systemd).";static examples=["<%= config.bin %> service install","<%= config.bin %> service install --port 3000","<%= config.bin %> service install --skip-build","<%= config.bin %> service install --no-proxy","<%= config.bin %> service install --worker-only"];static flags={port:v.integer({char:"p",default:3e3,description:"API server port"}),force:v.boolean({char:"f",default:!1,description:"Overwrite existing service configuration and reclaim conflicting ports"}),"skip-build":v.boolean({default:!1,description:"Skip the pre-install workspace build (API/web/cli dist must already exist)"}),"no-proxy":v.boolean({default:!1,description:"Skip gateway + mitmproxy plists (just install API + worker)"}),"auto-update":v.boolean({description:"Opt this machine into automatic stable CLI updates after active worker jobs finish (requires --worker-only)",dependsOn:["worker-only"]}),"worker-only":v.boolean({default:!1,description:"Install ONLY the job worker as a persistent service, targeting the globally-installed CLI (no repo checkout, no build, no API/gateway/proxy). Sources auth from ~/.config/rulemetric/env. macOS (launchd) + Linux (systemd --user)."})};async run(){let{flags:i}=await this.parse(O),t=i.port,e=i["skip-build"],s=i["no-proxy"];if(i["worker-only"]){await this.runWorkerOnly(i.force,i["auto-update"]);return}if(process.platform!=="darwin"&&this.error("The full service install is macOS-only (launchd). For just the job worker on Linux (or a clean npm install), use: rulemetric service install --worker-only"),u(L)&&!i.force){this.log(`Service already installed at ${L}`),this.log("Use --force to overwrite, or run: rulemetric service status");return}try{if((await fetch(`http://localhost:${t}/health`)).ok&&!i.force){this.warn(`Port ${t} is already in use (API may be running via start.sh or in another terminal).`),this.warn("Stop it first with scripts/dev/stop.sh, or use --force to take over the port.");return}}catch{}let r=this.findProjectRoot();r||this.error("Could not find RuleMetric project root. Run this command from within the momento-mori repo, or set RULEMETRIC_PROJECT_ROOT.");let o=n(r,".env.local");u(o)||this.error(`.env.local not found at ${o}. The API needs Supabase credentials to start.`);let a=this.guardAlwaysOnDatabaseUrl(this.loadEnvVars(r)),c=this.findBinary("node"),d=this.findBinary("pnpm");(!c||!d)&&this.error("Could not find node or pnpm. Ensure they are in your PATH.");let g=null;if(s||(g=this.findBinary("mitmdump"),g||this.error(`mitmdump not found in PATH. Install with: pipx install mitmproxy (or brew install mitmproxy), then re-run.
|
|
2
|
+
Or skip the capture proxy with --no-proxy.`)),e)this.log("[..] Skipping pre-install build (--skip-build)");else{this.log("[..] Building workspace artifacts (api, web, cli) via turbo...");let R=D(d,["exec","turbo","run","build",...["--filter","@rulemetric/api...","--filter","@rulemetric/web...","--filter","@rulemetric/cli"]],{cwd:r,stdio:"inherit"});R.status!==0&&this.error(`Workspace build failed (exit ${R.status}). Fix the build first, or use --skip-build if dist/ already exists.`),this.log("[OK] Build complete")}let f=n(r,"apps","api","dist","index.js");u(f)||this.error(`API entry not found at ${f}. Re-run without --skip-build, or: pnpm --filter @rulemetric/api... build`);let k=n(r,"apps","web","dist","index.html");if(u(k)||this.warn(`Web bundle not found at ${k}. Dashboard at :${t} will 404 until you build apps/web.`),!s){let b=n(r,"apps","cli","dist","lib","gateway-entry.js");u(b)||this.error(`Gateway entry not found at ${b}. Re-run without --skip-build, or: pnpm --filter @rulemetric/cli build`)}i.force&&this.killStaleProcess(t,null,"API on :"+t),s||(this.killStaleProcess(st,n(T,"gateway.pid"),"gateway"),this.killStaleProcess(X,n(T,"proxy.pid"),"mitmproxy")),E(n(y(),"Library","LaunchAgents"),{recursive:!0}),E(h,{recursive:!0});let m=Y("id -u",{encoding:"utf-8"}).trim(),tt=this.buildPlist({port:t,projectRoot:r,nodePath:c,pnpmPath:d,envVars:a});this.bootoutAndWrite(m,L,tt,"API"),this.bootstrapPlist(m,L,"API"),this.log(`[..] Waiting for API on :${t}...`),await this.waitForApi(t,15)?(this.log(`[OK] RuleMetric API running on :${t}`),u(k)&&this.log(`[OK] Dashboard available at http://localhost:${t}`)):(this.warn("API did not respond within 15s. Check logs:"),this.log(` tail -f ${h}/api-stdout.log`),this.log(` tail -f ${h}/api-stderr.log`)),this.log(""),this.log("Installing worker service..."),this.killStaleAgents();let et=this.buildWorkerPlist({cliBin:n(r,"apps","cli","bin","run.js"),cliDist:n(r,"apps","cli","dist"),workingDir:r,nodePath:c,pnpmPath:d,envVars:a});if(this.bootoutAndWrite(m,w,et,"Worker"),this.bootstrapPlist(m,w,"Worker"),!s){this.log(""),this.log("Installing gateway + capture proxy services...");let b=this.buildGatewayPlist({projectRoot:r,nodePath:c});this.bootoutAndWrite(m,H,b,"Gateway"),this.bootstrapPlist(m,H,"Gateway");let R=this.buildProxyPlist({projectRoot:r,mitmdumpPath:g,envVars:a});this.bootoutAndWrite(m,F,R,"Proxy"),this.bootstrapPlist(m,F,"Proxy")}if(u(C)){try{p("launchctl",["bootout",`gui/${m}`,C],{encoding:"utf-8"})}catch{}try{p("rm",["-f",C]),this.log("[OK] Removed stale daily worker-restart agent (no longer needed on agent path)")}catch{}}this.log(""),s?this.log("Installed: API + worker. Gateway/proxy skipped (--no-proxy)."):this.log("Installed: API + worker + gateway + capture proxy."),this.log("All services start at login, restart on crash, and pick up rebuilds via WatchPaths."),this.log(""),this.log("NOTE: Env vars are baked in at install time. If you change"),this.log(".env.local or credentials, re-run: rulemetric service install --force"),this.log(""),this.log("Manage with:"),this.log(" rulemetric service status \u2014 check if running"),this.log(" rulemetric service uninstall \u2014 remove all services"),await $();let S=await G();this.log(""),S.available?this.log(`[OK] tmux found${S.version?` (v${S.version})`:""} \u2014 live send enabled`):this.log("[!!] tmux not found \u2014 live send will fall back to opening Terminal. Install with: brew install tmux")}async runWorkerOnly(i,t){let e=process.platform;e!=="darwin"&&e!=="linux"&&this.error(`--worker-only supports macOS (launchd) and Linux (systemd) only; detected '${e}'.`);let s=this.findBinary("node");s||this.error("Could not find `node` in PATH.");let r=n(this.config.root,"bin","run.js");u(r)||this.error(`Could not locate the installed CLI entry at ${r}. Reinstall the CLI (e.g. npm i -g @rulemetric/cli) and re-run.`);let o=n(this.config.root,"dist");t&&await K(this.config.root);let a=this.loadGlobalWorkerEnv();!a.RULEMETRIC_API_KEY&&!a.RULEMETRIC_ACCESS_TOKEN&&this.error("Not authenticated \u2014 no RULEMETRIC_API_KEY/RULEMETRIC_ACCESS_TOKEN in ~/.config/rulemetric/env.\nRun `rulemetric auth login` first, then re-run `rulemetric service install --worker-only`."),a.RULEMETRIC_API_URL||(a.RULEMETRIC_API_URL="https://rulemetric.com");let c=e==="darwin"?w:W;if(u(c)&&!i){this.log(`Worker already installed at ${c}. Use --force to overwrite.`);return}if(a.RULEMETRIC_MANAGED_WORKER="1",t&&N(U(),this.config.root,!0),E(h,{recursive:!0}),this.killStaleAgents(),e==="darwin"){E(n(y(),"Library","LaunchAgents"),{recursive:!0});let d=Y("id -u",{encoding:"utf-8"}).trim(),g=this.buildWorkerPlist({cliBin:r,cliDist:o,workingDir:y(),nodePath:s,nodeEnv:"production",watchDist:!1,envVars:a});this.bootoutAndWrite(d,w,g,"Worker"),this.bootstrapPlist(d,w,"Worker"),this.log(""),this.log("[OK] Worker installed (launchd). Starts at login, restarts on crash."),this.log(` Logs: tail -f ${n(h,"worker-stdout.log")}`)}else{E(Z,{recursive:!0});let d=this.buildWorkerSystemdUnit({cliBin:r,nodePath:s,envVars:a});V(W,d,{mode:384}),this.log(`[OK] Wrote ${W}`);try{p("systemctl",["--user","daemon-reload"]),p("systemctl",["--user","enable","--now",A]),i&&p("systemctl",["--user","restart",A]),this.log("[OK] Worker enabled + started (systemctl --user).");try{p("loginctl",["enable-linger",rt().username]),this.log("[OK] Enabled linger \u2014 worker survives logout/reboot.")}catch{this.log("[!!] Could not enable linger (worker will stop on logout)."),this.log(' Run: sudo loginctl enable-linger "$USER"')}this.log(` Logs: journalctl --user -u ${A} -f`)}catch(g){this.warn(`Wrote the unit but \`systemctl --user\` failed: ${g instanceof Error?g.message:String(g)}`),this.log(`Enable it manually: systemctl --user daemon-reload && systemctl --user enable --now ${A}`)}}this.log(""),this.log("Manage with:"),this.log(" rulemetric service status \u2014 check if running"),this.log(" rulemetric service uninstall \u2014 remove the worker"),this.log(" rulemetric service updates \u2014 automatic-update preference and last result"),t&&this.log("Automatic updates enabled on this machine. New releases install after active jobs finish."),await $(),M("worker_started",{mode:"worker-only"},this.config.version)}loadGlobalWorkerEnv(){let i={},t=n(T,"env");if(u(t))for(let e of I(t,"utf-8").split(`
|
|
3
|
+
`)){let s=e.trim();if(!s||s.startsWith("#"))continue;let r=s.indexOf("=");r>0&&(i[s.slice(0,r)]=s.slice(r+1))}return Object.fromEntries(Object.entries(i).filter(([e])=>x.has(e)))}buildWorkerSystemdUnit(i){let{cliBin:t,nodePath:e,envVars:s}=i,r={...s,NODE_ENV:"production",PATH:[...new Set([P(e),n(y(),".local","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin"])].join(":"),PG_POOL_MAX:s.PG_POOL_MAX??"3",PG_IDLE_TIMEOUT:s.PG_IDLE_TIMEOUT??"10"},o=Object.entries(r).map(([a,c])=>`Environment="${a}=${c.replace(/\\/g,"\\\\").replace(/"/g,'\\"')}"`).join(`
|
|
4
4
|
`);return`[Unit]
|
|
5
5
|
Description=RuleMetric job worker (evals agent)
|
|
6
6
|
After=network-online.target
|
|
@@ -11,25 +11,25 @@ Type=simple
|
|
|
11
11
|
ExecStart=${e} ${t} evals agent
|
|
12
12
|
Restart=on-failure
|
|
13
13
|
RestartSec=15
|
|
14
|
-
${
|
|
14
|
+
${o}
|
|
15
15
|
|
|
16
16
|
[Install]
|
|
17
17
|
WantedBy=default.target
|
|
18
|
-
`}findProjectRoot(){if(process.env.RULEMETRIC_PROJECT_ROOT)return process.env.RULEMETRIC_PROJECT_ROOT;let
|
|
19
|
-
`)){let
|
|
20
|
-
`)){let
|
|
21
|
-
`).filter(Boolean).map(e=>parseInt(e,10)).filter(e=>!isNaN(e)&&e!==process.pid);for(let e of t)try{process.kill(e,"SIGTERM"),this.log(`[OK] Reaped orphan evals agent (PID ${e})`)}catch{}t.length&&
|
|
22
|
-
`).filter(Boolean);for(let a of
|
|
23
|
-
${c}`;
|
|
18
|
+
`}findProjectRoot(){if(process.env.RULEMETRIC_PROJECT_ROOT)return process.env.RULEMETRIC_PROJECT_ROOT;let i=process.cwd();for(let t=0;t<10;t++){if(u(n(i,"apps","api","package.json")))return i;let e=n(i,"..");if(e===i)break;i=e}return null}findBinary(i){try{return p("which",[i],{encoding:"utf-8",stdio:["pipe","pipe","ignore"]}).trim()||null}catch{return null}}loadEnvVars(i){let t={},e=n(i,".env.local");if(u(e))for(let r of I(e,"utf-8").split(`
|
|
19
|
+
`)){let o=r.trim();if(!o||o.startsWith("#"))continue;let a=o.indexOf("=");a>0&&(t[o.slice(0,a)]=o.slice(a+1))}let s=n(T,"env");if(u(s))for(let r of I(s,"utf-8").split(`
|
|
20
|
+
`)){let o=r.trim();if(!o||o.startsWith("#"))continue;let a=o.indexOf("=");a>0&&(t[o.slice(0,a)]=o.slice(a+1))}return Object.fromEntries(Object.entries(t).filter(([r])=>x.has(r)))}guardAlwaysOnDatabaseUrl(i){let t=i.DATABASE_URL;return t?t.includes("pooler.supabase.com:5432")?(this.warn("DATABASE_URL points at the SESSION-mode pooler (:5432, 15-slot cap). The always-on API/worker must use TRANSACTION mode (:6543) \u2014 auto-correcting for the installed services. Fix .env.local to silence this warning."),{...i,DATABASE_URL:t.replace("pooler.supabase.com:5432","pooler.supabase.com:6543")}):(/@db\.[a-z0-9]+\.supabase\.co[:/]/.test(t)&&this.warn("DATABASE_URL is a DIRECT database connection (db.<ref>.supabase.co), not the pooler. Always-on services should use the transaction pooler (aws-*.pooler.supabase.com:6543) to avoid exhausting Postgres connections."),i):i}killStaleAgents(){try{let t=p("pgrep",["-f","bin/run.js evals agent"],{encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim().split(`
|
|
21
|
+
`).filter(Boolean).map(e=>parseInt(e,10)).filter(e=>!isNaN(e)&&e!==process.pid);for(let e of t)try{process.kill(e,"SIGTERM"),this.log(`[OK] Reaped orphan evals agent (PID ${e})`)}catch{}t.length&&D("sleep",["1"],{stdio:"ignore"})}catch{}}killStaleProcess(i,t,e){let s=!1;if(t&&u(t)){try{let r=I(t,"utf-8").trim(),o=parseInt(r,10);if(!isNaN(o))try{process.kill(o,"SIGTERM"),s=!0,this.log(`[OK] Stopped existing ${e} (PID ${o} from ${t})`)}catch{}}catch{}try{p("rm",["-f",t])}catch{}}try{let o=p("lsof",["-ti",`:${i}`,"-sTCP:LISTEN"],{encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim().split(`
|
|
22
|
+
`).filter(Boolean);for(let a of o){let c=parseInt(a,10);if(!isNaN(c))try{process.kill(c,"SIGTERM"),s=!0,this.log(`[OK] Stopped orphan on :${i} (PID ${c})`)}catch{}}}catch{}s&&D("sleep",["1"],{stdio:"ignore"})}bootoutAndWrite(i,t,e,s){let r=["Could not find specified service","No such process","3: No such process","5: Input/output error"];try{p("launchctl",["bootout",`gui/${i}`,t],{encoding:"utf-8",stdio:["ignore","pipe","pipe"]}),this.log(`[OK] Unloaded existing ${s} service`)}catch(o){let a=o.message||"",c=(o.stderr??"").toString(),d=`${a}
|
|
23
|
+
${c}`;r.some(g=>d.includes(g))||this.warn(`Could not unload existing ${s} service: ${a.trim()}`)}V(t,e,{mode:384}),this.log(`[OK] ${s} plist written to ${t}`)}bootstrapPlist(i,t,e){try{p("launchctl",["bootstrap",`gui/${i}`,t]),this.log(`[OK] ${e} service loaded into launchd`)}catch(s){try{p("launchctl",["load",t]),this.log(`[OK] ${e} service loaded into launchd (legacy)`)}catch(r){this.warn(`Could not load ${e} service.
|
|
24
24
|
bootstrap: ${s.message.trim()}
|
|
25
|
-
load: ${
|
|
25
|
+
load: ${r.message.trim()}`)}}}buildPlist(i){let{port:t,projectRoot:e,nodePath:s,pnpmPath:r,envVars:o}=i,a=[...new Set([P(s),P(r),"/usr/local/bin","/usr/bin","/bin"])],c=Object.entries({...o,PORT:String(t),NODE_ENV:"production",PATH:a.join(":"),PG_POOL_MAX:o.PG_POOL_MAX??"10",PG_STATEMENT_TIMEOUT_MS:o.PG_STATEMENT_TIMEOUT_MS??"10000",PG_IDLE_TIMEOUT:o.PG_IDLE_TIMEOUT??"30",OTEL_SPAN_EXPORT:o.OTEL_SPAN_EXPORT??"none"}).map(([f,k])=>` <key>${l(f)}</key>
|
|
26
26
|
<string>${l(k)}</string>`).join(`
|
|
27
|
-
`),d=
|
|
27
|
+
`),d=n(e,"apps","api","dist","index.js"),g=n(e,"apps","api","dist");return`<?xml version="1.0" encoding="UTF-8"?>
|
|
28
28
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
29
29
|
<plist version="1.0">
|
|
30
30
|
<dict>
|
|
31
31
|
<key>Label</key>
|
|
32
|
-
<string>${
|
|
32
|
+
<string>${q}</string>
|
|
33
33
|
|
|
34
34
|
<key>ProgramArguments</key>
|
|
35
35
|
<array>
|
|
@@ -59,31 +59,31 @@ ${c}
|
|
|
59
59
|
|
|
60
60
|
<key>WatchPaths</key>
|
|
61
61
|
<array>
|
|
62
|
-
<string>${l(
|
|
62
|
+
<string>${l(g)}</string>
|
|
63
63
|
</array>
|
|
64
64
|
|
|
65
65
|
<key>StandardOutPath</key>
|
|
66
|
-
<string>${l(
|
|
66
|
+
<string>${l(n(h,"api-stdout.log"))}</string>
|
|
67
67
|
|
|
68
68
|
<key>StandardErrorPath</key>
|
|
69
|
-
<string>${l(
|
|
69
|
+
<string>${l(n(h,"api-stderr.log"))}</string>
|
|
70
70
|
|
|
71
71
|
<key>ProcessType</key>
|
|
72
72
|
<string>Background</string>
|
|
73
73
|
</dict>
|
|
74
74
|
</plist>
|
|
75
|
-
`}buildWorkerPlist(
|
|
75
|
+
`}buildWorkerPlist(i){let{cliBin:t,cliDist:e,workingDir:s,nodePath:r,pnpmPath:o,envVars:a}=i,c=i.nodeEnv??"development",d=[...new Set([P(r),o?P(o):null,n(y(),".local","bin"),"/opt/homebrew/bin","/usr/local/bin","/usr/bin","/bin"].filter(f=>!!f))],g=Object.entries({...a,NODE_ENV:c,PATH:d.join(":"),PG_POOL_MAX:a.PG_POOL_MAX??"3",PG_IDLE_TIMEOUT:a.PG_IDLE_TIMEOUT??"10"}).map(([f,k])=>` <key>${l(f)}</key>
|
|
76
76
|
<string>${l(k)}</string>`).join(`
|
|
77
77
|
`);return`<?xml version="1.0" encoding="UTF-8"?>
|
|
78
78
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
79
79
|
<plist version="1.0">
|
|
80
80
|
<dict>
|
|
81
81
|
<key>Label</key>
|
|
82
|
-
<string>${
|
|
82
|
+
<string>${J}</string>
|
|
83
83
|
|
|
84
84
|
<key>ProgramArguments</key>
|
|
85
85
|
<array>
|
|
86
|
-
<string>${l(
|
|
86
|
+
<string>${l(r)}</string>
|
|
87
87
|
<string>${l(t)}</string>
|
|
88
88
|
<string>evals</string>
|
|
89
89
|
<string>agent</string>
|
|
@@ -94,7 +94,7 @@ ${c}
|
|
|
94
94
|
|
|
95
95
|
<key>EnvironmentVariables</key>
|
|
96
96
|
<dict>
|
|
97
|
-
${
|
|
97
|
+
${g}
|
|
98
98
|
</dict>
|
|
99
99
|
|
|
100
100
|
<key>RunAtLoad</key>
|
|
@@ -109,29 +109,29 @@ ${u}
|
|
|
109
109
|
<key>ThrottleInterval</key>
|
|
110
110
|
<integer>15</integer>
|
|
111
111
|
|
|
112
|
-
<key>WatchPaths</key>
|
|
112
|
+
${i.watchDist===!1?"":` <key>WatchPaths</key>
|
|
113
113
|
<array>
|
|
114
114
|
<string>${l(e)}</string>
|
|
115
|
-
</array
|
|
115
|
+
</array>`}
|
|
116
116
|
|
|
117
117
|
<key>StandardOutPath</key>
|
|
118
|
-
<string>${l(
|
|
118
|
+
<string>${l(n(h,"worker-stdout.log"))}</string>
|
|
119
119
|
|
|
120
120
|
<key>StandardErrorPath</key>
|
|
121
|
-
<string>${l(
|
|
121
|
+
<string>${l(n(h,"worker-stderr.log"))}</string>
|
|
122
122
|
|
|
123
123
|
<key>ProcessType</key>
|
|
124
124
|
<string>Background</string>
|
|
125
125
|
</dict>
|
|
126
126
|
</plist>
|
|
127
|
-
`}buildGatewayPlist(
|
|
128
|
-
<string>${l(
|
|
127
|
+
`}buildGatewayPlist(i){let{projectRoot:t,nodePath:e}=i,s=n(t,"apps","cli","dist","lib","gateway-entry.js"),r=n(t,"apps","cli","bin","run.js"),o=[...new Set([P(e),"/usr/local/bin","/usr/bin","/bin"])],a={RULEMETRIC_CLI_VERSION:this.config.version,RULEMETRIC_CLI_ENTRY:r,PATH:o.join(":")},c=Object.entries(a).map(([d,g])=>` <key>${l(d)}</key>
|
|
128
|
+
<string>${l(g)}</string>`).join(`
|
|
129
129
|
`);return`<?xml version="1.0" encoding="UTF-8"?>
|
|
130
130
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
131
131
|
<plist version="1.0">
|
|
132
132
|
<dict>
|
|
133
133
|
<key>Label</key>
|
|
134
|
-
<string>${
|
|
134
|
+
<string>${z}</string>
|
|
135
135
|
|
|
136
136
|
<key>ProgramArguments</key>
|
|
137
137
|
<array>
|
|
@@ -160,31 +160,31 @@ ${c}
|
|
|
160
160
|
<integer>10</integer>
|
|
161
161
|
|
|
162
162
|
<key>StandardOutPath</key>
|
|
163
|
-
<string>${l(
|
|
163
|
+
<string>${l(n(h,"gateway-stdout.log"))}</string>
|
|
164
164
|
|
|
165
165
|
<key>StandardErrorPath</key>
|
|
166
|
-
<string>${l(
|
|
166
|
+
<string>${l(n(h,"gateway-stderr.log"))}</string>
|
|
167
167
|
|
|
168
168
|
<key>ProcessType</key>
|
|
169
169
|
<string>Background</string>
|
|
170
170
|
</dict>
|
|
171
171
|
</plist>
|
|
172
|
-
`}buildProxyPlist(
|
|
173
|
-
<string>${l(
|
|
172
|
+
`}buildProxyPlist(i){let{projectRoot:t,mitmdumpPath:e,envVars:s}=i,r=n(t,"packages","proxy","addon","rulemetric_addon.py"),o=[...new Set([P(e),"/usr/local/bin","/usr/bin","/bin"])],a={...s,RULEMETRIC_PROJECT_PATH:t,RULEMETRIC_CLI_VERSION:this.config.version,PATH:o.join(":")},c=Object.entries(a).map(([d,g])=>` <key>${l(d)}</key>
|
|
173
|
+
<string>${l(g)}</string>`).join(`
|
|
174
174
|
`);return`<?xml version="1.0" encoding="UTF-8"?>
|
|
175
175
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
176
176
|
<plist version="1.0">
|
|
177
177
|
<dict>
|
|
178
178
|
<key>Label</key>
|
|
179
|
-
<string>${
|
|
179
|
+
<string>${Q}</string>
|
|
180
180
|
|
|
181
181
|
<key>ProgramArguments</key>
|
|
182
182
|
<array>
|
|
183
183
|
<string>${l(e)}</string>
|
|
184
184
|
<string>--listen-port</string>
|
|
185
|
-
<string>${
|
|
185
|
+
<string>${X}</string>
|
|
186
186
|
<string>-s</string>
|
|
187
|
-
<string>${l(
|
|
187
|
+
<string>${l(r)}</string>
|
|
188
188
|
<string>--set</string>
|
|
189
189
|
<string>console_eventlog_verbosity=info</string>
|
|
190
190
|
</array>
|
|
@@ -210,13 +210,13 @@ ${c}
|
|
|
210
210
|
<integer>15</integer>
|
|
211
211
|
|
|
212
212
|
<key>StandardOutPath</key>
|
|
213
|
-
<string>${l(
|
|
213
|
+
<string>${l(n(h,"proxy-stdout.log"))}</string>
|
|
214
214
|
|
|
215
215
|
<key>StandardErrorPath</key>
|
|
216
|
-
<string>${l(
|
|
216
|
+
<string>${l(n(h,"proxy-stderr.log"))}</string>
|
|
217
217
|
|
|
218
218
|
<key>ProcessType</key>
|
|
219
219
|
<string>Background</string>
|
|
220
220
|
</dict>
|
|
221
221
|
</plist>
|
|
222
|
-
`}async waitForApi(
|
|
222
|
+
`}async waitForApi(i,t){let e=null;for(let s=0;s<t;s++){try{let r=await fetch(`http://localhost:${i}/health`);if(r.ok)return!0;e=`health check returned ${r.status}`}catch(r){e=r.message}await new Promise(r=>setTimeout(r,1e3))}return e&&this.warn(`Last health check error: ${e}`),!1}};function l(O){return O.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""")}_(l,"escapeXml");export{j as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as b}from"../../chunk-6XEC6474.js";import"../../chunk-N7ODX6PO.js";import{a as w}from"../../chunk-
|
|
1
|
+
import{a as b}from"../../chunk-6XEC6474.js";import"../../chunk-N7ODX6PO.js";import{a as w}from"../../chunk-Z7LBSVG3.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-RFLO7L5X.js";import"../../chunk-KTLRSRHF.js";import"../../chunk-7CQBFCHP.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-E5FI5YHO.js";import"../../chunk-I2U5GNNM.js";import"../../chunk-XQYAVSUQ.js";import"../../chunk-PZNWH4VQ.js";import{a as T}from"../../chunk-ZLLER3HP.js";import{existsSync as c,readFileSync as A}from"node:fs";import{execFileSync as x,execSync as M}from"node:child_process";import{homedir as l}from"node:os";import{join as a}from"node:path";var k="com.rulemetric.api",g=a(l(),"Library","LaunchAgents",`${k}.plist`),u="com.rulemetric.worker",o=a(l(),"Library","LaunchAgents",`${u}.plist`),v="com.rulemetric.gateway",E=a(l(),"Library","LaunchAgents",`${v}.plist`),L="com.rulemetric.proxy",R=a(l(),"Library","LaunchAgents",`${L}.plist`),_=a(l(),".config","rulemetric","logs"),y=8787,$=8788,p="rulemetric-worker.service",W=a(l(),".config","systemd","user",p),P=class extends w{static{T(this,"ServiceStatus")}static description="Check the status of installed RuleMetric services (launchd on macOS; systemd --user worker on Linux)";async run(){if(process.platform!=="darwin"){if(process.platform==="linux"){this.reportLinuxWorkerStatus();return}this.error(`Service status supports macOS (launchd) and Linux (systemd --user, worker-only installs) only; detected '${process.platform}'.`)}if(!c(g)){if(c(o)){this.reportWorkerOnlyStatus();return}this.log("Service: not installed"),this.log("Run: rulemetric service install (repo checkout) or rulemetric service install --worker-only");return}let t=this.readServiceState(k,g),e=this.readApiPort(g),r=await this.probeApiHealth(e),d=await this.probeDashboard(e),s=this.readServiceState(u,o),h=this.readWorkerMode(),i=this.readServiceState(v,E),S=this.isPortListening(y),n=this.readServiceState(L,R),m=this.isPortListening($),O=`${r} (port ${e})${d?" \u2014 dashboard served":""}`;this.log(`API: ${this.fmtState(t)} \u2014 ${O}`);let I=h==="listen"?" [mode: listen \u2014 DEPRECATED, run `rulemetric service install --force` to upgrade]":"";this.log(`Worker: ${this.fmtState(s)}${I}`),this.log(`Gateway: ${this.fmtState(i)} \u2014 ${S?`listening :${y}`:`NOT listening :${y}`}`),this.log(`Proxy: ${this.fmtState(n)} \u2014 ${m?`listening :${$}`:`NOT listening :${$}`}`);let f=await b();this.log(`Tmux: ${f.available?f.version?`v${f.version}`:"available":"not found"}`),this.log(""),this.log(`Plists: ${g}`),this.log(` ${o}`),i.installed&&this.log(` ${E}`),n.installed&&this.log(` ${R}`),this.log(`Logs: ${_}/{api,worker,gateway,proxy}-{stdout,stderr}.log`);let D=t.launchdStatus==="running"&&r==="healthy"&&s.launchdStatus==="running"&&(!i.installed||i.launchdStatus==="running"&&S)&&(!n.installed||n.launchdStatus==="running"&&m);this.log(""),D?this.log("All good \u2014 sessions tracked, jobs processed, capture pipeline live."):(t.launchdStatus!=="running"&&(this.log("API is not running. Try:"),this.log(` launchctl kickstart gui/$(id -u)/${k}`)),s.installed&&s.launchdStatus!=="running"&&(this.log("Worker is not running. Try:"),this.log(` launchctl kickstart gui/$(id -u)/${u}`)),i.installed&&(i.launchdStatus!=="running"||!S)&&(this.log("Gateway is not running. Try:"),this.log(` launchctl kickstart gui/$(id -u)/${v}`)),n.installed&&(n.launchdStatus!=="running"||!m)&&(this.log("Proxy is not running. Try:"),this.log(` launchctl kickstart gui/$(id -u)/${L}`)),(!i.installed||!n.installed)&&this.log("Gateway/proxy not installed. Run: rulemetric service install --force"))}reportWorkerOnlyStatus(){let t=this.readServiceState(u,o),r=this.readWorkerMode()==="listen"?" [mode: listen \u2014 DEPRECATED, run `rulemetric service install --worker-only --force` to upgrade]":"";this.log(`Worker: ${this.fmtState(t)}${r} (worker-only install)`),this.log(""),this.log(`Plist: ${o}`),this.log(`Logs: ${_}/worker-{stdout,stderr}.log`),this.log(""),t.launchdStatus==="running"?this.log("All good \u2014 jobs processed by the background worker."):(this.log("Worker is not running. Try:"),this.log(` launchctl kickstart gui/$(id -u)/${u}`))}reportLinuxWorkerStatus(){if(!c(W)){this.log("Service: not installed"),this.log("Run: rulemetric service install --worker-only");return}let t;try{t=x("systemctl",["--user","is-active",p],{encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim()}catch(e){t=(e.stdout??"").toString().trim()||"not loaded"}this.log(`Worker: ${t} (systemd --user, worker-only install)`),this.log(""),this.log(`Unit: ${W}`),this.log(`Logs: journalctl --user -u ${p} -f`),this.log(""),t==="active"?this.log("All good \u2014 jobs processed by the background worker."):(this.log("Worker is not running. Try:"),this.log(` systemctl --user restart ${p}`))}readServiceState(t,e){if(!c(e))return{installed:!1,launchdStatus:"not installed",pid:null};try{let d=M(`launchctl list ${t} 2>/dev/null`,{encoding:"utf-8"}),s=d.match(/"PID"\s*=\s*(\d+)/),h=d.match(/"LastExitStatus"\s*=\s*(\d+)/);if(s)return{installed:!0,launchdStatus:"running",pid:s[1]};if(h){let i=h[1];return{installed:!0,launchdStatus:i==="0"?"stopped (clean exit)":`stopped (exit ${i})`,pid:null}}return{installed:!0,launchdStatus:"loaded",pid:null}}catch{return{installed:!0,launchdStatus:"not loaded",pid:null}}}fmtState(t){return t.installed?`${t.launchdStatus}${t.pid?` (PID ${t.pid})`:""}`:"not installed"}readApiPort(t){try{let r=A(t,"utf-8").match(/<key>PORT<\/key>\s*<string>(\d+)<\/string>/);if(r)return Number.parseInt(r[1])}catch{}return 3e3}readWorkerMode(){if(!c(o))return null;try{let e=A(o,"utf-8").match(/<string>evals<\/string>\s*<string>(listen|agent)<\/string>/);if(e)return e[1]}catch{}return null}async probeApiHealth(t){try{let e=await fetch(`http://localhost:${t}/health`);return e.ok?"healthy":`unhealthy (${e.status})`}catch{return"unreachable"}}async probeDashboard(t){try{let e=await fetch(`http://localhost:${t}/`);return e.ok?(e.headers.get("content-type")??"").includes("text/html"):!1}catch{return!1}}isPortListening(t){try{return x("lsof",["-ti",`:${t}`,"-sTCP:LISTEN"],{encoding:"utf-8",stdio:["ignore","pipe","ignore"]}).trim().length>0}catch{return!1}}};export{P as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as u}from"../../chunk-
|
|
1
|
+
import{a as u}from"../../chunk-Z7LBSVG3.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-RFLO7L5X.js";import"../../chunk-KTLRSRHF.js";import"../../chunk-7CQBFCHP.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-E5FI5YHO.js";import"../../chunk-I2U5GNNM.js";import"../../chunk-XQYAVSUQ.js";import"../../chunk-PZNWH4VQ.js";import{a as n}from"../../chunk-ZLLER3HP.js";import{existsSync as m,unlinkSync as d}from"node:fs";import{execSync as g,execFileSync as s}from"node:child_process";import{homedir as y}from"node:os";import{join as p}from"node:path";var v=[{label:"com.rulemetric.api",description:"API"},{label:"com.rulemetric.worker",description:"Worker"},{label:"com.rulemetric.gateway",description:"Gateway"},{label:"com.rulemetric.proxy",description:"Proxy"},{label:"com.rulemetric.worker.restart",description:"Worker restart agent"}];function h(a){return p(y(),"Library","LaunchAgents",`${a}.plist`)}n(h,"plistPathFor");var l="rulemetric-worker.service",i=p(y(),".config","systemd","user",l),c=class extends u{static{n(this,"ServiceUninstall")}static description="Remove RuleMetric services (macOS launchd: API/worker/gateway/proxy; Linux: the --worker-only systemd unit)";async run(){if(process.platform==="linux"){this.uninstallLinuxWorker();return}process.platform!=="darwin"&&this.error("Service uninstall supports macOS (launchd) and Linux (systemd) only.");let r=v.filter(t=>m(h(t.label)));if(r.length===0){this.log("No RuleMetric services are installed.");return}let o=g("id -u",{encoding:"utf-8"}).trim();for(let t of r){let e=h(t.label);this.stopService(o,e,t.label,t.description),this.removePlist(e,t.description)}this.log(""),this.log("All RuleMetric services removed. They will no longer start automatically."),this.log("Use scripts/dev/start.sh (dev) or `rulemetric service install` (always-on) to bring them back.")}stopService(r,o,t,e){try{s("launchctl",["bootout",`gui/${r}`,o],{encoding:"utf-8"}),this.log(`[OK] ${e} stopped`);return}catch{}try{s("launchctl",["unload",o],{encoding:"utf-8"}),this.log(`[OK] ${e} stopped (legacy)`);return}catch{try{g(`launchctl list ${t} 2>&1`,{encoding:"utf-8"}).includes("PID")?(this.warn(`${e} appears to still be running. Try manually:`),this.warn(` launchctl bootout gui/${r} "${o}"`)):this.log(`[OK] ${e} was not running`)}catch{this.log(`[OK] ${e} was not running`)}}}removePlist(r,o){try{d(r),this.log(`[OK] Removed ${r}`)}catch(t){this.warn(`Could not remove ${o} plist: ${t.message}. Try: rm "${r}"`)}}uninstallLinuxWorker(){if(!m(i)){this.log("No RuleMetric worker is installed (no systemd unit found).");return}try{s("systemctl",["--user","disable","--now",l],{encoding:"utf-8"}),this.log("[OK] Worker stopped + disabled (systemctl --user)")}catch(r){this.warn(`Could not disable the worker unit: ${r.message}`),this.warn(` systemctl --user disable --now ${l}`)}try{d(i),this.log(`[OK] Removed ${i}`)}catch(r){this.warn(`Could not remove ${i}: ${r.message}. Try: rm "${i}"`)}try{s("systemctl",["--user","daemon-reload"],{encoding:"utf-8"})}catch{}this.log(""),this.log("RuleMetric worker removed. It will no longer start automatically.")}};export{c as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{a as c,b as d,c as a,g as f}from"../../chunk-YMIO3CVV.js";import{a as l}from"../../chunk-Z7LBSVG3.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-RFLO7L5X.js";import"../../chunk-KTLRSRHF.js";import"../../chunk-7CQBFCHP.js";import"../../chunk-3AV3GTMP.js";import"../../chunk-E5FI5YHO.js";import"../../chunk-I2U5GNNM.js";import"../../chunk-XQYAVSUQ.js";import{l as n}from"../../chunk-PZNWH4VQ.js";import{a as r}from"../../chunk-ZLLER3HP.js";import{Flags as u}from"@oclif/core";var o=class p extends l{static{r(this,"ServiceUpdates")}static description="Show or change automatic worker updates on this machine (off by default)";static examples=["<%= config.bin %> service updates","<%= config.bin %> service updates --enable","<%= config.bin %> service updates --disable"];static flags={enable:u.boolean({description:"Install stable npm releases automatically after active jobs finish",exclusive:["disable"]}),disable:u.boolean({description:"Stop future automatic updates",exclusive:["enable"]})};async run(){let{flags:i}=await this.parse(p),t=n();if(i.enable){let b=await f(this.config.root);a(t,b,!0)}else i.disable&&a(t,this.config.root,!1);let s=c(t),e=d(t);this.log(`Automatic worker updates: ${s.enabled?"ON":"OFF"}`),s.enabled&&(this.log("Checks npm latest every six hours; finishes active jobs before updating the global CLI and restarting."),this.log("Requires a worker-only service installed with this release. If needed: rulemetric service install --worker-only --force")),e.outcome&&this.log(`Last update check: ${e.checkedAt??"unknown"} \u2014 ${e.outcome}${e.version?` (${e.version})`:""}`),i.disable&&this.log("The worker rechecks consent before installation and activation. An already activated update is not undone.")}};export{o as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a}from"../../chunk-WLVQJH4E.js";import{a as o}from"../../chunk-
|
|
1
|
+
import{a}from"../../chunk-WLVQJH4E.js";import{a as o}from"../../chunk-Z7LBSVG3.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-RFLO7L5X.js";import"../../chunk-KTLRSRHF.js";import"../../chunk-7CQBFCHP.js";import"../../chunk-3AV3GTMP.js";import{f as r}from"../../chunk-E5FI5YHO.js";import"../../chunk-I2U5GNNM.js";import"../../chunk-XQYAVSUQ.js";import"../../chunk-PZNWH4VQ.js";import{a as t}from"../../chunk-ZLLER3HP.js";import{Args as l}from"@oclif/core";var s=class n extends o{static{t(this,"SessionsAnalyze")}static description="Trigger AI analysis on a session";static examples=["<%= config.bin %> sessions analyze <session-id>"];static args={id:l.string({description:"Session ID",required:!0})};async run(){let{args:i}=await this.parse(n);this.requireAuth(),a(i.id,"session ID");let e=await r(`/api/sessions/${i.id}/analyze`,{});this.log(`Analysis queued (job ${e.jobId}, status: ${e.status}).`),this.log("A running worker picks it up automatically \u2014 start one with `rulemetric evals agent`"),this.log("(or install it persistently: `rulemetric service install --worker-only`)."),this.log("Results appear on the session once processed \u2014 see the session detail page in the dashboard.")}};export{s as default};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a as u}from"../../chunk-
|
|
1
|
+
import{a as u}from"../../chunk-Z7LBSVG3.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-RFLO7L5X.js";import"../../chunk-KTLRSRHF.js";import"../../chunk-7CQBFCHP.js";import"../../chunk-3AV3GTMP.js";import{e as f,i as g}from"../../chunk-E5FI5YHO.js";import"../../chunk-I2U5GNNM.js";import"../../chunk-XQYAVSUQ.js";import"../../chunk-PZNWH4VQ.js";import{a as h}from"../../chunk-ZLLER3HP.js";import{Args as w,Flags as b}from"@oclif/core";var a=class m extends u{static{h(this,"SessionsDelete")}static description="Permanently delete captured sessions and everything stored with them (events, context snapshots, offloaded blobs)";static examples=["<%= config.bin %> sessions delete 4f9d\u2026","<%= config.bin %> sessions delete 4f9d\u2026 8a21\u2026","<%= config.bin %> sessions delete --project /work/client-a --yes"];static args={ids:w.string({description:"Session id(s) to delete",required:!1})};static strict=!1;static flags={project:b.string({description:"Delete every session captured under this project path (use with --yes)."}),yes:b.boolean({description:"Skip the confirmation prompt. Required for --project in non-interactive use.",default:!1})};async run(){let{argv:v,flags:o}=await this.parse(m);this.requireAuth();let n=v.map(t=>t.trim()).filter(Boolean);n.length===0&&!o.project&&this.error("Nothing to delete. Pass one or more session ids, or --project <path> for a bulk scrub."),n.length>0&&o.project&&this.error("Pass either session ids or --project, not both.");let s=n;if(o.project){s=[];let t=0,e=100;for(;;){let r=await f(`/api/sessions?projectPath=${encodeURIComponent(o.project)}&hideEmpty=false&limit=${e}&offset=${t}`);if(s.push(...r.map($=>$.id)),r.length<e)break;t+=e}if(s.length===0){this.log(`No sessions found under ${o.project}. Nothing to delete.`);return}this.log(`${s.length} session(s) captured under ${o.project}.`)}if(!o.yes){process.stdin.isTTY||this.error(`Refusing to delete ${s.length} session(s) without --yes in a non-interactive shell.`);let{createInterface:t}=await import("node:readline/promises"),e=t({input:process.stdin,output:process.stdout}),r=await e.question(`Permanently delete ${s.length} session(s) and all captured content? This cannot be undone. [y/N] `);if(e.close(),r.trim().toLowerCase()!=="y"){this.log("Aborted \u2014 nothing deleted.");return}}let d=0,c=0,p=0,l=0,i=0;for(let t of s)try{let e=await g(`/api/sessions/${t}`);d+=e.eventsDeleted??0,c+=e.snapshotsDeleted??0,p+=e.blobsDeleted??0,l+=e.blobsFailed??0,this.log(`deleted ${t} (${e.eventsDeleted??0} events, ${e.snapshotsDeleted??0} snapshots)`)}catch(e){i+=1,this.warn(`failed to delete ${t}: ${e.message}`)}this.log(""),this.log(`Deleted ${s.length-i}/${s.length} session(s): ${d} events, ${c} snapshots, ${p} storage blob(s) removed.`),l>0&&this.warn(`${l} storage blob(s) could not be removed (rows are gone; blobs are orphaned).`),i>0&&this.error(`${i} session(s) failed to delete \u2014 see warnings above.`)}};export{a as default};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{a as d}from"../../chunk-
|
|
1
|
+
import{a as d}from"../../chunk-Z7LBSVG3.js";import"../../chunk-IZTIYR5Q.js";import"../../chunk-RFLO7L5X.js";import"../../chunk-KTLRSRHF.js";import"../../chunk-7CQBFCHP.js";import"../../chunk-3AV3GTMP.js";import{f as m}from"../../chunk-E5FI5YHO.js";import"../../chunk-I2U5GNNM.js";import"../../chunk-XQYAVSUQ.js";import"../../chunk-PZNWH4VQ.js";import{a as l}from"../../chunk-ZLLER3HP.js";import{readdirSync as f,readFileSync as h,unlinkSync as p,statSync as S}from"node:fs";import{tmpdir as g}from"node:os";import{join as r}from"node:path";var v=[".log",".seq",".ctxhash",".pid",".lock"],c=class u extends d{static{l(this,"SessionsEnd")}static description="End the active capture session";static examples=["<%= config.bin %> sessions end"];async run(){await this.parse(u),this.requireAuth();let i=r(g(),"rulemetric"),s=this.findActiveSession(i);s||this.error("No active session found. Start one with: rulemetric sessions start --tool <name>");try{await m(`/api/sessions/${s.rwSessionId}/close`,{})}catch(e){this.error(`Could not end session ${s.rwSessionId} via API: ${e.message}. Local session files were left in place \u2014 fix the connection/auth issue and retry.`)}this.cleanupSessionFiles(i,s.externalId),this.log(`Session ended: ${s.rwSessionId}`)}findActiveSession(i){let s;try{s=f(i)}catch{return null}let e=[];for(let t of s){if(v.some(o=>t.endsWith(o)))continue;let n=r(i,t);try{let o=S(n);if(!o.isFile())continue;let a=h(n,"utf-8").trim();if(!a)continue;e.push({externalId:t,rwSessionId:a.split(`
|
|
2
2
|
`)[0].trim(),path:n,mtime:o.mtimeMs})}catch{continue}}return e.length===0?null:(e.sort((t,n)=>n.mtime-t.mtime),e[0])}cleanupSessionFiles(i,s){let e=r(i,s);for(let t of["",".seq",".ctxhash",".log"])try{p(e+t)}catch{}}};export{c as default};
|