nexus-agents 2.79.3 → 2.79.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/{child-mcp-config-CTO2MBRM.js → child-mcp-config-DFRYTRBK.js} +2 -2
- package/dist/{chunk-HB4MIDHJ.js → chunk-3ENBGGYA.js} +104 -61
- package/dist/{chunk-HB4MIDHJ.js.map → chunk-3ENBGGYA.js.map} +1 -1
- package/dist/{chunk-6E3NMMEY.js → chunk-3RZWLQSC.js} +2 -2
- package/dist/{chunk-6E3NMMEY.js.map → chunk-3RZWLQSC.js.map} +1 -1
- package/dist/{chunk-KT5FIBWS.js → chunk-42MM7GKW.js} +2 -2
- package/dist/{chunk-3NIPH6UP.js → chunk-45NUO4FE.js} +2 -2
- package/dist/{chunk-2YPG6PDG.js → chunk-ACP4YARI.js} +3 -3
- package/dist/{chunk-D6TM2VHX.js → chunk-BIH2CBC5.js} +44 -21
- package/dist/chunk-BIH2CBC5.js.map +1 -0
- package/dist/{chunk-SD76JZBG.js → chunk-BSQ4KTY4.js} +2 -2
- package/dist/{chunk-6TFTVW77.js → chunk-BXI6DKBU.js} +3 -3
- package/dist/{chunk-PLX6FCFC.js → chunk-DOI7RE3X.js} +2 -2
- package/dist/{chunk-SWFJU3W2.js → chunk-DW3UTO43.js} +56 -46
- package/dist/{chunk-SWFJU3W2.js.map → chunk-DW3UTO43.js.map} +1 -1
- package/dist/{chunk-7XCUZI4G.js → chunk-IPDUZJPH.js} +3 -3
- package/dist/{chunk-2UYTFLMO.js → chunk-JMRCMMZ5.js} +2 -2
- package/dist/{chunk-GONMG4NM.js → chunk-LFTK5ZQG.js} +2 -2
- package/dist/{chunk-DLXT23AC.js → chunk-NJPFN75N.js} +2 -2
- package/dist/{chunk-YXWGEIQR.js → chunk-NVSJXN4S.js} +2 -2
- package/dist/{chunk-Q5CFPIJ5.js → chunk-NXNNT5XW.js} +3 -3
- package/dist/chunk-OFRDE7MK.js +136 -0
- package/dist/chunk-OFRDE7MK.js.map +1 -0
- package/dist/{chunk-L6SCKLGO.js → chunk-OGV7J5WG.js} +3 -3
- package/dist/{chunk-ZVCED4Z4.js → chunk-PAKVXGS2.js} +2 -2
- package/dist/{chunk-DNO2INX5.js → chunk-PDCLBWH5.js} +3 -3
- package/dist/{chunk-K2QILJG4.js → chunk-PHBRELUK.js} +33 -9
- package/dist/chunk-PHBRELUK.js.map +1 -0
- package/dist/{chunk-JI7S55R3.js → chunk-SU3Y6LU2.js} +8 -8
- package/dist/chunk-SU3Y6LU2.js.map +1 -0
- package/dist/{chunk-FJWWSVWB.js → chunk-TN5ZKSGC.js} +2 -2
- package/dist/{chunk-5O6XLBPP.js → chunk-UNFS6YBY.js} +2 -2
- package/dist/{chunk-HYU4GZY6.js → chunk-UNRTM43V.js} +2 -2
- package/dist/{chunk-VIQOVK4E.js → chunk-UOR2JWFH.js} +7 -136
- package/dist/chunk-UOR2JWFH.js.map +1 -0
- package/dist/{chunk-WDYCIJWN.js → chunk-UQOSVOEU.js} +4 -3
- package/dist/{chunk-WDYCIJWN.js.map → chunk-UQOSVOEU.js.map} +1 -1
- package/dist/{chunk-FVPYP5DD.js → chunk-UWDVEMYZ.js} +4 -4
- package/dist/{cli-circuit-breaker-I74ZQ44Q.js → cli-circuit-breaker-T75HOLZK.js} +4 -4
- package/dist/cli.js +46 -45
- package/dist/cli.js.map +1 -1
- package/dist/{composite-router-V3OC57IE.js → composite-router-OPSK5FCQ.js} +2 -2
- package/dist/{consensus-vote-ESFPGEJE.js → consensus-vote-CYUPIJXR.js} +11 -11
- package/dist/{context-retriever-MB3D7KS6.js → context-retriever-6AWHCHRP.js} +5 -5
- package/dist/{doctor-deep-KQ765XZA.js → doctor-deep-XBPRQ6ZP.js} +3 -3
- package/dist/expert-bridge-5YOPK5IT.js +11 -0
- package/dist/{factory-BUUXNGIB.js → factory-DN7SJZ5Z.js} +5 -5
- package/dist/{factory-LHHYDVZX.js → factory-Y3TMP4OQ.js} +4 -4
- package/dist/index.d.ts +24 -2
- package/dist/index.js +30 -28
- package/dist/index.js.map +1 -1
- package/dist/{init-opencode-GXZN2W5S.js → init-opencode-RV6IQEMS.js} +5 -5
- package/dist/{issue-triage-RMXPDZ2K.js → issue-triage-UTWKXLKC.js} +4 -4
- package/dist/{pr-reviewer-helpers-XCY7HOPE.js → pr-reviewer-helpers-L4L324FQ.js} +2 -2
- package/dist/{registry-command-6E4YKAMT.js → registry-command-6KJWW3W7.js} +2 -2
- package/dist/{repo-security-plan-AGRU72DL.js → repo-security-plan-HNLMF7J7.js} +3 -3
- package/dist/{research-helpers-synthesize-K2UCJQQG.js → research-helpers-synthesize-77TLYSW4.js} +3 -3
- package/dist/{routing-memory-3B6DDZ76.js → routing-memory-6DV6ZPAH.js} +2 -2
- package/dist/{session-memory-L7EQIY2O.js → session-memory-XZ3NJIR4.js} +3 -3
- package/dist/{setup-command-QSAGFMGN.js → setup-command-QOXG36UV.js} +10 -9
- package/dist/{setup-config-EQT24DD4.js → setup-config-B4V4QHDP.js} +3 -3
- package/dist/{setup-custom-api-IBDV654K.js → setup-custom-api-PJ6TGHJH.js} +4 -4
- package/dist/{tool-memory-6HCHQLAN.js → tool-memory-K2QPTPKV.js} +4 -4
- package/dist/{weather-report-ER3WUZ7S.js → weather-report-ZB4AKOIA.js} +2 -2
- package/package.json +4 -4
- package/scripts/postinstall.js +1 -1
- package/dist/chunk-D6TM2VHX.js.map +0 -1
- package/dist/chunk-JI7S55R3.js.map +0 -1
- package/dist/chunk-K2QILJG4.js.map +0 -1
- package/dist/chunk-VIQOVK4E.js.map +0 -1
- package/dist/expert-bridge-JKLC57IC.js +0 -10
- /package/dist/{child-mcp-config-CTO2MBRM.js.map → child-mcp-config-DFRYTRBK.js.map} +0 -0
- /package/dist/{chunk-KT5FIBWS.js.map → chunk-42MM7GKW.js.map} +0 -0
- /package/dist/{chunk-3NIPH6UP.js.map → chunk-45NUO4FE.js.map} +0 -0
- /package/dist/{chunk-2YPG6PDG.js.map → chunk-ACP4YARI.js.map} +0 -0
- /package/dist/{chunk-SD76JZBG.js.map → chunk-BSQ4KTY4.js.map} +0 -0
- /package/dist/{chunk-6TFTVW77.js.map → chunk-BXI6DKBU.js.map} +0 -0
- /package/dist/{chunk-PLX6FCFC.js.map → chunk-DOI7RE3X.js.map} +0 -0
- /package/dist/{chunk-7XCUZI4G.js.map → chunk-IPDUZJPH.js.map} +0 -0
- /package/dist/{chunk-2UYTFLMO.js.map → chunk-JMRCMMZ5.js.map} +0 -0
- /package/dist/{chunk-GONMG4NM.js.map → chunk-LFTK5ZQG.js.map} +0 -0
- /package/dist/{chunk-DLXT23AC.js.map → chunk-NJPFN75N.js.map} +0 -0
- /package/dist/{chunk-YXWGEIQR.js.map → chunk-NVSJXN4S.js.map} +0 -0
- /package/dist/{chunk-Q5CFPIJ5.js.map → chunk-NXNNT5XW.js.map} +0 -0
- /package/dist/{chunk-L6SCKLGO.js.map → chunk-OGV7J5WG.js.map} +0 -0
- /package/dist/{chunk-ZVCED4Z4.js.map → chunk-PAKVXGS2.js.map} +0 -0
- /package/dist/{chunk-DNO2INX5.js.map → chunk-PDCLBWH5.js.map} +0 -0
- /package/dist/{chunk-FJWWSVWB.js.map → chunk-TN5ZKSGC.js.map} +0 -0
- /package/dist/{chunk-5O6XLBPP.js.map → chunk-UNFS6YBY.js.map} +0 -0
- /package/dist/{chunk-HYU4GZY6.js.map → chunk-UNRTM43V.js.map} +0 -0
- /package/dist/{chunk-FVPYP5DD.js.map → chunk-UWDVEMYZ.js.map} +0 -0
- /package/dist/{cli-circuit-breaker-I74ZQ44Q.js.map → cli-circuit-breaker-T75HOLZK.js.map} +0 -0
- /package/dist/{composite-router-V3OC57IE.js.map → composite-router-OPSK5FCQ.js.map} +0 -0
- /package/dist/{consensus-vote-ESFPGEJE.js.map → consensus-vote-CYUPIJXR.js.map} +0 -0
- /package/dist/{context-retriever-MB3D7KS6.js.map → context-retriever-6AWHCHRP.js.map} +0 -0
- /package/dist/{doctor-deep-KQ765XZA.js.map → doctor-deep-XBPRQ6ZP.js.map} +0 -0
- /package/dist/{expert-bridge-JKLC57IC.js.map → expert-bridge-5YOPK5IT.js.map} +0 -0
- /package/dist/{factory-BUUXNGIB.js.map → factory-DN7SJZ5Z.js.map} +0 -0
- /package/dist/{factory-LHHYDVZX.js.map → factory-Y3TMP4OQ.js.map} +0 -0
- /package/dist/{init-opencode-GXZN2W5S.js.map → init-opencode-RV6IQEMS.js.map} +0 -0
- /package/dist/{issue-triage-RMXPDZ2K.js.map → issue-triage-UTWKXLKC.js.map} +0 -0
- /package/dist/{pr-reviewer-helpers-XCY7HOPE.js.map → pr-reviewer-helpers-L4L324FQ.js.map} +0 -0
- /package/dist/{registry-command-6E4YKAMT.js.map → registry-command-6KJWW3W7.js.map} +0 -0
- /package/dist/{repo-security-plan-AGRU72DL.js.map → repo-security-plan-HNLMF7J7.js.map} +0 -0
- /package/dist/{research-helpers-synthesize-K2UCJQQG.js.map → research-helpers-synthesize-77TLYSW4.js.map} +0 -0
- /package/dist/{routing-memory-3B6DDZ76.js.map → routing-memory-6DV6ZPAH.js.map} +0 -0
- /package/dist/{session-memory-L7EQIY2O.js.map → session-memory-XZ3NJIR4.js.map} +0 -0
- /package/dist/{setup-command-QSAGFMGN.js.map → setup-command-QOXG36UV.js.map} +0 -0
- /package/dist/{setup-config-EQT24DD4.js.map → setup-config-B4V4QHDP.js.map} +0 -0
- /package/dist/{setup-custom-api-IBDV654K.js.map → setup-custom-api-PJ6TGHJH.js.map} +0 -0
- /package/dist/{tool-memory-6HCHQLAN.js.map → tool-memory-K2QPTPKV.js.map} +0 -0
- /package/dist/{weather-report-ER3WUZ7S.js.map → weather-report-ZB4AKOIA.js.map} +0 -0
|
@@ -144,7 +144,7 @@ ${findingsSection}
|
|
|
144
144
|
${statsSection}
|
|
145
145
|
|
|
146
146
|
---
|
|
147
|
-
*Reviewed by [nexus-agents](https://github.com/
|
|
147
|
+
*Reviewed by [nexus-agents](https://github.com/nexus-substrate/nexus-agents) in ${String(result.totalDurationMs)}ms*`;
|
|
148
148
|
}
|
|
149
149
|
function formatFindingsSection(result) {
|
|
150
150
|
const allFindings = result.expertReviews.flatMap((r) => r.findings);
|
|
@@ -216,4 +216,4 @@ export {
|
|
|
216
216
|
formatReviewComment,
|
|
217
217
|
createFailedReview
|
|
218
218
|
};
|
|
219
|
-
//# sourceMappingURL=chunk-
|
|
219
|
+
//# sourceMappingURL=chunk-3RZWLQSC.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/dogfooding/pr-reviewer-helpers.ts"],"sourcesContent":["/**\n * nexus-agents/dogfooding - PR Reviewer Helpers\n *\n * Helper functions for PR review formatting and aggregation.\n *\n * @module dogfooding/pr-reviewer-helpers\n * (Source: Issue #161, Alignment Roadmap Phase 3)\n */\n\nimport { randomUUID } from 'node:crypto';\nimport type {\n PRMetadata,\n PRReviewResult,\n ExpertReviewResult,\n ReviewFinding,\n ReviewCategory,\n ReviewSeverity,\n ReviewDecision,\n} from './pr-review-types.js';\nimport {\n SEVERITY_ORDER,\n CATEGORY_DISPLAY_NAMES,\n SEVERITY_EMOJI,\n DECISION_EMOJI,\n} from './pr-review-types.js';\n\n// =============================================================================\n// Parsing Helpers\n// =============================================================================\n\nexport function parseSeverity(value: unknown): ReviewSeverity {\n if (typeof value === 'string') {\n const lower = value.toLowerCase();\n if (lower in SEVERITY_ORDER) return lower as ReviewSeverity;\n }\n return 'medium';\n}\n\nexport function parseCategory(value: unknown): ReviewCategory {\n if (typeof value === 'string') {\n const lower = value.toLowerCase();\n if (lower in CATEGORY_DISPLAY_NAMES) return lower as ReviewCategory;\n }\n return 'code_quality';\n}\n\nexport function extractSummary(output: Record<string, unknown>): string {\n if (typeof output.summary === 'string') return output.summary;\n if (typeof output.content === 'string') return output.content;\n if (typeof output.message === 'string') return output.message;\n return 'Review completed';\n}\n\nexport function extractStringField(\n record: Record<string, unknown>,\n ...keys: string[]\n): string | undefined {\n for (const key of keys) {\n const value = record[key];\n if (typeof value === 'string') return value;\n }\n return undefined;\n}\n\n// =============================================================================\n// Finding Parsing\n// =============================================================================\n\nexport function parseFindings(\n output: Record<string, unknown>,\n expertId: string,\n minSeverity: ReviewSeverity\n): ReviewFinding[] {\n const minOrder = SEVERITY_ORDER[minSeverity];\n const sources = collectSources(output);\n\n const findings: ReviewFinding[] = [];\n for (const source of sources) {\n if (!Array.isArray(source)) continue;\n for (const item of source) {\n const finding = parseOneFinding(item, expertId, minOrder);\n if (finding !== null) findings.push(finding);\n }\n }\n return findings;\n}\n\nfunction collectSources(output: Record<string, unknown>): unknown[] {\n return [\n output.findings,\n output.vulnerabilities,\n output.issues,\n (output as { content?: { findings?: unknown } }).content,\n ];\n}\n\nfunction parseOneFinding(item: unknown, expertId: string, minOrder: number): ReviewFinding | null {\n if (typeof item !== 'object' || item === null) return null;\n\n const record = item as Record<string, unknown>;\n const severity = parseSeverity(record.severity);\n if (SEVERITY_ORDER[severity] < minOrder) return null;\n\n return {\n id: randomUUID(),\n category: parseCategory(record.category),\n severity,\n title: extractStringField(record, 'title', 'name') ?? 'Finding',\n description: extractStringField(record, 'description', 'message') ?? '',\n file: typeof record.file === 'string' ? record.file : undefined,\n line: typeof record.line === 'number' ? record.line : undefined,\n suggestion: typeof record.suggestion === 'string' ? record.suggestion : undefined,\n expertId,\n confidence: typeof record.confidence === 'number' ? record.confidence : 0.7,\n };\n}\n\n// =============================================================================\n// Decision Helpers\n// =============================================================================\n\nexport function determineApproval(findings: ReviewFinding[]): boolean {\n const hasBlocking = findings.some((f) => f.severity === 'critical' || f.severity === 'high');\n return !hasBlocking;\n}\n\nexport function determineDecision(\n reviews: ExpertReviewResult[],\n findings: ReviewFinding[]\n): ReviewDecision {\n const hasCritical = findings.some((f) => f.severity === 'critical');\n const hasHigh = findings.some((f) => f.severity === 'high');\n const allApproved = reviews.every((r) => r.approved);\n\n if (hasCritical) return 'request_changes';\n if (hasHigh && !allApproved) return 'request_changes';\n if (findings.length > 0) return 'comment';\n return 'approve';\n}\n\nexport function calculateConsensus(reviews: ExpertReviewResult[]): number {\n if (reviews.length === 0) return 1;\n const approvals = reviews.filter((r) => r.approved).length;\n return approvals / reviews.length;\n}\n\n// =============================================================================\n// Counting Helpers\n// =============================================================================\n\nexport function countBySeverity(findings: ReviewFinding[]): Record<ReviewSeverity, number> {\n const counts: Record<ReviewSeverity, number> = {\n critical: 0,\n high: 0,\n medium: 0,\n low: 0,\n info: 0,\n };\n\n for (const f of findings) {\n counts[f.severity]++;\n }\n\n return counts;\n}\n\nexport function countByCategory(findings: ReviewFinding[]): Record<ReviewCategory, number> {\n const counts: Record<ReviewCategory, number> = {\n security: 0,\n performance: 0,\n code_quality: 0,\n testing: 0,\n documentation: 0,\n architecture: 0,\n };\n\n for (const f of findings) {\n counts[f.category]++;\n }\n\n return counts;\n}\n\nexport function sumFindings(counts: Record<ReviewSeverity, number>): number {\n return Object.values(counts).reduce((a, b) => a + b, 0);\n}\n\n// =============================================================================\n// Summary Generation\n// =============================================================================\n\nexport function generateSummary(\n pr: PRMetadata,\n reviews: ExpertReviewResult[],\n decision: ReviewDecision\n): string {\n const expertSummaries = reviews\n .map((r) => `- **${CATEGORY_DISPLAY_NAMES[r.expertType as ReviewCategory]}**: ${r.summary}`)\n .join('\\n');\n\n return `Reviewed PR #${String(pr.number)}: ${pr.title}\n\n**Decision:** ${decision.replaceAll('_', ' ')}\n**Experts consulted:** ${String(reviews.length)}\n\n${expertSummaries}`;\n}\n\n// =============================================================================\n// GitHub Comment Formatting\n// =============================================================================\n\n/**\n * Formats the review result as a GitHub comment.\n */\nexport function formatReviewComment(result: PRReviewResult): string {\n const emoji = DECISION_EMOJI[result.decision];\n const decisionText = result.decision.replaceAll('_', ' ').toUpperCase();\n\n const findingsSection = formatFindingsSection(result);\n const statsSection = formatStatsSection(result);\n\n return `## ${emoji} Nexus Agents Review: ${decisionText}\n\n${result.summary}\n\n${findingsSection}\n\n${statsSection}\n\n---\n*Reviewed by [nexus-agents](https://github.com/williamzujkowski/nexus-agents) in ${String(result.totalDurationMs)}ms*`;\n}\n\nfunction formatFindingsSection(result: PRReviewResult): string {\n const allFindings = result.expertReviews.flatMap((r) => r.findings);\n\n if (allFindings.length === 0) {\n return '_No issues found._';\n }\n\n const sorted = [...allFindings].sort(\n (a, b) => SEVERITY_ORDER[b.severity] - SEVERITY_ORDER[a.severity]\n );\n\n const lines = ['### Findings', ''];\n\n for (const f of sorted) {\n const emoji = SEVERITY_EMOJI[f.severity];\n const loc =\n f.file !== undefined\n ? ` (\\`${f.file}${f.line !== undefined ? `:${String(f.line)}` : ''}\\`)`\n : '';\n lines.push(`${emoji} **${f.title}**${loc}`);\n lines.push(`> ${f.description}`);\n if (f.suggestion !== undefined) {\n lines.push(`> 💡 ${f.suggestion}`);\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\nfunction formatStatsSection(result: PRReviewResult): string {\n const { findingsBySeverity } = result;\n const total = sumFindings(findingsBySeverity);\n\n const parts: string[] = [];\n for (const severity of ['critical', 'high', 'medium', 'low', 'info'] as ReviewSeverity[]) {\n const count = findingsBySeverity[severity];\n if (count > 0) {\n parts.push(`${SEVERITY_EMOJI[severity]} ${String(count)} ${severity}`);\n }\n }\n\n return `<details>\n<summary>Review Statistics (${String(total)} findings)</summary>\n\n- Experts: ${String(result.expertCount)}\n- Consensus: ${(result.consensusScore * 100).toFixed(0)}%\n- Duration: ${String(result.totalDurationMs)}ms\n- Findings: ${parts.join(', ') || 'none'}\n\n</details>`;\n}\n\n// =============================================================================\n// Failed Review Factory\n// =============================================================================\n\nexport function createFailedReview(\n expertId: string,\n category: ReviewCategory,\n durationMs: number,\n error: string\n): ExpertReviewResult {\n return {\n expertId,\n expertType: category,\n approved: true, // Don't block on failures\n summary: `Review failed: ${error}`,\n findings: [],\n durationMs,\n confidence: 0,\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/dogfooding/pr-reviewer-helpers.ts"],"sourcesContent":["/**\n * nexus-agents/dogfooding - PR Reviewer Helpers\n *\n * Helper functions for PR review formatting and aggregation.\n *\n * @module dogfooding/pr-reviewer-helpers\n * (Source: Issue #161, Alignment Roadmap Phase 3)\n */\n\nimport { randomUUID } from 'node:crypto';\nimport type {\n PRMetadata,\n PRReviewResult,\n ExpertReviewResult,\n ReviewFinding,\n ReviewCategory,\n ReviewSeverity,\n ReviewDecision,\n} from './pr-review-types.js';\nimport {\n SEVERITY_ORDER,\n CATEGORY_DISPLAY_NAMES,\n SEVERITY_EMOJI,\n DECISION_EMOJI,\n} from './pr-review-types.js';\n\n// =============================================================================\n// Parsing Helpers\n// =============================================================================\n\nexport function parseSeverity(value: unknown): ReviewSeverity {\n if (typeof value === 'string') {\n const lower = value.toLowerCase();\n if (lower in SEVERITY_ORDER) return lower as ReviewSeverity;\n }\n return 'medium';\n}\n\nexport function parseCategory(value: unknown): ReviewCategory {\n if (typeof value === 'string') {\n const lower = value.toLowerCase();\n if (lower in CATEGORY_DISPLAY_NAMES) return lower as ReviewCategory;\n }\n return 'code_quality';\n}\n\nexport function extractSummary(output: Record<string, unknown>): string {\n if (typeof output.summary === 'string') return output.summary;\n if (typeof output.content === 'string') return output.content;\n if (typeof output.message === 'string') return output.message;\n return 'Review completed';\n}\n\nexport function extractStringField(\n record: Record<string, unknown>,\n ...keys: string[]\n): string | undefined {\n for (const key of keys) {\n const value = record[key];\n if (typeof value === 'string') return value;\n }\n return undefined;\n}\n\n// =============================================================================\n// Finding Parsing\n// =============================================================================\n\nexport function parseFindings(\n output: Record<string, unknown>,\n expertId: string,\n minSeverity: ReviewSeverity\n): ReviewFinding[] {\n const minOrder = SEVERITY_ORDER[minSeverity];\n const sources = collectSources(output);\n\n const findings: ReviewFinding[] = [];\n for (const source of sources) {\n if (!Array.isArray(source)) continue;\n for (const item of source) {\n const finding = parseOneFinding(item, expertId, minOrder);\n if (finding !== null) findings.push(finding);\n }\n }\n return findings;\n}\n\nfunction collectSources(output: Record<string, unknown>): unknown[] {\n return [\n output.findings,\n output.vulnerabilities,\n output.issues,\n (output as { content?: { findings?: unknown } }).content,\n ];\n}\n\nfunction parseOneFinding(item: unknown, expertId: string, minOrder: number): ReviewFinding | null {\n if (typeof item !== 'object' || item === null) return null;\n\n const record = item as Record<string, unknown>;\n const severity = parseSeverity(record.severity);\n if (SEVERITY_ORDER[severity] < minOrder) return null;\n\n return {\n id: randomUUID(),\n category: parseCategory(record.category),\n severity,\n title: extractStringField(record, 'title', 'name') ?? 'Finding',\n description: extractStringField(record, 'description', 'message') ?? '',\n file: typeof record.file === 'string' ? record.file : undefined,\n line: typeof record.line === 'number' ? record.line : undefined,\n suggestion: typeof record.suggestion === 'string' ? record.suggestion : undefined,\n expertId,\n confidence: typeof record.confidence === 'number' ? record.confidence : 0.7,\n };\n}\n\n// =============================================================================\n// Decision Helpers\n// =============================================================================\n\nexport function determineApproval(findings: ReviewFinding[]): boolean {\n const hasBlocking = findings.some((f) => f.severity === 'critical' || f.severity === 'high');\n return !hasBlocking;\n}\n\nexport function determineDecision(\n reviews: ExpertReviewResult[],\n findings: ReviewFinding[]\n): ReviewDecision {\n const hasCritical = findings.some((f) => f.severity === 'critical');\n const hasHigh = findings.some((f) => f.severity === 'high');\n const allApproved = reviews.every((r) => r.approved);\n\n if (hasCritical) return 'request_changes';\n if (hasHigh && !allApproved) return 'request_changes';\n if (findings.length > 0) return 'comment';\n return 'approve';\n}\n\nexport function calculateConsensus(reviews: ExpertReviewResult[]): number {\n if (reviews.length === 0) return 1;\n const approvals = reviews.filter((r) => r.approved).length;\n return approvals / reviews.length;\n}\n\n// =============================================================================\n// Counting Helpers\n// =============================================================================\n\nexport function countBySeverity(findings: ReviewFinding[]): Record<ReviewSeverity, number> {\n const counts: Record<ReviewSeverity, number> = {\n critical: 0,\n high: 0,\n medium: 0,\n low: 0,\n info: 0,\n };\n\n for (const f of findings) {\n counts[f.severity]++;\n }\n\n return counts;\n}\n\nexport function countByCategory(findings: ReviewFinding[]): Record<ReviewCategory, number> {\n const counts: Record<ReviewCategory, number> = {\n security: 0,\n performance: 0,\n code_quality: 0,\n testing: 0,\n documentation: 0,\n architecture: 0,\n };\n\n for (const f of findings) {\n counts[f.category]++;\n }\n\n return counts;\n}\n\nexport function sumFindings(counts: Record<ReviewSeverity, number>): number {\n return Object.values(counts).reduce((a, b) => a + b, 0);\n}\n\n// =============================================================================\n// Summary Generation\n// =============================================================================\n\nexport function generateSummary(\n pr: PRMetadata,\n reviews: ExpertReviewResult[],\n decision: ReviewDecision\n): string {\n const expertSummaries = reviews\n .map((r) => `- **${CATEGORY_DISPLAY_NAMES[r.expertType as ReviewCategory]}**: ${r.summary}`)\n .join('\\n');\n\n return `Reviewed PR #${String(pr.number)}: ${pr.title}\n\n**Decision:** ${decision.replaceAll('_', ' ')}\n**Experts consulted:** ${String(reviews.length)}\n\n${expertSummaries}`;\n}\n\n// =============================================================================\n// GitHub Comment Formatting\n// =============================================================================\n\n/**\n * Formats the review result as a GitHub comment.\n */\nexport function formatReviewComment(result: PRReviewResult): string {\n const emoji = DECISION_EMOJI[result.decision];\n const decisionText = result.decision.replaceAll('_', ' ').toUpperCase();\n\n const findingsSection = formatFindingsSection(result);\n const statsSection = formatStatsSection(result);\n\n return `## ${emoji} Nexus Agents Review: ${decisionText}\n\n${result.summary}\n\n${findingsSection}\n\n${statsSection}\n\n---\n*Reviewed by [nexus-agents](https://github.com/nexus-substrate/nexus-agents) in ${String(result.totalDurationMs)}ms*`;\n}\n\nfunction formatFindingsSection(result: PRReviewResult): string {\n const allFindings = result.expertReviews.flatMap((r) => r.findings);\n\n if (allFindings.length === 0) {\n return '_No issues found._';\n }\n\n const sorted = [...allFindings].sort(\n (a, b) => SEVERITY_ORDER[b.severity] - SEVERITY_ORDER[a.severity]\n );\n\n const lines = ['### Findings', ''];\n\n for (const f of sorted) {\n const emoji = SEVERITY_EMOJI[f.severity];\n const loc =\n f.file !== undefined\n ? ` (\\`${f.file}${f.line !== undefined ? `:${String(f.line)}` : ''}\\`)`\n : '';\n lines.push(`${emoji} **${f.title}**${loc}`);\n lines.push(`> ${f.description}`);\n if (f.suggestion !== undefined) {\n lines.push(`> 💡 ${f.suggestion}`);\n }\n lines.push('');\n }\n\n return lines.join('\\n');\n}\n\nfunction formatStatsSection(result: PRReviewResult): string {\n const { findingsBySeverity } = result;\n const total = sumFindings(findingsBySeverity);\n\n const parts: string[] = [];\n for (const severity of ['critical', 'high', 'medium', 'low', 'info'] as ReviewSeverity[]) {\n const count = findingsBySeverity[severity];\n if (count > 0) {\n parts.push(`${SEVERITY_EMOJI[severity]} ${String(count)} ${severity}`);\n }\n }\n\n return `<details>\n<summary>Review Statistics (${String(total)} findings)</summary>\n\n- Experts: ${String(result.expertCount)}\n- Consensus: ${(result.consensusScore * 100).toFixed(0)}%\n- Duration: ${String(result.totalDurationMs)}ms\n- Findings: ${parts.join(', ') || 'none'}\n\n</details>`;\n}\n\n// =============================================================================\n// Failed Review Factory\n// =============================================================================\n\nexport function createFailedReview(\n expertId: string,\n category: ReviewCategory,\n durationMs: number,\n error: string\n): ExpertReviewResult {\n return {\n expertId,\n expertType: category,\n approved: true, // Don't block on failures\n summary: `Review failed: ${error}`,\n findings: [],\n durationMs,\n confidence: 0,\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createLogger
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-UQOSVOEU.js";
|
|
4
4
|
|
|
5
5
|
// src/config/available-models-cache.ts
|
|
6
6
|
var logger = createLogger({ component: "available-models-cache" });
|
|
@@ -150,4 +150,4 @@ export {
|
|
|
150
150
|
getDefaultAvailableModelsCache,
|
|
151
151
|
setDefaultAvailableModelsCache
|
|
152
152
|
};
|
|
153
|
-
//# sourceMappingURL=chunk-
|
|
153
|
+
//# sourceMappingURL=chunk-42MM7GKW.js.map
|
|
@@ -4,7 +4,7 @@ import {
|
|
|
4
4
|
getErrorMessage,
|
|
5
5
|
getTimeProvider,
|
|
6
6
|
ok
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-UQOSVOEU.js";
|
|
8
8
|
|
|
9
9
|
// src/context/session-memory.ts
|
|
10
10
|
import * as fs from "fs";
|
|
@@ -351,4 +351,4 @@ export {
|
|
|
351
351
|
SessionMemory,
|
|
352
352
|
createSessionMemory
|
|
353
353
|
};
|
|
354
|
-
//# sourceMappingURL=chunk-
|
|
354
|
+
//# sourceMappingURL=chunk-45NUO4FE.js.map
|
|
@@ -2,14 +2,14 @@ import {
|
|
|
2
2
|
CircuitBreakerRegistry,
|
|
3
3
|
CircuitError,
|
|
4
4
|
mapCliErrorToCategory
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-NJPFN75N.js";
|
|
6
6
|
import {
|
|
7
7
|
createLogger,
|
|
8
8
|
err,
|
|
9
9
|
getFallbackChainForCategory,
|
|
10
10
|
getTimeProvider,
|
|
11
11
|
ok
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-UQOSVOEU.js";
|
|
13
13
|
|
|
14
14
|
// src/cli-adapters/cli-circuit-breaker.ts
|
|
15
15
|
var CATEGORY_TO_FALLBACK = {
|
|
@@ -152,4 +152,4 @@ export {
|
|
|
152
152
|
CliCircuitBreakerIntegration,
|
|
153
153
|
createCliCircuitBreakerIntegration
|
|
154
154
|
};
|
|
155
|
-
//# sourceMappingURL=chunk-
|
|
155
|
+
//# sourceMappingURL=chunk-ACP4YARI.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
CliCircuitBreaker,
|
|
3
3
|
DEFAULT_CIRCUIT_BREAKER_CONFIG
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-NJPFN75N.js";
|
|
5
5
|
import {
|
|
6
6
|
CLI_SUBPROCESS_TIMEOUTS,
|
|
7
7
|
CLI_TIMEOUTS,
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
getTimeProvider,
|
|
25
25
|
isRateLimitText,
|
|
26
26
|
ok
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-UQOSVOEU.js";
|
|
28
28
|
|
|
29
29
|
// src/cli-adapters/subprocess-adapter.ts
|
|
30
30
|
import { spawn } from "child_process";
|
|
@@ -1267,7 +1267,7 @@ var ClaudeCliAdapter = class extends SubprocessCliAdapter {
|
|
|
1267
1267
|
};
|
|
1268
1268
|
|
|
1269
1269
|
// src/cli-adapters/adapters/gemini-adapter.ts
|
|
1270
|
-
import { writeFileSync,
|
|
1270
|
+
import { writeFileSync, rmSync, mkdtempSync } from "fs";
|
|
1271
1271
|
import { tmpdir } from "os";
|
|
1272
1272
|
import { join } from "path";
|
|
1273
1273
|
|
|
@@ -1653,7 +1653,7 @@ var GeminiCliAdapter = class extends SubprocessCliAdapter {
|
|
|
1653
1653
|
args.push("--policy", file);
|
|
1654
1654
|
cleanup = () => {
|
|
1655
1655
|
try {
|
|
1656
|
-
|
|
1656
|
+
rmSync(dir, { recursive: true, force: true });
|
|
1657
1657
|
} catch {
|
|
1658
1658
|
}
|
|
1659
1659
|
};
|
|
@@ -1709,7 +1709,7 @@ var GeminiCliAdapter = class extends SubprocessCliAdapter {
|
|
|
1709
1709
|
};
|
|
1710
1710
|
|
|
1711
1711
|
// src/cli-adapters/adapters/codex-adapter.ts
|
|
1712
|
-
import { writeFileSync as writeFileSync2,
|
|
1712
|
+
import { writeFileSync as writeFileSync2, rmSync as rmSync2, mkdtempSync as mkdtempSync2 } from "fs";
|
|
1713
1713
|
import { tmpdir as tmpdir2 } from "os";
|
|
1714
1714
|
import { join as join2 } from "path";
|
|
1715
1715
|
|
|
@@ -1930,7 +1930,7 @@ var CodexCliAdapter = class extends SubprocessCliAdapter {
|
|
|
1930
1930
|
args.push("-c", `model_instructions_file=${file}`);
|
|
1931
1931
|
cleanup = () => {
|
|
1932
1932
|
try {
|
|
1933
|
-
|
|
1933
|
+
rmSync2(dir, { recursive: true, force: true });
|
|
1934
1934
|
} catch {
|
|
1935
1935
|
}
|
|
1936
1936
|
};
|
|
@@ -2146,15 +2146,25 @@ var OpenCodeResponseParser = class {
|
|
|
2146
2146
|
parse(raw) {
|
|
2147
2147
|
const lines = raw.trim().split("\n");
|
|
2148
2148
|
const state = this.processAllLines(lines);
|
|
2149
|
+
const errorMessage = state.errorMessages.length > 0 ? state.errorMessages.join("; ") : void 0;
|
|
2149
2150
|
if (state.contentParts.length === 0) {
|
|
2151
|
+
if (errorMessage !== void 0) {
|
|
2152
|
+
return this.buildResponse("", state.sessionId, state.usage, errorMessage);
|
|
2153
|
+
}
|
|
2150
2154
|
return this.handleEmptyContent(raw, lines.length, state);
|
|
2151
2155
|
}
|
|
2152
|
-
return this.buildResponse(
|
|
2156
|
+
return this.buildResponse(
|
|
2157
|
+
state.contentParts.join(""),
|
|
2158
|
+
state.sessionId,
|
|
2159
|
+
state.usage,
|
|
2160
|
+
errorMessage
|
|
2161
|
+
);
|
|
2153
2162
|
}
|
|
2154
2163
|
/** Processes all NDJSON lines and returns aggregated state. */
|
|
2155
2164
|
processAllLines(lines) {
|
|
2156
2165
|
let sessionId;
|
|
2157
2166
|
const contentParts = [];
|
|
2167
|
+
const errorMessages = [];
|
|
2158
2168
|
let usage;
|
|
2159
2169
|
let hasStepEvents = false;
|
|
2160
2170
|
let hasAnyRecognizedEvent = false;
|
|
@@ -2163,7 +2173,7 @@ var OpenCodeResponseParser = class {
|
|
|
2163
2173
|
if (line === void 0 || line.trim() === "") continue;
|
|
2164
2174
|
const hadEvent = this.processLine(
|
|
2165
2175
|
line,
|
|
2166
|
-
contentParts,
|
|
2176
|
+
{ contentParts, errorMessages },
|
|
2167
2177
|
(id) => sessionId = id,
|
|
2168
2178
|
(u) => usage = u,
|
|
2169
2179
|
idx
|
|
@@ -2171,7 +2181,14 @@ var OpenCodeResponseParser = class {
|
|
|
2171
2181
|
if (hadEvent) hasStepEvents = true;
|
|
2172
2182
|
if (hadEvent || this.isRecognizedLegacyEvent(line)) hasAnyRecognizedEvent = true;
|
|
2173
2183
|
}
|
|
2174
|
-
return {
|
|
2184
|
+
return {
|
|
2185
|
+
sessionId,
|
|
2186
|
+
contentParts,
|
|
2187
|
+
errorMessages,
|
|
2188
|
+
usage,
|
|
2189
|
+
hasStepEvents,
|
|
2190
|
+
hasAnyRecognizedEvent
|
|
2191
|
+
};
|
|
2175
2192
|
}
|
|
2176
2193
|
/** Handles the case where no text content was extracted from NDJSON. */
|
|
2177
2194
|
handleEmptyContent(raw, lineCount, state) {
|
|
@@ -2191,11 +2208,12 @@ var OpenCodeResponseParser = class {
|
|
|
2191
2208
|
return this.parsePlainJson(raw, state.hasAnyRecognizedEvent);
|
|
2192
2209
|
}
|
|
2193
2210
|
/** Builds an OpenCodeCliResponse from parsed components. */
|
|
2194
|
-
buildResponse(content, sessionId, usage) {
|
|
2211
|
+
buildResponse(content, sessionId, usage, errorMessage) {
|
|
2195
2212
|
return {
|
|
2196
2213
|
content,
|
|
2197
2214
|
...sessionId !== void 0 && { sessionId },
|
|
2198
|
-
...usage !== void 0 && { usage }
|
|
2215
|
+
...usage !== void 0 && { usage },
|
|
2216
|
+
...errorMessage !== void 0 && { errorMessage }
|
|
2199
2217
|
};
|
|
2200
2218
|
}
|
|
2201
2219
|
/**
|
|
@@ -2269,13 +2287,13 @@ var OpenCodeResponseParser = class {
|
|
|
2269
2287
|
* Returns true if a real v1.2.x step event was processed (step_start/text/tool_use/step_finish).
|
|
2270
2288
|
* Legacy events return false since they don't indicate tool-only responses.
|
|
2271
2289
|
*/
|
|
2272
|
-
processLine(line,
|
|
2290
|
+
processLine(line, collectors, setSessionId, setUsage, lineIndex) {
|
|
2273
2291
|
try {
|
|
2274
2292
|
const record = asRecord(JSON.parse(line));
|
|
2275
2293
|
if (record === null) return false;
|
|
2276
|
-
const isReal = this.processRealEvent(record,
|
|
2294
|
+
const isReal = this.processRealEvent(record, collectors, setSessionId, setUsage);
|
|
2277
2295
|
if (isReal) return true;
|
|
2278
|
-
this.processLegacyEvent(record, contentParts, setSessionId, setUsage);
|
|
2296
|
+
this.processLegacyEvent(record, collectors.contentParts, setSessionId, setUsage);
|
|
2279
2297
|
return false;
|
|
2280
2298
|
} catch {
|
|
2281
2299
|
logger3.debug("Skipped malformed NDJSON line", {
|
|
@@ -2286,7 +2304,7 @@ var OpenCodeResponseParser = class {
|
|
|
2286
2304
|
}
|
|
2287
2305
|
}
|
|
2288
2306
|
/** Processes real opencode v1.2.x event types. Returns true if handled. */
|
|
2289
|
-
processRealEvent(record,
|
|
2307
|
+
processRealEvent(record, collectors, setSessionId, setUsage) {
|
|
2290
2308
|
switch (record.type) {
|
|
2291
2309
|
case "step_start":
|
|
2292
2310
|
case "tool_use":
|
|
@@ -2294,7 +2312,7 @@ var OpenCodeResponseParser = class {
|
|
|
2294
2312
|
return true;
|
|
2295
2313
|
case "text":
|
|
2296
2314
|
this.handleRealSessionId(record, setSessionId);
|
|
2297
|
-
this.pushRealTextContent(record, contentParts);
|
|
2315
|
+
this.pushRealTextContent(record, collectors.contentParts);
|
|
2298
2316
|
return true;
|
|
2299
2317
|
case "step_finish":
|
|
2300
2318
|
this.handleRealSessionId(record, setSessionId);
|
|
@@ -2302,20 +2320,25 @@ var OpenCodeResponseParser = class {
|
|
|
2302
2320
|
return true;
|
|
2303
2321
|
case "error":
|
|
2304
2322
|
this.handleRealSessionId(record, setSessionId);
|
|
2305
|
-
this.
|
|
2323
|
+
this.captureErrorMessage(record, collectors.errorMessages);
|
|
2306
2324
|
return true;
|
|
2307
2325
|
default:
|
|
2308
2326
|
return false;
|
|
2309
2327
|
}
|
|
2310
2328
|
}
|
|
2311
|
-
/**
|
|
2312
|
-
|
|
2329
|
+
/**
|
|
2330
|
+
* Captures an error-event message for the response's `errorMessage` field
|
|
2331
|
+
* (#2821). Previously this pushed `[OpenCode error: ...]` into `contentParts`,
|
|
2332
|
+
* which made error-only streams look like successful responses to consensus
|
|
2333
|
+
* voters and the routing learner.
|
|
2334
|
+
*/
|
|
2335
|
+
captureErrorMessage(record, errorMessages) {
|
|
2313
2336
|
const errorObj = asRecord(record.error);
|
|
2314
2337
|
if (errorObj === null) return;
|
|
2315
2338
|
const data = asRecord(errorObj.data);
|
|
2316
2339
|
const message = data !== null && typeof data.message === "string" ? data.message : typeof errorObj.name === "string" ? errorObj.name : "Unknown error";
|
|
2317
2340
|
logger3.warn("OpenCode returned error event", { message });
|
|
2318
|
-
|
|
2341
|
+
errorMessages.push(message);
|
|
2319
2342
|
}
|
|
2320
2343
|
/** Processes legacy assumed event types. */
|
|
2321
2344
|
processLegacyEvent(record, contentParts, setSessionId, setUsage) {
|
|
@@ -3062,4 +3085,4 @@ export {
|
|
|
3062
3085
|
isCliAvailable,
|
|
3063
3086
|
getAvailableClis
|
|
3064
3087
|
};
|
|
3065
|
-
//# sourceMappingURL=chunk-
|
|
3088
|
+
//# sourceMappingURL=chunk-BIH2CBC5.js.map
|