@gmickel/gno 1.19.0 → 1.20.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/README.md +12 -7
- package/assets/skill/SKILL.md +27 -12
- package/assets/skill/mcp-reference.md +7 -2
- package/assets/skill/recipes/citation-and-provenance.md +32 -9
- package/package.json +1 -1
- package/spec/cli.md +42 -17
- package/spec/evals-agentic.md +87 -5
- package/spec/mcp.md +53 -3
- package/spec/output-schemas/ask.schema.json +198 -0
- package/spec/output-schemas/claim-verification.schema.json +291 -0
- package/spec/output-schemas/context-capsule-v1.schema.json +36 -1
- package/src/app/context-runtime-contract.ts +10 -5
- package/src/app/context-runtime-input.ts +29 -1
- package/src/app/context-runtime-types.ts +4 -0
- package/src/app/context-runtime.ts +5 -1
- package/src/app/context-surface.ts +4 -0
- package/src/app/verified-ask.ts +291 -0
- package/src/cli/commands/ask-format.ts +255 -0
- package/src/cli/commands/ask.ts +40 -149
- package/src/cli/program.ts +32 -1
- package/src/core/context-budget.ts +6 -0
- package/src/core/context-capsule-retrieval-schema.ts +4 -0
- package/src/core/context-capsule-schema.ts +17 -0
- package/src/core/context-capsule-validation.ts +3 -2
- package/src/core/context-capsule.ts +18 -0
- package/src/core/context-compiler.ts +33 -21
- package/src/core/context-evidence.ts +6 -0
- package/src/core/retrieval-trace-evidence-origin.ts +3 -0
- package/src/core/retrieval-trace-session.ts +15 -2
- package/src/llm/errors.ts +10 -1
- package/src/llm/httpGeneration.ts +11 -1
- package/src/llm/nodeLlamaCpp/generation.ts +54 -10
- package/src/llm/types.ts +6 -0
- package/src/mcp/tools/ask.ts +228 -0
- package/src/mcp/tools/context.ts +28 -7
- package/src/mcp/tools/index.ts +9 -0
- package/src/pipeline/claim-verification-schema.ts +235 -0
- package/src/pipeline/claim-verification.ts +487 -0
- package/src/pipeline/claim-verifier.ts +474 -0
- package/src/pipeline/types.ts +25 -0
- package/src/sdk/client.ts +35 -2
- package/src/serve/public/components/AskVerificationPanel.tsx +189 -0
- package/src/serve/public/globals.built.css +1 -1
- package/src/serve/public/pages/Ask.tsx +42 -4
- package/src/serve/routes/api.ts +149 -3
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import { AlertTriangle, CheckCircle2, CircleHelp, ShieldX } from "lucide-react";
|
|
2
|
+
|
|
3
|
+
import type { AskResult } from "../../../pipeline/types";
|
|
4
|
+
|
|
5
|
+
import { cn } from "../lib/utils";
|
|
6
|
+
import { Badge } from "./ui/badge";
|
|
7
|
+
|
|
8
|
+
export type AskVerification = NonNullable<AskResult["verification"]>;
|
|
9
|
+
|
|
10
|
+
interface AskVerificationPanelProps {
|
|
11
|
+
navigate: (to: string) => void;
|
|
12
|
+
verification: AskVerification;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const STATUS_PRESENTATION = {
|
|
16
|
+
supported: {
|
|
17
|
+
label: "supported",
|
|
18
|
+
icon: CheckCircle2,
|
|
19
|
+
className: "border-emerald-500/30 bg-emerald-500/10 text-emerald-300",
|
|
20
|
+
},
|
|
21
|
+
contradicted: {
|
|
22
|
+
label: "contradicted",
|
|
23
|
+
icon: ShieldX,
|
|
24
|
+
className: "border-destructive/40 bg-destructive/10 text-destructive",
|
|
25
|
+
},
|
|
26
|
+
insufficient: {
|
|
27
|
+
label: "insufficient",
|
|
28
|
+
icon: AlertTriangle,
|
|
29
|
+
className: "border-amber-500/30 bg-amber-500/10 text-amber-300",
|
|
30
|
+
},
|
|
31
|
+
uncertain: {
|
|
32
|
+
label: "uncertain",
|
|
33
|
+
icon: CircleHelp,
|
|
34
|
+
className: "border-sky-500/30 bg-sky-500/10 text-sky-300",
|
|
35
|
+
},
|
|
36
|
+
} as const;
|
|
37
|
+
|
|
38
|
+
const evidenceLabel = (uri: string, startLine: number, endLine: number) =>
|
|
39
|
+
`${uri}:L${startLine}${startLine === endLine ? "" : `-L${endLine}`}`;
|
|
40
|
+
|
|
41
|
+
export function AskVerificationPanel({
|
|
42
|
+
navigate,
|
|
43
|
+
verification,
|
|
44
|
+
}: AskVerificationPanelProps) {
|
|
45
|
+
const { claims, capsule, semantic } = verification;
|
|
46
|
+
const degradedCapabilities = Object.entries(
|
|
47
|
+
capsule.retrieval.capabilityStates
|
|
48
|
+
).filter(([, state]) => state.requested && state.outcome !== "used");
|
|
49
|
+
const gaps = capsule.coverage.gaps;
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<details className="group rounded-lg border border-border/50 bg-card/55">
|
|
53
|
+
<summary className="flex cursor-pointer list-none items-center justify-between gap-3 px-4 py-3">
|
|
54
|
+
<div className="min-w-0">
|
|
55
|
+
<div className="flex flex-wrap items-center gap-2">
|
|
56
|
+
<span className="font-medium text-sm">
|
|
57
|
+
{claims.answerStatus === "verified"
|
|
58
|
+
? "All claims verified"
|
|
59
|
+
: "Answer withheld"}
|
|
60
|
+
</span>
|
|
61
|
+
<Badge
|
|
62
|
+
className="font-mono text-[9px]"
|
|
63
|
+
variant={
|
|
64
|
+
claims.answerStatus === "verified" ? "default" : "outline"
|
|
65
|
+
}
|
|
66
|
+
>
|
|
67
|
+
{claims.coverage.supportedClaims}/{claims.coverage.totalClaims}{" "}
|
|
68
|
+
supported
|
|
69
|
+
</Badge>
|
|
70
|
+
</div>
|
|
71
|
+
<p className="mt-1 text-muted-foreground text-xs">
|
|
72
|
+
{claims.abstentionReason ??
|
|
73
|
+
`${claims.coverage.supportedRatio * 100}% support coverage`}
|
|
74
|
+
</p>
|
|
75
|
+
</div>
|
|
76
|
+
<span className="shrink-0 font-mono text-[10px] text-muted-foreground group-open:hidden">
|
|
77
|
+
details
|
|
78
|
+
</span>
|
|
79
|
+
</summary>
|
|
80
|
+
|
|
81
|
+
<div className="space-y-4 border-border/40 border-t px-4 py-4">
|
|
82
|
+
<div className="flex flex-wrap gap-2">
|
|
83
|
+
<Badge className="font-mono text-[9px]" variant="outline">
|
|
84
|
+
semantic: {semantic.status}/{semantic.reason}
|
|
85
|
+
</Badge>
|
|
86
|
+
{degradedCapabilities.map(([name, state]) => (
|
|
87
|
+
<Badge
|
|
88
|
+
className="font-mono text-[9px]"
|
|
89
|
+
key={name}
|
|
90
|
+
variant="outline"
|
|
91
|
+
>
|
|
92
|
+
{name}: {state.outcome}
|
|
93
|
+
{state.fallbackReasons.length > 0
|
|
94
|
+
? ` (${state.fallbackReasons.join(", ")})`
|
|
95
|
+
: ""}
|
|
96
|
+
</Badge>
|
|
97
|
+
))}
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
<div className="grid grid-cols-2 gap-2 font-mono text-[10px] text-muted-foreground sm:grid-cols-4">
|
|
101
|
+
<span>{claims.coverage.supportedClaims} supported</span>
|
|
102
|
+
<span>{claims.coverage.contradictedClaims} contradicted</span>
|
|
103
|
+
<span>{claims.coverage.insufficientClaims} insufficient</span>
|
|
104
|
+
<span>{claims.coverage.uncertainClaims} uncertain</span>
|
|
105
|
+
</div>
|
|
106
|
+
|
|
107
|
+
<div className="space-y-2">
|
|
108
|
+
{claims.claims.map((claim) => {
|
|
109
|
+
const presentation = STATUS_PRESENTATION[claim.status];
|
|
110
|
+
const StatusIcon = presentation.icon;
|
|
111
|
+
return (
|
|
112
|
+
<details
|
|
113
|
+
className="rounded-md border border-border/35 bg-background/20"
|
|
114
|
+
key={claim.claimId}
|
|
115
|
+
>
|
|
116
|
+
<summary className="flex cursor-pointer list-none items-start gap-2 px-3 py-2">
|
|
117
|
+
<StatusIcon className="mt-0.5 size-3.5 shrink-0" />
|
|
118
|
+
<span className="min-w-0 flex-1 text-xs">{claim.text}</span>
|
|
119
|
+
<Badge
|
|
120
|
+
className={cn(
|
|
121
|
+
"shrink-0 font-mono text-[9px]",
|
|
122
|
+
presentation.className
|
|
123
|
+
)}
|
|
124
|
+
variant="outline"
|
|
125
|
+
>
|
|
126
|
+
{presentation.label}
|
|
127
|
+
</Badge>
|
|
128
|
+
</summary>
|
|
129
|
+
<div className="space-y-2 border-border/30 border-t px-3 py-2">
|
|
130
|
+
{claim.evidence.length > 0 ? (
|
|
131
|
+
claim.evidence.map((evidence) => (
|
|
132
|
+
<button
|
|
133
|
+
className="block w-full truncate text-left font-mono text-[10px] text-primary hover:underline"
|
|
134
|
+
key={evidence.evidenceId}
|
|
135
|
+
onClick={() =>
|
|
136
|
+
navigate(
|
|
137
|
+
`/doc?uri=${encodeURIComponent(evidence.uri)}`
|
|
138
|
+
)
|
|
139
|
+
}
|
|
140
|
+
title={evidenceLabel(
|
|
141
|
+
evidence.uri,
|
|
142
|
+
evidence.startLine,
|
|
143
|
+
evidence.endLine
|
|
144
|
+
)}
|
|
145
|
+
type="button"
|
|
146
|
+
>
|
|
147
|
+
{evidenceLabel(
|
|
148
|
+
evidence.uri,
|
|
149
|
+
evidence.startLine,
|
|
150
|
+
evidence.endLine
|
|
151
|
+
)}
|
|
152
|
+
</button>
|
|
153
|
+
))
|
|
154
|
+
) : (
|
|
155
|
+
<p className="text-muted-foreground text-xs">
|
|
156
|
+
No retained evidence span.
|
|
157
|
+
</p>
|
|
158
|
+
)}
|
|
159
|
+
<p className="font-mono text-[10px] text-muted-foreground">
|
|
160
|
+
{claim.rationaleCode}
|
|
161
|
+
{claim.confidence === null
|
|
162
|
+
? ""
|
|
163
|
+
: ` · confidence ${claim.confidence.toFixed(2)}`}
|
|
164
|
+
</p>
|
|
165
|
+
</div>
|
|
166
|
+
</details>
|
|
167
|
+
);
|
|
168
|
+
})}
|
|
169
|
+
</div>
|
|
170
|
+
|
|
171
|
+
{(capsule.coverage.unresolvedFacets.length > 0 || gaps.length > 0) && (
|
|
172
|
+
<div className="rounded-md border border-amber-500/25 bg-amber-500/5 px-3 py-2">
|
|
173
|
+
<p className="font-medium text-amber-200 text-xs">Evidence gaps</p>
|
|
174
|
+
<ul className="mt-1 space-y-1 font-mono text-[10px] text-muted-foreground">
|
|
175
|
+
{capsule.coverage.unresolvedFacets.map((facet) => (
|
|
176
|
+
<li key={`facet:${facet}`}>unresolved facet: {facet}</li>
|
|
177
|
+
))}
|
|
178
|
+
{gaps.map((gap) => (
|
|
179
|
+
<li key={`${gap.facet}:${gap.code}`}>
|
|
180
|
+
{gap.facet}: {gap.code}
|
|
181
|
+
</li>
|
|
182
|
+
))}
|
|
183
|
+
</ul>
|
|
184
|
+
</div>
|
|
185
|
+
)}
|
|
186
|
+
</div>
|
|
187
|
+
</details>
|
|
188
|
+
);
|
|
189
|
+
}
|