@gmickel/gno 2.3.2 → 2.4.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 +24 -4
- package/assets/skill/SKILL.md +30 -0
- package/assets/skill/cli-reference.md +12 -0
- package/assets/skill/examples.md +15 -0
- package/assets/skill/mcp-reference.md +16 -0
- package/assets/spa-production.json.gz +0 -0
- package/browser-extension/artifacts/{gno-browser-clipper-v2.3.2.zip → gno-browser-clipper-v2.4.0.zip} +0 -0
- package/browser-extension/artifacts/gno-browser-clipper-v2.4.0.zip.sha256 +1 -0
- package/browser-extension/dist/manifest.json +1 -1
- package/package.json +1 -1
- package/spec/cli.md +30 -0
- package/spec/db/schema.sql +2 -0
- package/spec/evals.md +48 -0
- package/spec/mcp.md +12 -0
- package/spec/output-schemas/ask.schema.json +12 -0
- package/spec/output-schemas/context-capsule-v1.schema.json +205 -32
- package/spec/output-schemas/context-capsule-verification.schema.json +32 -9
- package/spec/output-schemas/evidence-fixtures.schema.json +176 -0
- package/spec/output-schemas/evidence-report.schema.json +322 -0
- package/spec/output-schemas/evidence-run.schema.json +277 -0
- package/spec/output-schemas/metadata-predicate.schema.json +460 -0
- package/spec/output-schemas/retrieval-trace-filters.schema.json +13 -4
- package/spec/output-schemas/search-results.schema.json +12 -0
- package/spec/output-schemas/status.schema.json +37 -6
- package/src/app/context-runtime-contract.ts +33 -2
- package/src/app/context-runtime-input.ts +17 -0
- package/src/app/context-runtime-types.ts +2 -0
- package/src/app/context-runtime.ts +27 -3
- package/src/app/context-surface.ts +2 -0
- package/src/app/verified-ask.ts +1 -0
- package/src/cli/commands/ask.ts +1 -0
- package/src/cli/commands/context-build.ts +1 -0
- package/src/cli/commands/search.ts +1 -0
- package/src/cli/commands/status.ts +10 -0
- package/src/cli/options.ts +19 -0
- package/src/cli/program.ts +12 -0
- package/src/converters/types.ts +2 -0
- package/src/core/context-capsule-retrieval-schema.ts +8 -0
- package/src/core/context-capsule-schema.ts +47 -3
- package/src/core/context-capsule-validation.ts +14 -2
- package/src/core/context-capsule-verification.ts +1 -0
- package/src/core/context-capsule.ts +16 -2
- package/src/core/context-compiler.ts +3 -0
- package/src/core/record-metadata.ts +1 -1
- package/src/core/retrieval-replay-candidate.ts +5 -0
- package/src/core/retrieval-trace-filter-normalization.ts +4 -0
- package/src/core/retrieval-trace-request.ts +1 -0
- package/src/core/retrieval-trace-session.ts +5 -1
- package/src/core/retrieval-trace.ts +2 -0
- package/src/core/typed-metadata.ts +224 -0
- package/src/ingestion/record-adapter-canonical.ts +13 -2
- package/src/ingestion/record-container.ts +9 -0
- package/src/ingestion/sync.ts +11 -1
- package/src/ingestion/typed-metadata.ts +55 -0
- package/src/mcp/tools/ask.ts +10 -2
- package/src/mcp/tools/context.ts +1 -0
- package/src/mcp/tools/index.ts +12 -1
- package/src/mcp/tools/query.ts +13 -0
- package/src/mcp/tools/search.ts +9 -0
- package/src/mcp/tools/status.ts +4 -0
- package/src/mcp/tools/vsearch.ts +9 -0
- package/src/pipeline/diagnose.ts +6 -0
- package/src/pipeline/filters.ts +65 -0
- package/src/pipeline/graph-retrieval.ts +9 -1
- package/src/pipeline/hybrid.ts +22 -2
- package/src/pipeline/search.ts +11 -0
- package/src/pipeline/types.ts +7 -1
- package/src/pipeline/vsearch.ts +21 -1
- package/src/sdk/client.ts +29 -1
- package/src/sdk/index.ts +4 -0
- package/src/sdk/types.ts +7 -0
- package/src/serve/context-capsule.ts +1 -0
- package/src/serve/public/app.tsx +1 -1
- package/src/serve/public/components/MetadataFilter.tsx +186 -0
- package/src/serve/public/globals.built.css +1 -1
- package/src/serve/public/lib/metadata-filter.ts +28 -0
- package/src/serve/public/lib/retrieval-filters.ts +3 -0
- package/src/serve/public/pages/Ask.tsx +48 -3
- package/src/serve/public/pages/DocView.tsx +33 -0
- package/src/serve/public/pages/Search.tsx +44 -1
- package/src/serve/routes/api.ts +50 -0
- package/src/store/migrations/030-typed-metadata.ts +13 -0
- package/src/store/migrations/index.ts +2 -0
- package/src/store/sqlite/adapter.ts +55 -4
- package/src/store/sqlite/eligibility.ts +12 -0
- package/src/store/sqlite/metadata-predicate.ts +71 -0
- package/src/store/types.ts +11 -0
- package/browser-extension/artifacts/gno-browser-clipper-v2.3.2.zip.sha256 +0 -1
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { useId, useState } from "react";
|
|
2
|
+
|
|
3
|
+
import { parseMetadataFilter } from "../lib/metadata-filter";
|
|
4
|
+
import { Button } from "./ui/button";
|
|
5
|
+
import { Input } from "./ui/input";
|
|
6
|
+
import { Textarea } from "./ui/textarea";
|
|
7
|
+
|
|
8
|
+
const OPERATORS = [
|
|
9
|
+
"eq",
|
|
10
|
+
"ne",
|
|
11
|
+
"gt",
|
|
12
|
+
"gte",
|
|
13
|
+
"lt",
|
|
14
|
+
"lte",
|
|
15
|
+
"in",
|
|
16
|
+
"nin",
|
|
17
|
+
"all",
|
|
18
|
+
"exists",
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
/** The JSON text is the single source of truth, including invalid drafts. */
|
|
22
|
+
export function MetadataFilter({
|
|
23
|
+
value,
|
|
24
|
+
onChange,
|
|
25
|
+
}: {
|
|
26
|
+
value: string;
|
|
27
|
+
onChange: (value: string) => void;
|
|
28
|
+
}) {
|
|
29
|
+
const id = useId();
|
|
30
|
+
const [draftValue, setDraftValue] = useState<string | null>(null);
|
|
31
|
+
const [draftLeaf, setDraftLeaf] = useState<Record<string, unknown> | null>(
|
|
32
|
+
null
|
|
33
|
+
);
|
|
34
|
+
const { error } = parseMetadataFilter(value);
|
|
35
|
+
let leaf: Record<string, unknown> | null = null;
|
|
36
|
+
try {
|
|
37
|
+
const parsed: unknown = JSON.parse(value);
|
|
38
|
+
if (
|
|
39
|
+
parsed &&
|
|
40
|
+
typeof parsed === "object" &&
|
|
41
|
+
!Array.isArray(parsed) &&
|
|
42
|
+
"op" in parsed &&
|
|
43
|
+
OPERATORS.includes(String(parsed.op))
|
|
44
|
+
)
|
|
45
|
+
leaf = parsed as Record<string, unknown>;
|
|
46
|
+
} catch {
|
|
47
|
+
/* Invalid JSON stays editable below. */
|
|
48
|
+
}
|
|
49
|
+
if (value.trim()) leaf ??= draftLeaf;
|
|
50
|
+
const update = (patch: Record<string, unknown>) => {
|
|
51
|
+
const next = { ...leaf, ...patch };
|
|
52
|
+
setDraftLeaf(next);
|
|
53
|
+
if (draftValue !== null) {
|
|
54
|
+
const property = "values" in next ? "values" : "value";
|
|
55
|
+
onChange(
|
|
56
|
+
`{"op":${JSON.stringify(next.op)},"key":${JSON.stringify(next.key)},"${property}":${draftValue}}`
|
|
57
|
+
);
|
|
58
|
+
} else onChange(JSON.stringify(next));
|
|
59
|
+
};
|
|
60
|
+
return (
|
|
61
|
+
<fieldset className="min-w-0 space-y-3 border-border/40 border-t pt-3">
|
|
62
|
+
<legend className="px-1 font-mono text-muted-foreground text-xs">
|
|
63
|
+
Custom metadata
|
|
64
|
+
</legend>
|
|
65
|
+
<p className="text-muted-foreground text-xs">
|
|
66
|
+
Filter indexed gno.metadata fields. Text is case-sensitive. Values use
|
|
67
|
+
JSON: "approved", 0.8, true, or ["alpha"]. Filters are included in this
|
|
68
|
+
page’s URL.
|
|
69
|
+
</p>
|
|
70
|
+
{leaf ? (
|
|
71
|
+
<div className="grid min-w-0 gap-2 sm:grid-cols-3">
|
|
72
|
+
<label className="space-y-1 text-xs">
|
|
73
|
+
Field
|
|
74
|
+
<Input
|
|
75
|
+
onChange={(e) => update({ key: e.target.value })}
|
|
76
|
+
value={typeof leaf.key === "string" ? leaf.key : ""}
|
|
77
|
+
/>
|
|
78
|
+
</label>
|
|
79
|
+
<label className="space-y-1 text-xs">
|
|
80
|
+
Operator
|
|
81
|
+
<select
|
|
82
|
+
className="h-9 w-full cursor-pointer rounded-md border border-input bg-background px-2 focus-visible:ring-2 focus-visible:ring-primary/50"
|
|
83
|
+
onChange={(e) => {
|
|
84
|
+
setDraftValue(null);
|
|
85
|
+
setDraftLeaf(null);
|
|
86
|
+
const op = e.target.value;
|
|
87
|
+
onChange(
|
|
88
|
+
JSON.stringify({
|
|
89
|
+
op,
|
|
90
|
+
key: leaf?.key ?? "",
|
|
91
|
+
...(["in", "nin", "all"].includes(op)
|
|
92
|
+
? { values: [] }
|
|
93
|
+
: { value: op === "exists" ? true : "" }),
|
|
94
|
+
})
|
|
95
|
+
);
|
|
96
|
+
}}
|
|
97
|
+
value={String(leaf.op)}
|
|
98
|
+
>
|
|
99
|
+
{OPERATORS.map((op) => (
|
|
100
|
+
<option key={op} value={op}>
|
|
101
|
+
{op}
|
|
102
|
+
</option>
|
|
103
|
+
))}
|
|
104
|
+
</select>
|
|
105
|
+
</label>
|
|
106
|
+
<label className="space-y-1 text-xs">
|
|
107
|
+
Value (JSON)
|
|
108
|
+
<Input
|
|
109
|
+
onChange={(e) => {
|
|
110
|
+
const raw = e.target.value;
|
|
111
|
+
setDraftValue(raw);
|
|
112
|
+
setDraftLeaf(leaf);
|
|
113
|
+
const property = ["in", "nin", "all"].includes(String(leaf?.op))
|
|
114
|
+
? "values"
|
|
115
|
+
: "value";
|
|
116
|
+
// Preserve malformed JSON verbatim for correction; never drop the filter.
|
|
117
|
+
onChange(
|
|
118
|
+
`{"op":${JSON.stringify(leaf?.op)},"key":${JSON.stringify(leaf?.key ?? "")},"${property}":${raw}}`
|
|
119
|
+
);
|
|
120
|
+
}}
|
|
121
|
+
value={
|
|
122
|
+
draftValue ??
|
|
123
|
+
JSON.stringify("values" in leaf ? leaf.values : leaf.value) ??
|
|
124
|
+
""
|
|
125
|
+
}
|
|
126
|
+
/>
|
|
127
|
+
</label>
|
|
128
|
+
</div>
|
|
129
|
+
) : !value.trim() ? (
|
|
130
|
+
<Button
|
|
131
|
+
onClick={() => {
|
|
132
|
+
setDraftValue(null);
|
|
133
|
+
setDraftLeaf(null);
|
|
134
|
+
onChange(
|
|
135
|
+
JSON.stringify({ op: "eq", key: "status", value: "approved" })
|
|
136
|
+
);
|
|
137
|
+
}}
|
|
138
|
+
size="sm"
|
|
139
|
+
type="button"
|
|
140
|
+
variant="outline"
|
|
141
|
+
>
|
|
142
|
+
Add metadata filter
|
|
143
|
+
</Button>
|
|
144
|
+
) : null}
|
|
145
|
+
<label className="block space-y-1 text-xs" htmlFor={`${id}-json`}>
|
|
146
|
+
Advanced filter (JSON)
|
|
147
|
+
<Textarea
|
|
148
|
+
aria-describedby={error ? `${id}-error` : undefined}
|
|
149
|
+
aria-invalid={Boolean(error)}
|
|
150
|
+
className="min-h-20 font-mono text-xs"
|
|
151
|
+
id={`${id}-json`}
|
|
152
|
+
onChange={(e) => {
|
|
153
|
+
setDraftValue(null);
|
|
154
|
+
setDraftLeaf(null);
|
|
155
|
+
onChange(e.target.value);
|
|
156
|
+
}}
|
|
157
|
+
placeholder='{"op":"gte","key":"confidence","value":0.8}'
|
|
158
|
+
value={value}
|
|
159
|
+
/>
|
|
160
|
+
</label>
|
|
161
|
+
{error && (
|
|
162
|
+
<p
|
|
163
|
+
className="break-words text-destructive text-xs"
|
|
164
|
+
id={`${id}-error`}
|
|
165
|
+
role="alert"
|
|
166
|
+
>
|
|
167
|
+
{error}
|
|
168
|
+
</p>
|
|
169
|
+
)}
|
|
170
|
+
{value && (
|
|
171
|
+
<Button
|
|
172
|
+
onClick={() => {
|
|
173
|
+
setDraftValue(null);
|
|
174
|
+
setDraftLeaf(null);
|
|
175
|
+
onChange("");
|
|
176
|
+
}}
|
|
177
|
+
size="sm"
|
|
178
|
+
type="button"
|
|
179
|
+
variant="ghost"
|
|
180
|
+
>
|
|
181
|
+
Clear metadata filter
|
|
182
|
+
</Button>
|
|
183
|
+
)}
|
|
184
|
+
</fieldset>
|
|
185
|
+
);
|
|
186
|
+
}
|