hq-jr 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +22 -0
- package/LICENSE +176 -0
- package/README.md +207 -0
- package/app.yml +17 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +193 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +11 -0
- package/dist/config.js +16 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +827 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/review.d.ts +217 -0
- package/dist/schemas/review.js +52 -0
- package/dist/schemas/review.js.map +1 -0
- package/dist/services/ai.d.ts +58 -0
- package/dist/services/ai.js +268 -0
- package/dist/services/ai.js.map +1 -0
- package/dist/services/context-packager.d.ts +26 -0
- package/dist/services/context-packager.js +105 -0
- package/dist/services/context-packager.js.map +1 -0
- package/dist/services/db.d.ts +31 -0
- package/dist/services/db.js +133 -0
- package/dist/services/db.js.map +1 -0
- package/dist/services/diff-parser.d.ts +43 -0
- package/dist/services/diff-parser.js +190 -0
- package/dist/services/diff-parser.js.map +1 -0
- package/dist/services/discussion.d.ts +20 -0
- package/dist/services/discussion.js +78 -0
- package/dist/services/discussion.js.map +1 -0
- package/dist/services/file-filter.d.ts +10 -0
- package/dist/services/file-filter.js +167 -0
- package/dist/services/file-filter.js.map +1 -0
- package/dist/services/json-repair.d.ts +4 -0
- package/dist/services/json-repair.js +100 -0
- package/dist/services/json-repair.js.map +1 -0
- package/dist/services/remediation.d.ts +41 -0
- package/dist/services/remediation.js +370 -0
- package/dist/services/remediation.js.map +1 -0
- package/dist/services/review-memory.d.ts +44 -0
- package/dist/services/review-memory.js +99 -0
- package/dist/services/review-memory.js.map +1 -0
- package/dist/services/sandbox-runner.d.ts +66 -0
- package/dist/services/sandbox-runner.js +144 -0
- package/dist/services/sandbox-runner.js.map +1 -0
- package/dist/services/scrubber.d.ts +7 -0
- package/dist/services/scrubber.js +46 -0
- package/dist/services/scrubber.js.map +1 -0
- package/dist/services/symbol-cache.d.ts +34 -0
- package/dist/services/symbol-cache.js +49 -0
- package/dist/services/symbol-cache.js.map +1 -0
- package/package.json +61 -0
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { dispatchSandboxVerification } from "./ai.js";
|
|
2
|
+
export function detectTestCommand(filePaths) {
|
|
3
|
+
const hasCargo = filePaths.some((p) => p.includes("Cargo.toml") || /\.rs($|\b)/.test(p));
|
|
4
|
+
if (hasCargo)
|
|
5
|
+
return "cargo test";
|
|
6
|
+
const hasGo = filePaths.some((p) => p.includes("go.mod") || /\.go($|\b)/.test(p));
|
|
7
|
+
if (hasGo)
|
|
8
|
+
return "go test ./...";
|
|
9
|
+
const hasPython = filePaths.some((p) => p.includes("pytest.ini") ||
|
|
10
|
+
p.includes("pyproject.toml") ||
|
|
11
|
+
p.includes("requirements.txt") ||
|
|
12
|
+
/\.py($|\b)/.test(p));
|
|
13
|
+
if (hasPython)
|
|
14
|
+
return "pytest";
|
|
15
|
+
return "npm test";
|
|
16
|
+
}
|
|
17
|
+
export function formatSandboxCheckRunSummary(params) {
|
|
18
|
+
const { pullNumber, branch, testCommand, verificationGoal, interactionId, probes = [] } = params;
|
|
19
|
+
let matrixTable = "";
|
|
20
|
+
if (probes.length > 0) {
|
|
21
|
+
const rows = probes.map((p, idx) => `| #${idx + 1} | \`${p.targetFile}${p.targetLine ? `:${p.targetLine}` : ""}\` | \`${p.archetype}\` | \`${p.expectedFailureKind}\` | ${p.failureHypothesis} |`);
|
|
22
|
+
matrixTable = `\n### ๐ Adversarial Test Execution Matrix\n\n` +
|
|
23
|
+
`| # | Target Component | Archetype | Expected Mode | Hypothesis |\n` +
|
|
24
|
+
`|:---:|---|:---:|:---:|---|\n` +
|
|
25
|
+
rows.join("\n") +
|
|
26
|
+
`\n`;
|
|
27
|
+
}
|
|
28
|
+
return `## ๐งช Tier 3 Antigravity Sandbox Verification\n\n` +
|
|
29
|
+
`- **Status:** Dispatched to remote Linux container\n` +
|
|
30
|
+
`- **Agent Harness:** \`antigravity-preview-05-2026\`\n` +
|
|
31
|
+
`- **Interaction ID:** \`${interactionId}\`\n` +
|
|
32
|
+
`- **Target Branch:** \`${branch}\` (PR #${pullNumber})\n` +
|
|
33
|
+
`- **Baseline Command:** \`${testCommand}\`\n` +
|
|
34
|
+
`- **Objective:** ${verificationGoal}\n` +
|
|
35
|
+
matrixTable +
|
|
36
|
+
`\n### ๐ ๏ธ One-Click Test Adoption\n` +
|
|
37
|
+
`Maintainers can adopt the synthesized reproduction test directly into the PR by clicking **"Commit Repro Test"** in the Checks tab action header or typing \`@hq-jr commit-repro\` in PR comments.`;
|
|
38
|
+
}
|
|
39
|
+
export async function executeSandboxCheckRun(params) {
|
|
40
|
+
const { octokit, owner, repo, pullNumber, headSha, branch, verificationGoal, modifiedFiles = [], authToken, } = params;
|
|
41
|
+
const testCommand = params.testCommand || detectTestCommand(modifiedFiles);
|
|
42
|
+
let checkRunId;
|
|
43
|
+
try {
|
|
44
|
+
const checkRun = await octokit.checks.create({
|
|
45
|
+
owner,
|
|
46
|
+
repo,
|
|
47
|
+
name: "hq-jr AI Sandbox Verification",
|
|
48
|
+
head_sha: headSha,
|
|
49
|
+
status: "in_progress",
|
|
50
|
+
started_at: new Date().toISOString(),
|
|
51
|
+
actions: [
|
|
52
|
+
{
|
|
53
|
+
label: "Commit Repro Test",
|
|
54
|
+
description: "Commit synthesized reproduction test directly to PR branch",
|
|
55
|
+
identifier: "commit_repro_test",
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
label: "Re-run Sandbox",
|
|
59
|
+
description: "Re-run autonomous sandbox verification with fresh container",
|
|
60
|
+
identifier: "rerun_sandbox",
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
output: {
|
|
64
|
+
title: "Dispatching Adversarial Sandbox Verification",
|
|
65
|
+
summary: `Dispatching Tier 3 Antigravity autonomous reproduction agent for PR #${pullNumber}.\n\n- **Objective:** ${verificationGoal}\n- **Test Command:** \`${testCommand}\`\n- **Branch:** \`${branch}\`\n- **Probes:** ${params.probes?.length || 0} adversarial targets`,
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
checkRunId = checkRun.data.id;
|
|
69
|
+
}
|
|
70
|
+
catch (err) {
|
|
71
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
72
|
+
return {
|
|
73
|
+
status: "failed",
|
|
74
|
+
summary: `Failed to create Sandbox Check Run on GitHub: ${errorMsg}`,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
try {
|
|
78
|
+
const repoUrl = `https://github.com/${owner}/${repo}`;
|
|
79
|
+
const base64AuthToken = authToken
|
|
80
|
+
? Buffer.from(`x-access-token:${authToken}`).toString("base64")
|
|
81
|
+
: undefined;
|
|
82
|
+
const interactionId = await dispatchSandboxVerification({
|
|
83
|
+
repoUrl,
|
|
84
|
+
branch,
|
|
85
|
+
testCommand,
|
|
86
|
+
base64AuthToken,
|
|
87
|
+
instructions: `Execute containerized reproduction and verification in /workspace/repo.\nVerification Goal: ${verificationGoal}\nRun command: ${testCommand}`,
|
|
88
|
+
probes: params.probes,
|
|
89
|
+
});
|
|
90
|
+
const completionSummary = formatSandboxCheckRunSummary({
|
|
91
|
+
pullNumber,
|
|
92
|
+
branch,
|
|
93
|
+
testCommand,
|
|
94
|
+
verificationGoal,
|
|
95
|
+
interactionId,
|
|
96
|
+
probes: params.probes,
|
|
97
|
+
});
|
|
98
|
+
await octokit.checks.update({
|
|
99
|
+
owner,
|
|
100
|
+
repo,
|
|
101
|
+
check_run_id: checkRunId,
|
|
102
|
+
status: "completed",
|
|
103
|
+
conclusion: "success",
|
|
104
|
+
completed_at: new Date().toISOString(),
|
|
105
|
+
output: {
|
|
106
|
+
title: "Sandbox Verification Dispatched",
|
|
107
|
+
summary: completionSummary,
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
return {
|
|
111
|
+
checkRunId,
|
|
112
|
+
interactionId,
|
|
113
|
+
status: "dispatched",
|
|
114
|
+
summary: completionSummary,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
catch (err) {
|
|
118
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
119
|
+
const failureSummary = `### Sandbox Verification Unavailable\n\nTertiary sandbox agent dispatch encountered an error: ${errorMsg}\n\nStandard Tier 1 & 2 reviews were completed.`;
|
|
120
|
+
if (checkRunId) {
|
|
121
|
+
try {
|
|
122
|
+
await octokit.checks.update({
|
|
123
|
+
owner,
|
|
124
|
+
repo,
|
|
125
|
+
check_run_id: checkRunId,
|
|
126
|
+
status: "completed",
|
|
127
|
+
conclusion: "neutral",
|
|
128
|
+
completed_at: new Date().toISOString(),
|
|
129
|
+
output: {
|
|
130
|
+
title: "Sandbox Dispatch Skipped",
|
|
131
|
+
summary: failureSummary,
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
catch { }
|
|
136
|
+
}
|
|
137
|
+
return {
|
|
138
|
+
checkRunId,
|
|
139
|
+
status: "failed",
|
|
140
|
+
summary: failureSummary,
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=sandbox-runner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox-runner.js","sourceRoot":"","sources":["../../src/services/sandbox-runner.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Patterns matching high-risk secrets and credentials.
|
|
3
|
+
*/
|
|
4
|
+
const SECRET_PATTERNS = [
|
|
5
|
+
// Private keys (RSA, EC, PGP, OPENSSH)
|
|
6
|
+
/-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g,
|
|
7
|
+
// GitHub tokens (Classic tokens, OAuth, App tokens, and Fine-Grained PATs)
|
|
8
|
+
/\b(?:ghp|gho|ghu|ghs|ghr)_[A-Za-z0-9_]{36,255}\b/g,
|
|
9
|
+
/\bgithub_pat_[A-Za-z0-9_]{82}\b/g,
|
|
10
|
+
// Google Cloud API keys and service account private keys
|
|
11
|
+
/\bAIza[0-9A-Za-z-_]{35}\b/g,
|
|
12
|
+
// AWS Access Key ID
|
|
13
|
+
/\b(?:AKIA|ABIA|ACCA|ASIA)[0-9A-Z]{16}\b/g,
|
|
14
|
+
// AWS Secret Access Key (heuristics near keywords)
|
|
15
|
+
/(?:aws_secret_access_key|aws_access_key_id|secret_key)\s*[:=]\s*["'`]?([A-Za-z0-9/+=]{40})["'`]?/gi,
|
|
16
|
+
// Slack tokens
|
|
17
|
+
/\bxox[baprs]-[0-9]{10,13}-[0-9]{10,13}[a-zA-Z0-9-]*\b/g,
|
|
18
|
+
// Generic JWT tokens
|
|
19
|
+
/\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g,
|
|
20
|
+
// OpenAI / Anthropic / Generic AI API tokens (including modern sk-proj-, sk-ant-api03-, sk-admin-)
|
|
21
|
+
/\bsk-(?:proj-|admin-|ant-(?:api03|admin01)-)?[a-zA-Z0-9_-]{20,250}\b/g,
|
|
22
|
+
// Generic secret / password assignments in code, JSON, YAML, and .env
|
|
23
|
+
/(?:["']?(?:password|passwd|api_key|apiKey|secret|private_token|client_secret|access_token|auth_token|refresh_token|api_secret)["']?)\s*[:=]\s*["'`]?([^"'`\r\n\s]{8,128})["'`]?/gi,
|
|
24
|
+
];
|
|
25
|
+
/**
|
|
26
|
+
* Scrubs credentials and secrets from text before transmission to AI models.
|
|
27
|
+
*/
|
|
28
|
+
export function scrubSecrets(input) {
|
|
29
|
+
if (!input) {
|
|
30
|
+
return { scrubbed: "", redactedCount: 0 };
|
|
31
|
+
}
|
|
32
|
+
let scrubbed = input;
|
|
33
|
+
let redactedCount = 0;
|
|
34
|
+
for (const pattern of SECRET_PATTERNS) {
|
|
35
|
+
scrubbed = scrubbed.replace(pattern, (match, ...args) => {
|
|
36
|
+
redactedCount++;
|
|
37
|
+
const captures = args.slice(0, -2);
|
|
38
|
+
if (captures.length > 0 && typeof captures[0] === "string" && captures[0].length > 0) {
|
|
39
|
+
return match.replace(captures[0], "[REDACTED_SECRET]");
|
|
40
|
+
}
|
|
41
|
+
return "[REDACTED_SECRET]";
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return { scrubbed, redactedCount };
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=scrubber.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scrubber.js","sourceRoot":"","sources":["../../src/services/scrubber.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,eAAe,GAAG;IACtB,uCAAuC;IACvC,6EAA6E;IAE7E,2EAA2E;IAC3E,mDAAmD;IACnD,kCAAkC;IAElC,yDAAyD;IACzD,4BAA4B;IAE5B,oBAAoB;IACpB,0CAA0C;IAE1C,mDAAmD;IACnD,oGAAoG;IAEpG,eAAe;IACf,wDAAwD;IAExD,qBAAqB;IACrB,oEAAoE;IAEpE,mGAAmG;IACnG,uEAAuE;IAEvE,sEAAsE;IACtE,mLAAmL;CACpL,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,aAAa,EAAE,CAAC,EAAE,CAAC;IAC5C,CAAC;IAED,IAAI,QAAQ,GAAG,KAAK,CAAC;IACrB,IAAI,aAAa,GAAG,CAAC,CAAC;IAEtB,KAAK,MAAM,OAAO,IAAI,eAAe,EAAE,CAAC;QACtC,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,GAAG,IAAI,EAAE,EAAE;YACtD,aAAa,EAAE,CAAC;YAChB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;YACnC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,QAAQ,CAAC,CAAC,CAAC,KAAK,QAAQ,IAAI,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACrF,OAAO,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,mBAAmB,CAAC,CAAC;YACzD,CAAC;YACD,OAAO,mBAAmB,CAAC;QAC7B,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC;AACrC,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type Database from "better-sqlite3";
|
|
2
|
+
export interface ExtractedSymbol {
|
|
3
|
+
name: string;
|
|
4
|
+
kind: "function" | "class" | "interface" | "type" | "variable" | "constant" | "method";
|
|
5
|
+
line?: number;
|
|
6
|
+
exported?: boolean;
|
|
7
|
+
signature?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function computeContentHash(content: string | Buffer): string;
|
|
10
|
+
export interface CacheSymbolsParams {
|
|
11
|
+
repo: string;
|
|
12
|
+
commitSha: string;
|
|
13
|
+
filePath: string;
|
|
14
|
+
content: string | Buffer;
|
|
15
|
+
symbols: ExtractedSymbol[];
|
|
16
|
+
db?: Database.Database;
|
|
17
|
+
}
|
|
18
|
+
export declare function cacheSymbols(params: CacheSymbolsParams): string;
|
|
19
|
+
export interface GetCachedSymbolsParams {
|
|
20
|
+
repo: string;
|
|
21
|
+
commitSha: string;
|
|
22
|
+
filePath: string;
|
|
23
|
+
content?: string | Buffer;
|
|
24
|
+
db?: Database.Database;
|
|
25
|
+
}
|
|
26
|
+
export declare function getCachedSymbols(params: GetCachedSymbolsParams): ExtractedSymbol[] | null;
|
|
27
|
+
export interface IsContentUnmodifiedParams {
|
|
28
|
+
repo: string;
|
|
29
|
+
commitSha: string;
|
|
30
|
+
filePath: string;
|
|
31
|
+
content: string | Buffer;
|
|
32
|
+
db?: Database.Database;
|
|
33
|
+
}
|
|
34
|
+
export declare function isContentUnmodified(params: IsContentUnmodifiedParams): boolean;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { setCachedSymbol, getCachedSymbol } from "./db.js";
|
|
3
|
+
export function computeContentHash(content) {
|
|
4
|
+
return createHash("sha256").update(content).digest("hex");
|
|
5
|
+
}
|
|
6
|
+
export function cacheSymbols(params) {
|
|
7
|
+
const contentHash = computeContentHash(params.content);
|
|
8
|
+
setCachedSymbol({
|
|
9
|
+
repo: params.repo,
|
|
10
|
+
commitSha: params.commitSha,
|
|
11
|
+
filePath: params.filePath,
|
|
12
|
+
contentHash,
|
|
13
|
+
symbolsJson: JSON.stringify(params.symbols),
|
|
14
|
+
}, params.db);
|
|
15
|
+
return contentHash;
|
|
16
|
+
}
|
|
17
|
+
export function getCachedSymbols(params) {
|
|
18
|
+
const contentHash = params.content !== undefined ? computeContentHash(params.content) : undefined;
|
|
19
|
+
const rawJson = getCachedSymbol({
|
|
20
|
+
repo: params.repo,
|
|
21
|
+
commitSha: params.commitSha,
|
|
22
|
+
filePath: params.filePath,
|
|
23
|
+
contentHash,
|
|
24
|
+
}, params.db);
|
|
25
|
+
if (!rawJson) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
const parsed = JSON.parse(rawJson);
|
|
30
|
+
if (Array.isArray(parsed)) {
|
|
31
|
+
return parsed;
|
|
32
|
+
}
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export function isContentUnmodified(params) {
|
|
40
|
+
const currentHash = computeContentHash(params.content);
|
|
41
|
+
const raw = getCachedSymbol({
|
|
42
|
+
repo: params.repo,
|
|
43
|
+
commitSha: params.commitSha,
|
|
44
|
+
filePath: params.filePath,
|
|
45
|
+
contentHash: currentHash,
|
|
46
|
+
}, params.db);
|
|
47
|
+
return raw !== null;
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=symbol-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"symbol-cache.js","sourceRoot":"","sources":["../../src/services/symbol-cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAW3D,MAAM,UAAU,kBAAkB,CAAC,OAAwB;IACzD,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC5D,CAAC;AAWD,MAAM,UAAU,YAAY,CAAC,MAA0B;IACrD,MAAM,WAAW,GAAG,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACvD,eAAe,CACb;QACE,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,WAAW;QACX,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC;KAC5C,EACD,MAAM,CAAC,EAAE,CACV,CAAC;IACF,OAAO,WAAW,CAAC;AACrB,CAAC;AAUD,MAAM,UAAU,gBAAgB,CAAC,MAA8B;IAC7D,MAAM,WAAW,GAAG,MAAM,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAClG,MAAM,OAAO,GAAG,eAAe,CAC7B;QACE,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,WAAW;KACZ,EACD,MAAM,CAAC,EAAE,CACV,CAAC;IAEF,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACnC,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YAC1B,OAAO,MAA2B,CAAC;QACrC,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAUD,MAAM,UAAU,mBAAmB,CAAC,MAAiC;IACnE,MAAM,WAAW,GAAG,kBAAkB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACvD,MAAM,GAAG,GAAG,eAAe,CACzB;QACE,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,QAAQ,EAAE,MAAM,CAAC,QAAQ;QACzB,WAAW,EAAE,WAAW;KACzB,EACD,MAAM,CAAC,EAAE,CACV,CAAC;IACF,OAAO,GAAG,KAAK,IAAI,CAAC;AACtB,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "hq-jr",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Self-hosted GitHub App that reviews PRs with Vertex AI, remembers past findings, and can reproduce bugs in a sandbox before it speaks.",
|
|
5
|
+
"homepage": "https://github.com/adi-IL/hq-jr",
|
|
6
|
+
"repository": "https://github.com/adi-IL/hq-jr",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"bin": {
|
|
9
|
+
"hq-jr": "dist/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"scripts": {
|
|
13
|
+
"build": "tsc",
|
|
14
|
+
"start": "probot run ./dist/index.js",
|
|
15
|
+
"dev": "tsx watch src/index.ts",
|
|
16
|
+
"test": "vitest run",
|
|
17
|
+
"typecheck": "tsc --noEmit",
|
|
18
|
+
"lint": "tsc --noEmit"
|
|
19
|
+
},
|
|
20
|
+
"keywords": [
|
|
21
|
+
"ai-code-review",
|
|
22
|
+
"code-review",
|
|
23
|
+
"developer-tools",
|
|
24
|
+
"github-app",
|
|
25
|
+
"pull-request",
|
|
26
|
+
"probot",
|
|
27
|
+
"sandbox",
|
|
28
|
+
"self-hosted",
|
|
29
|
+
"sqlite",
|
|
30
|
+
"typescript",
|
|
31
|
+
"vertex-ai",
|
|
32
|
+
"hq-jr"
|
|
33
|
+
],
|
|
34
|
+
"author": "Aditya Gaurav <adi-IL>",
|
|
35
|
+
"license": "Apache-2.0",
|
|
36
|
+
"dependencies": {
|
|
37
|
+
"@google/genai": "^2.3.0",
|
|
38
|
+
"better-sqlite3": "^13.0.3",
|
|
39
|
+
"dotenv": "^16.4.5",
|
|
40
|
+
"probot": "^13.4.0",
|
|
41
|
+
"zod": "^3.23.8"
|
|
42
|
+
},
|
|
43
|
+
"devDependencies": {
|
|
44
|
+
"@types/better-sqlite3": "^9.6.0",
|
|
45
|
+
"@types/node": "^22.5.5",
|
|
46
|
+
"smee-client": "^5.0.0",
|
|
47
|
+
"tsx": "^4.19.1",
|
|
48
|
+
"typescript": "^5.6.2",
|
|
49
|
+
"vitest": "^2.1.1"
|
|
50
|
+
},
|
|
51
|
+
"engines": {
|
|
52
|
+
"node": ">=22.0.0"
|
|
53
|
+
},
|
|
54
|
+
"files": [
|
|
55
|
+
"dist",
|
|
56
|
+
"README.md",
|
|
57
|
+
"LICENSE",
|
|
58
|
+
"app.yml",
|
|
59
|
+
".env.example"
|
|
60
|
+
]
|
|
61
|
+
}
|