@mindstudio-ai/agent 0.1.86 → 0.1.87
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/dist/cli.js +57 -14
- package/dist/index.d.ts +161 -0
- package/dist/index.js +46 -3
- package/dist/index.js.map +1 -1
- package/dist/postinstall.js +57 -14
- package/llms.txt +11 -3
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -1508,6 +1508,16 @@ interface Citation {
|
|
|
1508
1508
|
filename: string | null;
|
|
1509
1509
|
/** 1-based. Null for formats with no pagination (plain text, html). */
|
|
1510
1510
|
pageNumber: number | null;
|
|
1511
|
+
/**
|
|
1512
|
+
* Position within the document, 0-based.
|
|
1513
|
+
*
|
|
1514
|
+
* `(documentId, chunkIndex)` is the stable identity of a chunk — use it as
|
|
1515
|
+
* the key for an eval set or a regression check rather than matching on
|
|
1516
|
+
* `text`. Stable for as long as the corpus keeps its current configuration:
|
|
1517
|
+
* re-chunking a source (a different chunk size, say) moves the boundaries and
|
|
1518
|
+
* therefore renumbers, which is inherent rather than a wobble.
|
|
1519
|
+
*/
|
|
1520
|
+
chunkIndex: number | null;
|
|
1511
1521
|
/** Enclosing headings, outermost first. */
|
|
1512
1522
|
headingPath: string[];
|
|
1513
1523
|
/**
|
|
@@ -1527,12 +1537,49 @@ interface Citation {
|
|
|
1527
1537
|
*/
|
|
1528
1538
|
url: string;
|
|
1529
1539
|
}
|
|
1540
|
+
/** Where one retrieval branch put a hit, and what that branch scored it. */
|
|
1541
|
+
interface BranchPosition {
|
|
1542
|
+
/** 0-based position within that branch's own results. */
|
|
1543
|
+
rank: number;
|
|
1544
|
+
score: number;
|
|
1545
|
+
}
|
|
1546
|
+
/**
|
|
1547
|
+
* Which half of hybrid retrieval found a hit. Only present when `explain` was
|
|
1548
|
+
* requested — see {@link SearchOptions.explain}.
|
|
1549
|
+
*/
|
|
1550
|
+
interface SearchExplain {
|
|
1551
|
+
/** Semantic (embedding) retrieval. Null if this branch didn't find the hit. */
|
|
1552
|
+
dense: BranchPosition | null;
|
|
1553
|
+
/** Keyword/IDF retrieval. Null when `hybrid` is off, or if it didn't find it. */
|
|
1554
|
+
lexical: BranchPosition | null;
|
|
1555
|
+
matchedVia: 'dense' | 'lexical' | 'both';
|
|
1556
|
+
}
|
|
1530
1557
|
interface SearchHit {
|
|
1531
1558
|
/** Provider relevance score. Comparable within a response, not across them. */
|
|
1532
1559
|
score: number;
|
|
1533
1560
|
/** The matched chunk, prefixed with its heading path for context. */
|
|
1534
1561
|
text: string;
|
|
1535
1562
|
citation: Citation;
|
|
1563
|
+
/**
|
|
1564
|
+
* Where retrieval put this hit BEFORE reranking, and what it scored.
|
|
1565
|
+
*
|
|
1566
|
+
* With reranking on, `score` is the reranker's relevance score and this is
|
|
1567
|
+
* the retriever's — different quantities, so they're kept apart rather than
|
|
1568
|
+
* blended. Comparing `retrievalRank` with the hit's final position is how you
|
|
1569
|
+
* see what reranking actually did ("retrieved 7th, reranked to 1st").
|
|
1570
|
+
*
|
|
1571
|
+
* Named for the stage rather than the method: it's a fused hybrid score when
|
|
1572
|
+
* `hybrid` is on and a cosine similarity when it's off.
|
|
1573
|
+
*/
|
|
1574
|
+
retrievalRank?: number;
|
|
1575
|
+
retrievalScore?: number;
|
|
1576
|
+
/** Only when `explain` was requested. */
|
|
1577
|
+
explain?: SearchExplain;
|
|
1578
|
+
/** Only when `expand` was requested. Outermost first, so `[...before, text, ...after]` reads in order. */
|
|
1579
|
+
neighbors?: {
|
|
1580
|
+
before: string[];
|
|
1581
|
+
after: string[];
|
|
1582
|
+
};
|
|
1536
1583
|
}
|
|
1537
1584
|
/**
|
|
1538
1585
|
* Per-query overrides.
|
|
@@ -1566,6 +1613,23 @@ interface SearchOptions {
|
|
|
1566
1613
|
* that an embedding model never learned. Rarely worth disabling.
|
|
1567
1614
|
*/
|
|
1568
1615
|
hybrid?: boolean;
|
|
1616
|
+
/**
|
|
1617
|
+
* Report which branch found each hit, and where each ranked it.
|
|
1618
|
+
*
|
|
1619
|
+
* A debugging aid, off by default because it costs two extra round trips: a
|
|
1620
|
+
* fused result carries one blended score, so the branches have to be asked
|
|
1621
|
+
* separately. Results and their order are identical either way — this only
|
|
1622
|
+
* adds {@link SearchHit.explain}.
|
|
1623
|
+
*/
|
|
1624
|
+
explain?: boolean;
|
|
1625
|
+
/**
|
|
1626
|
+
* Also return this many chunks either side of each hit, in
|
|
1627
|
+
* {@link SearchHit.neighbors} — for showing a passage in context. 0-2.
|
|
1628
|
+
*
|
|
1629
|
+
* `text` is untouched, so citations and highlighting still point at the
|
|
1630
|
+
* chunk that actually matched.
|
|
1631
|
+
*/
|
|
1632
|
+
expand?: number;
|
|
1569
1633
|
}
|
|
1570
1634
|
interface AddOptions {
|
|
1571
1635
|
/**
|
|
@@ -1585,6 +1649,68 @@ interface DataSourceDocument {
|
|
|
1585
1649
|
createdAt: string;
|
|
1586
1650
|
ingestedAt: string | null;
|
|
1587
1651
|
}
|
|
1652
|
+
/** One chunk exactly as it was indexed. See {@link DataSource.chunks}. */
|
|
1653
|
+
interface DataSourceChunk {
|
|
1654
|
+
index: number;
|
|
1655
|
+
text: string;
|
|
1656
|
+
pageNumber: number;
|
|
1657
|
+
headingPath: string[];
|
|
1658
|
+
/**
|
|
1659
|
+
* Offsets into the page's extracted markdown. Null for PDFs, which carry a
|
|
1660
|
+
* `boundingBox` instead — there is no character stream to point into.
|
|
1661
|
+
*/
|
|
1662
|
+
charStart: number | null;
|
|
1663
|
+
charEnd: number | null;
|
|
1664
|
+
boundingBox?: {
|
|
1665
|
+
topLeftX: number;
|
|
1666
|
+
topLeftY: number;
|
|
1667
|
+
bottomRightX: number;
|
|
1668
|
+
bottomRightY: number;
|
|
1669
|
+
};
|
|
1670
|
+
/** base64 of a Float32Array. Only when `vectors: true` was passed. */
|
|
1671
|
+
vector?: string;
|
|
1672
|
+
}
|
|
1673
|
+
/** How a corpus was built and what is in it. See {@link DataSource.stats}. */
|
|
1674
|
+
interface DataSourceStats {
|
|
1675
|
+
/** False for a source nothing has created yet — everything else reads zero. */
|
|
1676
|
+
exists: boolean;
|
|
1677
|
+
documentCount: number;
|
|
1678
|
+
counts: {
|
|
1679
|
+
total: number;
|
|
1680
|
+
done: number;
|
|
1681
|
+
processing: number;
|
|
1682
|
+
error: number;
|
|
1683
|
+
};
|
|
1684
|
+
chunkCount: number;
|
|
1685
|
+
/** Original document bytes, not index size. */
|
|
1686
|
+
storageBytes: number;
|
|
1687
|
+
lastIngestedAt: string | null;
|
|
1688
|
+
/**
|
|
1689
|
+
* The configuration these documents were actually built with — not the
|
|
1690
|
+
* platform default, and not necessarily the newest. Changing it is an
|
|
1691
|
+
* explicit, owner-triggered migration.
|
|
1692
|
+
*/
|
|
1693
|
+
pipeline: {
|
|
1694
|
+
version: number;
|
|
1695
|
+
embeddingModelId: string;
|
|
1696
|
+
dimensions: number;
|
|
1697
|
+
chunking: {
|
|
1698
|
+
strategy: string;
|
|
1699
|
+
version: number;
|
|
1700
|
+
maxChars: number;
|
|
1701
|
+
minChars: number;
|
|
1702
|
+
dropBlockTypes: string[];
|
|
1703
|
+
};
|
|
1704
|
+
contextual: {
|
|
1705
|
+
enabled: boolean;
|
|
1706
|
+
modelId: string | null;
|
|
1707
|
+
};
|
|
1708
|
+
images: {
|
|
1709
|
+
describe: boolean;
|
|
1710
|
+
modelId: string | null;
|
|
1711
|
+
};
|
|
1712
|
+
} | null;
|
|
1713
|
+
}
|
|
1588
1714
|
/**
|
|
1589
1715
|
* A typed handle to one data source. Lazy — nothing executes until a method is
|
|
1590
1716
|
* awaited, so it's safe to `defineDataSource()` at module scope and import the
|
|
@@ -1602,10 +1728,39 @@ declare class DataSource {
|
|
|
1602
1728
|
* Returns chunks ranked by relevance, each with a citation. Searching a
|
|
1603
1729
|
* source that doesn't exist yet returns no results rather than throwing —
|
|
1604
1730
|
* code may name a corpus the build hasn't populated.
|
|
1731
|
+
*
|
|
1732
|
+
* **Deterministic** for a fixed corpus and configuration: the same query
|
|
1733
|
+
* returns the same hits in the same order, so it's safe to build an eval set
|
|
1734
|
+
* or a regression check on top of it. There is no seed to set. Two things do
|
|
1735
|
+
* legitimately move the results: adding or removing documents, and changing
|
|
1736
|
+
* the corpus configuration — both of which you control.
|
|
1605
1737
|
*/
|
|
1606
1738
|
search(query: string, options?: SearchOptions): Promise<{
|
|
1607
1739
|
results: SearchHit[];
|
|
1740
|
+
latencyMs: number;
|
|
1608
1741
|
}>;
|
|
1742
|
+
/**
|
|
1743
|
+
* What is in the corpus, and how it was built.
|
|
1744
|
+
*
|
|
1745
|
+
* Document and chunk counts, storage, and the embedding model and chunking
|
|
1746
|
+
* settings actually in effect — which is not the same as the platform
|
|
1747
|
+
* default, since a corpus keeps the configuration it was built with until
|
|
1748
|
+
* someone migrates it.
|
|
1749
|
+
*/
|
|
1750
|
+
stats(): Promise<DataSourceStats>;
|
|
1751
|
+
/**
|
|
1752
|
+
* Every chunk of one document, exactly as it was indexed.
|
|
1753
|
+
*
|
|
1754
|
+
* The direct answer to "why isn't this document coming back?" — search only
|
|
1755
|
+
* shows you the chunks that surface, which is no help when none do. Reading
|
|
1756
|
+
* how a document was actually split usually is.
|
|
1757
|
+
*
|
|
1758
|
+
* Pass `{ vectors: true }` to include each chunk's embedding. Large: roughly
|
|
1759
|
+
* 8KB per chunk, so a 500-chunk document is several megabytes.
|
|
1760
|
+
*/
|
|
1761
|
+
chunks(documentId: string, options?: {
|
|
1762
|
+
vectors?: boolean;
|
|
1763
|
+
}): Promise<DataSourceChunk[]>;
|
|
1609
1764
|
/**
|
|
1610
1765
|
* Add a document to the corpus.
|
|
1611
1766
|
*
|
|
@@ -2300,6 +2455,12 @@ declare class MindStudioAgent$1 {
|
|
|
2300
2455
|
*
|
|
2301
2456
|
* Gets a presigned upload request from the API, POSTs the file as
|
|
2302
2457
|
* multipart/form-data, and returns the permanent public URL.
|
|
2458
|
+
*
|
|
2459
|
+
* @deprecated For app file storage use the `files` store
|
|
2460
|
+
* (`files.defineStore(...).put(...)`) — private by default, app-scoped, and
|
|
2461
|
+
* served on the app's own domain. `uploadFile` uploads to the shared account
|
|
2462
|
+
* media CDN; it remains only for account-level assets (e.g. an agent avatar
|
|
2463
|
+
* passed to `changeProfilePicture`).
|
|
2303
2464
|
*/
|
|
2304
2465
|
uploadFile(content: Buffer | Uint8Array, options: {
|
|
2305
2466
|
extension: string;
|
package/dist/index.js
CHANGED
|
@@ -2128,17 +2128,54 @@ var DataSource = class {
|
|
|
2128
2128
|
* Returns chunks ranked by relevance, each with a citation. Searching a
|
|
2129
2129
|
* source that doesn't exist yet returns no results rather than throwing —
|
|
2130
2130
|
* code may name a corpus the build hasn't populated.
|
|
2131
|
+
*
|
|
2132
|
+
* **Deterministic** for a fixed corpus and configuration: the same query
|
|
2133
|
+
* returns the same hits in the same order, so it's safe to build an eval set
|
|
2134
|
+
* or a regression check on top of it. There is no seed to set. Two things do
|
|
2135
|
+
* legitimately move the results: adding or removing documents, and changing
|
|
2136
|
+
* the corpus configuration — both of which you control.
|
|
2131
2137
|
*/
|
|
2132
2138
|
async search(query, options) {
|
|
2133
|
-
const { results } = await this._call("search", {
|
|
2139
|
+
const { results, latencyMs } = await this._call("search", {
|
|
2134
2140
|
slug: this._slug,
|
|
2135
2141
|
query,
|
|
2136
2142
|
...options?.topK !== void 0 ? { topK: options.topK } : {},
|
|
2137
2143
|
...options?.scoreThreshold !== void 0 ? { scoreThreshold: options.scoreThreshold } : {},
|
|
2138
2144
|
...options?.rerank !== void 0 ? { rerank: options.rerank } : {},
|
|
2139
|
-
...options?.hybrid !== void 0 ? { hybrid: options.hybrid } : {}
|
|
2145
|
+
...options?.hybrid !== void 0 ? { hybrid: options.hybrid } : {},
|
|
2146
|
+
...options?.explain !== void 0 ? { explain: options.explain } : {},
|
|
2147
|
+
...options?.expand !== void 0 ? { expand: options.expand } : {}
|
|
2140
2148
|
});
|
|
2141
|
-
return { results: results ?? [] };
|
|
2149
|
+
return { results: results ?? [], latencyMs: latencyMs ?? 0 };
|
|
2150
|
+
}
|
|
2151
|
+
/**
|
|
2152
|
+
* What is in the corpus, and how it was built.
|
|
2153
|
+
*
|
|
2154
|
+
* Document and chunk counts, storage, and the embedding model and chunking
|
|
2155
|
+
* settings actually in effect — which is not the same as the platform
|
|
2156
|
+
* default, since a corpus keeps the configuration it was built with until
|
|
2157
|
+
* someone migrates it.
|
|
2158
|
+
*/
|
|
2159
|
+
async stats() {
|
|
2160
|
+
return this._call("stats", { slug: this._slug });
|
|
2161
|
+
}
|
|
2162
|
+
/**
|
|
2163
|
+
* Every chunk of one document, exactly as it was indexed.
|
|
2164
|
+
*
|
|
2165
|
+
* The direct answer to "why isn't this document coming back?" — search only
|
|
2166
|
+
* shows you the chunks that surface, which is no help when none do. Reading
|
|
2167
|
+
* how a document was actually split usually is.
|
|
2168
|
+
*
|
|
2169
|
+
* Pass `{ vectors: true }` to include each chunk's embedding. Large: roughly
|
|
2170
|
+
* 8KB per chunk, so a 500-chunk document is several megabytes.
|
|
2171
|
+
*/
|
|
2172
|
+
async chunks(documentId, options) {
|
|
2173
|
+
const { chunks } = await this._call("chunks", {
|
|
2174
|
+
slug: this._slug,
|
|
2175
|
+
documentId,
|
|
2176
|
+
...options?.vectors ? { vectors: true } : {}
|
|
2177
|
+
});
|
|
2178
|
+
return chunks ?? [];
|
|
2142
2179
|
}
|
|
2143
2180
|
/**
|
|
2144
2181
|
* Add a document to the corpus.
|
|
@@ -5572,6 +5609,12 @@ var MindStudioAgent = class {
|
|
|
5572
5609
|
*
|
|
5573
5610
|
* Gets a presigned upload request from the API, POSTs the file as
|
|
5574
5611
|
* multipart/form-data, and returns the permanent public URL.
|
|
5612
|
+
*
|
|
5613
|
+
* @deprecated For app file storage use the `files` store
|
|
5614
|
+
* (`files.defineStore(...).put(...)`) — private by default, app-scoped, and
|
|
5615
|
+
* served on the app's own domain. `uploadFile` uploads to the shared account
|
|
5616
|
+
* media CDN; it remains only for account-level assets (e.g. an agent avatar
|
|
5617
|
+
* passed to `changeProfilePicture`).
|
|
5575
5618
|
*/
|
|
5576
5619
|
async uploadFile(content, options) {
|
|
5577
5620
|
const filename = options.filename ?? `upload.${options.extension}`;
|