kyd-shared-badge 0.3.39 → 0.3.40
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/package.json +1 -1
- package/src/SharedBadgeDisplay.tsx +70 -12
- package/src/chat/ChatWidget.tsx +2 -3
- package/src/types.ts +16 -4
package/package.json
CHANGED
|
@@ -583,20 +583,78 @@ const SharedBadgeDisplay = ({ badgeData, chatProps, headless }: { badgeData: Pub
|
|
|
583
583
|
const AiSection = () => (
|
|
584
584
|
<div className={`${wrapperMaxWidth} mx-auto`}>
|
|
585
585
|
<div className={'rounded-xl shadow-xl p-6 sm:p-8 mt-6 border'} style={{ backgroundColor: 'var(--content-card-background)', borderColor: 'var(--icon-button-secondary)' }}>
|
|
586
|
+
<Reveal headless={isHeadless} as={'h4'} offsetY={8} className={'text-2xl font-semibold mb-3'} style={{ color: 'var(--text-main)' }}>KYD AI (Beta)</Reveal>
|
|
586
587
|
{(() => {
|
|
587
|
-
const
|
|
588
|
-
|
|
589
|
-
const
|
|
588
|
+
const ai = assessmentResult?.ai_usage_summary;
|
|
589
|
+
if (!ai) return null;
|
|
590
|
+
const techGauge = {
|
|
591
|
+
percent: Math.max(0, Math.min(100, Number(ai.originality_score ?? 0))),
|
|
592
|
+
label: 'Originality',
|
|
593
|
+
};
|
|
594
|
+
const riskGauge = {
|
|
595
|
+
percent: Math.max(0, Math.min(100, Number(ai.transparency_score ?? 0))),
|
|
596
|
+
label: ai.transparency_descriptor ? `Transparency — ${ai.transparency_descriptor}` : 'Transparency',
|
|
597
|
+
};
|
|
598
|
+
const stats: Array<{ label: string; value: string }>= [
|
|
599
|
+
{ label: 'Files analyzed', value: String(ai.files_analyzed ?? 0) },
|
|
600
|
+
{ label: 'Files with AI findings', value: String(ai.files_with_ai_findings ?? 0) },
|
|
601
|
+
{ label: 'Files with disclosure', value: String(ai.files_with_disclosure ?? 0) },
|
|
602
|
+
{ label: 'Repos analyzed', value: String(ai.repos_analyzed ?? 0) },
|
|
603
|
+
{ label: 'Repos with AI findings', value: String(ai.repos_with_ai_findings ?? 0) },
|
|
604
|
+
];
|
|
605
|
+
const findings = Array.isArray(ai.evidence) ? ai.evidence.slice(0, 5) : [];
|
|
606
|
+
const topMovers = Array.isArray(ai.key_findings) ? ai.key_findings : [];
|
|
590
607
|
return (
|
|
591
|
-
<
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
608
|
+
<div className="space-y-8">
|
|
609
|
+
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4 *:min-h-full">
|
|
610
|
+
<GaugeCard
|
|
611
|
+
key={'ai-originality'}
|
|
612
|
+
title={'Originality'}
|
|
613
|
+
description={'Estimated share of human-authored code based on linguistic signals in comments.'}
|
|
614
|
+
percent={techGauge.percent}
|
|
615
|
+
label={techGauge.label}
|
|
616
|
+
topMovers={[]}
|
|
617
|
+
/>
|
|
618
|
+
<GaugeCard
|
|
619
|
+
key={'ai-transparency'}
|
|
620
|
+
title={'Transparency'}
|
|
621
|
+
description={'Proportion of AI-influenced files that include an explicit disclosure.'}
|
|
622
|
+
percent={riskGauge.percent}
|
|
623
|
+
label={riskGauge.label}
|
|
624
|
+
topMovers={topMovers.map(t => ({ label: t, uid: 'ai-usage' }))}
|
|
625
|
+
topMoversTitle={'Key Findings'}
|
|
626
|
+
/>
|
|
627
|
+
</div>
|
|
628
|
+
<div className="grid grid-cols-2 sm:grid-cols-5 gap-4">
|
|
629
|
+
{stats.map((s, i) => (
|
|
630
|
+
<div key={i} className={'rounded-md p-3 border'} style={{ borderColor: 'var(--icon-button-secondary)', background: 'var(--content-card-background)' }}>
|
|
631
|
+
<div className={'text-xs'} style={{ color: 'var(--text-secondary)' }}>{s.label}</div>
|
|
632
|
+
<div className={'text-lg font-semibold'} style={{ color: 'var(--text-main)' }}>{s.value}</div>
|
|
633
|
+
</div>
|
|
634
|
+
))}
|
|
635
|
+
</div>
|
|
636
|
+
{findings.length > 0 && (
|
|
637
|
+
<div>
|
|
638
|
+
<div className={'text-sm font-semibold mb-3'} style={{ color: 'var(--text-main)' }}>Sample Findings</div>
|
|
639
|
+
<div className="space-y-3">
|
|
640
|
+
{findings.map((f, idx) => (
|
|
641
|
+
<div key={idx} className={'rounded-md p-3 border'} style={{ borderColor: 'var(--icon-button-secondary)', background: 'var(--content-card-background)' }}>
|
|
642
|
+
<div className={'text-xs mb-1'} style={{ color: 'var(--text-secondary)' }}>{f.file_path || 'file'}</div>
|
|
643
|
+
{f.snippet ? (
|
|
644
|
+
<pre className={'text-xs overflow-auto p-2 rounded'} style={{ background: 'rgba(0,0,0,0.04)', color: 'var(--text-main)' }}>{f.snippet}</pre>
|
|
645
|
+
) : null}
|
|
646
|
+
{f.reason ? (
|
|
647
|
+
<div className={'text-xs mt-2'} style={{ color: 'var(--text-secondary)' }}>{f.reason}</div>
|
|
648
|
+
) : null}
|
|
649
|
+
</div>
|
|
650
|
+
))}
|
|
651
|
+
</div>
|
|
652
|
+
</div>
|
|
653
|
+
)}
|
|
654
|
+
{ai.explanation && (
|
|
655
|
+
<div className={'text-sm'} style={{ color: 'var(--text-secondary)' }}>{ai.explanation}</div>
|
|
656
|
+
)}
|
|
657
|
+
</div>
|
|
600
658
|
);
|
|
601
659
|
})()}
|
|
602
660
|
</div>
|
package/src/chat/ChatWidget.tsx
CHANGED
|
@@ -54,8 +54,7 @@ export default function ChatWidget({ api = '/api/chat', title = 'KYD Bot', hintT
|
|
|
54
54
|
|
|
55
55
|
useEffect(() => {
|
|
56
56
|
// when sidebar is closed, dismiss hint
|
|
57
|
-
if (open)
|
|
58
|
-
setShowHint(false);
|
|
57
|
+
if (!open) setShowHint(false);
|
|
59
58
|
}, [open]);
|
|
60
59
|
|
|
61
60
|
// Sidebar width with bounds and persistence
|
|
@@ -278,7 +277,7 @@ export default function ChatWidget({ api = '/api/chat', title = 'KYD Bot', hintT
|
|
|
278
277
|
)}
|
|
279
278
|
</div>
|
|
280
279
|
) : (
|
|
281
|
-
<div style={{ position: 'fixed', right: 0, top: Math.max(headerTop + 16, tabTop), height: 160, width: 44 }}>
|
|
280
|
+
<div style={{ position: 'fixed', right: 0, top: Math.max(headerTop + 16, tabTop), height: 160, width: 44, overflow: 'hidden' }}>
|
|
282
281
|
<button
|
|
283
282
|
aria-label={'Open chat sidebar'}
|
|
284
283
|
aria-expanded={open}
|
package/src/types.ts
CHANGED
|
@@ -203,10 +203,16 @@ export interface AssessmentResult {
|
|
|
203
203
|
ai_usage_summary?: {
|
|
204
204
|
explanation: string;
|
|
205
205
|
key_findings: string[];
|
|
206
|
+
originality_score: number;
|
|
207
|
+
transparency_score: number;
|
|
208
|
+
transparency_descriptor?: string;
|
|
206
209
|
files_with_ai_findings: number;
|
|
207
210
|
files_analyzed: number;
|
|
208
|
-
files_with_disclosure
|
|
209
|
-
|
|
211
|
+
files_with_disclosure?: number;
|
|
212
|
+
repos_analyzed?: number;
|
|
213
|
+
repos_with_ai_findings?: number;
|
|
214
|
+
evidence?: Array<{ file_path?: string; snippet?: string; reason?: string }>;
|
|
215
|
+
findings_by_repo?: Record<string, Array<{ file_path?: string; snippet?: string; reason?: string }>>;
|
|
210
216
|
};
|
|
211
217
|
key_skills?: string[];
|
|
212
218
|
summary_scores?: {
|
|
@@ -394,13 +400,19 @@ export interface GraphInsightsPayload {
|
|
|
394
400
|
top_movers?: Array<{ label?: string; uid?: string }>;
|
|
395
401
|
};
|
|
396
402
|
};
|
|
397
|
-
ai_usage_summary
|
|
403
|
+
ai_usage_summary?: {
|
|
398
404
|
explanation: string;
|
|
399
405
|
key_findings: string[];
|
|
406
|
+
originality_score: number;
|
|
407
|
+
transparency_score: number;
|
|
408
|
+
transparency_descriptor?: string;
|
|
400
409
|
files_with_ai_findings: number;
|
|
401
410
|
files_analyzed: number;
|
|
402
411
|
files_with_disclosure?: number;
|
|
403
|
-
|
|
412
|
+
repos_analyzed?: number;
|
|
413
|
+
repos_with_ai_findings?: number;
|
|
414
|
+
evidence?: Array<{ file_path?: string; snippet?: string; reason?: string }>;
|
|
415
|
+
findings_by_repo?: Record<string, Array<{ file_path?: string; snippet?: string; reason?: string }>>;
|
|
404
416
|
}
|
|
405
417
|
}
|
|
406
418
|
|