@gmickel/gno 2.7.1 → 2.8.1

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 (96) hide show
  1. package/README.md +3 -2
  2. package/assets/skill/SKILL.md +11 -1
  3. package/assets/skill/cli-reference.md +8 -1
  4. package/assets/skill/examples.md +2 -1
  5. package/assets/skill/mcp-reference.md +3 -1
  6. package/assets/skill/recipes/memory-scoped-recall.md +10 -5
  7. package/assets/spa-production.json.gz +0 -0
  8. package/browser-extension/artifacts/{gno-browser-clipper-v2.7.1.zip → gno-browser-clipper-v2.8.1.zip} +0 -0
  9. package/browser-extension/artifacts/gno-browser-clipper-v2.8.1.zip.sha256 +1 -0
  10. package/browser-extension/dist/manifest.json +1 -1
  11. package/package.json +1 -1
  12. package/spec/cli.md +86 -9
  13. package/spec/db/schema.sql +0 -1
  14. package/spec/mcp.md +26 -7
  15. package/spec/output-schemas/audit-report.schema.json +18 -4
  16. package/spec/output-schemas/backlinks.schema.json +4 -0
  17. package/spec/output-schemas/collection-list.schema.json +13 -0
  18. package/spec/output-schemas/graph.schema.json +2 -0
  19. package/spec/output-schemas/links-list.schema.json +4 -0
  20. package/spec/output-schemas/memory-recall.schema.json +1 -1
  21. package/spec/output-schemas/status.schema.json +18 -3
  22. package/src/cli/commands/audit.ts +23 -4
  23. package/src/cli/commands/collection/list.ts +39 -5
  24. package/src/cli/commands/embed.ts +3 -3
  25. package/src/cli/commands/graph.ts +3 -1
  26. package/src/cli/commands/links.ts +61 -180
  27. package/src/cli/commands/shared.ts +7 -0
  28. package/src/cli/commands/status.ts +6 -0
  29. package/src/cli/program.ts +12 -2
  30. package/src/config/loader.ts +43 -0
  31. package/src/config/types.ts +8 -0
  32. package/src/core/audit-contract.ts +16 -4
  33. package/src/core/audit-freshness.ts +11 -1
  34. package/src/core/audit-links.ts +197 -25
  35. package/src/core/audit-outside-index.ts +215 -0
  36. package/src/core/audit-provenance.ts +11 -4
  37. package/src/core/audit-workspace.ts +30 -9
  38. package/src/core/audit.ts +76 -16
  39. package/src/core/context-compiler.ts +3 -0
  40. package/src/core/context-evidence.ts +11 -0
  41. package/src/core/graph-edge-confidence.ts +23 -1
  42. package/src/core/host-paths.ts +1 -0
  43. package/src/core/knowledge-impact.ts +28 -0
  44. package/src/core/link-inventory-markdown.ts +2 -3
  45. package/src/core/link-workspace.ts +324 -0
  46. package/src/core/links.ts +40 -17
  47. package/src/core/memory-recall.ts +254 -15
  48. package/src/core/memory-types.ts +12 -0
  49. package/src/core/memory.ts +2 -0
  50. package/src/core/retrieval-replay-candidate.ts +6 -0
  51. package/src/core/retrieval-trace-request.ts +3 -0
  52. package/src/index.ts +14 -1
  53. package/src/ingestion/graph-reconciliation.ts +77 -15
  54. package/src/ingestion/source-availability/darwin-path.ts +9 -3
  55. package/src/ingestion/sync.ts +27 -4
  56. package/src/ingestion/types.ts +14 -0
  57. package/src/llm/inference-scope.ts +4 -3
  58. package/src/mcp/http-egress.ts +42 -3
  59. package/src/mcp/tools/audit.ts +11 -2
  60. package/src/mcp/tools/changes.ts +1 -0
  61. package/src/mcp/tools/links.ts +74 -93
  62. package/src/mcp/tools/sessions.ts +33 -4
  63. package/src/mcp/tools/status.ts +4 -0
  64. package/src/pipeline/expansion.ts +19 -31
  65. package/src/pipeline/graph-retrieval.ts +22 -2
  66. package/src/pipeline/hybrid.ts +1 -1
  67. package/src/pipeline/search.ts +2 -0
  68. package/src/pipeline/types.ts +10 -3
  69. package/src/sdk/client.ts +1 -0
  70. package/src/serve/findings-pass.ts +1 -1
  71. package/src/serve/public/components/editor/MarkdownPreview.tsx +5 -3
  72. package/src/serve/public/pages/GraphView.tsx +2 -0
  73. package/src/serve/routes/changes.ts +6 -1
  74. package/src/serve/routes/graph.ts +3 -1
  75. package/src/serve/routes/links.ts +45 -50
  76. package/src/serve/routes/sessions.ts +41 -53
  77. package/src/serve/server.ts +2 -1
  78. package/src/serve/status.ts +1 -0
  79. package/src/sessions/config-refresh.ts +111 -0
  80. package/src/store/migrations/033-drop-documents-active-index.ts +30 -0
  81. package/src/store/migrations/034-collection-link-workspace.ts +47 -0
  82. package/src/store/migrations/index.ts +4 -0
  83. package/src/store/sqlite/adapter.ts +477 -337
  84. package/src/store/sqlite/eligibility.ts +8 -2
  85. package/src/store/sqlite/graph-link-resolver.ts +259 -5
  86. package/src/store/sqlite/graph-neighbors.ts +147 -40
  87. package/src/store/sqlite/graph-reference-state.ts +13 -2
  88. package/src/store/sqlite/graph-similarity.ts +96 -0
  89. package/src/store/sqlite/workspace-link-resolver.ts +742 -0
  90. package/src/store/types.ts +64 -5
  91. package/src/store/vector/stats.ts +1 -1
  92. package/src/store/vector/status.ts +27 -0
  93. package/src/store/vector/stored-vectors.ts +158 -0
  94. package/src/store/vector/types.ts +6 -0
  95. package/src/store/vector/variant-search.ts +30 -14
  96. package/browser-extension/artifacts/gno-browser-clipper-v2.7.1.zip.sha256 +0 -1
@@ -20,6 +20,7 @@ import type {
20
20
  FileRefactorRecoveryReceipt,
21
21
  FileRefactorRecoveryReceiptDraft,
22
22
  } from "../core/file-refactor-journal";
23
+ import type { LinkWorkspaceSource } from "../core/link-workspace";
23
24
  import type { MetadataPredicate, TypedMetadata } from "../core/typed-metadata";
24
25
  import type {
25
26
  ChunkingPolicyToken,
@@ -113,6 +114,14 @@ export interface CollectionRow {
113
114
  egressPolicy: EgressPolicy;
114
115
  /** Whether policy was explicit or supplied by a safe default. */
115
116
  egressPolicySource: EgressPolicySource;
117
+ /** Canonical collection root (real path), when resolvable. */
118
+ realPath?: string | null;
119
+ /** Effective link workspace root; null means collection-scoped links. */
120
+ workspaceRoot?: string | null;
121
+ /** How the workspace root was established. */
122
+ workspaceSource?: LinkWorkspaceSource;
123
+ /** Collection-relative prefixes of nested vaults with their own workspace. */
124
+ workspaceNested?: string[];
116
125
  syncedAt: string;
117
126
  }
118
127
 
@@ -351,6 +360,8 @@ export interface BacklinkRow {
351
360
  sourceDocUri: string;
352
361
  /** Source document title */
353
362
  sourceDocTitle: string | null;
363
+ /** Collection of the source document */
364
+ sourceCollection?: string;
354
365
  /** Link display text */
355
366
  linkText: string | null;
356
367
  /** 1-based line number in source */
@@ -731,6 +742,11 @@ export interface FtsSearchOptions extends DocumentEligibilityOptions {
731
742
  snippet?: boolean;
732
743
  /** Match documents containing ANY positive term instead of ALL of them. */
733
744
  anyTerm?: boolean;
745
+ /**
746
+ * Drop rows whose raw BM25 score is below this fraction (0-1) of the best
747
+ * row's score, so matches carried only by near-zero-IDF terms fall away.
748
+ */
749
+ minRelativeScore?: number;
734
750
  }
735
751
 
736
752
  /** Managed-memory eligibility query (unbounded, executed in one SQL query). */
@@ -793,6 +809,10 @@ export interface CollectionStatus {
793
809
  egressPolicy: EgressPolicy;
794
810
  /** Whether policy was explicit or supplied by a safe default. */
795
811
  egressPolicySource: EgressPolicySource;
812
+ /** Effective link workspace root (host path); null when collection-scoped. */
813
+ workspaceRoot?: string | null;
814
+ /** How the link workspace was established. */
815
+ workspaceSource?: LinkWorkspaceSource;
796
816
  totalDocuments: number;
797
817
  activeDocuments: number;
798
818
  errorDocuments: number;
@@ -818,11 +838,11 @@ export interface IndexStatus {
818
838
  ftsTokenizer: FtsTokenizer;
819
839
  /** Per-collection status */
820
840
  collections: CollectionStatus[];
821
- /** Total documents across all collections */
841
+ /** Total documents across the reported collections */
822
842
  totalDocuments: number;
823
843
  /** Active (non-deleted) documents */
824
844
  activeDocuments: number;
825
- /** Total chunks across all collections */
845
+ /** Distinct chunks of active documents across the reported collections */
826
846
  totalChunks: number;
827
847
  /** Chunks without embeddings */
828
848
  embeddingBacklog: number;
@@ -876,6 +896,10 @@ export interface GraphEdgeAudit {
876
896
  resolution:
877
897
  | "exact-title"
878
898
  | "exact-path"
899
+ /** Only file with that name (or path suffix) in its link workspace. */
900
+ | "exact-name"
901
+ /** Won over same-named files by the same-folder / shallower tie-break. */
902
+ | "tie-break"
879
903
  | "path-fallback"
880
904
  | "ambiguous-fallback"
881
905
  | "similarity";
@@ -1058,6 +1082,8 @@ export interface GetGraphOptions {
1058
1082
  linkedOnly?: boolean;
1059
1083
  /** Top-K similar docs per node (default 5, clamped 1-20) */
1060
1084
  similarTopK?: number;
1085
+ /** Embedding model whose stored vectors score similarity edges */
1086
+ embedModel?: string;
1061
1087
  }
1062
1088
 
1063
1089
  /** Options for seed-scoped one-hop graph neighbor lookup (query-time expansion). */
@@ -1066,6 +1092,12 @@ export interface GetGraphNeighborsOptions {
1066
1092
  seedDocumentIds: number[];
1067
1093
  /** Filter neighbors to a single collection */
1068
1094
  collection?: string;
1095
+ /**
1096
+ * Graph allowlist: every edge's resolved source and target must be in one
1097
+ * of these collections. Takes precedence over `collection`; empty denies
1098
+ * all. Undefined (with no `collection`) is unrestricted.
1099
+ */
1100
+ collections?: string[];
1069
1101
  /** Max edges to return (default 10000) */
1070
1102
  limitEdges?: number;
1071
1103
  }
@@ -1113,6 +1145,11 @@ export interface GraphQueryEdge {
1113
1145
  export interface GraphQueryOptions {
1114
1146
  direction?: GraphQueryDirection;
1115
1147
  edgeType?: DocEdgeType;
1148
+ /**
1149
+ * Collection allowlist: only documents in these collections are visited
1150
+ * (the root must be in scope too). Undefined means every collection.
1151
+ */
1152
+ collections?: string[];
1116
1153
  maxDepth?: number;
1117
1154
  maxNodes?: number;
1118
1155
  frontierLimit?: number;
@@ -1599,6 +1636,14 @@ export interface StorePort {
1599
1636
  */
1600
1637
  getCollections(): Promise<StoreResult<CollectionRow[]>>;
1601
1638
 
1639
+ /**
1640
+ * Re-detect nested vaults below a collection root from its indexed
1641
+ * document directories; returns whether stored membership changed.
1642
+ */
1643
+ refreshCollectionNestedWorkspaces?(
1644
+ collection: string
1645
+ ): Promise<StoreResult<boolean>>;
1646
+
1602
1647
  /**
1603
1648
  * Get all contexts from DB.
1604
1649
  */
@@ -2242,18 +2287,26 @@ export interface StorePort {
2242
2287
  ): Promise<StoreResult<BacklinkRow[]>>;
2243
2288
 
2244
2289
  /**
2245
- * Resolve link targets to their documents.
2246
- * Returns array of resolved docs (or null for unresolved) matching input order.
2290
+ * Resolve link targets to their documents with the shared link resolver.
2291
+ * With `source`, plain wiki links from a document inside a link workspace
2292
+ * resolve across the workspace. Returns resolved docs (or null for
2293
+ * unresolved and tied links) matching input order.
2247
2294
  */
2248
2295
  resolveLinks(
2249
2296
  targets: Array<{
2250
2297
  targetRefNorm: string;
2251
2298
  targetCollection: string;
2252
2299
  linkType: "wiki" | "markdown";
2300
+ source?: { collection: string; relPath: string; explicit: boolean };
2253
2301
  }>
2254
2302
  ): Promise<
2255
2303
  StoreResult<
2256
- Array<{ docid: string; uri: string; title: string | null } | null>
2304
+ Array<{
2305
+ docid: string;
2306
+ uri: string;
2307
+ title: string | null;
2308
+ collection?: string;
2309
+ } | null>
2257
2310
  >
2258
2311
  >;
2259
2312
 
@@ -2340,6 +2393,12 @@ export interface StorePort {
2340
2393
  embedModel?: string;
2341
2394
  embedFingerprint?: string;
2342
2395
  chunking?: Partial<ChunkingParams>;
2396
+ /**
2397
+ * Configured collection names. When given, the collection list and the
2398
+ * document/chunk totals cover only these collections, so a collection
2399
+ * removed from config stops being reported before its rows are pruned.
2400
+ */
2401
+ configuredCollections?: readonly string[];
2343
2402
  }): Promise<StoreResult<IndexStatus>>;
2344
2403
 
2345
2404
  // ─────────────────────────────────────────────────────────────────────────
@@ -34,7 +34,7 @@ export function createVectorStatsPort(db: Database): VectorStatsPort {
34
34
  return {
35
35
  sql: `
36
36
  EXISTS (
37
- SELECT 1 FROM documents d
37
+ SELECT 1 FROM documents d INDEXED BY idx_documents_mirror_hash
38
38
  WHERE d.mirror_hash = c.mirror_hash AND d.active = 1 AND d.collection = ?
39
39
  )
40
40
  `,
@@ -148,6 +148,33 @@ function retrievalPartition(
148
148
  : candidates.find((p) => p.partition_id === selection);
149
149
  }
150
150
 
151
+ /**
152
+ * The activated partition that stored-vector readers (document similarity)
153
+ * use for `model`, chosen as status counts it. Undefined leaves legacy
154
+ * `content_vectors` authority, exactly as vector search does before any
155
+ * partition activates.
156
+ */
157
+ export function storedVectorPartition(
158
+ db: Database,
159
+ model: string
160
+ ): { partitionId: string; dimensions: number } | undefined {
161
+ return db.transaction(() => {
162
+ if (!hasPartitionTable(db)) return undefined;
163
+ const partition = countedPartition(
164
+ db,
165
+ model,
166
+ readPartitions(db, model),
167
+ readSelections(db).get(model)
168
+ );
169
+ return partition && activated(partition)
170
+ ? {
171
+ partitionId: partition.partition_id,
172
+ dimensions: partition.dimensions,
173
+ }
174
+ : undefined;
175
+ })();
176
+ }
177
+
151
178
  function readPartitions(db: Database, model: string | null): Partition[] {
152
179
  return db
153
180
  .query<Partition, [string | null, string | null]>(`
@@ -0,0 +1,158 @@
1
+ /**
2
+ * Stored document vectors for document-to-document similarity. Reads the
3
+ * activated vector partition (legacy `content_vectors` only before any
4
+ * partition activates) and never loads an embedding model.
5
+ *
6
+ * @module src/store/vector/stored-vectors
7
+ */
8
+ import type { Database } from "bun:sqlite";
9
+
10
+ import type { VectorSearchResult } from "./types";
11
+
12
+ import { formatDocForEmbedding } from "../../pipeline/contextual";
13
+ import { decodeEmbedding } from "./sqlite-vec";
14
+ import { storedVectorPartition } from "./status";
15
+ import { embeddingInputHash } from "./variants";
16
+
17
+ export type StoredVectorSource =
18
+ | {
19
+ kind: "partition";
20
+ model: string;
21
+ partitionId: string;
22
+ dimensions: number;
23
+ }
24
+ | { kind: "legacy"; model: string };
25
+
26
+ export function resolveStoredVectorSource(
27
+ db: Database,
28
+ model: string
29
+ ): StoredVectorSource {
30
+ const partition = storedVectorPartition(db, model);
31
+ return partition
32
+ ? { kind: "partition", model, ...partition }
33
+ : { kind: "legacy", model };
34
+ }
35
+
36
+ /** Search options that keep a similarity search in the source's vector space. */
37
+ export function storedVectorSearchOptions(source: StoredVectorSource): {
38
+ partitionId?: string;
39
+ } {
40
+ return source.kind === "partition" ? { partitionId: source.partitionId } : {};
41
+ }
42
+
43
+ export interface StoredVectorDocument {
44
+ id: number;
45
+ mirrorHash: string;
46
+ }
47
+
48
+ interface PartitionVectorRow {
49
+ documentId: number;
50
+ text: string;
51
+ title: string | null;
52
+ inputHash: string;
53
+ embedding: Uint8Array;
54
+ }
55
+
56
+ /**
57
+ * Chunk vectors of current active documents, ordered by chunk seq, keyed by
58
+ * document id. Partition vectors count only while their owner still yields
59
+ * the stored input (the rule vector search applies). `firstChunkOnly` keeps
60
+ * the lowest-seq vector per document.
61
+ */
62
+ export function readStoredDocumentVectors(
63
+ db: Database,
64
+ source: StoredVectorSource,
65
+ documents: StoredVectorDocument[],
66
+ options: { firstChunkOnly?: boolean } = {}
67
+ ): Map<number, Float32Array[]> {
68
+ const vectors = new Map<number, Float32Array[]>();
69
+ const add = (documentId: number, blob: Uint8Array): void => {
70
+ const existing = vectors.get(documentId);
71
+ if (existing && options.firstChunkOnly) return;
72
+ const embedding = decodeEmbedding(blob);
73
+ if (existing) existing.push(embedding);
74
+ else vectors.set(documentId, [embedding]);
75
+ };
76
+ if (documents.length === 0) return vectors;
77
+
78
+ if (source.kind === "partition") {
79
+ const rows = db
80
+ .query<PartitionVectorRow, [string, string]>(`
81
+ SELECT o.document_id AS documentId, c.text, d.title,
82
+ v.input_hash AS inputHash, v.embedding
83
+ FROM vector_owners o
84
+ JOIN documents d ON d.id = o.document_id AND d.active = 1
85
+ AND d.mirror_hash = o.mirror_hash
86
+ JOIN content_chunks c ON c.mirror_hash = o.mirror_hash AND c.seq = o.seq
87
+ JOIN vector_variants v ON v.variant_id = o.variant_id
88
+ AND v.partition_id = o.partition_id
89
+ WHERE o.partition_id = ?
90
+ AND o.document_id IN (SELECT value FROM json_each(?))
91
+ ORDER BY o.document_id, o.seq
92
+ `)
93
+ .all(
94
+ source.partitionId,
95
+ JSON.stringify(documents.map((document) => document.id))
96
+ );
97
+ for (const row of rows) {
98
+ if (options.firstChunkOnly && vectors.has(row.documentId)) continue;
99
+ const input = formatDocForEmbedding(
100
+ row.text,
101
+ row.title ?? undefined,
102
+ source.model
103
+ );
104
+ if (row.inputHash === embeddingInputHash(input))
105
+ add(row.documentId, row.embedding);
106
+ }
107
+ return vectors;
108
+ }
109
+
110
+ const idsByMirror = new Map<string, number[]>();
111
+ for (const document of documents) {
112
+ const ids = idsByMirror.get(document.mirrorHash);
113
+ if (ids) ids.push(document.id);
114
+ else idsByMirror.set(document.mirrorHash, [document.id]);
115
+ }
116
+ const rows = db
117
+ .query<{ mirrorHash: string; embedding: Uint8Array }, [string, string]>(`
118
+ SELECT mirror_hash AS mirrorHash, embedding FROM content_vectors
119
+ WHERE model = ? AND mirror_hash IN (SELECT value FROM json_each(?))
120
+ ORDER BY mirror_hash, seq
121
+ `)
122
+ .all(source.model, JSON.stringify([...idsByMirror.keys()]));
123
+ for (const row of rows) {
124
+ for (const id of idsByMirror.get(row.mirrorHash) ?? [])
125
+ add(id, row.embedding);
126
+ }
127
+ return vectors;
128
+ }
129
+
130
+ /**
131
+ * Candidate documents of similarity search hits, in hit order. Partition hits
132
+ * name their exact owners (a title is part of the embedded input, so documents
133
+ * sharing content can hold different vectors); only those owners count, and
134
+ * an owner without its own vector never inherits another's score. Legacy
135
+ * `content_vectors` hits carry no owners and map to the first document with
136
+ * that content, as before.
137
+ */
138
+ export function similarityHitDocuments<
139
+ T extends { id: number; mirrorHash: string | null },
140
+ >(
141
+ hits: VectorSearchResult[],
142
+ documents: T[]
143
+ ): Array<{ document: T; distance: number }> {
144
+ const byId = new Map(documents.map((document) => [document.id, document]));
145
+ const byHash = new Map<string, T>();
146
+ for (const document of documents) {
147
+ if (document.mirrorHash && !byHash.has(document.mirrorHash))
148
+ byHash.set(document.mirrorHash, document);
149
+ }
150
+ return hits.flatMap((hit) => {
151
+ const owners = hit.documentIds
152
+ ? hit.documentIds.map((id) => byId.get(id))
153
+ : [byHash.get(hit.mirrorHash)];
154
+ return owners.flatMap((document) =>
155
+ document ? [{ document, distance: hit.distance }] : []
156
+ );
157
+ });
158
+ }
@@ -43,6 +43,12 @@ export interface VectorRow {
43
43
 
44
44
  export interface VectorSearchOptions {
45
45
  embeddingIdentity?: VectorVariantIdentity;
46
+ /**
47
+ * Search this activated stored partition directly. Document-to-document
48
+ * similarity reuses a stored vector, so no runtime identity applies; the
49
+ * partition must match the port's model and dimensions.
50
+ */
51
+ partitionId?: string;
46
52
  minScore?: number;
47
53
  allowedMirrorHashes?: string[];
48
54
  /** Exact active owner/chunk domain, applied before the nearest-neighbor budget. */
@@ -103,27 +103,43 @@ function searchVectorVariantsInSnapshot(
103
103
  )
104
104
  .get(model);
105
105
  const identity = options.embeddingIdentity;
106
- if (!identity) {
107
- if (activated)
108
- throw new Error(
109
- "Effective embedding identity unavailable after variant activation"
110
- );
111
- return null;
106
+ let partitionId: string;
107
+ if (options.partitionId !== undefined) {
108
+ const stored = db
109
+ .query<{ model: string; dimensions: number }, [string]>(
110
+ "SELECT model, dimensions FROM vector_partitions WHERE partition_id = ?"
111
+ )
112
+ .get(options.partitionId);
113
+ if (
114
+ stored?.model !== model ||
115
+ stored.dimensions !== dimensions ||
116
+ embedding.length !== dimensions
117
+ )
118
+ throw new Error("Stored vector partition does not match vector index");
119
+ partitionId = options.partitionId;
120
+ } else {
121
+ if (!identity) {
122
+ if (activated)
123
+ throw new Error(
124
+ "Effective embedding identity unavailable after variant activation"
125
+ );
126
+ return null;
127
+ }
128
+ if (
129
+ identity.model !== model ||
130
+ identity.dimensions !== dimensions ||
131
+ embedding.length !== dimensions
132
+ )
133
+ throw new Error("Query embedding identity does not match vector index");
134
+ partitionId = identityPartitionId(identity);
112
135
  }
113
- if (
114
- identity.model !== model ||
115
- identity.dimensions !== dimensions ||
116
- embedding.length !== dimensions
117
- )
118
- throw new Error("Query embedding identity does not match vector index");
119
- const partitionId = identityPartitionId(identity);
120
136
  const partition = db
121
137
  .query<{ state: string; activated_epoch: number | null }, [string]>(
122
138
  "SELECT state, activated_epoch FROM vector_partitions WHERE partition_id = ?"
123
139
  )
124
140
  .get(partitionId);
125
141
  if (partition?.state !== "active" || partition.activated_epoch === null) {
126
- if (activated)
142
+ if (activated || options.partitionId !== undefined)
127
143
  throw new Error(
128
144
  "Selected embedding variant partition has not activated; run gno embed"
129
145
  );
@@ -1 +0,0 @@
1
- 0566f9eb5eb5db6a1632063e63f37dab01a9d2a0aa3dde5658356926a53c395e gno-browser-clipper-v2.7.1.zip