@sid-ai/sid-sdk 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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 SID
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,155 @@
1
+ # SID SDK for TypeScript
2
+
3
+ `@sid-ai/sid-sdk` turns search results into compact, model-facing document views.
4
+ It assigns stable short IDs, selects relevant snippets, tracks character ranges
5
+ already shown, masks repeated text, and renders SID's `<doc>` format.
6
+
7
+ Node.js 22+ is supported through ESM and CommonJS. The package includes the Rust
8
+ snippet engine compiled to WebAssembly; installation needs no compiler and runs
9
+ no install scripts. Browser and shared-memory worker-thread caches are not supported.
10
+
11
+ ## Installation and use
12
+
13
+ ```sh
14
+ npm install @sid-ai/sid-sdk
15
+ ```
16
+
17
+ ```ts
18
+ import { DocumentCache } from '@sid-ai/sid-sdk';
19
+
20
+ const cache = new DocumentCache({ language: 'english' });
21
+ cache.addDocument('database-id', {
22
+ title: 'Example',
23
+ content: 'The complete document text ...',
24
+ });
25
+ const view = cache.applySnippet('database-id', {
26
+ snippetField: 'content',
27
+ query: 'complete document',
28
+ });
29
+ console.log(view.renderXml());
30
+ cache.updateSeen(view);
31
+ ```
32
+
33
+ CommonJS: `const { DocumentCache } = require('@sid-ai/sid-sdk')`.
34
+ All SDK methods are synchronous, including automatic WASM initialization on first
35
+ snippet selection. Both entry points share the same classes.
36
+
37
+ ## API
38
+
39
+ - `new DocumentCache<T>({ language?, rangeMode? })`: defaults to English and lenient ranges.
40
+ - `addDocument(dataId, document)`: stores a `structuredClone` on first insertion and returns a stable five-letter ID. Re-adding an ID does not inspect or replace its document.
41
+ - `applySnippet(dataId, { snippetField, query, snippetSize?, minSeenOverlap?, displayFields?, language? })`: chooses a snippet and masks seen text. Defaults are 50 source tokens and 100 characters of minimum overlap.
42
+ - `getSingleSpanDocumentView(dataId, { snippetField?, snippetDisplaySpan?, displayFields? })`: displays an exact range, or the whole content when the range is omitted; ignores the seen ledger. Views without a snippet field require explicit display fields.
43
+ - `resolveCharRange(dataId, snippetField, [start, end])`: validates or clamps a model-provided range.
44
+ - `updateSeen(view)`: records only displayed spans. Render and update are separate operations.
45
+ - `fork(n)`: creates caches with shared documents, mappings, and ID stream, and independent copies of the parent's current seen ledger.
46
+ - `contains(dataId)`, `containsModelFacingId(modelId)`, `toDataId(modelId)`, `toModelFacingId(dataId)`, `getDocument(dataId)`, `getDocumentFromModelFacingId(modelId)`: lookups across a fork family; unknown IDs throw.
47
+ - `parseRenderedModelFacingId(reference)`: returns `[modelId, [start, end] | null]`.
48
+ - `renderMarkdownTable(views, displayFields?)`: tabular rendering of document views.
49
+ - `bm25SnippetWithStride(query, content, { windowSize?, stride?, language? })`: direct snippet helper, defaults to 50 tokens and stride 10.
50
+ - `IdStream({ alphabet?, length?, seed? })`: `mint()` returns an ID, `at(index)` does not consume it, and `next()` follows the iterator protocol. Exhaustion throws `IdSpaceExhausted`. Counters `space`, `minted`, and `remaining` are BigInts.
51
+
52
+ Document records can contain structured-cloneable values. Returned documents are
53
+ the shared stored objects, matching Python; avoid modifying them after recording
54
+ seen ranges. Display fields default to all document keys, so keep private fields
55
+ out of the record or pass an explicit list. The seen ledger is keyed by document
56
+ ID, matching Python: use one content field per document when tracking seen text.
57
+
58
+ ## Character ranges and language support
59
+
60
+ Ranges are half-open **Unicode code-point offsets**, matching Python, not UTF-16
61
+ indices used by JavaScript `String.slice`. For example, `😀a` has two SDK
62
+ characters. Combining marks count separately. Rendered references and
63
+ `doc_length` use the same coordinate system.
64
+
65
+ Lenient mode intersects partially overlapping ranges with the document. Strict
66
+ mode requires `0 <= start < end <= document length`. Empty, inverted, malformed,
67
+ unsafe-integer, and wholly disjoint ranges throw `InvalidCharacterRange`. Ranges
68
+ are never expanded to word boundaries. The snippet engine rejects strings with
69
+ unpaired UTF-16 surrogates rather than silently replacing them.
70
+
71
+ Named languages are Danish, Dutch, English, Finnish, French, German, Hungarian,
72
+ Italian, Norwegian, Portuguese, Russian, Spanish, and Swedish. `generic` uses
73
+ lowercase Unicode UAX #29 tokenization without removing stopwords. Named
74
+ languages use Alyze's stopword lists; there is no stemming. A per-call `language`
75
+ overrides the cache default. Stopword-only queries select the earliest window.
76
+
77
+ ## Python compatibility
78
+
79
+ The reference is [`sidhq/sid-python` at `c25f929`](https://github.com/sidhq/sid-python/tree/c25f9299a90d17735473ca401ae45fa4b41e25d8).
80
+ The Rust algorithm and Alyze 0.1.5 are retained. Tests include Python-generated
81
+ snippet offsets and exact XML/Markdown fixtures, including every language.
82
+
83
+ XML preserves SID's model-facing format: escape `&`, `<`, and `>`; leave quotes
84
+ unchanged; omit falsy attributes; write integers unquoted. This is the SID
85
+ observation format and is not general-purpose XML serialization. Lists join
86
+ with commas, booleans render as `True`/`False`, and `null` renders as `None` in
87
+ Markdown. JavaScript-only values and nested objects use JavaScript `String()`;
88
+ integral numbers render as integers because JavaScript does not distinguish
89
+ `1` from `1.0`. Use strings for custom metadata representations. Default field
90
+ order follows JavaScript key ordering; pass `displayFields` for explicit order.
91
+
92
+ Seeded ID streams are reproducible within this SDK but do not reproduce Python's
93
+ random seed expansion. Fork sharing and collision-free permutation semantics are
94
+ preserved. Invalid input throws `TypeError` or `RangeError`; document lookup
95
+ failures throw `Error`.
96
+
97
+ ## Development
98
+
99
+ Install Node.js 22+ and Rust through rustup. The checked-in toolchain selects
100
+ Rust 1.88.0 and the WASM target.
101
+
102
+ ```sh
103
+ cargo install wasm-bindgen-cli --version 0.2.100 --locked
104
+ npm ci
105
+ npm run check
106
+ ```
107
+
108
+ The ignored `sid-python/` checkout is only a development reference. To regenerate
109
+ fixtures, check out the pinned revision, build its extension with the Python
110
+ project's development instructions, then run:
111
+
112
+ ```sh
113
+ sid-python/.venv/bin/python scripts/generate-python-fixtures.py
114
+ ```
115
+
116
+ Normal builds and CI require no Python checkout. `npm run test:package` installs
117
+ the tarball into a temporary directory with lifecycle scripts disabled, checks
118
+ both module formats, and compiles TypeScript consumers.
119
+
120
+ ## Releases
121
+
122
+ Every successful push to `main` publishes its head revision, including documentation
123
+ changes. CI tests Node 22 and 24 on Linux, macOS, and Windows before publishing.
124
+ Versions begin at `0.1.0` and automatically increment the highest published or
125
+ reserved patch version. Versions change only in the release workspace; Git tags
126
+ identify source revisions, whose package manifest retains the development version.
127
+
128
+ The release queue serializes runs (up to GitHub's 100 pending-run limit). A `v*`
129
+ tag reserves a version for a SHA before publication. Rerun a failed workflow to
130
+ reuse that version and recover missing GitHub release metadata. Do not delete or
131
+ move reservation tags. Network, authorization, and version conflicts fail loudly.
132
+ An older delayed revision gets a `revision-<sha>` npm tag, so it cannot move
133
+ `latest` backward. npm publishing selects the tag directly and needs no separate
134
+ token-authorized `npm dist-tag` operation.
135
+
136
+ ### One-time npm setup
137
+
138
+ 1. Ensure the publishing account can create public packages in the `sid-ai` npm organization.
139
+ 2. Add a narrowly scoped, short-lived granular npm token as the repository/environment
140
+ secret `NPM_TOKEN`, with creation/publish rights and any required 2FA bypass.
141
+ Rerun the initial Release workflow to publish the fully tested `0.1.0` package.
142
+ 3. In the npm package settings, configure a GitHub trusted publisher: organization
143
+ `sidhq`, repository `sid-typescript`, workflow `release.yml`, environment `npm`.
144
+ Allow direct `npm publish`. Avoid required environment approvals if releases
145
+ should remain automatic.
146
+ 4. Remove the bootstrap secret and revoke the token. Subsequent runs authenticate
147
+ with GitHub OIDC and publish with provenance.
148
+
149
+ See [npm trusted publishing](https://docs.npmjs.com/trusted-publishers/) and
150
+ [GitHub concurrency](https://docs.github.com/en/actions/how-tos/write-workflows/choose-when-workflows-run/control-workflow-concurrency).
151
+
152
+ ## License
153
+
154
+ MIT. See [LICENSE](LICENSE) and [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)
155
+ for the vendored Python/Rust reference and bundled Rust dependency notices.