@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.
Files changed (88) hide show
  1. package/README.md +24 -4
  2. package/assets/skill/SKILL.md +30 -0
  3. package/assets/skill/cli-reference.md +12 -0
  4. package/assets/skill/examples.md +15 -0
  5. package/assets/skill/mcp-reference.md +16 -0
  6. package/assets/spa-production.json.gz +0 -0
  7. package/browser-extension/artifacts/{gno-browser-clipper-v2.3.2.zip → gno-browser-clipper-v2.4.0.zip} +0 -0
  8. package/browser-extension/artifacts/gno-browser-clipper-v2.4.0.zip.sha256 +1 -0
  9. package/browser-extension/dist/manifest.json +1 -1
  10. package/package.json +1 -1
  11. package/spec/cli.md +30 -0
  12. package/spec/db/schema.sql +2 -0
  13. package/spec/evals.md +48 -0
  14. package/spec/mcp.md +12 -0
  15. package/spec/output-schemas/ask.schema.json +12 -0
  16. package/spec/output-schemas/context-capsule-v1.schema.json +205 -32
  17. package/spec/output-schemas/context-capsule-verification.schema.json +32 -9
  18. package/spec/output-schemas/evidence-fixtures.schema.json +176 -0
  19. package/spec/output-schemas/evidence-report.schema.json +322 -0
  20. package/spec/output-schemas/evidence-run.schema.json +277 -0
  21. package/spec/output-schemas/metadata-predicate.schema.json +460 -0
  22. package/spec/output-schemas/retrieval-trace-filters.schema.json +13 -4
  23. package/spec/output-schemas/search-results.schema.json +12 -0
  24. package/spec/output-schemas/status.schema.json +37 -6
  25. package/src/app/context-runtime-contract.ts +33 -2
  26. package/src/app/context-runtime-input.ts +17 -0
  27. package/src/app/context-runtime-types.ts +2 -0
  28. package/src/app/context-runtime.ts +27 -3
  29. package/src/app/context-surface.ts +2 -0
  30. package/src/app/verified-ask.ts +1 -0
  31. package/src/cli/commands/ask.ts +1 -0
  32. package/src/cli/commands/context-build.ts +1 -0
  33. package/src/cli/commands/search.ts +1 -0
  34. package/src/cli/commands/status.ts +10 -0
  35. package/src/cli/options.ts +19 -0
  36. package/src/cli/program.ts +12 -0
  37. package/src/converters/types.ts +2 -0
  38. package/src/core/context-capsule-retrieval-schema.ts +8 -0
  39. package/src/core/context-capsule-schema.ts +47 -3
  40. package/src/core/context-capsule-validation.ts +14 -2
  41. package/src/core/context-capsule-verification.ts +1 -0
  42. package/src/core/context-capsule.ts +16 -2
  43. package/src/core/context-compiler.ts +3 -0
  44. package/src/core/record-metadata.ts +1 -1
  45. package/src/core/retrieval-replay-candidate.ts +5 -0
  46. package/src/core/retrieval-trace-filter-normalization.ts +4 -0
  47. package/src/core/retrieval-trace-request.ts +1 -0
  48. package/src/core/retrieval-trace-session.ts +5 -1
  49. package/src/core/retrieval-trace.ts +2 -0
  50. package/src/core/typed-metadata.ts +224 -0
  51. package/src/ingestion/record-adapter-canonical.ts +13 -2
  52. package/src/ingestion/record-container.ts +9 -0
  53. package/src/ingestion/sync.ts +11 -1
  54. package/src/ingestion/typed-metadata.ts +55 -0
  55. package/src/mcp/tools/ask.ts +10 -2
  56. package/src/mcp/tools/context.ts +1 -0
  57. package/src/mcp/tools/index.ts +12 -1
  58. package/src/mcp/tools/query.ts +13 -0
  59. package/src/mcp/tools/search.ts +9 -0
  60. package/src/mcp/tools/status.ts +4 -0
  61. package/src/mcp/tools/vsearch.ts +9 -0
  62. package/src/pipeline/diagnose.ts +6 -0
  63. package/src/pipeline/filters.ts +65 -0
  64. package/src/pipeline/graph-retrieval.ts +9 -1
  65. package/src/pipeline/hybrid.ts +22 -2
  66. package/src/pipeline/search.ts +11 -0
  67. package/src/pipeline/types.ts +7 -1
  68. package/src/pipeline/vsearch.ts +21 -1
  69. package/src/sdk/client.ts +29 -1
  70. package/src/sdk/index.ts +4 -0
  71. package/src/sdk/types.ts +7 -0
  72. package/src/serve/context-capsule.ts +1 -0
  73. package/src/serve/public/app.tsx +1 -1
  74. package/src/serve/public/components/MetadataFilter.tsx +186 -0
  75. package/src/serve/public/globals.built.css +1 -1
  76. package/src/serve/public/lib/metadata-filter.ts +28 -0
  77. package/src/serve/public/lib/retrieval-filters.ts +3 -0
  78. package/src/serve/public/pages/Ask.tsx +48 -3
  79. package/src/serve/public/pages/DocView.tsx +33 -0
  80. package/src/serve/public/pages/Search.tsx +44 -1
  81. package/src/serve/routes/api.ts +50 -0
  82. package/src/store/migrations/030-typed-metadata.ts +13 -0
  83. package/src/store/migrations/index.ts +2 -0
  84. package/src/store/sqlite/adapter.ts +55 -4
  85. package/src/store/sqlite/eligibility.ts +12 -0
  86. package/src/store/sqlite/metadata-predicate.ts +71 -0
  87. package/src/store/types.ts +11 -0
  88. 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
+ }