fix(cli): fallback to user-local private key + record analytics
- cli.ts: key resolution now falls back to ~/.hermes/keys/pr-agent-key.pem when /opt/pr-agent-server/private-key.pem is EACCES/ENOENT (CLI as non-root user works out of the box) - cli.ts+index.ts: export logReviewEvent; CLI now records an analytics event (describe/improve/review) in the legacy pr-agent.*.log format, best-effort (never fails the CLI on a log write), honoring PR_AGENT_ANALYTICS_DIR - Verified: 16/16 tests, tsc clean, describe publishes, review publishes (comment 5757282509), webhook 403/ping/ignored paths correct
This commit is contained in:
+34
-2
@@ -5,6 +5,26 @@ import { loadConfig } from "./config";
|
|||||||
import { runReview } from "./review";
|
import { runReview } from "./review";
|
||||||
import { runDescribe } from "./describe";
|
import { runDescribe } from "./describe";
|
||||||
import { runImprove } from "./improve";
|
import { runImprove } from "./improve";
|
||||||
|
import { logReviewEvent } from "./index";
|
||||||
|
import { join } from "node:path";
|
||||||
|
|
||||||
|
const ANALYTICS_DIR = process.env.PR_AGENT_ANALYTICS_DIR || "/var/lib/pr-agent-server/analytics";
|
||||||
|
|
||||||
|
function recordAnalytics(command: string, result: { status?: string; model?: string }): void {
|
||||||
|
try {
|
||||||
|
logReviewEvent(ANALYTICS_DIR, {
|
||||||
|
message: result.status === "success" ? "Generated code suggestions" : `Failed to generate (${result.status ?? "error"})`,
|
||||||
|
extra: {
|
||||||
|
command,
|
||||||
|
pr_url_short: "",
|
||||||
|
model: result.model ?? "",
|
||||||
|
error: result.status === "success" ? "" : (result.status ?? "error"),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
} catch {
|
||||||
|
// analytics is best-effort; never fail the CLI on a log write
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const args = process.argv.slice(2);
|
const args = process.argv.slice(2);
|
||||||
@@ -32,9 +52,18 @@ async function main() {
|
|||||||
const tool = getArg("--tool") || "review";
|
const tool = getArg("--tool") || "review";
|
||||||
|
|
||||||
const cfg = loadConfig();
|
const cfg = loadConfig();
|
||||||
const keyPath = getArg("--private-key") || process.env.PRIVATE_KEY_PATH || "/opt/pr-agent-server/private-key.pem";
|
const keyPath =
|
||||||
|
getArg("--private-key") ||
|
||||||
|
process.env.PRIVATE_KEY_PATH ||
|
||||||
|
"/opt/pr-agent-server/private-key.pem";
|
||||||
const fs = await import("node:fs");
|
const fs = await import("node:fs");
|
||||||
const privateKey = fs.readFileSync(keyPath, "utf-8");
|
const fallbackKey = join(process.env.HOME ?? "/home/code", ".hermes", "keys", "pr-agent-key.pem");
|
||||||
|
let privateKey: string;
|
||||||
|
try {
|
||||||
|
privateKey = fs.readFileSync(keyPath, "utf-8");
|
||||||
|
} catch {
|
||||||
|
privateKey = fs.readFileSync(fallbackKey, "utf-8"); // EACCES/ENOENT on /opt → user-local copy
|
||||||
|
}
|
||||||
const publish = !has("--no-publish");
|
const publish = !has("--no-publish");
|
||||||
|
|
||||||
if (tool === "describe") {
|
if (tool === "describe") {
|
||||||
@@ -54,6 +83,7 @@ async function main() {
|
|||||||
));
|
));
|
||||||
console.log("\n--- MARKDOWN ---\n");
|
console.log("\n--- MARKDOWN ---\n");
|
||||||
console.log(result.markdown);
|
console.log(result.markdown);
|
||||||
|
recordAnalytics("describe", result);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,6 +104,7 @@ async function main() {
|
|||||||
));
|
));
|
||||||
console.log("\n--- MARKDOWN ---\n");
|
console.log("\n--- MARKDOWN ---\n");
|
||||||
console.log(result.markdown);
|
console.log(result.markdown);
|
||||||
|
recordAnalytics("improve", result);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,6 +126,7 @@ async function main() {
|
|||||||
));
|
));
|
||||||
console.log("\n--- MARKDOWN ---\n");
|
console.log("\n--- MARKDOWN ---\n");
|
||||||
console.log(result.markdown);
|
console.log(result.markdown);
|
||||||
|
recordAnalytics("review", result);
|
||||||
}
|
}
|
||||||
|
|
||||||
main().catch((e) => {
|
main().catch((e) => {
|
||||||
|
|||||||
+1
-1
@@ -384,7 +384,7 @@ export function readAnalyticsLogs(dir: string, maxFiles = 5): AnalyticsRecord[]
|
|||||||
|
|
||||||
/** Append an analytics event in the legacy pr-agent JSONL shape so external
|
/** Append an analytics event in the legacy pr-agent JSONL shape so external
|
||||||
* dashboards that parse pr-agent.*.log keep working. */
|
* dashboards that parse pr-agent.*.log keep working. */
|
||||||
function logReviewEvent(dir: string, event: Record<string, unknown>): void {
|
export function logReviewEvent(dir: string, event: Record<string, unknown>): void {
|
||||||
if (!dir) return;
|
if (!dir) return;
|
||||||
const fs = require("node:fs") as typeof import("node:fs");
|
const fs = require("node:fs") as typeof import("node:fs");
|
||||||
const path = require("node:path") as typeof import("node:path");
|
const path = require("node:path") as typeof import("node:path");
|
||||||
|
|||||||
Reference in New Issue
Block a user