@tangle-network/agent-knowledge 0.1.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 ADDED
@@ -0,0 +1,57 @@
1
+ # agent-knowledge
2
+
3
+ Source-grounded, eval-gated knowledge growth primitives for agents.
4
+
5
+ This package turns raw sources and generated markdown knowledge into a versionable graph that agents can search, lint, evaluate, and improve over time. It is intentionally domain-agnostic: legal, tax, coding, research, finance, business, and scientific workflows define their own policies and rubrics on top.
6
+
7
+ ## Install
8
+
9
+ ```bash
10
+ pnpm add @tangle-network/agent-knowledge @tangle-network/agent-eval
11
+ ```
12
+
13
+ ## CLI
14
+
15
+ ```bash
16
+ agent-knowledge init --root .
17
+ agent-knowledge source-add ./docs/spec.md --root .
18
+ agent-knowledge sources --root .
19
+ agent-knowledge apply-write-blocks ./proposal.txt --root .
20
+ agent-knowledge index --root .
21
+ agent-knowledge search "portfolio risk" --root .
22
+ agent-knowledge inspect --root .
23
+ agent-knowledge explain knowledge/concepts/risk.md --root .
24
+ agent-knowledge graph --root . --format json
25
+ agent-knowledge lint --root .
26
+ agent-knowledge viz --root .
27
+ ```
28
+
29
+ The default layout is:
30
+
31
+ ```txt
32
+ raw/
33
+ sources/
34
+ knowledge/
35
+ index.md
36
+ log.md
37
+ .agent-knowledge/
38
+ sources.json
39
+ index.json
40
+ ```
41
+
42
+ ## Design
43
+
44
+ - Raw sources are immutable evidence.
45
+ - Generated knowledge is editable but validated.
46
+ - Claims should cite source records when promoted.
47
+ - Lint fails on pages that cite unknown source IDs.
48
+ - Text sources get deterministic anchors (`all`, `l1`, `l51`, ...) for precise citations like `[^src_id#all]`.
49
+ - Agent write proposals can be safely applied with `apply-write-blocks`.
50
+ - Graph/search/lint are deterministic and fast.
51
+ - Optimization uses `@tangle-network/agent-eval` internally instead of reimplementing eval gates.
52
+
53
+ The `/viz` subpath exports graph insight helpers without UI dependencies.
54
+
55
+ ## Agent-Eval Integration
56
+
57
+ Use `runKnowledgeBaseOptimization()` when the question is whether a candidate knowledge base actually improves agent task success. The candidate is passed through `runMultiShotOptimization`, so `n=1` single-turn tasks and variable-length multi-turn traces use the same path.
@@ -0,0 +1,147 @@
1
+ // src/viz/index.ts
2
+ function toKnowledgeVizGraph(graph) {
3
+ const adjacency = buildAdjacency(graph);
4
+ const communities = assignCommunities(graph.nodes, adjacency);
5
+ const communityByNode = /* @__PURE__ */ new Map();
6
+ communities.forEach((community) => {
7
+ for (const nodeId of community.nodeIds) communityByNode.set(hashNode(nodeId), community.id);
8
+ });
9
+ const nodes = graph.nodes.map((node) => ({
10
+ ...node,
11
+ degree: node.inDegree + node.outDegree,
12
+ community: communityByNode.get(hashNode(node.id)) ?? 0
13
+ }));
14
+ return {
15
+ nodes,
16
+ edges: graph.edges.map((edge) => ({ ...edge, id: `${edge.source}->${edge.target}` })),
17
+ communities
18
+ };
19
+ }
20
+ function detectKnowledgeGaps(graph, limit = 10) {
21
+ const gaps = [];
22
+ const isolated = graph.nodes.filter((node) => node.degree <= 1 && !isStructural(node.path));
23
+ if (isolated.length > 0) {
24
+ gaps.push({
25
+ type: "isolated-node",
26
+ title: `${isolated.length} isolated page${isolated.length === 1 ? "" : "s"}`,
27
+ nodeIds: isolated.map((node) => node.id),
28
+ suggestion: "Add cross-links, sources, or follow-up research to connect these pages to the knowledge graph."
29
+ });
30
+ }
31
+ for (const community of graph.communities) {
32
+ if (community.nodeIds.length >= 3 && community.cohesion < 0.15) {
33
+ gaps.push({
34
+ type: "sparse-community",
35
+ title: `Sparse cluster: ${community.topTitles[0] ?? `community ${community.id}`}`,
36
+ nodeIds: community.nodeIds,
37
+ suggestion: "This cluster has weak internal evidence. Add synthesis pages or relation links between its strongest concepts."
38
+ });
39
+ }
40
+ }
41
+ const byCommunityNeighbors = /* @__PURE__ */ new Map();
42
+ const nodeById = new Map(graph.nodes.map((node) => [node.id, node]));
43
+ for (const edge of graph.edges) {
44
+ const source = nodeById.get(edge.source);
45
+ const target = nodeById.get(edge.target);
46
+ if (!source || !target) continue;
47
+ if (!byCommunityNeighbors.has(source.id)) byCommunityNeighbors.set(source.id, /* @__PURE__ */ new Set());
48
+ if (!byCommunityNeighbors.has(target.id)) byCommunityNeighbors.set(target.id, /* @__PURE__ */ new Set());
49
+ byCommunityNeighbors.get(source.id).add(target.community);
50
+ byCommunityNeighbors.get(target.id).add(source.community);
51
+ }
52
+ for (const node of graph.nodes) {
53
+ if ((byCommunityNeighbors.get(node.id)?.size ?? 0) >= 3) {
54
+ gaps.push({
55
+ type: "bridge-node",
56
+ title: `Bridge page: ${node.title}`,
57
+ nodeIds: [node.id],
58
+ suggestion: "This page connects multiple knowledge areas. Keep it well cited and current."
59
+ });
60
+ }
61
+ }
62
+ return gaps.slice(0, limit);
63
+ }
64
+ function findSurprisingConnections(graph, limit = 10) {
65
+ const nodeById = new Map(graph.nodes.map((node) => [node.id, node]));
66
+ const scored = [];
67
+ for (const edge of graph.edges) {
68
+ const source = nodeById.get(edge.source);
69
+ const target = nodeById.get(edge.target);
70
+ if (!source || !target) continue;
71
+ let score = edge.weight;
72
+ const reasons = [...edge.reasons];
73
+ if (source.community !== target.community) {
74
+ score += 3;
75
+ reasons.push("cross-community");
76
+ }
77
+ if (source.tags.some((tag) => !target.tags.includes(tag))) {
78
+ score += 1;
79
+ reasons.push("cross-tag");
80
+ }
81
+ if (score >= 3) scored.push({ source, target, score, reasons });
82
+ }
83
+ return scored.sort((a, b) => b.score - a.score).slice(0, limit);
84
+ }
85
+ function buildAdjacency(graph) {
86
+ const out = /* @__PURE__ */ new Map();
87
+ for (const node of graph.nodes) out.set(node.id, /* @__PURE__ */ new Set());
88
+ for (const edge of graph.edges) {
89
+ out.get(edge.source)?.add(edge.target);
90
+ out.get(edge.target)?.add(edge.source);
91
+ }
92
+ return out;
93
+ }
94
+ function assignCommunities(nodes, adjacency) {
95
+ const seen = /* @__PURE__ */ new Set();
96
+ const communities = [];
97
+ for (const node of nodes) {
98
+ if (seen.has(node.id)) continue;
99
+ const queue = [node.id];
100
+ const ids = [];
101
+ seen.add(node.id);
102
+ while (queue.length > 0) {
103
+ const id = queue.shift();
104
+ ids.push(id);
105
+ for (const next of adjacency.get(id) ?? []) {
106
+ if (!seen.has(next)) {
107
+ seen.add(next);
108
+ queue.push(next);
109
+ }
110
+ }
111
+ }
112
+ const memberNodes = ids.map((id) => nodes.find((candidate) => candidate.id === id)).filter((item) => Boolean(item));
113
+ communities.push({
114
+ id: communities.length,
115
+ nodeIds: ids,
116
+ topTitles: memberNodes.sort((a, b) => b.inDegree + b.outDegree - (a.inDegree + a.outDegree)).slice(0, 5).map((item) => item.title),
117
+ cohesion: cohesion(ids, adjacency)
118
+ });
119
+ }
120
+ return communities.sort((a, b) => b.nodeIds.length - a.nodeIds.length);
121
+ }
122
+ function cohesion(ids, adjacency) {
123
+ if (ids.length < 2) return 0;
124
+ let edges = 0;
125
+ const idSet = new Set(ids);
126
+ for (const id of ids) {
127
+ for (const next of adjacency.get(id) ?? []) {
128
+ if (idSet.has(next)) edges++;
129
+ }
130
+ }
131
+ return edges / (ids.length * (ids.length - 1));
132
+ }
133
+ function hashNode(id) {
134
+ let hash = 0;
135
+ for (const char of id) hash = hash * 31 + char.charCodeAt(0) | 0;
136
+ return hash;
137
+ }
138
+ function isStructural(path) {
139
+ return path.endsWith("/index.md") || path.endsWith("/log.md");
140
+ }
141
+
142
+ export {
143
+ toKnowledgeVizGraph,
144
+ detectKnowledgeGaps,
145
+ findSurprisingConnections
146
+ };
147
+ //# sourceMappingURL=chunk-TXNYP4WI.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/viz/index.ts"],"sourcesContent":["import type { KnowledgeGraph, KnowledgeGraphEdge, KnowledgeGraphNode } from '../types'\n\nexport interface KnowledgeVizNode extends KnowledgeGraphNode {\n degree: number\n community: number\n}\n\nexport interface KnowledgeVizEdge extends KnowledgeGraphEdge {\n id: string\n}\n\nexport interface KnowledgeCommunity {\n id: number\n nodeIds: string[]\n topTitles: string[]\n cohesion: number\n}\n\nexport interface KnowledgeVizGraph {\n nodes: KnowledgeVizNode[]\n edges: KnowledgeVizEdge[]\n communities: KnowledgeCommunity[]\n}\n\nexport interface KnowledgeGap {\n type: 'isolated-node' | 'sparse-community' | 'bridge-node'\n title: string\n nodeIds: string[]\n suggestion: string\n}\n\nexport interface SurprisingConnection {\n source: KnowledgeVizNode\n target: KnowledgeVizNode\n score: number\n reasons: string[]\n}\n\nexport function toKnowledgeVizGraph(graph: KnowledgeGraph): KnowledgeVizGraph {\n const adjacency = buildAdjacency(graph)\n const communities = assignCommunities(graph.nodes, adjacency)\n const communityByNode = new Map<number, number>()\n communities.forEach((community) => {\n for (const nodeId of community.nodeIds) communityByNode.set(hashNode(nodeId), community.id)\n })\n const nodes = graph.nodes.map((node) => ({\n ...node,\n degree: node.inDegree + node.outDegree,\n community: communityByNode.get(hashNode(node.id)) ?? 0,\n }))\n return {\n nodes,\n edges: graph.edges.map((edge) => ({ ...edge, id: `${edge.source}->${edge.target}` })),\n communities,\n }\n}\n\nexport function detectKnowledgeGaps(graph: KnowledgeVizGraph, limit = 10): KnowledgeGap[] {\n const gaps: KnowledgeGap[] = []\n const isolated = graph.nodes.filter((node) => node.degree <= 1 && !isStructural(node.path))\n if (isolated.length > 0) {\n gaps.push({\n type: 'isolated-node',\n title: `${isolated.length} isolated page${isolated.length === 1 ? '' : 's'}`,\n nodeIds: isolated.map((node) => node.id),\n suggestion: 'Add cross-links, sources, or follow-up research to connect these pages to the knowledge graph.',\n })\n }\n for (const community of graph.communities) {\n if (community.nodeIds.length >= 3 && community.cohesion < 0.15) {\n gaps.push({\n type: 'sparse-community',\n title: `Sparse cluster: ${community.topTitles[0] ?? `community ${community.id}`}`,\n nodeIds: community.nodeIds,\n suggestion: 'This cluster has weak internal evidence. Add synthesis pages or relation links between its strongest concepts.',\n })\n }\n }\n const byCommunityNeighbors = new Map<string, Set<number>>()\n const nodeById = new Map(graph.nodes.map((node) => [node.id, node]))\n for (const edge of graph.edges) {\n const source = nodeById.get(edge.source)\n const target = nodeById.get(edge.target)\n if (!source || !target) continue\n if (!byCommunityNeighbors.has(source.id)) byCommunityNeighbors.set(source.id, new Set())\n if (!byCommunityNeighbors.has(target.id)) byCommunityNeighbors.set(target.id, new Set())\n byCommunityNeighbors.get(source.id)!.add(target.community)\n byCommunityNeighbors.get(target.id)!.add(source.community)\n }\n for (const node of graph.nodes) {\n if ((byCommunityNeighbors.get(node.id)?.size ?? 0) >= 3) {\n gaps.push({\n type: 'bridge-node',\n title: `Bridge page: ${node.title}`,\n nodeIds: [node.id],\n suggestion: 'This page connects multiple knowledge areas. Keep it well cited and current.',\n })\n }\n }\n return gaps.slice(0, limit)\n}\n\nexport function findSurprisingConnections(graph: KnowledgeVizGraph, limit = 10): SurprisingConnection[] {\n const nodeById = new Map(graph.nodes.map((node) => [node.id, node]))\n const scored: SurprisingConnection[] = []\n for (const edge of graph.edges) {\n const source = nodeById.get(edge.source)\n const target = nodeById.get(edge.target)\n if (!source || !target) continue\n let score = edge.weight\n const reasons = [...edge.reasons]\n if (source.community !== target.community) {\n score += 3\n reasons.push('cross-community')\n }\n if (source.tags.some((tag) => !target.tags.includes(tag))) {\n score += 1\n reasons.push('cross-tag')\n }\n if (score >= 3) scored.push({ source, target, score, reasons })\n }\n return scored.sort((a, b) => b.score - a.score).slice(0, limit)\n}\n\nfunction buildAdjacency(graph: KnowledgeGraph): Map<string, Set<string>> {\n const out = new Map<string, Set<string>>()\n for (const node of graph.nodes) out.set(node.id, new Set())\n for (const edge of graph.edges) {\n out.get(edge.source)?.add(edge.target)\n out.get(edge.target)?.add(edge.source)\n }\n return out\n}\n\nfunction assignCommunities(nodes: KnowledgeGraphNode[], adjacency: Map<string, Set<string>>): KnowledgeCommunity[] {\n const seen = new Set<string>()\n const communities: KnowledgeCommunity[] = []\n for (const node of nodes) {\n if (seen.has(node.id)) continue\n const queue = [node.id]\n const ids: string[] = []\n seen.add(node.id)\n while (queue.length > 0) {\n const id = queue.shift()!\n ids.push(id)\n for (const next of adjacency.get(id) ?? []) {\n if (!seen.has(next)) {\n seen.add(next)\n queue.push(next)\n }\n }\n }\n const memberNodes = ids.map((id) => nodes.find((candidate) => candidate.id === id)).filter((item): item is KnowledgeGraphNode => Boolean(item))\n communities.push({\n id: communities.length,\n nodeIds: ids,\n topTitles: memberNodes.sort((a, b) => b.inDegree + b.outDegree - (a.inDegree + a.outDegree)).slice(0, 5).map((item) => item.title),\n cohesion: cohesion(ids, adjacency),\n })\n }\n return communities.sort((a, b) => b.nodeIds.length - a.nodeIds.length)\n}\n\nfunction cohesion(ids: string[], adjacency: Map<string, Set<string>>): number {\n if (ids.length < 2) return 0\n let edges = 0\n const idSet = new Set(ids)\n for (const id of ids) {\n for (const next of adjacency.get(id) ?? []) {\n if (idSet.has(next)) edges++\n }\n }\n return edges / (ids.length * (ids.length - 1))\n}\n\nfunction hashNode(id: string): number {\n let hash = 0\n for (const char of id) hash = (hash * 31 + char.charCodeAt(0)) | 0\n return hash\n}\n\nfunction isStructural(path: string): boolean {\n return path.endsWith('/index.md') || path.endsWith('/log.md')\n}\n"],"mappings":";AAsCO,SAAS,oBAAoB,OAA0C;AAC5E,QAAM,YAAY,eAAe,KAAK;AACtC,QAAM,cAAc,kBAAkB,MAAM,OAAO,SAAS;AAC5D,QAAM,kBAAkB,oBAAI,IAAoB;AAChD,cAAY,QAAQ,CAAC,cAAc;AACjC,eAAW,UAAU,UAAU,QAAS,iBAAgB,IAAI,SAAS,MAAM,GAAG,UAAU,EAAE;AAAA,EAC5F,CAAC;AACD,QAAM,QAAQ,MAAM,MAAM,IAAI,CAAC,UAAU;AAAA,IACvC,GAAG;AAAA,IACH,QAAQ,KAAK,WAAW,KAAK;AAAA,IAC7B,WAAW,gBAAgB,IAAI,SAAS,KAAK,EAAE,CAAC,KAAK;AAAA,EACvD,EAAE;AACF,SAAO;AAAA,IACL;AAAA,IACA,OAAO,MAAM,MAAM,IAAI,CAAC,UAAU,EAAE,GAAG,MAAM,IAAI,GAAG,KAAK,MAAM,KAAK,KAAK,MAAM,GAAG,EAAE;AAAA,IACpF;AAAA,EACF;AACF;AAEO,SAAS,oBAAoB,OAA0B,QAAQ,IAAoB;AACxF,QAAM,OAAuB,CAAC;AAC9B,QAAM,WAAW,MAAM,MAAM,OAAO,CAAC,SAAS,KAAK,UAAU,KAAK,CAAC,aAAa,KAAK,IAAI,CAAC;AAC1F,MAAI,SAAS,SAAS,GAAG;AACvB,SAAK,KAAK;AAAA,MACR,MAAM;AAAA,MACN,OAAO,GAAG,SAAS,MAAM,iBAAiB,SAAS,WAAW,IAAI,KAAK,GAAG;AAAA,MAC1E,SAAS,SAAS,IAAI,CAAC,SAAS,KAAK,EAAE;AAAA,MACvC,YAAY;AAAA,IACd,CAAC;AAAA,EACH;AACA,aAAW,aAAa,MAAM,aAAa;AACzC,QAAI,UAAU,QAAQ,UAAU,KAAK,UAAU,WAAW,MAAM;AAC9D,WAAK,KAAK;AAAA,QACR,MAAM;AAAA,QACN,OAAO,mBAAmB,UAAU,UAAU,CAAC,KAAK,aAAa,UAAU,EAAE,EAAE;AAAA,QAC/E,SAAS,UAAU;AAAA,QACnB,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AAAA,EACF;AACA,QAAM,uBAAuB,oBAAI,IAAyB;AAC1D,QAAM,WAAW,IAAI,IAAI,MAAM,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AACnE,aAAW,QAAQ,MAAM,OAAO;AAC9B,UAAM,SAAS,SAAS,IAAI,KAAK,MAAM;AACvC,UAAM,SAAS,SAAS,IAAI,KAAK,MAAM;AACvC,QAAI,CAAC,UAAU,CAAC,OAAQ;AACxB,QAAI,CAAC,qBAAqB,IAAI,OAAO,EAAE,EAAG,sBAAqB,IAAI,OAAO,IAAI,oBAAI,IAAI,CAAC;AACvF,QAAI,CAAC,qBAAqB,IAAI,OAAO,EAAE,EAAG,sBAAqB,IAAI,OAAO,IAAI,oBAAI,IAAI,CAAC;AACvF,yBAAqB,IAAI,OAAO,EAAE,EAAG,IAAI,OAAO,SAAS;AACzD,yBAAqB,IAAI,OAAO,EAAE,EAAG,IAAI,OAAO,SAAS;AAAA,EAC3D;AACA,aAAW,QAAQ,MAAM,OAAO;AAC9B,SAAK,qBAAqB,IAAI,KAAK,EAAE,GAAG,QAAQ,MAAM,GAAG;AACvD,WAAK,KAAK;AAAA,QACR,MAAM;AAAA,QACN,OAAO,gBAAgB,KAAK,KAAK;AAAA,QACjC,SAAS,CAAC,KAAK,EAAE;AAAA,QACjB,YAAY;AAAA,MACd,CAAC;AAAA,IACH;AAAA,EACF;AACA,SAAO,KAAK,MAAM,GAAG,KAAK;AAC5B;AAEO,SAAS,0BAA0B,OAA0B,QAAQ,IAA4B;AACtG,QAAM,WAAW,IAAI,IAAI,MAAM,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC;AACnE,QAAM,SAAiC,CAAC;AACxC,aAAW,QAAQ,MAAM,OAAO;AAC9B,UAAM,SAAS,SAAS,IAAI,KAAK,MAAM;AACvC,UAAM,SAAS,SAAS,IAAI,KAAK,MAAM;AACvC,QAAI,CAAC,UAAU,CAAC,OAAQ;AACxB,QAAI,QAAQ,KAAK;AACjB,UAAM,UAAU,CAAC,GAAG,KAAK,OAAO;AAChC,QAAI,OAAO,cAAc,OAAO,WAAW;AACzC,eAAS;AACT,cAAQ,KAAK,iBAAiB;AAAA,IAChC;AACA,QAAI,OAAO,KAAK,KAAK,CAAC,QAAQ,CAAC,OAAO,KAAK,SAAS,GAAG,CAAC,GAAG;AACzD,eAAS;AACT,cAAQ,KAAK,WAAW;AAAA,IAC1B;AACA,QAAI,SAAS,EAAG,QAAO,KAAK,EAAE,QAAQ,QAAQ,OAAO,QAAQ,CAAC;AAAA,EAChE;AACA,SAAO,OAAO,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,KAAK;AAChE;AAEA,SAAS,eAAe,OAAiD;AACvE,QAAM,MAAM,oBAAI,IAAyB;AACzC,aAAW,QAAQ,MAAM,MAAO,KAAI,IAAI,KAAK,IAAI,oBAAI,IAAI,CAAC;AAC1D,aAAW,QAAQ,MAAM,OAAO;AAC9B,QAAI,IAAI,KAAK,MAAM,GAAG,IAAI,KAAK,MAAM;AACrC,QAAI,IAAI,KAAK,MAAM,GAAG,IAAI,KAAK,MAAM;AAAA,EACvC;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB,OAA6B,WAA2D;AACjH,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,cAAoC,CAAC;AAC3C,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,IAAI,KAAK,EAAE,EAAG;AACvB,UAAM,QAAQ,CAAC,KAAK,EAAE;AACtB,UAAM,MAAgB,CAAC;AACvB,SAAK,IAAI,KAAK,EAAE;AAChB,WAAO,MAAM,SAAS,GAAG;AACvB,YAAM,KAAK,MAAM,MAAM;AACvB,UAAI,KAAK,EAAE;AACX,iBAAW,QAAQ,UAAU,IAAI,EAAE,KAAK,CAAC,GAAG;AAC1C,YAAI,CAAC,KAAK,IAAI,IAAI,GAAG;AACnB,eAAK,IAAI,IAAI;AACb,gBAAM,KAAK,IAAI;AAAA,QACjB;AAAA,MACF;AAAA,IACF;AACA,UAAM,cAAc,IAAI,IAAI,CAAC,OAAO,MAAM,KAAK,CAAC,cAAc,UAAU,OAAO,EAAE,CAAC,EAAE,OAAO,CAAC,SAAqC,QAAQ,IAAI,CAAC;AAC9I,gBAAY,KAAK;AAAA,MACf,IAAI,YAAY;AAAA,MAChB,SAAS;AAAA,MACT,WAAW,YAAY,KAAK,CAAC,GAAG,MAAM,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,GAAG,CAAC,EAAE,IAAI,CAAC,SAAS,KAAK,KAAK;AAAA,MACjI,UAAU,SAAS,KAAK,SAAS;AAAA,IACnC,CAAC;AAAA,EACH;AACA,SAAO,YAAY,KAAK,CAAC,GAAG,MAAM,EAAE,QAAQ,SAAS,EAAE,QAAQ,MAAM;AACvE;AAEA,SAAS,SAAS,KAAe,WAA6C;AAC5E,MAAI,IAAI,SAAS,EAAG,QAAO;AAC3B,MAAI,QAAQ;AACZ,QAAM,QAAQ,IAAI,IAAI,GAAG;AACzB,aAAW,MAAM,KAAK;AACpB,eAAW,QAAQ,UAAU,IAAI,EAAE,KAAK,CAAC,GAAG;AAC1C,UAAI,MAAM,IAAI,IAAI,EAAG;AAAA,IACvB;AAAA,EACF;AACA,SAAO,SAAS,IAAI,UAAU,IAAI,SAAS;AAC7C;AAEA,SAAS,SAAS,IAAoB;AACpC,MAAI,OAAO;AACX,aAAW,QAAQ,GAAI,QAAQ,OAAO,KAAK,KAAK,WAAW,CAAC,IAAK;AACjE,SAAO;AACT;AAEA,SAAS,aAAa,MAAuB;AAC3C,SAAO,KAAK,SAAS,WAAW,KAAK,KAAK,SAAS,SAAS;AAC9D;","names":[]}