@semiont/api-client 0.2.33-build.84 → 0.2.33-build.86
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/{index-vuErmLIm.d.ts → index-CJqmerJr.d.ts} +33 -5
- package/dist/index.d.ts +4 -4
- package/dist/index.js +104 -77
- package/dist/index.js.map +1 -1
- package/dist/utils/index.d.ts +1 -1
- package/dist/utils/index.js +100 -74
- package/dist/utils/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -1585,7 +1585,7 @@ interface paths {
|
|
|
1585
1585
|
patch?: never;
|
|
1586
1586
|
trace?: never;
|
|
1587
1587
|
};
|
|
1588
|
-
"/api/
|
|
1588
|
+
"/api/clone-tokens/{token}": {
|
|
1589
1589
|
parameters: {
|
|
1590
1590
|
query?: never;
|
|
1591
1591
|
header?: never;
|
|
@@ -1626,7 +1626,7 @@ interface paths {
|
|
|
1626
1626
|
patch?: never;
|
|
1627
1627
|
trace?: never;
|
|
1628
1628
|
};
|
|
1629
|
-
"/api/
|
|
1629
|
+
"/api/clone-tokens/create-resource": {
|
|
1630
1630
|
parameters: {
|
|
1631
1631
|
query?: never;
|
|
1632
1632
|
header?: never;
|
|
@@ -3451,16 +3451,43 @@ interface TextPosition {
|
|
|
3451
3451
|
start: number;
|
|
3452
3452
|
end: number;
|
|
3453
3453
|
}
|
|
3454
|
+
type MatchQuality = 'exact' | 'normalized' | 'case-insensitive' | 'fuzzy';
|
|
3455
|
+
/**
|
|
3456
|
+
* Normalize text for comparison - handles common document editing changes
|
|
3457
|
+
*
|
|
3458
|
+
* Collapses whitespace, converts curly quotes to straight quotes,
|
|
3459
|
+
* and normalizes common punctuation variations.
|
|
3460
|
+
*/
|
|
3461
|
+
declare function normalizeText(text: string): string;
|
|
3462
|
+
/**
|
|
3463
|
+
* Find best match for text in content using multi-strategy search
|
|
3464
|
+
*
|
|
3465
|
+
* Shared core logic used by both findTextWithContext and validateAndCorrectOffsets.
|
|
3466
|
+
*
|
|
3467
|
+
* @param content - Full text content to search within
|
|
3468
|
+
* @param searchText - The text to find
|
|
3469
|
+
* @param positionHint - Optional hint for where to search (TextPositionSelector.start)
|
|
3470
|
+
* @returns Match with position and quality, or null if not found
|
|
3471
|
+
*/
|
|
3472
|
+
declare function findBestTextMatch(content: string, searchText: string, positionHint?: number): {
|
|
3473
|
+
start: number;
|
|
3474
|
+
end: number;
|
|
3475
|
+
matchQuality: MatchQuality;
|
|
3476
|
+
} | null;
|
|
3454
3477
|
/**
|
|
3455
3478
|
* Find text using exact match with optional prefix/suffix context
|
|
3456
3479
|
*
|
|
3457
3480
|
* When the exact text appears multiple times in the content, prefix and suffix
|
|
3458
3481
|
* are used to disambiguate and find the correct occurrence.
|
|
3459
3482
|
*
|
|
3483
|
+
* If exact text is not found, uses multi-strategy fuzzy matching (normalization,
|
|
3484
|
+
* case-insensitive, Levenshtein distance) to locate changed text.
|
|
3485
|
+
*
|
|
3460
3486
|
* @param content - Full text content to search within
|
|
3461
3487
|
* @param exact - The exact text to find
|
|
3462
3488
|
* @param prefix - Optional text that should appear immediately before the match
|
|
3463
3489
|
* @param suffix - Optional text that should appear immediately after the match
|
|
3490
|
+
* @param positionHint - Optional position hint (from TextPositionSelector) for fuzzy search
|
|
3464
3491
|
* @returns Position of the matched text, or null if not found
|
|
3465
3492
|
*
|
|
3466
3493
|
* @example
|
|
@@ -3471,7 +3498,7 @@ interface TextPosition {
|
|
|
3471
3498
|
* // Returns { start: 13, end: 20 }
|
|
3472
3499
|
* ```
|
|
3473
3500
|
*/
|
|
3474
|
-
declare function findTextWithContext(content: string, exact: string, prefix?: string, suffix?: string): TextPosition | null;
|
|
3501
|
+
declare function findTextWithContext(content: string, exact: string, prefix?: string, suffix?: string, positionHint?: number): TextPosition | null;
|
|
3475
3502
|
/**
|
|
3476
3503
|
* Verify that a position correctly points to the exact text
|
|
3477
3504
|
* Useful for debugging and validation
|
|
@@ -3664,6 +3691,7 @@ declare function scaleSvgToNative(svg: string, displayWidth: number, displayHeig
|
|
|
3664
3691
|
*
|
|
3665
3692
|
* @see https://www.w3.org/TR/annotation-model/#text-quote-selector
|
|
3666
3693
|
*/
|
|
3694
|
+
|
|
3667
3695
|
/**
|
|
3668
3696
|
* Extract prefix and suffix context for TextQuoteSelector
|
|
3669
3697
|
*
|
|
@@ -3699,7 +3727,7 @@ interface ValidatedAnnotation {
|
|
|
3699
3727
|
suffix?: string;
|
|
3700
3728
|
corrected: boolean;
|
|
3701
3729
|
fuzzyMatched?: boolean;
|
|
3702
|
-
matchQuality?:
|
|
3730
|
+
matchQuality?: MatchQuality;
|
|
3703
3731
|
}
|
|
3704
3732
|
/**
|
|
3705
3733
|
* Validate and correct AI-provided annotation offsets with fuzzy matching tolerance
|
|
@@ -3828,4 +3856,4 @@ declare function validateData<T>(schema: {
|
|
|
3828
3856
|
*/
|
|
3829
3857
|
declare function isValidEmail(email: string): boolean;
|
|
3830
3858
|
|
|
3831
|
-
export { type $defs as $, type AccessToken as A, type BaseUrl as B, type ContentFormat as C, getExactText as D, type EntityType as E, type FragmentSelector as F, type GoogleCredential as G, getAnnotationExactText as H, getPrimarySelector as I, type JobId as J, getTextPositionSelector as K, getTextQuoteSelector as L, type Motivation as M, getSvgSelector as N, getFragmentSelector as O, validateSvgMarkup as P, extractBoundingBox as Q, type ResourceUri as R, type SearchQuery as S, type TextPositionSelector as T, type UserDID as U, type TextPosition as V,
|
|
3859
|
+
export { type $defs as $, type AccessToken as A, type BaseUrl as B, type ContentFormat as C, getExactText as D, type EntityType as E, type FragmentSelector as F, type GoogleCredential as G, getAnnotationExactText as H, getPrimarySelector as I, type JobId as J, getTextPositionSelector as K, getTextQuoteSelector as L, type Motivation as M, getSvgSelector as N, getFragmentSelector as O, validateSvgMarkup as P, extractBoundingBox as Q, type ResourceUri as R, type SearchQuery as S, type TextPositionSelector as T, type UserDID as U, type TextPosition as V, type MatchQuality as W, normalizeText as X, findBestTextMatch as Y, findTextWithContext as Z, verifyPosition as _, type AnnotationUri as a, type LocaleInfo as a0, LOCALES as a1, getLocaleInfo as a2, getLocaleNativeName as a3, getLocaleEnglishName as a4, formatLocaleDisplay as a5, getAllLocaleCodes as a6, getResourceId as a7, getPrimaryRepresentation as a8, getPrimaryMediaType as a9, JWTTokenSchema as aA, validateData as aB, isValidEmail as aC, type AuthCode as aD, type MCPToken as aE, email as aF, authCode as aG, googleCredential as aH, accessToken as aI, refreshToken as aJ, mcpToken as aK, cloneToken as aL, jobId as aM, userDID as aN, entityType as aO, searchQuery as aP, baseUrl as aQ, resourceUri as aR, annotationUri as aS, resourceAnnotationUri as aT, getChecksum as aa, getLanguage as ab, getStorageUri as ac, getCreator as ad, getDerivedFrom as ae, isArchived as af, getResourceEntityTypes as ag, isDraft as ah, getNodeEncoding as ai, decodeRepresentation as aj, type Point as ak, type BoundingBox as al, createRectangleSvg as am, createPolygonSvg as an, createCircleSvg as ao, parseSvgSelector as ap, normalizeCoordinates as aq, scaleSvgToNative as ar, extractContext as as, type ValidatedAnnotation as at, validateAndCorrectOffsets as au, extractCharset as av, decodeWithCharset as aw, type ValidationSuccess as ax, type ValidationFailure as ay, type ValidationResult as az, type Email as b, type components as c, type RefreshToken as d, type CloneToken as e, type ResourceAnnotationUri as f, type TextQuoteSelector as g, type SvgSelector as h, type Selector as i, getBodySource as j, getBodyType as k, isBodyResolved as l, getTargetSource as m, getTargetSelector as n, type operations as o, type paths as p, hasTargetSelector as q, isHighlight as r, isReference as s, isAssessment as t, isComment as u, isTag as v, type webhooks as w, getCommentText as x, isStubReference as y, isResolvedReference as z };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { B as BaseUrl, R as ResourceUri, E as EntityType, A as AccessToken, a as AnnotationUri, c as components, b as Email, p as paths, d as RefreshToken, G as GoogleCredential, C as ContentFormat, S as SearchQuery, e as CloneToken, f as ResourceAnnotationUri, M as Motivation, U as UserDID, J as JobId } from './index-
|
|
2
|
-
export { $ as $defs,
|
|
1
|
+
import { B as BaseUrl, R as ResourceUri, E as EntityType, A as AccessToken, a as AnnotationUri, c as components, b as Email, p as paths, d as RefreshToken, G as GoogleCredential, C as ContentFormat, S as SearchQuery, e as CloneToken, f as ResourceAnnotationUri, M as Motivation, U as UserDID, J as JobId } from './index-CJqmerJr.js';
|
|
2
|
+
export { $ as $defs, aD as AuthCode, al as BoundingBox, F as FragmentSelector, aA as JWTTokenSchema, a1 as LOCALES, a0 as LocaleInfo, aE as MCPToken, W as MatchQuality, ak as Point, i as Selector, h as SvgSelector, V as TextPosition, T as TextPositionSelector, g as TextQuoteSelector, at as ValidatedAnnotation, ay as ValidationFailure, az as ValidationResult, ax as ValidationSuccess, aI as accessToken, aS as annotationUri, aG as authCode, aQ as baseUrl, aL as cloneToken, ao as createCircleSvg, an as createPolygonSvg, am as createRectangleSvg, aj as decodeRepresentation, aw as decodeWithCharset, aF as email, aO as entityType, Q as extractBoundingBox, av as extractCharset, as as extractContext, Y as findBestTextMatch, Z as findTextWithContext, a5 as formatLocaleDisplay, a6 as getAllLocaleCodes, H as getAnnotationExactText, j as getBodySource, k as getBodyType, aa as getChecksum, x as getCommentText, ad as getCreator, ae as getDerivedFrom, D as getExactText, O as getFragmentSelector, ab as getLanguage, a4 as getLocaleEnglishName, a2 as getLocaleInfo, a3 as getLocaleNativeName, ai as getNodeEncoding, a9 as getPrimaryMediaType, a8 as getPrimaryRepresentation, I as getPrimarySelector, ag as getResourceEntityTypes, a7 as getResourceId, ac as getStorageUri, N as getSvgSelector, n as getTargetSelector, m as getTargetSource, K as getTextPositionSelector, L as getTextQuoteSelector, aH as googleCredential, q as hasTargetSelector, af as isArchived, t as isAssessment, l as isBodyResolved, u as isComment, ah as isDraft, r as isHighlight, s as isReference, z as isResolvedReference, y as isStubReference, v as isTag, aC as isValidEmail, aM as jobId, aK as mcpToken, aq as normalizeCoordinates, X as normalizeText, o as operations, ap as parseSvgSelector, aJ as refreshToken, aT as resourceAnnotationUri, aR as resourceUri, ar as scaleSvgToNative, aP as searchQuery, aN as userDID, au as validateAndCorrectOffsets, aB as validateData, P as validateSvgMarkup, _ as verifyPosition, w as webhooks } from './index-CJqmerJr.js';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* TypeScript types for Server-Sent Events (SSE) streaming
|
|
@@ -878,8 +878,8 @@ declare class SemiontApiClient {
|
|
|
878
878
|
referencedBy: any[];
|
|
879
879
|
}>;
|
|
880
880
|
generateCloneToken(resourceUri: ResourceUri, options?: RequestOptions): Promise<ResponseContent<paths['/resources/{id}/clone-with-token']['post']>>;
|
|
881
|
-
getResourceByToken(token: CloneToken, options?: RequestOptions): Promise<ResponseContent<paths['/api/
|
|
882
|
-
createResourceFromToken(data: RequestContent<paths['/api/
|
|
881
|
+
getResourceByToken(token: CloneToken, options?: RequestOptions): Promise<ResponseContent<paths['/api/clone-tokens/{token}']['get']>>;
|
|
882
|
+
createResourceFromToken(data: RequestContent<paths['/api/clone-tokens/create-resource']['post']>, options?: RequestOptions): Promise<ResponseContent<paths['/api/clone-tokens/create-resource']['post']>>;
|
|
883
883
|
createAnnotation(resourceUri: ResourceUri, data: RequestContent<paths['/resources/{id}/annotations']['post']>, options?: RequestOptions): Promise<ResponseContent<paths['/resources/{id}/annotations']['post']>>;
|
|
884
884
|
getAnnotation(annotationUri: AnnotationUri, options?: RequestOptions): Promise<ResponseContent<paths['/annotations/{id}']['get']>>;
|
|
885
885
|
getResourceAnnotation(annotationUri: ResourceAnnotationUri, options?: RequestOptions): Promise<ResponseContent<paths['/resources/{resourceId}/annotations/{annotationId}']['get']>>;
|
package/dist/index.js
CHANGED
|
@@ -939,19 +939,20 @@ var SemiontApiClient = class {
|
|
|
939
939
|
}).json();
|
|
940
940
|
}
|
|
941
941
|
async generateCloneToken(resourceUri2, options) {
|
|
942
|
-
|
|
942
|
+
const id = resourceUri2.split("/").pop();
|
|
943
|
+
return this.http.post(`${this.baseUrl}/resources/${id}/clone-with-token`, {
|
|
943
944
|
...options,
|
|
944
945
|
auth: options?.auth
|
|
945
946
|
}).json();
|
|
946
947
|
}
|
|
947
948
|
async getResourceByToken(token, options) {
|
|
948
|
-
return this.http.get(`${this.baseUrl}/api/
|
|
949
|
+
return this.http.get(`${this.baseUrl}/api/clone-tokens/${token}`, {
|
|
949
950
|
...options,
|
|
950
951
|
auth: options?.auth
|
|
951
952
|
}).json();
|
|
952
953
|
}
|
|
953
954
|
async createResourceFromToken(data, options) {
|
|
954
|
-
return this.http.post(`${this.baseUrl}/api/
|
|
955
|
+
return this.http.post(`${this.baseUrl}/api/clone-tokens/create-resource`, {
|
|
955
956
|
json: data,
|
|
956
957
|
...options,
|
|
957
958
|
auth: options?.auth
|
|
@@ -1377,7 +1378,94 @@ function extractBoundingBox(svg) {
|
|
|
1377
1378
|
}
|
|
1378
1379
|
|
|
1379
1380
|
// src/utils/fuzzy-anchor.ts
|
|
1380
|
-
function
|
|
1381
|
+
function normalizeText(text) {
|
|
1382
|
+
return text.replace(/\s+/g, " ").replace(/[\u2018\u2019]/g, "'").replace(/[\u201C\u201D]/g, '"').replace(/\u2014/g, "--").replace(/\u2013/g, "-").trim();
|
|
1383
|
+
}
|
|
1384
|
+
function levenshteinDistance(str1, str2) {
|
|
1385
|
+
const len1 = str1.length;
|
|
1386
|
+
const len2 = str2.length;
|
|
1387
|
+
const matrix = [];
|
|
1388
|
+
for (let i = 0; i <= len1; i++) {
|
|
1389
|
+
matrix[i] = [i];
|
|
1390
|
+
}
|
|
1391
|
+
for (let j = 0; j <= len2; j++) {
|
|
1392
|
+
matrix[0][j] = j;
|
|
1393
|
+
}
|
|
1394
|
+
for (let i = 1; i <= len1; i++) {
|
|
1395
|
+
for (let j = 1; j <= len2; j++) {
|
|
1396
|
+
const cost = str1[i - 1] === str2[j - 1] ? 0 : 1;
|
|
1397
|
+
const deletion = matrix[i - 1][j] + 1;
|
|
1398
|
+
const insertion = matrix[i][j - 1] + 1;
|
|
1399
|
+
const substitution = matrix[i - 1][j - 1] + cost;
|
|
1400
|
+
matrix[i][j] = Math.min(deletion, insertion, substitution);
|
|
1401
|
+
}
|
|
1402
|
+
}
|
|
1403
|
+
return matrix[len1][len2];
|
|
1404
|
+
}
|
|
1405
|
+
function findBestTextMatch(content, searchText, positionHint) {
|
|
1406
|
+
const maxFuzzyDistance = Math.max(5, Math.floor(searchText.length * 0.05));
|
|
1407
|
+
const exactIndex = content.indexOf(searchText);
|
|
1408
|
+
if (exactIndex !== -1) {
|
|
1409
|
+
return {
|
|
1410
|
+
start: exactIndex,
|
|
1411
|
+
end: exactIndex + searchText.length,
|
|
1412
|
+
matchQuality: "exact"
|
|
1413
|
+
};
|
|
1414
|
+
}
|
|
1415
|
+
const normalizedSearch = normalizeText(searchText);
|
|
1416
|
+
const normalizedContent = normalizeText(content);
|
|
1417
|
+
const normalizedIndex = normalizedContent.indexOf(normalizedSearch);
|
|
1418
|
+
if (normalizedIndex !== -1) {
|
|
1419
|
+
let actualPos = 0;
|
|
1420
|
+
let normalizedPos = 0;
|
|
1421
|
+
while (normalizedPos < normalizedIndex && actualPos < content.length) {
|
|
1422
|
+
const char = content[actualPos];
|
|
1423
|
+
const normalizedChar = normalizeText(char);
|
|
1424
|
+
if (normalizedChar) {
|
|
1425
|
+
normalizedPos += normalizedChar.length;
|
|
1426
|
+
}
|
|
1427
|
+
actualPos++;
|
|
1428
|
+
}
|
|
1429
|
+
return {
|
|
1430
|
+
start: actualPos,
|
|
1431
|
+
end: actualPos + searchText.length,
|
|
1432
|
+
matchQuality: "normalized"
|
|
1433
|
+
};
|
|
1434
|
+
}
|
|
1435
|
+
const lowerContent = content.toLowerCase();
|
|
1436
|
+
const lowerSearch = searchText.toLowerCase();
|
|
1437
|
+
const caseInsensitiveIndex = lowerContent.indexOf(lowerSearch);
|
|
1438
|
+
if (caseInsensitiveIndex !== -1) {
|
|
1439
|
+
return {
|
|
1440
|
+
start: caseInsensitiveIndex,
|
|
1441
|
+
end: caseInsensitiveIndex + searchText.length,
|
|
1442
|
+
matchQuality: "case-insensitive"
|
|
1443
|
+
};
|
|
1444
|
+
}
|
|
1445
|
+
const windowSize = searchText.length;
|
|
1446
|
+
const searchRadius = Math.min(500, content.length);
|
|
1447
|
+
const searchStart = positionHint !== void 0 ? Math.max(0, positionHint - searchRadius) : 0;
|
|
1448
|
+
const searchEnd = positionHint !== void 0 ? Math.min(content.length, positionHint + searchRadius) : content.length;
|
|
1449
|
+
let bestMatch = null;
|
|
1450
|
+
for (let i = searchStart; i <= searchEnd - windowSize; i++) {
|
|
1451
|
+
const candidate = content.substring(i, i + windowSize);
|
|
1452
|
+
const distance = levenshteinDistance(searchText, candidate);
|
|
1453
|
+
if (distance <= maxFuzzyDistance) {
|
|
1454
|
+
if (!bestMatch || distance < bestMatch.distance) {
|
|
1455
|
+
bestMatch = { start: i, distance };
|
|
1456
|
+
}
|
|
1457
|
+
}
|
|
1458
|
+
}
|
|
1459
|
+
if (bestMatch) {
|
|
1460
|
+
return {
|
|
1461
|
+
start: bestMatch.start,
|
|
1462
|
+
end: bestMatch.start + windowSize,
|
|
1463
|
+
matchQuality: "fuzzy"
|
|
1464
|
+
};
|
|
1465
|
+
}
|
|
1466
|
+
return null;
|
|
1467
|
+
}
|
|
1468
|
+
function findTextWithContext(content, exact, prefix, suffix, positionHint) {
|
|
1381
1469
|
if (!exact) return null;
|
|
1382
1470
|
const occurrences = [];
|
|
1383
1471
|
let index = content.indexOf(exact);
|
|
@@ -1386,7 +1474,15 @@ function findTextWithContext(content, exact, prefix, suffix) {
|
|
|
1386
1474
|
index = content.indexOf(exact, index + 1);
|
|
1387
1475
|
}
|
|
1388
1476
|
if (occurrences.length === 0) {
|
|
1389
|
-
console.warn(`[FuzzyAnchor]
|
|
1477
|
+
console.warn(`[FuzzyAnchor] Exact text not found, trying fuzzy match: "${exact.substring(0, 50)}..."`);
|
|
1478
|
+
const fuzzyMatch = findBestTextMatch(content, exact, positionHint);
|
|
1479
|
+
if (fuzzyMatch) {
|
|
1480
|
+
console.warn(
|
|
1481
|
+
`[FuzzyAnchor] Found ${fuzzyMatch.matchQuality} match at position ${fuzzyMatch.start}`
|
|
1482
|
+
);
|
|
1483
|
+
return { start: fuzzyMatch.start, end: fuzzyMatch.end };
|
|
1484
|
+
}
|
|
1485
|
+
console.warn(`[FuzzyAnchor] No acceptable match found for: "${exact.substring(0, 50)}..."`);
|
|
1390
1486
|
return null;
|
|
1391
1487
|
}
|
|
1392
1488
|
if (occurrences.length === 1) {
|
|
@@ -1414,7 +1510,7 @@ function findTextWithContext(content, exact, prefix, suffix) {
|
|
|
1414
1510
|
const fuzzyPrefixMatch = !prefix || actualPrefix.includes(prefix.trim());
|
|
1415
1511
|
const fuzzySuffixMatch = !suffix || actualSuffix.includes(suffix.trim());
|
|
1416
1512
|
if (fuzzyPrefixMatch && fuzzySuffixMatch) {
|
|
1417
|
-
console.warn(`[FuzzyAnchor] Using fuzzy match at position ${pos2}`);
|
|
1513
|
+
console.warn(`[FuzzyAnchor] Using fuzzy context match at position ${pos2}`);
|
|
1418
1514
|
return { start: pos2, end: pos2 + exact.length };
|
|
1419
1515
|
}
|
|
1420
1516
|
}
|
|
@@ -1684,75 +1780,6 @@ function extractContext(content, start, end) {
|
|
|
1684
1780
|
}
|
|
1685
1781
|
return { prefix, suffix };
|
|
1686
1782
|
}
|
|
1687
|
-
function levenshteinDistance(str1, str2) {
|
|
1688
|
-
const len1 = str1.length;
|
|
1689
|
-
const len2 = str2.length;
|
|
1690
|
-
const matrix = [];
|
|
1691
|
-
for (let i = 0; i <= len1; i++) {
|
|
1692
|
-
matrix[i] = [i];
|
|
1693
|
-
}
|
|
1694
|
-
for (let j = 0; j <= len2; j++) {
|
|
1695
|
-
matrix[0][j] = j;
|
|
1696
|
-
}
|
|
1697
|
-
for (let i = 1; i <= len1; i++) {
|
|
1698
|
-
for (let j = 1; j <= len2; j++) {
|
|
1699
|
-
const cost = str1[i - 1] === str2[j - 1] ? 0 : 1;
|
|
1700
|
-
const deletion = matrix[i - 1][j] + 1;
|
|
1701
|
-
const insertion = matrix[i][j - 1] + 1;
|
|
1702
|
-
const substitution = matrix[i - 1][j - 1] + cost;
|
|
1703
|
-
matrix[i][j] = Math.min(deletion, insertion, substitution);
|
|
1704
|
-
}
|
|
1705
|
-
}
|
|
1706
|
-
return matrix[len1][len2];
|
|
1707
|
-
}
|
|
1708
|
-
function findBestMatch(content, searchText, aiStart, aiEnd) {
|
|
1709
|
-
const maxFuzzyDistance = Math.max(5, Math.floor(searchText.length * 0.05));
|
|
1710
|
-
const exactIndex = content.indexOf(searchText);
|
|
1711
|
-
if (exactIndex !== -1) {
|
|
1712
|
-
return {
|
|
1713
|
-
start: exactIndex,
|
|
1714
|
-
end: exactIndex + searchText.length,
|
|
1715
|
-
matchQuality: "exact"
|
|
1716
|
-
};
|
|
1717
|
-
}
|
|
1718
|
-
console.log("[findBestMatch] Exact match failed, trying case-insensitive...");
|
|
1719
|
-
const lowerContent = content.toLowerCase();
|
|
1720
|
-
const lowerSearch = searchText.toLowerCase();
|
|
1721
|
-
const caseInsensitiveIndex = lowerContent.indexOf(lowerSearch);
|
|
1722
|
-
if (caseInsensitiveIndex !== -1) {
|
|
1723
|
-
console.log("[findBestMatch] Found case-insensitive match");
|
|
1724
|
-
return {
|
|
1725
|
-
start: caseInsensitiveIndex,
|
|
1726
|
-
end: caseInsensitiveIndex + searchText.length,
|
|
1727
|
-
matchQuality: "case-insensitive"
|
|
1728
|
-
};
|
|
1729
|
-
}
|
|
1730
|
-
console.log("[findBestMatch] Case-insensitive failed, trying fuzzy match...");
|
|
1731
|
-
const windowSize = searchText.length;
|
|
1732
|
-
const searchRadius = Math.min(500, content.length);
|
|
1733
|
-
const searchStart = Math.max(0, aiStart - searchRadius);
|
|
1734
|
-
const searchEnd = Math.min(content.length, aiEnd + searchRadius);
|
|
1735
|
-
let bestMatch = null;
|
|
1736
|
-
for (let i = searchStart; i <= searchEnd - windowSize; i++) {
|
|
1737
|
-
const candidate = content.substring(i, i + windowSize);
|
|
1738
|
-
const distance = levenshteinDistance(searchText, candidate);
|
|
1739
|
-
if (distance <= maxFuzzyDistance) {
|
|
1740
|
-
if (!bestMatch || distance < bestMatch.distance) {
|
|
1741
|
-
bestMatch = { start: i, distance };
|
|
1742
|
-
console.log(`[findBestMatch] Found fuzzy match at ${i} with distance ${distance}`);
|
|
1743
|
-
}
|
|
1744
|
-
}
|
|
1745
|
-
}
|
|
1746
|
-
if (bestMatch) {
|
|
1747
|
-
return {
|
|
1748
|
-
start: bestMatch.start,
|
|
1749
|
-
end: bestMatch.start + windowSize,
|
|
1750
|
-
matchQuality: "fuzzy"
|
|
1751
|
-
};
|
|
1752
|
-
}
|
|
1753
|
-
console.log("[findBestMatch] No acceptable match found");
|
|
1754
|
-
return null;
|
|
1755
|
-
}
|
|
1756
1783
|
function validateAndCorrectOffsets(content, aiStart, aiEnd, exact) {
|
|
1757
1784
|
const exactPreview = exact.length > 50 ? exact.substring(0, 50) + "..." : exact;
|
|
1758
1785
|
const textAtOffset = content.substring(aiStart, aiEnd);
|
|
@@ -1776,7 +1803,7 @@ function validateAndCorrectOffsets(content, aiStart, aiEnd, exact) {
|
|
|
1776
1803
|
Found at AI offset (${aiStart}-${aiEnd}): "${foundPreview}"
|
|
1777
1804
|
Attempting multi-strategy search...`
|
|
1778
1805
|
);
|
|
1779
|
-
const match =
|
|
1806
|
+
const match = findBestTextMatch(content, exact, aiStart);
|
|
1780
1807
|
if (!match) {
|
|
1781
1808
|
const exactLong = exact.length > 100 ? exact.substring(0, 100) + "..." : exact;
|
|
1782
1809
|
console.error(
|
|
@@ -1911,6 +1938,6 @@ function getMimeCategory(mimeType) {
|
|
|
1911
1938
|
return "unsupported";
|
|
1912
1939
|
}
|
|
1913
1940
|
|
|
1914
|
-
export { APIError, JWTTokenSchema, LOCALES, SSEClient, SemiontApiClient, accessToken, annotationUri, authCode, baseUrl, cloneToken, createCircleSvg, createPolygonSvg, createRectangleSvg, decodeRepresentation, decodeWithCharset, email, entityType, extractBoundingBox, extractCharset, extractContext, findTextWithContext, formatLocaleDisplay, getAllLocaleCodes, getAnnotationExactText, getBodySource, getBodyType, getChecksum, getCommentText, getCreator, getDerivedFrom, getExactText, getExtensionForMimeType, getFragmentSelector, getLanguage, getLocaleEnglishName, getLocaleInfo, getLocaleNativeName, getMimeCategory, getNodeEncoding, getPrimaryMediaType, getPrimaryRepresentation, getPrimarySelector, getResourceEntityTypes, getResourceId, getStorageUri, getSvgSelector, getTargetSelector, getTargetSource, getTextPositionSelector, getTextQuoteSelector, googleCredential, hasTargetSelector, isArchived, isAssessment, isBodyResolved, isComment, isDraft, isHighlight, isImageMimeType, isPdfMimeType, isReference, isResolvedReference, isStubReference, isTag, isTextMimeType, isValidEmail, jobId, mcpToken, normalizeCoordinates, parseSvgSelector, refreshToken, resourceAnnotationUri, resourceUri, scaleSvgToNative, searchQuery, userDID, validateAndCorrectOffsets, validateData, validateSvgMarkup, verifyPosition };
|
|
1941
|
+
export { APIError, JWTTokenSchema, LOCALES, SSEClient, SemiontApiClient, accessToken, annotationUri, authCode, baseUrl, cloneToken, createCircleSvg, createPolygonSvg, createRectangleSvg, decodeRepresentation, decodeWithCharset, email, entityType, extractBoundingBox, extractCharset, extractContext, findBestTextMatch, findTextWithContext, formatLocaleDisplay, getAllLocaleCodes, getAnnotationExactText, getBodySource, getBodyType, getChecksum, getCommentText, getCreator, getDerivedFrom, getExactText, getExtensionForMimeType, getFragmentSelector, getLanguage, getLocaleEnglishName, getLocaleInfo, getLocaleNativeName, getMimeCategory, getNodeEncoding, getPrimaryMediaType, getPrimaryRepresentation, getPrimarySelector, getResourceEntityTypes, getResourceId, getStorageUri, getSvgSelector, getTargetSelector, getTargetSource, getTextPositionSelector, getTextQuoteSelector, googleCredential, hasTargetSelector, isArchived, isAssessment, isBodyResolved, isComment, isDraft, isHighlight, isImageMimeType, isPdfMimeType, isReference, isResolvedReference, isStubReference, isTag, isTextMimeType, isValidEmail, jobId, mcpToken, normalizeCoordinates, normalizeText, parseSvgSelector, refreshToken, resourceAnnotationUri, resourceUri, scaleSvgToNative, searchQuery, userDID, validateAndCorrectOffsets, validateData, validateSvgMarkup, verifyPosition };
|
|
1915
1942
|
//# sourceMappingURL=index.js.map
|
|
1916
1943
|
//# sourceMappingURL=index.js.map
|