@fortemi/core 2026.6.1 → 2026.6.3

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 CHANGED
@@ -15,6 +15,7 @@ pnpm add @fortemi/core
15
15
  [![License: AGPL-3.0-only](https://img.shields.io/badge/License-AGPL--3.0--only-blue.svg?style=flat-square)](https://github.com/Fortemi/fortemi-react/blob/main/LICENSE)
16
16
  [![Node Version](https://img.shields.io/badge/node-%3E%3D22.0.0-brightgreen?style=flat-square&logo=node.js)](https://nodejs.org)
17
17
  [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue?style=flat-square&logo=typescript)](https://www.typescriptlang.org)
18
+ [![Built with aiwg](https://img.shields.io/npm/v/aiwg?label=built%20with%20aiwg&color=CB3837&logo=npm&style=flat-square)](https://www.npmjs.com/package/aiwg)
18
19
 
19
20
  [**Install**](#installation) · [**Why Fortemi**](#why-fortemi-core) · [**Quick Start**](#quick-start) · [**Surface**](#what-you-get) · [**Tools**](#tool-surface) · [**Docs**](#documentation) · [**License**](#license)
20
21
 
@@ -102,6 +103,62 @@ const results = await search.search('hello')
102
103
  await registerServiceWorker()
103
104
  ```
104
105
 
106
+ ## Static AIWG Index Search
107
+
108
+ Static documentation hosts can import the AIWG index helpers without pulling in
109
+ PGlite, workers, shards, or browser storage:
110
+
111
+ ```ts
112
+ import { createAiwgIndexController } from '@fortemi/core/aiwg-index'
113
+
114
+ const controller = createAiwgIndexController()
115
+ controller.loadIndex(await fetch('/aiwg-index.json').then((res) => res.json()))
116
+
117
+ const results = controller.query('deployment', {
118
+ types: ['docs.page'],
119
+ rank: true,
120
+ snippets: true,
121
+ limit: 10,
122
+ })
123
+ ```
124
+
125
+ Use this subpath for Pagenary-style command palettes, static docs search, and
126
+ vanilla JavaScript review surfaces. The top-level `@fortemi/core` export remains
127
+ available for full archive/runtime integrations.
128
+
129
+ Large static indexes can use the chunked browser path instead of downloading one
130
+ full `aiwg.fortemi.index.export.v1` file. Host a manifest plus deterministic part
131
+ files:
132
+
133
+ ```text
134
+ /search/aiwg-index/manifest.json
135
+ /search/aiwg-index/part-0000.json
136
+ /search/aiwg-index/part-0001.json
137
+ ```
138
+
139
+ ```ts
140
+ import {
141
+ createAiwgFetchChunkLoader,
142
+ createAiwgIndexController,
143
+ } from '@fortemi/core/aiwg-index'
144
+
145
+ const controller = createAiwgIndexController()
146
+ const manifest = await fetch('/search/aiwg-index/manifest.json').then((res) => res.json())
147
+
148
+ controller.loadChunkedIndex(
149
+ manifest,
150
+ createAiwgFetchChunkLoader('/search/aiwg-index/'),
151
+ { maxCachedParts: 3 },
152
+ )
153
+
154
+ const page = await controller.queryChunked('', { offset: 100, limit: 25 })
155
+ ```
156
+
157
+ Unfiltered browse requests fetch only the part files intersecting the requested
158
+ `offset` and `limit`. Filtered or ranked searches scan part files to compute exact
159
+ results, but the controller keeps only a bounded part cache and never sets a
160
+ materialized full export in `getIndex()`.
161
+
105
162
  ## What You Get
106
163
 
107
164
  | Surface | Description |
@@ -0,0 +1,242 @@
1
+ type AiwgFortemiRecordType = 'crm.contact' | 'crm.organization' | 'crm.event' | 'crm.interaction' | 'aiwg.artifact' | 'docs.page';
2
+ type AiwgPrivacyClassification = 'private' | 'sanitized' | 'public';
3
+ type AiwgProvenanceConfidence = 'source' | 'candidate' | 'reviewed' | 'rejected';
4
+ type AiwgReviewAction = 'accept' | 'reject' | 'defer';
5
+ interface AiwgFortemiRecordSource {
6
+ path: string;
7
+ repo_relative_path: string;
8
+ locator: string;
9
+ }
10
+ interface AiwgFortemiRelationship {
11
+ type: string;
12
+ target_id: string;
13
+ source_path?: string;
14
+ }
15
+ interface AiwgFortemiProvenance {
16
+ field: string;
17
+ source: string;
18
+ path: string;
19
+ confidence: AiwgProvenanceConfidence;
20
+ privacy: AiwgPrivacyClassification;
21
+ }
22
+ interface AiwgFortemiRecord {
23
+ schema_version: 'aiwg.fortemi.index.record.v1';
24
+ id: string;
25
+ type: AiwgFortemiRecordType;
26
+ source: AiwgFortemiRecordSource;
27
+ title: string;
28
+ text: string;
29
+ facets: Record<string, string[]>;
30
+ tags: string[];
31
+ concepts: string[];
32
+ relationships: AiwgFortemiRelationship[];
33
+ provenance: AiwgFortemiProvenance[];
34
+ privacy: {
35
+ classification: AiwgPrivacyClassification;
36
+ pii: boolean;
37
+ };
38
+ updated_at: string;
39
+ }
40
+ interface AiwgFortemiIndexExport {
41
+ schema_version: 'aiwg.fortemi.index.export.v1';
42
+ generated_at: string;
43
+ source: {
44
+ repo: string;
45
+ privacy: AiwgPrivacyClassification;
46
+ };
47
+ items: AiwgFortemiRecord[];
48
+ }
49
+ interface AiwgFortemiChunkPartRef {
50
+ href: string;
51
+ offset: number;
52
+ count: number;
53
+ }
54
+ declare const AIWG_SCAN_REQUIRED_FIELDS: Array<keyof AiwgFortemiRecord>;
55
+ type AiwgFortemiProjectedRecord = Pick<AiwgFortemiRecord, 'schema_version' | 'id' | 'type' | 'title' | 'text' | 'facets' | 'tags' | 'concepts' | 'privacy'> & Partial<AiwgFortemiRecord>;
56
+ interface AiwgFortemiChunkDetailRef {
57
+ href: string;
58
+ }
59
+ interface AiwgFortemiChunkManifest {
60
+ schema_version: 'aiwg.fortemi.index.chunk-manifest.v1';
61
+ generated_at: string;
62
+ source: AiwgFortemiIndexExport['source'];
63
+ total: number;
64
+ part_size: number;
65
+ facets?: Record<string, Record<string, number>>;
66
+ projection?: Array<keyof AiwgFortemiRecord>;
67
+ detail?: AiwgFortemiChunkDetailRef;
68
+ parts: AiwgFortemiChunkPartRef[];
69
+ }
70
+ interface AiwgFortemiChunkPart {
71
+ schema_version: 'aiwg.fortemi.index.chunk.v1';
72
+ manifest_schema_version: 'aiwg.fortemi.index.chunk-manifest.v1';
73
+ offset: number;
74
+ items: AiwgFortemiRecord[];
75
+ }
76
+ interface AiwgIndexValidationResult {
77
+ valid: boolean;
78
+ errors: string[];
79
+ counts: Partial<Record<AiwgFortemiRecordType, number>>;
80
+ }
81
+ interface AiwgChunkedIndexValidationResult {
82
+ valid: boolean;
83
+ errors: string[];
84
+ }
85
+ interface AiwgIndexQueryOptions {
86
+ types?: AiwgFortemiRecordType[];
87
+ facets?: Record<string, string[]>;
88
+ tags?: string[];
89
+ concepts?: string[];
90
+ privacy?: AiwgPrivacyClassification[];
91
+ relationshipTargetId?: string;
92
+ limit?: number;
93
+ offset?: number;
94
+ rank?: boolean;
95
+ snippets?: boolean;
96
+ snippetLength?: number;
97
+ weights?: Partial<AiwgIndexQueryWeights>;
98
+ includeMatches?: boolean;
99
+ }
100
+ interface AiwgIndexQueryWeights {
101
+ title: number;
102
+ text: number;
103
+ tag: number;
104
+ concept: number;
105
+ }
106
+ interface AiwgIndexQueryMatch {
107
+ field: 'title' | 'text' | 'tag' | 'concept';
108
+ value: string;
109
+ }
110
+ interface AiwgIndexQueryRankedItem {
111
+ item: AiwgFortemiRecord;
112
+ rank: number;
113
+ snippet?: string;
114
+ matches?: AiwgIndexQueryMatch[];
115
+ }
116
+ interface AiwgIndexQueryResult {
117
+ items: AiwgFortemiRecord[];
118
+ total: number;
119
+ facets: Record<string, Record<string, number>>;
120
+ rankedItems?: AiwgIndexQueryRankedItem[];
121
+ }
122
+ type AiwgChunkedIndexLoader = (part: AiwgFortemiChunkPartRef, manifest: AiwgFortemiChunkManifest) => Promise<unknown>;
123
+ type AiwgChunkedIndexDetailLoader = (id: string, manifest: AiwgFortemiChunkManifest) => Promise<unknown>;
124
+ interface AiwgChunkedIndexLoadOptions {
125
+ maxCachedParts?: number;
126
+ detailLoader?: AiwgChunkedIndexDetailLoader;
127
+ maxCachedDetails?: number;
128
+ }
129
+ type AiwgChunkedIndexProgressPhase = 'part' | 'query';
130
+ interface AiwgChunkedIndexProgress {
131
+ phase: AiwgChunkedIndexProgressPhase;
132
+ done: number;
133
+ total: number;
134
+ href?: string;
135
+ }
136
+ interface AiwgChunkedIndexQueryOptions extends AiwgIndexQueryOptions {
137
+ onProgress?: (progress: AiwgChunkedIndexProgress) => void;
138
+ }
139
+ interface AiwgChunkedIndexQueryResult extends AiwgIndexQueryResult {
140
+ manifestTotal: number;
141
+ scannedParts: number;
142
+ fetchedParts: number;
143
+ complete: boolean;
144
+ }
145
+ interface AiwgReviewDecision {
146
+ item_id: string;
147
+ action: AiwgReviewAction;
148
+ reason?: string;
149
+ updated_at: string;
150
+ }
151
+ interface AiwgReviewDecisionExport {
152
+ schema_version: 'aiwg.fortemi.review-decisions.v1';
153
+ generated_at: string;
154
+ source_export_schema_version: string;
155
+ decisions: AiwgReviewDecision[];
156
+ }
157
+ interface AiwgIndexGraphOptions {
158
+ communityFacet?: string;
159
+ communityTagPrefix?: string;
160
+ relationshipWeights?: Record<string, number>;
161
+ includeDanglingRelationships?: boolean;
162
+ }
163
+ interface AiwgReviewInput {
164
+ item_id: string;
165
+ action: AiwgReviewAction;
166
+ reason?: string;
167
+ }
168
+ interface AiwgIndexControllerSnapshot {
169
+ index: AiwgFortemiIndexExport | null;
170
+ chunked: {
171
+ manifest: AiwgFortemiChunkManifest;
172
+ cachedParts: number;
173
+ maxCachedParts: number;
174
+ } | null;
175
+ data: AiwgIndexQueryResult | null;
176
+ error: Error | null;
177
+ reviewDecisions: AiwgReviewDecision[];
178
+ }
179
+ type AiwgIndexControllerListener = (snapshot: AiwgIndexControllerSnapshot) => void;
180
+ interface AiwgIndexController {
181
+ loadIndex(value: unknown): AiwgFortemiIndexExport;
182
+ loadChunkedIndex(manifest: unknown, loader: AiwgChunkedIndexLoader, options?: AiwgChunkedIndexLoadOptions): AiwgFortemiChunkManifest;
183
+ getIndex(): AiwgFortemiIndexExport | null;
184
+ getChunkedManifest(): AiwgFortemiChunkManifest | null;
185
+ getSnapshot(): AiwgIndexControllerSnapshot;
186
+ query(query?: string, options?: AiwgIndexQueryOptions): AiwgIndexQueryResult;
187
+ queryChunked(query?: string, options?: AiwgChunkedIndexQueryOptions): Promise<AiwgChunkedIndexQueryResult>;
188
+ getRecord(id: string): Promise<AiwgFortemiRecord>;
189
+ clearChunkCache(): void;
190
+ toCommunityGraph(options?: AiwgIndexGraphOptions): ReturnType<typeof aiwgFortemiIndexToCommunityGraph>;
191
+ setReviewDecision(input: AiwgReviewInput): AiwgReviewDecision;
192
+ clearReviewDecision(itemId: string): void;
193
+ createReviewDecisionExport(generatedAt?: string): AiwgReviewDecisionExport;
194
+ subscribe(listener: AiwgIndexControllerListener): () => void;
195
+ }
196
+ declare function validateAiwgFortemiIndexExport(value: unknown): AiwgIndexValidationResult;
197
+ declare function assertAiwgFortemiIndexExport(value: unknown): AiwgFortemiIndexExport;
198
+ declare function validateAiwgFortemiChunkManifest(value: unknown): AiwgChunkedIndexValidationResult;
199
+ declare function assertAiwgFortemiChunkManifest(value: unknown): AiwgFortemiChunkManifest;
200
+ declare function validateAiwgFortemiChunkPart(value: unknown, partRef?: AiwgFortemiChunkPartRef, manifest?: AiwgFortemiChunkManifest): AiwgChunkedIndexValidationResult;
201
+ declare function assertAiwgFortemiChunkPart(value: unknown, partRef?: AiwgFortemiChunkPartRef, manifest?: AiwgFortemiChunkManifest): AiwgFortemiChunkPart;
202
+ declare function createAiwgFetchChunkLoader(baseUrl?: string | URL): AiwgChunkedIndexLoader;
203
+ declare function createAiwgFetchDetailLoader(baseUrl?: string | URL): AiwgChunkedIndexDetailLoader;
204
+ declare function getAiwgFortemiFacets(items: AiwgFortemiRecord[]): Record<string, Record<string, number>>;
205
+ interface AiwgChunkedIndexBuildOptions {
206
+ partSize?: number;
207
+ projection?: Array<keyof AiwgFortemiRecord>;
208
+ detailHref?: string;
209
+ generatedAt?: string;
210
+ }
211
+ interface AiwgChunkedIndexBuildResult {
212
+ manifest: AiwgFortemiChunkManifest;
213
+ parts: Array<{
214
+ href: string;
215
+ part: AiwgFortemiChunkPart;
216
+ }>;
217
+ details: Array<{
218
+ id: string;
219
+ record: AiwgFortemiRecord;
220
+ }>;
221
+ }
222
+ declare function buildAiwgChunkedIndex(index: AiwgFortemiIndexExport, options?: AiwgChunkedIndexBuildOptions): AiwgChunkedIndexBuildResult;
223
+ declare function queryAiwgFortemiIndex(index: AiwgFortemiIndexExport, query?: string, options?: AiwgIndexQueryOptions): AiwgIndexQueryResult;
224
+ declare function createAiwgReviewDecisionExport(source: AiwgFortemiIndexExport, decisions: AiwgReviewDecision[], generatedAt?: string): AiwgReviewDecisionExport;
225
+ declare function createAiwgIndexController(initialIndex?: AiwgFortemiIndexExport): AiwgIndexController;
226
+ declare function aiwgFortemiIndexToCommunityGraph(index: AiwgFortemiIndexExport, options?: AiwgIndexGraphOptions): {
227
+ nodes: {
228
+ id: string;
229
+ }[];
230
+ edges: {
231
+ source: string;
232
+ target: string;
233
+ kind: string;
234
+ weight: number;
235
+ }[];
236
+ communities: {
237
+ id: string;
238
+ nodes: string[];
239
+ }[];
240
+ };
241
+
242
+ export { AIWG_SCAN_REQUIRED_FIELDS, type AiwgChunkedIndexBuildOptions, type AiwgChunkedIndexBuildResult, type AiwgChunkedIndexDetailLoader, type AiwgChunkedIndexLoadOptions, type AiwgChunkedIndexLoader, type AiwgChunkedIndexProgress, type AiwgChunkedIndexProgressPhase, type AiwgChunkedIndexQueryOptions, type AiwgChunkedIndexQueryResult, type AiwgChunkedIndexValidationResult, type AiwgFortemiChunkDetailRef, type AiwgFortemiChunkManifest, type AiwgFortemiChunkPart, type AiwgFortemiChunkPartRef, type AiwgFortemiIndexExport, type AiwgFortemiProjectedRecord, type AiwgFortemiProvenance, type AiwgFortemiRecord, type AiwgFortemiRecordSource, type AiwgFortemiRecordType, type AiwgFortemiRelationship, type AiwgIndexController, type AiwgIndexControllerListener, type AiwgIndexControllerSnapshot, type AiwgIndexGraphOptions, type AiwgIndexQueryMatch, type AiwgIndexQueryOptions, type AiwgIndexQueryRankedItem, type AiwgIndexQueryResult, type AiwgIndexQueryWeights, type AiwgIndexValidationResult, type AiwgPrivacyClassification, type AiwgProvenanceConfidence, type AiwgReviewAction, type AiwgReviewDecision, type AiwgReviewDecisionExport, type AiwgReviewInput, aiwgFortemiIndexToCommunityGraph, assertAiwgFortemiChunkManifest, assertAiwgFortemiChunkPart, assertAiwgFortemiIndexExport, buildAiwgChunkedIndex, createAiwgFetchChunkLoader, createAiwgFetchDetailLoader, createAiwgIndexController, createAiwgReviewDecisionExport, getAiwgFortemiFacets, queryAiwgFortemiIndex, validateAiwgFortemiChunkManifest, validateAiwgFortemiChunkPart, validateAiwgFortemiIndexExport };