@adia-ai/a2ui-retrieval 0.0.1 → 0.2.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 (30) hide show
  1. package/CHANGELOG.md +64 -0
  2. package/README.md +43 -12
  3. package/anti-patterns.js +1 -1
  4. package/authoring/index.js +13 -0
  5. package/{pattern-promotion.js → authoring/pattern-promotion.js} +1 -1
  6. package/{synthetic-data.js → authoring/synthetic-data.js} +6 -6
  7. package/catalog.js +1 -1
  8. package/concept-mapper.js +1 -1
  9. package/embedding/chunk-embedding-retriever.js +112 -0
  10. package/{embedding-retriever.js → embedding/embedding-retriever.js} +3 -2
  11. package/embedding/index.js +7 -0
  12. package/{dialog-recorder.js → feedback/dialog-recorder.js} +2 -2
  13. package/{feedback-analyzer.js → feedback/feedback-analyzer.js} +3 -2
  14. package/{feedback-store.js → feedback/feedback-store.js} +2 -1
  15. package/{gap-registry.js → feedback/gap-registry.js} +2 -1
  16. package/feedback/index.js +12 -0
  17. package/index.js +5 -5
  18. package/{clarity.js → intent/clarity.js} +2 -2
  19. package/{decomposer.js → intent/decomposer.js} +1 -1
  20. package/intent/index.js +14 -0
  21. package/{prompt-analyzer.js → intent/prompt-analyzer.js} +3 -2
  22. package/package.json +16 -4
  23. package/pattern-library.js +1 -1
  24. package/wiring-catalog.js +6 -6
  25. /package/{web-research.js → authoring/web-research.js} +0 -0
  26. /package/{embedding-provider.js → embedding/embedding-provider.js} +0 -0
  27. /package/{feedback.js → feedback/feedback.js} +0 -0
  28. /package/{intent-alignment.js → intent/intent-alignment.js} +0 -0
  29. /package/{intent-categorizer.js → intent/intent-categorizer.js} +0 -0
  30. /package/{intent-gate.js → intent/intent-gate.js} +0 -0
package/CHANGELOG.md CHANGED
@@ -9,6 +9,70 @@ _Nothing yet._
9
9
 
10
10
  ---
11
11
 
12
+ ## [0.2.0] - 2026-05-02
13
+
14
+ **Lockstep cut + boundary reorganization.** All 8 published
15
+ `@adia-ai/*` packages now share one version, governed by
16
+ [`docs/specs/package-architecture.md` § 15 (Versioning Policy)](../../../docs/specs/package-architecture.md#15-versioning-policy).
17
+ This release also lands the boundary cleanup from T4 of the
18
+ [`docs/plans/packages-architecture-fixes-2026-05-02.md`](../../../docs/plans/packages-architecture-fixes-2026-05-02.md)
19
+ plan.
20
+
21
+ ### Changed
22
+
23
+ - `version`: `0.0.1` → `0.2.0`.
24
+ - `dependencies["@adia-ai/a2ui-utils"]`: `^0.0.2` → `^0.2.0`.
25
+
26
+ - **Subdir reorganization** — 26 .js files at the top level
27
+ reorganized into 4 named concerns. Lookup-shaped files stay at the
28
+ top level; the rest move into subdirs. Top-level external imports
29
+ (`@adia-ai/a2ui-retrieval`) continue to work unchanged via the
30
+ re-exporting top-level barrel.
31
+
32
+ | New path | Members |
33
+ |---|---|
34
+ | `intent/` | `intent-alignment`, `intent-categorizer`, `intent-gate`, `prompt-analyzer`, `decomposer`, `clarity` |
35
+ | `embedding/` | `embedding-provider`, `embedding-retriever`, `chunk-embedding-retriever` |
36
+ | `feedback/` | `feedback`, `feedback-store`, `feedback-analyzer`, `dialog-recorder`, `gap-registry` |
37
+ | `authoring/` | `synthetic-data`, `web-research`, `pattern-promotion` |
38
+ | top level (kept) | `catalog`, `pattern-library`, `concept-mapper`, `domain-router`, `wiring-catalog`, `anti-patterns`, `context-assembler`, `component-entry`, `index` |
39
+
40
+ - New subpath exports: `./intent`, `./embedding`, `./feedback`,
41
+ `./authoring` each expose a barrel `index.js`. Wildcard subpaths
42
+ (`./intent/*`, `./embedding/*`, etc.) expose individual files for
43
+ fine-grained imports. The old wildcard `./*` is retained for
44
+ backward compatibility — direct imports of moved files still work
45
+ (e.g. `import { feedbackStore } from '@adia-ai/a2ui-retrieval/feedback/feedback-store'`)
46
+ but consumers should prefer the barrel form.
47
+
48
+ ### Fixed
49
+
50
+ - 6 `__dirname`-based path computations (in `dialog-recorder`,
51
+ `feedback-store`, `feedback-analyzer`, `gap-registry`, the two
52
+ embedding retrievers, and `prompt-analyzer`) gained one more `..`
53
+ segment to climb out of the new subdir to the corpus directory.
54
+ Without this, the moved files would write to a non-existent path
55
+ (`packages/a2ui/a2ui/corpus/...`). Caught during the post-move
56
+ smoke run; same class as the
57
+ `feedback_git_mv_audit_imports` memory entry.
58
+
59
+ ### Migration
60
+
61
+ ```diff
62
+ - import { feedbackStore } from '@adia-ai/a2ui-retrieval'; // still works (top-level barrel)
63
+ - import { feedbackStore } from '@adia-ai/a2ui-retrieval/feedback-store'; // BREAKS — file moved
64
+ + import { feedbackStore } from '@adia-ai/a2ui-retrieval/feedback'; // new barrel
65
+ + import { feedbackStore } from '@adia-ai/a2ui-retrieval/feedback/feedback-store'; // explicit
66
+ ```
67
+
68
+ The top-level `index.js` still re-exports the previously-public surface
69
+ (`assessClarity`, `isConversational`, `decomposeIntent`,
70
+ `checkIntentAlignment`, etc.) — those imports do not need updating.
71
+
72
+ ---
73
+
74
+ ---
75
+
12
76
  ## [0.0.1] - 2026-04-24
13
77
 
14
78
  First public release. Extracted from
package/README.md CHANGED
@@ -14,18 +14,49 @@ npm install @adia-ai/a2ui-retrieval
14
14
 
15
15
  ## What's here
16
16
 
17
- - **Pattern library** indexed search over the catalog's patterns and
18
- fragments; domain-aware ranking.
19
- - **Intent gate** classifies a user intent as UI-generating vs
20
- conversational based on domain-keyword signal.
21
- - **Domain router** — maps free-form text to catalog domains
22
- (`forms`, `data`, `agent`, `navigation`, etc.).
23
- - **Anti-pattern detector** — flags compositions that violate invariants
24
- (invented components, bad attribute combos).
25
- - **Clarity analyzer** scores how specific an intent is; drives
26
- clarification prompts when the signal is too weak to generate.
27
- - **Context assembly** stitches retrieval results into the prompt
28
- context consumed by the LLM adapters.
17
+ The package groups its 26 source files into 4 sub-concerns plus a
18
+ top-level lookup surface. Importers can pull the top-level barrel
19
+ (`@adia-ai/a2ui-retrieval`) for the previously-public surface, the
20
+ per-subdir barrels (`@adia-ai/a2ui-retrieval/intent` etc.), or
21
+ individual files for fine-grained imports.
22
+
23
+ ```
24
+ a2ui-retrieval/
25
+ ├── catalog.js top-levelcatalog lookup (loaded from corpus)
26
+ ├── pattern-library.js top-level keyword + semantic pattern search
27
+ ├── concept-mapper.js top-levelconcept catalog-entry mapping
28
+ ├── domain-router.js top-level intent catalog-domain classifier
29
+ ├── wiring-catalog.js top-level — controller / handler reference
30
+ ├── anti-patterns.js top-level — known-bad pattern detector
31
+ ├── context-assembler.js top-level — retrieval results → LLM context
32
+ ├── component-entry.js top-level — catalog row serializer
33
+ ├── index.js top-level — barrel
34
+
35
+ ├── intent/ intent classification + decomposition
36
+ │ ├── intent-alignment.js
37
+ │ ├── intent-categorizer.js
38
+ │ ├── intent-gate.js UI-generating vs conversational
39
+ │ ├── prompt-analyzer.js
40
+ │ ├── decomposer.js compound intents → subtasks
41
+ │ └── clarity.js clarity scoring
42
+
43
+ ├── embedding/ dense-vector retrieval
44
+ │ ├── embedding-provider.js adapter (Voyage / OpenAI / fallback)
45
+ │ ├── embedding-retriever.js top-N pattern retrieval
46
+ │ └── chunk-embedding-retriever.js chunk-level retrieval
47
+
48
+ ├── feedback/ user-feedback ingestion loop
49
+ │ ├── feedback.js
50
+ │ ├── feedback-store.js JSONL store under .brain/feedback/
51
+ │ ├── feedback-analyzer.js
52
+ │ ├── dialog-recorder.js LLM round-trip capture (gated by env)
53
+ │ └── gap-registry.js tracked gaps in catalog coverage
54
+
55
+ └── authoring/ corpus-authoring helpers (upstream of retrieval)
56
+ ├── synthetic-data.js
57
+ ├── web-research.js
58
+ └── pattern-promotion.js
59
+ ```
29
60
 
30
61
  ## Runtime
31
62
 
package/anti-patterns.js CHANGED
@@ -76,7 +76,7 @@ const antiPatterns = [
76
76
  'table-ui', 'chart-ui', 'embed-ui', 'stack-ui', 'block-ui', 'code-ui',
77
77
  'textarea-ui', 'radio-ui', 'radio-ui', 'tag-ui', 'accordion-ui',
78
78
  'modal-ui', 'alert-ui', 'tooltip-ui', 'menu-ui', 'breadcrumb-ui',
79
- 'nav-n', 'pagination-ui', 'avatar-group-ui', 'segmented-ui',
79
+ 'nav-ui', 'pagination-ui', 'avatar-group-ui', 'segmented-ui',
80
80
  'segment-ui', 'command-ui', 'command-item-ui', 'command-group-ui',
81
81
  'calendar-picker-ui', 'color-picker-ui', 'kbd-ui', 'toolbar-ui',
82
82
  'otp-input-ui',
@@ -0,0 +1,13 @@
1
+ /**
2
+ * @adia-ai/a2ui-retrieval/authoring — corpus authoring helpers.
3
+ *
4
+ * Scripts and helpers that produce or extend retrieval inputs:
5
+ * synthetic-data generation, web research, pattern promotion. These are
6
+ * upstream of retrieval (they create what retrieval reads) — kept inside
7
+ * the retrieval package because they share the catalog + pattern-library
8
+ * surfaces, but logically a separate concern from lookup.
9
+ */
10
+
11
+ export * from './synthetic-data.js';
12
+ export * from './web-research.js';
13
+ export * from './pattern-promotion.js';
@@ -14,7 +14,7 @@
14
14
  * the pattern library.
15
15
  */
16
16
 
17
- import { getAllPatterns } from './pattern-library.js';
17
+ import { getAllPatterns } from '../pattern-library.js';
18
18
 
19
19
  /**
20
20
  * Evaluate whether a generation should be promoted to a named pattern.
@@ -9,10 +9,10 @@
9
9
  * Spec: A003 section 6 — Synthetic Data Generation
10
10
  */
11
11
 
12
- import { getCatalog } from './catalog.js';
13
- import { getAntiPatterns } from './anti-patterns.js';
14
- import { getAllPatterns } from './pattern-library.js';
15
- import { serializeEntry } from './component-entry.js';
12
+ import { getCatalog } from '../catalog.js';
13
+ import { getAntiPatterns } from '../anti-patterns.js';
14
+ import { getAllPatterns } from '../pattern-library.js';
15
+ import { serializeEntry } from '../component-entry.js';
16
16
 
17
17
  // ── Coverage targets (spec section 6.2) ──
18
18
 
@@ -409,7 +409,7 @@ export class SyntheticDataGenerator {
409
409
 
410
410
  // Map A2UI types to their AdiaUI tag names for anti-pattern checking
411
411
  const tag = type.toLowerCase().replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase();
412
- const tagName = tag.endsWith('-n') ? tag : `${tag}-n`;
412
+ const tagName = tag.endsWith('-ui') ? tag : `${tag}-ui`;
413
413
 
414
414
  // Build a minimal HTML representation
415
415
  const attrs = [];
@@ -425,7 +425,7 @@ export class SyntheticDataGenerator {
425
425
  .filter(Boolean)
426
426
  .map(c => {
427
427
  const ct = c.component?.toLowerCase().replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase() || '';
428
- return ct.endsWith('-n') ? ct : ct;
428
+ return ct.endsWith('-ui') ? ct : ct;
429
429
  });
430
430
  lines.push(`<${tagName}${attrStr}>${childTypes.map(ct => `<${ct}>`).join('')}</${tagName}>`);
431
431
  } else {
package/catalog.js CHANGED
@@ -83,7 +83,7 @@ const categoryMap = {
83
83
  'section': 'card-child', 'header': 'card-child', 'footer': 'card-child',
84
84
  'stream-ui': 'agent', 'table-ui': 'agent', 'chart-ui': 'agent',
85
85
  'embed-ui': 'agent', 'noodles-ui': 'agent',
86
- 'breadcrumb-ui': 'navigation', 'nav-n': 'navigation', 'pagination-ui': 'navigation',
86
+ 'breadcrumb-ui': 'navigation', 'nav-ui': 'navigation', 'pagination-ui': 'navigation',
87
87
  'segmented-ui': 'navigation', 'segment-ui': 'navigation', 'router-ui': 'navigation',
88
88
  'toggle-group-ui': 'navigation', 'toggle-option-ui': 'navigation',
89
89
  };
package/concept-mapper.js CHANGED
@@ -20,7 +20,7 @@
20
20
  */
21
21
 
22
22
  import { searchBlocks } from '../engine/reference.js';
23
- import { scoreAll as embeddingScoreAll, available as embeddingAvailable } from './embedding-retriever.js';
23
+ import { scoreAll as embeddingScoreAll, available as embeddingAvailable } from './embedding/embedding-retriever.js';
24
24
 
25
25
  /** Weights for the combined score. Tuned to keep lexical authoritative
26
26
  * but let strong conceptual+structural+semantic signals override marginal
@@ -0,0 +1,112 @@
1
+ /**
2
+ * Chunk embedding retriever — loads the build-time chunk embedding index
3
+ * and scores a query against every chunk via cosine similarity.
4
+ *
5
+ * Sibling to `embedding-retriever.js` (pattern embeddings); same provider
6
+ * conventions, same graceful-degradation contract.
7
+ *
8
+ * Index: packages/a2ui/corpus/chunk-embeddings.json (built by
9
+ * scripts/build/embeddings-chunks.mjs). When missing or empty, the
10
+ * retriever is effectively a no-op — callers see an empty score map and
11
+ * should fall back to keyword-only ranking.
12
+ *
13
+ * Used by chunk-library.searchChunks() to blend semantic + keyword scores.
14
+ */
15
+
16
+ import { detectProvider, cosine, voyage, openai } from './embedding-provider.js';
17
+
18
+ const IS_NODE = typeof process !== 'undefined' && !!process.versions?.node;
19
+
20
+ let _index = null;
21
+ let _indexByName = null; // Map<chunk-name, Float32Array>
22
+ let _loadPromise = null;
23
+ let _embedFn = null;
24
+ let _available = null;
25
+
26
+ async function _loadIndex() {
27
+ if (_index !== null) return _index;
28
+ if (_loadPromise) return _loadPromise;
29
+ _loadPromise = (async () => {
30
+ try {
31
+ if (IS_NODE) {
32
+ const fs = await import(/* @vite-ignore */ 'node:fs/promises');
33
+ const path = await import(/* @vite-ignore */ 'node:path');
34
+ const url = await import(/* @vite-ignore */ 'node:url');
35
+ // packages/a2ui/retrieval/embedding → up 2 → packages/a2ui → corpus/chunk-embeddings.json
36
+ const here = path.dirname(url.fileURLToPath(import.meta.url));
37
+ const p = path.resolve(here, '../../corpus/chunk-embeddings.json');
38
+ const raw = await fs.readFile(p, 'utf8');
39
+ _index = JSON.parse(raw);
40
+ } else {
41
+ const url = new URL('../../corpus/chunk-embeddings.json', import.meta.url);
42
+ const res = await fetch(url).catch(() => null);
43
+ _index = res?.ok ? await res.json().catch(() => null) : null;
44
+ }
45
+ } catch {
46
+ _index = null;
47
+ }
48
+ if (_index?.chunks?.length) {
49
+ _indexByName = new Map();
50
+ for (const c of _index.chunks) {
51
+ if (c?.name && Array.isArray(c.vector)) {
52
+ _indexByName.set(c.name, Float32Array.from(c.vector));
53
+ }
54
+ }
55
+ }
56
+ return _index;
57
+ })();
58
+ return _loadPromise;
59
+ }
60
+
61
+ function _resolveEmbed(providerName, model) {
62
+ if (providerName === 'voyage') return voyage({ model });
63
+ if (providerName === 'openai') return openai({ model });
64
+ const auto = detectProvider();
65
+ return auto?.embed || null;
66
+ }
67
+
68
+ export async function available() {
69
+ if (_available !== null) return _available;
70
+ const idx = await _loadIndex();
71
+ if (!idx || !idx.chunks?.length) {
72
+ _available = false;
73
+ return false;
74
+ }
75
+ _embedFn = _resolveEmbed(idx.provider, idx.model);
76
+ _available = !!_embedFn;
77
+ return _available;
78
+ }
79
+
80
+ /**
81
+ * Embed a query and return a Map<chunk-name → cosine-score>.
82
+ * Returns an empty Map when unavailable (no index or no API key).
83
+ */
84
+ export async function scoreAll(query) {
85
+ if (!query || typeof query !== 'string') return new Map();
86
+ if (!(await available())) return new Map();
87
+
88
+ let qVec;
89
+ try {
90
+ const [v] = await _embedFn([query]);
91
+ qVec = v;
92
+ } catch (e) {
93
+ if (typeof console !== 'undefined') console.warn('[chunk-embedding-retriever]', e.message);
94
+ return new Map();
95
+ }
96
+
97
+ const out = new Map();
98
+ for (const [name, vec] of _indexByName) {
99
+ out.set(name, cosine(qVec, vec));
100
+ }
101
+ return out;
102
+ }
103
+
104
+ export async function size() {
105
+ const idx = await _loadIndex();
106
+ return idx?.chunks?.length || 0;
107
+ }
108
+
109
+ export async function providerInfo() {
110
+ const idx = await _loadIndex();
111
+ return idx ? { provider: idx.provider, model: idx.model, dims: idx.dims } : null;
112
+ }
@@ -32,12 +32,13 @@ async function _loadIndex() {
32
32
  const fs = await import(/* @vite-ignore */ 'node:fs/promises');
33
33
  const path = await import(/* @vite-ignore */ 'node:path');
34
34
  const url = await import(/* @vite-ignore */ 'node:url');
35
+ // packages/a2ui/retrieval/embedding → up 2 → packages/a2ui → corpus/pattern-embeddings.json
35
36
  const here = path.dirname(url.fileURLToPath(import.meta.url));
36
- const p = path.resolve(here, '../corpus/pattern-embeddings.json');
37
+ const p = path.resolve(here, '../../corpus/pattern-embeddings.json');
37
38
  const raw = await fs.readFile(p, 'utf8');
38
39
  _index = JSON.parse(raw);
39
40
  } else {
40
- const url = new URL('../corpus/pattern-embeddings.json', import.meta.url);
41
+ const url = new URL('../../corpus/pattern-embeddings.json', import.meta.url);
41
42
  const res = await fetch(url).catch(() => null);
42
43
  _index = res?.ok ? await res.json().catch(() => null) : null;
43
44
  }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @adia-ai/a2ui-retrieval/embedding — embedding-provider + retrievers surface.
3
+ */
4
+
5
+ export * from './embedding-provider.js';
6
+ export * from './embedding-retriever.js';
7
+ export * from './chunk-embedding-retriever.js';
@@ -36,9 +36,9 @@ async function _ensureModules() {
36
36
  _fs = await import(/* @vite-ignore */ 'node:fs/promises');
37
37
  _path = await import(/* @vite-ignore */ 'node:path');
38
38
  _url = await import(/* @vite-ignore */ 'node:url');
39
- // logs/ lives at the repo root: packages/a2ui/retrieval → up 3 → repo root
39
+ // logs/ lives at the repo root: packages/a2ui/retrieval/feedback → up 4 → repo root
40
40
  const __dirname = _path.dirname(_url.fileURLToPath(import.meta.url));
41
- _logsRoot = _path.resolve(__dirname, '..', '..', '..', 'logs', 'dialogs');
41
+ _logsRoot = _path.resolve(__dirname, '..', '..', '..', '..', 'logs', 'dialogs');
42
42
  }
43
43
 
44
44
  // In-memory turn counter per session — keeps the on-disk turn ordering correct
@@ -13,7 +13,7 @@
13
13
  */
14
14
 
15
15
  import { feedbackStore } from './feedback-store.js';
16
- import { categorizeIntent } from './intent-categorizer.js';
16
+ import { categorizeIntent } from '../intent/intent-categorizer.js';
17
17
 
18
18
  let fs, path;
19
19
  const IS_NODE = typeof process !== 'undefined' && process.versions?.node;
@@ -26,8 +26,9 @@ if (IS_NODE) {
26
26
  }
27
27
  }
28
28
 
29
+ // packages/a2ui/retrieval/feedback → up 3 → packages/a2ui → corpus/feedback
29
30
  const FEEDBACK_DIR = path
30
- ? path.join(path.dirname(new URL(import.meta.url).pathname), '..', '..', 'a2ui/corpus', 'feedback')
31
+ ? path.join(path.dirname(new URL(import.meta.url).pathname), '..', '..', '..', 'a2ui/corpus', 'feedback')
31
32
  : null;
32
33
 
33
34
  export class FeedbackAnalyzer {
@@ -23,8 +23,9 @@ if (IS_NODE) {
23
23
  }
24
24
  }
25
25
 
26
+ // packages/a2ui/retrieval/feedback → up 3 → packages/a2ui → corpus/feedback
26
27
  const FEEDBACK_DIR = path
27
- ? path.join(path.dirname(new URL(import.meta.url).pathname), '..', '..', 'a2ui/corpus', 'feedback')
28
+ ? path.join(path.dirname(new URL(import.meta.url).pathname), '..', '..', '..', 'a2ui/corpus', 'feedback')
28
29
  : null;
29
30
 
30
31
  function todayFile() {
@@ -24,8 +24,9 @@ if (IS_NODE) {
24
24
  }
25
25
  }
26
26
 
27
+ // packages/a2ui/retrieval/feedback → up 3 → packages/a2ui → corpus/gaps/registry.json
27
28
  const REGISTRY_PATH = path
28
- ? path.join(path.dirname(new URL(import.meta.url).pathname), '..', '..', 'a2ui/corpus', 'gaps', 'registry.json')
29
+ ? path.join(path.dirname(new URL(import.meta.url).pathname), '..', '..', '..', 'a2ui/corpus', 'gaps', 'registry.json')
29
30
  : null;
30
31
 
31
32
  /**
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @adia-ai/a2ui-retrieval/feedback — feedback-loop surface.
3
+ *
4
+ * Pairs the feedback store, analyzer, dialog recorder, and gap registry
5
+ * — all the artifacts that compose the user-feedback ingestion loop.
6
+ */
7
+
8
+ export { feedbackStore } from './feedback-store.js';
9
+ export { FeedbackAnalyzer } from './feedback-analyzer.js';
10
+ export * from './feedback.js';
11
+ export { recordTurn, isRecording } from './dialog-recorder.js';
12
+ export { loadGaps, addGap, updateGapStatus } from './gap-registry.js';
package/index.js CHANGED
@@ -6,11 +6,11 @@ export { getCatalog, getComponent, getComponentsByCategory, getTraits, getTraits
6
6
  export { serializeEntry } from './component-entry.js';
7
7
  export { getAntiPatterns, checkAntiPattern, checkAllAntiPatterns } from './anti-patterns.js';
8
8
  export { classifyIntent, getDomain, getAllDomains } from './domain-router.js';
9
- export { isConversational } from './intent-gate.js';
10
- export { assessClarity } from './clarity.js';
11
- export { detectReferences, researchIntent } from './web-research.js';
9
+ export { isConversational } from './intent/intent-gate.js';
10
+ export { assessClarity } from './intent/clarity.js';
11
+ export { detectReferences, researchIntent } from './authoring/web-research.js';
12
12
  export { assembleContext } from './context-assembler.js';
13
13
  export { getPattern, searchPatterns, semanticSearchPatterns, getAllPatterns, registerPattern } from './pattern-library.js';
14
- export { extractExpectations, verifyAlignment, checkIntentAlignment } from './intent-alignment.js';
15
- export { decomposeIntent, composeSubtasks } from './decomposer.js';
14
+ export { extractExpectations, verifyAlignment, checkIntentAlignment } from './intent/intent-alignment.js';
15
+ export { decomposeIntent, composeSubtasks } from './intent/decomposer.js';
16
16
  export { getWiringCatalog, getControllerInfo, getHandlerInfo } from './wiring-catalog.js';
@@ -12,8 +12,8 @@
12
12
  * Returns a clarity score (0-1) and targeted questions for what's missing.
13
13
  */
14
14
 
15
- import { classifyIntent } from './domain-router.js';
16
- import { searchPatterns } from './pattern-library.js';
15
+ import { classifyIntent } from '../domain-router.js';
16
+ import { searchPatterns } from '../pattern-library.js';
17
17
 
18
18
  // ── Dimension detectors ──────────────────────────────────────────────────
19
19
 
@@ -14,7 +14,7 @@
14
14
  * is almost trivial."
15
15
  */
16
16
 
17
- import { classifyIntent } from './domain-router.js';
17
+ import { classifyIntent } from '../domain-router.js';
18
18
 
19
19
  // ── Section Detection ────────────────────────────────────────────────────
20
20
 
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @adia-ai/a2ui-retrieval/intent — intent classification + decomposition surface.
3
+ *
4
+ * Re-exports the intent-shaped retrieval primitives. Importers can reach
5
+ * individual files directly (e.g. `@adia-ai/a2ui-retrieval/intent/clarity`)
6
+ * or pull the bundle via this barrel.
7
+ */
8
+
9
+ export { extractExpectations, verifyAlignment, checkIntentAlignment } from './intent-alignment.js';
10
+ export { categorizeIntent } from './intent-categorizer.js';
11
+ export { isConversational } from './intent-gate.js';
12
+ export { analyzePrompt } from './prompt-analyzer.js';
13
+ export { decomposeIntent, composeSubtasks } from './decomposer.js';
14
+ export { assessClarity } from './clarity.js';
@@ -45,11 +45,12 @@ async function getVocab() {
45
45
  const fs = await import(/* @vite-ignore */ 'node:fs/promises');
46
46
  const path = await import(/* @vite-ignore */ 'node:path');
47
47
  const url = await import(/* @vite-ignore */ 'node:url');
48
+ // packages/a2ui/retrieval/intent → up 2 → packages/a2ui → corpus/patterns/_components.json
48
49
  const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
49
- const raw = await fs.readFile(path.join(__dirname, '../corpus/patterns/_components.json'), 'utf8');
50
+ const raw = await fs.readFile(path.join(__dirname, '../../corpus/patterns/_components.json'), 'utf8');
50
51
  catalog = JSON.parse(raw);
51
52
  } else {
52
- const resp = await fetch(new URL('../corpus/patterns/_components.json', import.meta.url));
53
+ const resp = await fetch(new URL('../../corpus/patterns/_components.json', import.meta.url));
53
54
  if (resp.ok) catalog = await resp.json();
54
55
  }
55
56
  } catch { /* empty vocab — analyzer will still work, just unconstrained */ }
package/package.json CHANGED
@@ -1,15 +1,27 @@
1
1
  {
2
2
  "name": "@adia-ai/a2ui-retrieval",
3
- "version": "0.0.1",
3
+ "version": "0.2.0",
4
4
  "description": "AdiaUI A2UI retrieval layer — catalog lookup, intent classification, domain routing, pattern + anti-pattern matching, clarity + context assembly. Consumed by the compose engine and any A2UI-protocol tooling that needs to reason about user intent against the catalog.",
5
5
  "type": "module",
6
6
  "main": "./index.js",
7
7
  "exports": {
8
- ".": "./index.js",
9
- "./*": "./*.js"
8
+ ".": "./index.js",
9
+ "./intent": "./intent/index.js",
10
+ "./intent/*": "./intent/*.js",
11
+ "./embedding": "./embedding/index.js",
12
+ "./embedding/*": "./embedding/*.js",
13
+ "./feedback": "./feedback/index.js",
14
+ "./feedback/*": "./feedback/*.js",
15
+ "./authoring": "./authoring/index.js",
16
+ "./authoring/*": "./authoring/*.js",
17
+ "./*": "./*.js"
10
18
  },
11
19
  "files": [
12
20
  "*.js",
21
+ "intent/",
22
+ "embedding/",
23
+ "feedback/",
24
+ "authoring/",
13
25
  "README.md",
14
26
  "CHANGELOG.md"
15
27
  ],
@@ -24,6 +36,6 @@
24
36
  "directory": "packages/a2ui/retrieval"
25
37
  },
26
38
  "dependencies": {
27
- "@adia-ai/a2ui-utils": "^0.0.2"
39
+ "@adia-ai/a2ui-utils": "^0.2.0"
28
40
  }
29
41
  }
@@ -535,7 +535,7 @@ export async function semanticSearchPatterns(query, options = {}) {
535
535
  // where keyword collisions pick the wrong pattern. Graceful degradation:
536
536
  // empty map → no effect, pipeline behaves exactly as pre-embedding.
537
537
  try {
538
- const { scoreAll, available } = await import('./embedding-retriever.js');
538
+ const { scoreAll, available } = await import('./embedding/embedding-retriever.js');
539
539
  if (await available()) {
540
540
  const semanticMap = await scoreAll(query);
541
541
  if (semanticMap.size > 0) {
package/wiring-catalog.js CHANGED
@@ -7,7 +7,7 @@
7
7
  * The schema has 5 docking points:
8
8
  * DATA — sources, params (how the surface gets its data)
9
9
  * STATE — controllers, model (how components manage behavior)
10
- * ACTIONS — AdiaEvent → handler chains (what happens on events)
10
+ * ACTIONS — UIEvent → handler chains (what happens on events)
11
11
  * PROVIDES — context injection into subtrees
12
12
  * LIFECYCLE — onMount, onUnmount, onModelChange hooks
13
13
  *
@@ -17,7 +17,7 @@
17
17
  * A full app needs all five.
18
18
  */
19
19
 
20
- // ── AdiaEvent ──────────────────────────────────────────────────
20
+ // ── UIEvent ──────────────────────────────────────────────────
21
21
  // A typed event object that the wiring system understands natively.
22
22
  // Maps 1:1 to DOM events but with AdiaUI semantics and payload contracts.
23
23
  //
@@ -26,7 +26,7 @@
26
26
  // { "event": "submit", "target": "form-col" }
27
27
  // { "event": "mount" }
28
28
  //
29
- // "event" — AdiaEvent type name (see adiaEvents below)
29
+ // "event" — UIEvent type name (see adiaEvents below)
30
30
  // "target" — component id that emits. Omit for surface-level events.
31
31
  // "debounce" — ms, coalesce rapid-fire (input, resize)
32
32
  // "throttle" — ms, limit frequency (scroll, drag)
@@ -129,9 +129,9 @@ export function getWiringCatalog() {
129
129
  { name: 'notify', description: 'Show a toast/alert notification.', config: ['message', 'variant'] },
130
130
  ],
131
131
 
132
- // ── ACTION SHAPE (AdiaEvent → handler) ──
132
+ // ── ACTION SHAPE (UIEvent → handler) ──
133
133
  actionShape: {
134
- event: 'AdiaEvent object: { event, target?, debounce?, throttle?, condition? }',
134
+ event: 'UIEvent object: { event, target?, debounce?, throttle?, condition? }',
135
135
  handler: 'Handler name from the handlers list.',
136
136
  config: 'Handler-specific configuration object.',
137
137
  onSuccess: 'Follow-up actions array (each is { handler, config }).',
@@ -174,7 +174,7 @@ export function getWiringCatalog() {
174
174
  }
175
175
 
176
176
  /**
177
- * Get AdiaEvent type info.
177
+ * Get UIEvent type info.
178
178
  */
179
179
  export function getAdiaEvent(type) {
180
180
  return adiaEvents.find(e => e.event === type) || null;
File without changes
File without changes
File without changes