@anuma/sdk 10.5.0 → 10.5.1
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/expo/index.cjs +130 -6
- package/dist/expo/index.mjs +129 -6
- package/dist/react/{chunk-6ANL34M3.mjs → chunk-6QCUNXU6.mjs} +1 -0
- package/dist/react/{consolidate-JL4P6FXW.mjs → consolidate-RASCVKD2.mjs} +1 -1
- package/dist/react/index.cjs +130 -6
- package/dist/react/index.mjs +132 -8
- package/dist/server/{chunk-BIMEZT3O.mjs → chunk-JEY3L7WD.mjs} +1 -0
- package/dist/server/{consolidate-JZJYY3SZ.mjs → consolidate-5DFDLGSS.mjs} +1 -1
- package/dist/server/index.cjs +130 -6
- package/dist/server/index.mjs +132 -8
- package/package.json +1 -1
package/dist/expo/index.cjs
CHANGED
|
@@ -19287,6 +19287,7 @@ init_logger();
|
|
|
19287
19287
|
init_redactor();
|
|
19288
19288
|
|
|
19289
19289
|
// src/lib/memory/entitySalience.ts
|
|
19290
|
+
init_patterns();
|
|
19290
19291
|
var GENERIC_ENTITY_NAMES = /* @__PURE__ */ new Set([
|
|
19291
19292
|
"today",
|
|
19292
19293
|
"tomorrow",
|
|
@@ -19432,6 +19433,125 @@ var WEAK_MODIFIERS = /* @__PURE__ */ new Set([
|
|
|
19432
19433
|
"and",
|
|
19433
19434
|
"or"
|
|
19434
19435
|
]);
|
|
19436
|
+
var MAX_ENTITY_NAME_LENGTH = 120;
|
|
19437
|
+
var MAX_ENTITY_NAME_TOKENS = 11;
|
|
19438
|
+
var PREFIXED_HEX = /^0x[0-9a-f]{16,}$/i;
|
|
19439
|
+
var BARE_HEX = /^[0-9a-f]{32,}$/i;
|
|
19440
|
+
var BASE58_STRING = /^[1-9A-HJ-NP-Za-km-z]{32,88}$/;
|
|
19441
|
+
var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
19442
|
+
var TRUNCATED_ID = /^[0-9a-z]{3,}(?:…|\.{2,3})[0-9a-z]{3,}$/i;
|
|
19443
|
+
var KEY_SEGMENT_MIN_LENGTH = 16;
|
|
19444
|
+
var LONG_DIGIT_RUN = /^\d{6,}$/;
|
|
19445
|
+
var CURRENCY_MARKED = /[$€£¥₹₿]\d|\d[$€£¥₹₿]/;
|
|
19446
|
+
var NUMERIC_TOKEN = /^[~≈+\-−]?(?:us\$|[$€£¥₹₿])?\d(?:[\d,.]*\d)?(?:k|mm|m|bn|b|t|x|%|[$€£¥₹₿])?$/i;
|
|
19447
|
+
var PLAIN_YEAR = /^(?:1\d{3}|20\d{2})$/;
|
|
19448
|
+
var SUFFIXED_NAME = /^\d*[1-9][kmb]$/i;
|
|
19449
|
+
var BARE_INTEGER = /^\d+$/;
|
|
19450
|
+
var TICKER = /^\$?[A-Z]{2,6}$/;
|
|
19451
|
+
var DETACHED_CURRENCY_SYMBOL = /(^|\s)([$€£¥₹₿])\s+(?=\d)|(\d)\s+([$€£¥₹₿])(?=\s|$)/gu;
|
|
19452
|
+
var LEADING_PUNCTUATION = /^[^\p{L}\p{N}$€£¥₹₿~≈+\-−]+/u;
|
|
19453
|
+
var TRAILING_KEPT_CHARACTER = /[\p{L}\p{N}$€£¥₹₿%]/u;
|
|
19454
|
+
var LEADING_CURRENCY_CODES = /* @__PURE__ */ new Set(["usd", "eur", "gbp", "jpy", "cad", "aud", "chf", "cny"]);
|
|
19455
|
+
var QUANTITY_UNIT_WORDS = /* @__PURE__ */ new Set([
|
|
19456
|
+
"usd",
|
|
19457
|
+
"usdc",
|
|
19458
|
+
"usdt",
|
|
19459
|
+
"eur",
|
|
19460
|
+
"gbp",
|
|
19461
|
+
"sol",
|
|
19462
|
+
"eth",
|
|
19463
|
+
"btc",
|
|
19464
|
+
"dollar",
|
|
19465
|
+
"dollars",
|
|
19466
|
+
"euro",
|
|
19467
|
+
"euros",
|
|
19468
|
+
"buck",
|
|
19469
|
+
"bucks",
|
|
19470
|
+
"k",
|
|
19471
|
+
"thousand",
|
|
19472
|
+
"million",
|
|
19473
|
+
"billion",
|
|
19474
|
+
"trillion",
|
|
19475
|
+
"share",
|
|
19476
|
+
"shares",
|
|
19477
|
+
"token",
|
|
19478
|
+
"tokens",
|
|
19479
|
+
"coin",
|
|
19480
|
+
"coins",
|
|
19481
|
+
"unit",
|
|
19482
|
+
"units",
|
|
19483
|
+
"position",
|
|
19484
|
+
"balance",
|
|
19485
|
+
"stake",
|
|
19486
|
+
"holdings"
|
|
19487
|
+
]);
|
|
19488
|
+
var AMOUNT_WORDS = /* @__PURE__ */ new Set([...QUANTITY_UNIT_WORDS, "percent", "of"]);
|
|
19489
|
+
var NAME_PII_CATEGORIES = /* @__PURE__ */ new Set(["EMAIL", "PHONE", "SSN", "CREDIT_CARD"]);
|
|
19490
|
+
var NAME_PII_PATTERNS = PII_PATTERNS.filter(
|
|
19491
|
+
(pattern) => NAME_PII_CATEGORIES.has(pattern.category) && pattern.context === void 0
|
|
19492
|
+
);
|
|
19493
|
+
var KEPT_PLACEHOLDER_CATEGORIES = /* @__PURE__ */ new Set(["PERSON", "LOCATION", "ORG"]);
|
|
19494
|
+
var PLACEHOLDER_TOKEN = /\b([A-Za-z]+(?:_[A-Za-z]+)*)_\d+\b/g;
|
|
19495
|
+
function trimPunctuation(token) {
|
|
19496
|
+
const chars = Array.from(token.replace(LEADING_PUNCTUATION, ""));
|
|
19497
|
+
let end = chars.length;
|
|
19498
|
+
while (end > 0 && !TRAILING_KEPT_CHARACTER.test(chars[end - 1])) end--;
|
|
19499
|
+
return chars.slice(0, end).join("");
|
|
19500
|
+
}
|
|
19501
|
+
function hasLetterAndDigit(text16) {
|
|
19502
|
+
return /\p{L}/u.test(text16) && /\p{N}/u.test(text16);
|
|
19503
|
+
}
|
|
19504
|
+
function isIdentifierToken(token) {
|
|
19505
|
+
if (PREFIXED_HEX.test(token) || BARE_HEX.test(token) || BASE58_STRING.test(token)) return true;
|
|
19506
|
+
if (UUID.test(token) || LONG_DIGIT_RUN.test(token)) return true;
|
|
19507
|
+
if (TRUNCATED_ID.test(token) && hasLetterAndDigit(token)) return true;
|
|
19508
|
+
return token.split(/[-_.]/).some((segment) => segment.length >= KEY_SEGMENT_MIN_LENGTH && hasLetterAndDigit(segment));
|
|
19509
|
+
}
|
|
19510
|
+
function containsStructuredPii(name) {
|
|
19511
|
+
return NAME_PII_PATTERNS.some(
|
|
19512
|
+
(pattern) => (name.match(pattern.regex) ?? []).some((match) => pattern.validate?.(match) ?? true)
|
|
19513
|
+
);
|
|
19514
|
+
}
|
|
19515
|
+
function isAmountUnitToken(token) {
|
|
19516
|
+
return NUMERIC_TOKEN.test(token) || TICKER.test(token) || AMOUNT_WORDS.has(token.toLowerCase());
|
|
19517
|
+
}
|
|
19518
|
+
function isAmountWordOrNumber(token) {
|
|
19519
|
+
return NUMERIC_TOKEN.test(token) || AMOUNT_WORDS.has(token.toLowerCase());
|
|
19520
|
+
}
|
|
19521
|
+
function isAmount(tokens) {
|
|
19522
|
+
const start = LEADING_CURRENCY_CODES.has(tokens[0]?.toLowerCase() ?? "") ? 1 : 0;
|
|
19523
|
+
const first = tokens[start];
|
|
19524
|
+
if (first === void 0 || !NUMERIC_TOKEN.test(first)) return false;
|
|
19525
|
+
const units = tokens.slice(start + 1);
|
|
19526
|
+
if (start === 0 && units.length === 0)
|
|
19527
|
+
return !PLAIN_YEAR.test(first) && !SUFFIXED_NAME.test(first);
|
|
19528
|
+
if (!units.every(isAmountUnitToken)) return false;
|
|
19529
|
+
return start === 1 || !BARE_INTEGER.test(first) || units.some(isAmountWordOrNumber);
|
|
19530
|
+
}
|
|
19531
|
+
function hasQuantityPhrase(tokens) {
|
|
19532
|
+
return tokens.some(
|
|
19533
|
+
(token, i) => NUMERIC_TOKEN.test(token) && QUANTITY_UNIT_WORDS.has(tokens[i + 1]?.toLowerCase() ?? "")
|
|
19534
|
+
);
|
|
19535
|
+
}
|
|
19536
|
+
function isIdentifierOrAmountEntityName(name) {
|
|
19537
|
+
const trimmed = name.trim();
|
|
19538
|
+
if (trimmed.length > MAX_ENTITY_NAME_LENGTH) return true;
|
|
19539
|
+
if (containsStructuredPii(trimmed)) return true;
|
|
19540
|
+
const tokens = trimmed.replace(DETACHED_CURRENCY_SYMBOL, "$1$2$3$4").split(/\s+/).map(trimPunctuation).filter((token) => token.length > 0);
|
|
19541
|
+
if (tokens.length === 0) return false;
|
|
19542
|
+
if (tokens.length > MAX_ENTITY_NAME_TOKENS) return true;
|
|
19543
|
+
if (tokens.some(isIdentifierToken)) return true;
|
|
19544
|
+
if (tokens.some((token) => CURRENCY_MARKED.test(token))) return true;
|
|
19545
|
+
return isAmount(tokens) || hasQuantityPhrase(tokens);
|
|
19546
|
+
}
|
|
19547
|
+
function restoreEntityName(name, redactor) {
|
|
19548
|
+
for (const [token, category] of name.matchAll(PLACEHOLDER_TOKEN)) {
|
|
19549
|
+
if (KEPT_PLACEHOLDER_CATEGORIES.has(category.toUpperCase())) continue;
|
|
19550
|
+
if (redactor.restoreForStorage(token).text !== token) return null;
|
|
19551
|
+
}
|
|
19552
|
+
const restored = redactor.restoreForStorage(name);
|
|
19553
|
+
return restored.unresolved || isIdentifierOrAmountEntityName(restored.text) ? null : restored.text;
|
|
19554
|
+
}
|
|
19435
19555
|
|
|
19436
19556
|
// src/lib/memory/injectionClassifier.ts
|
|
19437
19557
|
init_logger();
|
|
@@ -22244,8 +22364,8 @@ function restoreCandidates(candidates, redactor, ownNames) {
|
|
|
22244
22364
|
...c,
|
|
22245
22365
|
content: content.text,
|
|
22246
22366
|
entities: c.entities.flatMap((e) => {
|
|
22247
|
-
const
|
|
22248
|
-
return
|
|
22367
|
+
const name = restoreEntityName(e.name, redactor);
|
|
22368
|
+
return name === null ? [] : [{ ...e, name }];
|
|
22249
22369
|
})
|
|
22250
22370
|
},
|
|
22251
22371
|
unresolved: content.unresolved
|
|
@@ -22513,18 +22633,21 @@ function validateCandidates(parsed, validIds, userIds, fallbackSourceId, ownName
|
|
|
22513
22633
|
}
|
|
22514
22634
|
return out;
|
|
22515
22635
|
}
|
|
22636
|
+
function isAcceptedEntityName(name) {
|
|
22637
|
+
return name.length > 0 && !isGenericEntityName(name) && !isIdentifierOrAmountEntityName(name);
|
|
22638
|
+
}
|
|
22516
22639
|
function parseEntities(raw) {
|
|
22517
22640
|
const out = [];
|
|
22518
22641
|
for (const e of raw) {
|
|
22519
22642
|
if (typeof e === "string") {
|
|
22520
22643
|
const name2 = e.trim();
|
|
22521
|
-
if (
|
|
22644
|
+
if (isAcceptedEntityName(name2)) out.push({ name: name2 });
|
|
22522
22645
|
continue;
|
|
22523
22646
|
}
|
|
22524
22647
|
if (typeof e !== "object" || e === null) continue;
|
|
22525
22648
|
const obj = e;
|
|
22526
22649
|
const name = typeof obj.name === "string" ? obj.name.trim() : "";
|
|
22527
|
-
if (
|
|
22650
|
+
if (!isAcceptedEntityName(name)) continue;
|
|
22528
22651
|
const kind = typeof obj.kind === "string" && ENTITY_KINDS.includes(obj.kind) ? obj.kind : void 0;
|
|
22529
22652
|
const weight = typeof obj.salience === "string" && Object.keys(TOPIC_SALIENCE_WEIGHTS).includes(obj.salience) ? TOPIC_SALIENCE_WEIGHTS[obj.salience] : void 0;
|
|
22530
22653
|
out.push({
|
|
@@ -24688,6 +24811,7 @@ Each memory is a short statement about the user. For each memory, list the NAMED
|
|
|
24688
24811
|
Include only NAMED entities, skip generic/common nouns. A topic must identify a specific thing the user could recognize by name; if it would be equally true of thousands of unrelated memories, leave it out:
|
|
24689
24812
|
- SKIP bare generic nouns even when the memory capitalizes them or a calendar entry is titled that way \u2014 "Home", "Work", "Meeting", "Lunch", "Birthday", "Appointment", "Trip", "Today", "Friday", "March" are NOT topics.
|
|
24690
24813
|
- KEEP the specific thing instead, when the memory names one: "Blue Bottle on Valencia" over "cafe", "Chicago Marathon" over "event", "Hollowpoint Labs" over "work".
|
|
24814
|
+
- SKIP identifiers and numbers \u2014 addresses, hashes, keys, account or order numbers, balances, prices, amounts and position sizes are NOT topics. Use the general subject instead: "Solana" or "trading" rather than "3.5 SOL" or an address.
|
|
24691
24815
|
- Prefer 0 entities over a weak one. A memory whose only candidate is a generic noun has NO entities.
|
|
24692
24816
|
${ENTITY_KIND_GUIDELINES}
|
|
24693
24817
|
|
|
@@ -24793,8 +24917,8 @@ List each memory's named entities.`,
|
|
|
24793
24917
|
}
|
|
24794
24918
|
function restoreEntities(entities, redactor) {
|
|
24795
24919
|
return entities.flatMap((e) => {
|
|
24796
|
-
const
|
|
24797
|
-
return
|
|
24920
|
+
const name = restoreEntityName(e.name, redactor);
|
|
24921
|
+
return name === null ? [] : [{ ...e, name }];
|
|
24798
24922
|
});
|
|
24799
24923
|
}
|
|
24800
24924
|
function parseTopicResponse(parsed, validIds) {
|
package/dist/expo/index.mjs
CHANGED
|
@@ -17756,6 +17756,125 @@ var WEAK_MODIFIERS = /* @__PURE__ */ new Set([
|
|
|
17756
17756
|
"and",
|
|
17757
17757
|
"or"
|
|
17758
17758
|
]);
|
|
17759
|
+
var MAX_ENTITY_NAME_LENGTH = 120;
|
|
17760
|
+
var MAX_ENTITY_NAME_TOKENS = 11;
|
|
17761
|
+
var PREFIXED_HEX = /^0x[0-9a-f]{16,}$/i;
|
|
17762
|
+
var BARE_HEX = /^[0-9a-f]{32,}$/i;
|
|
17763
|
+
var BASE58_STRING = /^[1-9A-HJ-NP-Za-km-z]{32,88}$/;
|
|
17764
|
+
var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
17765
|
+
var TRUNCATED_ID = /^[0-9a-z]{3,}(?:…|\.{2,3})[0-9a-z]{3,}$/i;
|
|
17766
|
+
var KEY_SEGMENT_MIN_LENGTH = 16;
|
|
17767
|
+
var LONG_DIGIT_RUN = /^\d{6,}$/;
|
|
17768
|
+
var CURRENCY_MARKED = /[$€£¥₹₿]\d|\d[$€£¥₹₿]/;
|
|
17769
|
+
var NUMERIC_TOKEN = /^[~≈+\-−]?(?:us\$|[$€£¥₹₿])?\d(?:[\d,.]*\d)?(?:k|mm|m|bn|b|t|x|%|[$€£¥₹₿])?$/i;
|
|
17770
|
+
var PLAIN_YEAR = /^(?:1\d{3}|20\d{2})$/;
|
|
17771
|
+
var SUFFIXED_NAME = /^\d*[1-9][kmb]$/i;
|
|
17772
|
+
var BARE_INTEGER = /^\d+$/;
|
|
17773
|
+
var TICKER = /^\$?[A-Z]{2,6}$/;
|
|
17774
|
+
var DETACHED_CURRENCY_SYMBOL = /(^|\s)([$€£¥₹₿])\s+(?=\d)|(\d)\s+([$€£¥₹₿])(?=\s|$)/gu;
|
|
17775
|
+
var LEADING_PUNCTUATION = /^[^\p{L}\p{N}$€£¥₹₿~≈+\-−]+/u;
|
|
17776
|
+
var TRAILING_KEPT_CHARACTER = /[\p{L}\p{N}$€£¥₹₿%]/u;
|
|
17777
|
+
var LEADING_CURRENCY_CODES = /* @__PURE__ */ new Set(["usd", "eur", "gbp", "jpy", "cad", "aud", "chf", "cny"]);
|
|
17778
|
+
var QUANTITY_UNIT_WORDS = /* @__PURE__ */ new Set([
|
|
17779
|
+
"usd",
|
|
17780
|
+
"usdc",
|
|
17781
|
+
"usdt",
|
|
17782
|
+
"eur",
|
|
17783
|
+
"gbp",
|
|
17784
|
+
"sol",
|
|
17785
|
+
"eth",
|
|
17786
|
+
"btc",
|
|
17787
|
+
"dollar",
|
|
17788
|
+
"dollars",
|
|
17789
|
+
"euro",
|
|
17790
|
+
"euros",
|
|
17791
|
+
"buck",
|
|
17792
|
+
"bucks",
|
|
17793
|
+
"k",
|
|
17794
|
+
"thousand",
|
|
17795
|
+
"million",
|
|
17796
|
+
"billion",
|
|
17797
|
+
"trillion",
|
|
17798
|
+
"share",
|
|
17799
|
+
"shares",
|
|
17800
|
+
"token",
|
|
17801
|
+
"tokens",
|
|
17802
|
+
"coin",
|
|
17803
|
+
"coins",
|
|
17804
|
+
"unit",
|
|
17805
|
+
"units",
|
|
17806
|
+
"position",
|
|
17807
|
+
"balance",
|
|
17808
|
+
"stake",
|
|
17809
|
+
"holdings"
|
|
17810
|
+
]);
|
|
17811
|
+
var AMOUNT_WORDS = /* @__PURE__ */ new Set([...QUANTITY_UNIT_WORDS, "percent", "of"]);
|
|
17812
|
+
var NAME_PII_CATEGORIES = /* @__PURE__ */ new Set(["EMAIL", "PHONE", "SSN", "CREDIT_CARD"]);
|
|
17813
|
+
var NAME_PII_PATTERNS = PII_PATTERNS.filter(
|
|
17814
|
+
(pattern) => NAME_PII_CATEGORIES.has(pattern.category) && pattern.context === void 0
|
|
17815
|
+
);
|
|
17816
|
+
var KEPT_PLACEHOLDER_CATEGORIES = /* @__PURE__ */ new Set(["PERSON", "LOCATION", "ORG"]);
|
|
17817
|
+
var PLACEHOLDER_TOKEN = /\b([A-Za-z]+(?:_[A-Za-z]+)*)_\d+\b/g;
|
|
17818
|
+
function trimPunctuation(token) {
|
|
17819
|
+
const chars = Array.from(token.replace(LEADING_PUNCTUATION, ""));
|
|
17820
|
+
let end = chars.length;
|
|
17821
|
+
while (end > 0 && !TRAILING_KEPT_CHARACTER.test(chars[end - 1])) end--;
|
|
17822
|
+
return chars.slice(0, end).join("");
|
|
17823
|
+
}
|
|
17824
|
+
function hasLetterAndDigit(text16) {
|
|
17825
|
+
return /\p{L}/u.test(text16) && /\p{N}/u.test(text16);
|
|
17826
|
+
}
|
|
17827
|
+
function isIdentifierToken(token) {
|
|
17828
|
+
if (PREFIXED_HEX.test(token) || BARE_HEX.test(token) || BASE58_STRING.test(token)) return true;
|
|
17829
|
+
if (UUID.test(token) || LONG_DIGIT_RUN.test(token)) return true;
|
|
17830
|
+
if (TRUNCATED_ID.test(token) && hasLetterAndDigit(token)) return true;
|
|
17831
|
+
return token.split(/[-_.]/).some((segment) => segment.length >= KEY_SEGMENT_MIN_LENGTH && hasLetterAndDigit(segment));
|
|
17832
|
+
}
|
|
17833
|
+
function containsStructuredPii(name) {
|
|
17834
|
+
return NAME_PII_PATTERNS.some(
|
|
17835
|
+
(pattern) => (name.match(pattern.regex) ?? []).some((match) => pattern.validate?.(match) ?? true)
|
|
17836
|
+
);
|
|
17837
|
+
}
|
|
17838
|
+
function isAmountUnitToken(token) {
|
|
17839
|
+
return NUMERIC_TOKEN.test(token) || TICKER.test(token) || AMOUNT_WORDS.has(token.toLowerCase());
|
|
17840
|
+
}
|
|
17841
|
+
function isAmountWordOrNumber(token) {
|
|
17842
|
+
return NUMERIC_TOKEN.test(token) || AMOUNT_WORDS.has(token.toLowerCase());
|
|
17843
|
+
}
|
|
17844
|
+
function isAmount(tokens) {
|
|
17845
|
+
const start = LEADING_CURRENCY_CODES.has(tokens[0]?.toLowerCase() ?? "") ? 1 : 0;
|
|
17846
|
+
const first = tokens[start];
|
|
17847
|
+
if (first === void 0 || !NUMERIC_TOKEN.test(first)) return false;
|
|
17848
|
+
const units = tokens.slice(start + 1);
|
|
17849
|
+
if (start === 0 && units.length === 0)
|
|
17850
|
+
return !PLAIN_YEAR.test(first) && !SUFFIXED_NAME.test(first);
|
|
17851
|
+
if (!units.every(isAmountUnitToken)) return false;
|
|
17852
|
+
return start === 1 || !BARE_INTEGER.test(first) || units.some(isAmountWordOrNumber);
|
|
17853
|
+
}
|
|
17854
|
+
function hasQuantityPhrase(tokens) {
|
|
17855
|
+
return tokens.some(
|
|
17856
|
+
(token, i) => NUMERIC_TOKEN.test(token) && QUANTITY_UNIT_WORDS.has(tokens[i + 1]?.toLowerCase() ?? "")
|
|
17857
|
+
);
|
|
17858
|
+
}
|
|
17859
|
+
function isIdentifierOrAmountEntityName(name) {
|
|
17860
|
+
const trimmed = name.trim();
|
|
17861
|
+
if (trimmed.length > MAX_ENTITY_NAME_LENGTH) return true;
|
|
17862
|
+
if (containsStructuredPii(trimmed)) return true;
|
|
17863
|
+
const tokens = trimmed.replace(DETACHED_CURRENCY_SYMBOL, "$1$2$3$4").split(/\s+/).map(trimPunctuation).filter((token) => token.length > 0);
|
|
17864
|
+
if (tokens.length === 0) return false;
|
|
17865
|
+
if (tokens.length > MAX_ENTITY_NAME_TOKENS) return true;
|
|
17866
|
+
if (tokens.some(isIdentifierToken)) return true;
|
|
17867
|
+
if (tokens.some((token) => CURRENCY_MARKED.test(token))) return true;
|
|
17868
|
+
return isAmount(tokens) || hasQuantityPhrase(tokens);
|
|
17869
|
+
}
|
|
17870
|
+
function restoreEntityName(name, redactor) {
|
|
17871
|
+
for (const [token, category] of name.matchAll(PLACEHOLDER_TOKEN)) {
|
|
17872
|
+
if (KEPT_PLACEHOLDER_CATEGORIES.has(category.toUpperCase())) continue;
|
|
17873
|
+
if (redactor.restoreForStorage(token).text !== token) return null;
|
|
17874
|
+
}
|
|
17875
|
+
const restored = redactor.restoreForStorage(name);
|
|
17876
|
+
return restored.unresolved || isIdentifierOrAmountEntityName(restored.text) ? null : restored.text;
|
|
17877
|
+
}
|
|
17759
17878
|
|
|
17760
17879
|
// src/lib/memory/injectionClassifier.ts
|
|
17761
17880
|
var DEFAULT_MODEL = "inclusionai/ling-2.6-flash";
|
|
@@ -20551,8 +20670,8 @@ function restoreCandidates(candidates, redactor, ownNames) {
|
|
|
20551
20670
|
...c,
|
|
20552
20671
|
content: content.text,
|
|
20553
20672
|
entities: c.entities.flatMap((e) => {
|
|
20554
|
-
const
|
|
20555
|
-
return
|
|
20673
|
+
const name = restoreEntityName(e.name, redactor);
|
|
20674
|
+
return name === null ? [] : [{ ...e, name }];
|
|
20556
20675
|
})
|
|
20557
20676
|
},
|
|
20558
20677
|
unresolved: content.unresolved
|
|
@@ -20820,18 +20939,21 @@ function validateCandidates(parsed, validIds, userIds, fallbackSourceId, ownName
|
|
|
20820
20939
|
}
|
|
20821
20940
|
return out;
|
|
20822
20941
|
}
|
|
20942
|
+
function isAcceptedEntityName(name) {
|
|
20943
|
+
return name.length > 0 && !isGenericEntityName(name) && !isIdentifierOrAmountEntityName(name);
|
|
20944
|
+
}
|
|
20823
20945
|
function parseEntities(raw) {
|
|
20824
20946
|
const out = [];
|
|
20825
20947
|
for (const e of raw) {
|
|
20826
20948
|
if (typeof e === "string") {
|
|
20827
20949
|
const name2 = e.trim();
|
|
20828
|
-
if (
|
|
20950
|
+
if (isAcceptedEntityName(name2)) out.push({ name: name2 });
|
|
20829
20951
|
continue;
|
|
20830
20952
|
}
|
|
20831
20953
|
if (typeof e !== "object" || e === null) continue;
|
|
20832
20954
|
const obj = e;
|
|
20833
20955
|
const name = typeof obj.name === "string" ? obj.name.trim() : "";
|
|
20834
|
-
if (
|
|
20956
|
+
if (!isAcceptedEntityName(name)) continue;
|
|
20835
20957
|
const kind = typeof obj.kind === "string" && ENTITY_KINDS.includes(obj.kind) ? obj.kind : void 0;
|
|
20836
20958
|
const weight = typeof obj.salience === "string" && Object.keys(TOPIC_SALIENCE_WEIGHTS).includes(obj.salience) ? TOPIC_SALIENCE_WEIGHTS[obj.salience] : void 0;
|
|
20837
20959
|
out.push({
|
|
@@ -22974,6 +23096,7 @@ Each memory is a short statement about the user. For each memory, list the NAMED
|
|
|
22974
23096
|
Include only NAMED entities, skip generic/common nouns. A topic must identify a specific thing the user could recognize by name; if it would be equally true of thousands of unrelated memories, leave it out:
|
|
22975
23097
|
- SKIP bare generic nouns even when the memory capitalizes them or a calendar entry is titled that way \u2014 "Home", "Work", "Meeting", "Lunch", "Birthday", "Appointment", "Trip", "Today", "Friday", "March" are NOT topics.
|
|
22976
23098
|
- KEEP the specific thing instead, when the memory names one: "Blue Bottle on Valencia" over "cafe", "Chicago Marathon" over "event", "Hollowpoint Labs" over "work".
|
|
23099
|
+
- SKIP identifiers and numbers \u2014 addresses, hashes, keys, account or order numbers, balances, prices, amounts and position sizes are NOT topics. Use the general subject instead: "Solana" or "trading" rather than "3.5 SOL" or an address.
|
|
22977
23100
|
- Prefer 0 entities over a weak one. A memory whose only candidate is a generic noun has NO entities.
|
|
22978
23101
|
${ENTITY_KIND_GUIDELINES}
|
|
22979
23102
|
|
|
@@ -23079,8 +23202,8 @@ List each memory's named entities.`,
|
|
|
23079
23202
|
}
|
|
23080
23203
|
function restoreEntities(entities, redactor) {
|
|
23081
23204
|
return entities.flatMap((e) => {
|
|
23082
|
-
const
|
|
23083
|
-
return
|
|
23205
|
+
const name = restoreEntityName(e.name, redactor);
|
|
23206
|
+
return name === null ? [] : [{ ...e, name }];
|
|
23084
23207
|
});
|
|
23085
23208
|
}
|
|
23086
23209
|
function parseTopicResponse(parsed, validIds) {
|
package/dist/react/index.cjs
CHANGED
|
@@ -21591,6 +21591,7 @@ init_logger();
|
|
|
21591
21591
|
init_redactor();
|
|
21592
21592
|
|
|
21593
21593
|
// src/lib/memory/entitySalience.ts
|
|
21594
|
+
init_patterns();
|
|
21594
21595
|
var GENERIC_ENTITY_NAMES = /* @__PURE__ */ new Set([
|
|
21595
21596
|
"today",
|
|
21596
21597
|
"tomorrow",
|
|
@@ -21736,6 +21737,125 @@ var WEAK_MODIFIERS = /* @__PURE__ */ new Set([
|
|
|
21736
21737
|
"and",
|
|
21737
21738
|
"or"
|
|
21738
21739
|
]);
|
|
21740
|
+
var MAX_ENTITY_NAME_LENGTH = 120;
|
|
21741
|
+
var MAX_ENTITY_NAME_TOKENS = 11;
|
|
21742
|
+
var PREFIXED_HEX = /^0x[0-9a-f]{16,}$/i;
|
|
21743
|
+
var BARE_HEX = /^[0-9a-f]{32,}$/i;
|
|
21744
|
+
var BASE58_STRING = /^[1-9A-HJ-NP-Za-km-z]{32,88}$/;
|
|
21745
|
+
var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
21746
|
+
var TRUNCATED_ID = /^[0-9a-z]{3,}(?:…|\.{2,3})[0-9a-z]{3,}$/i;
|
|
21747
|
+
var KEY_SEGMENT_MIN_LENGTH = 16;
|
|
21748
|
+
var LONG_DIGIT_RUN = /^\d{6,}$/;
|
|
21749
|
+
var CURRENCY_MARKED = /[$€£¥₹₿]\d|\d[$€£¥₹₿]/;
|
|
21750
|
+
var NUMERIC_TOKEN = /^[~≈+\-−]?(?:us\$|[$€£¥₹₿])?\d(?:[\d,.]*\d)?(?:k|mm|m|bn|b|t|x|%|[$€£¥₹₿])?$/i;
|
|
21751
|
+
var PLAIN_YEAR = /^(?:1\d{3}|20\d{2})$/;
|
|
21752
|
+
var SUFFIXED_NAME = /^\d*[1-9][kmb]$/i;
|
|
21753
|
+
var BARE_INTEGER = /^\d+$/;
|
|
21754
|
+
var TICKER = /^\$?[A-Z]{2,6}$/;
|
|
21755
|
+
var DETACHED_CURRENCY_SYMBOL = /(^|\s)([$€£¥₹₿])\s+(?=\d)|(\d)\s+([$€£¥₹₿])(?=\s|$)/gu;
|
|
21756
|
+
var LEADING_PUNCTUATION = /^[^\p{L}\p{N}$€£¥₹₿~≈+\-−]+/u;
|
|
21757
|
+
var TRAILING_KEPT_CHARACTER = /[\p{L}\p{N}$€£¥₹₿%]/u;
|
|
21758
|
+
var LEADING_CURRENCY_CODES = /* @__PURE__ */ new Set(["usd", "eur", "gbp", "jpy", "cad", "aud", "chf", "cny"]);
|
|
21759
|
+
var QUANTITY_UNIT_WORDS = /* @__PURE__ */ new Set([
|
|
21760
|
+
"usd",
|
|
21761
|
+
"usdc",
|
|
21762
|
+
"usdt",
|
|
21763
|
+
"eur",
|
|
21764
|
+
"gbp",
|
|
21765
|
+
"sol",
|
|
21766
|
+
"eth",
|
|
21767
|
+
"btc",
|
|
21768
|
+
"dollar",
|
|
21769
|
+
"dollars",
|
|
21770
|
+
"euro",
|
|
21771
|
+
"euros",
|
|
21772
|
+
"buck",
|
|
21773
|
+
"bucks",
|
|
21774
|
+
"k",
|
|
21775
|
+
"thousand",
|
|
21776
|
+
"million",
|
|
21777
|
+
"billion",
|
|
21778
|
+
"trillion",
|
|
21779
|
+
"share",
|
|
21780
|
+
"shares",
|
|
21781
|
+
"token",
|
|
21782
|
+
"tokens",
|
|
21783
|
+
"coin",
|
|
21784
|
+
"coins",
|
|
21785
|
+
"unit",
|
|
21786
|
+
"units",
|
|
21787
|
+
"position",
|
|
21788
|
+
"balance",
|
|
21789
|
+
"stake",
|
|
21790
|
+
"holdings"
|
|
21791
|
+
]);
|
|
21792
|
+
var AMOUNT_WORDS = /* @__PURE__ */ new Set([...QUANTITY_UNIT_WORDS, "percent", "of"]);
|
|
21793
|
+
var NAME_PII_CATEGORIES = /* @__PURE__ */ new Set(["EMAIL", "PHONE", "SSN", "CREDIT_CARD"]);
|
|
21794
|
+
var NAME_PII_PATTERNS = PII_PATTERNS.filter(
|
|
21795
|
+
(pattern) => NAME_PII_CATEGORIES.has(pattern.category) && pattern.context === void 0
|
|
21796
|
+
);
|
|
21797
|
+
var KEPT_PLACEHOLDER_CATEGORIES = /* @__PURE__ */ new Set(["PERSON", "LOCATION", "ORG"]);
|
|
21798
|
+
var PLACEHOLDER_TOKEN = /\b([A-Za-z]+(?:_[A-Za-z]+)*)_\d+\b/g;
|
|
21799
|
+
function trimPunctuation(token) {
|
|
21800
|
+
const chars = Array.from(token.replace(LEADING_PUNCTUATION, ""));
|
|
21801
|
+
let end = chars.length;
|
|
21802
|
+
while (end > 0 && !TRAILING_KEPT_CHARACTER.test(chars[end - 1])) end--;
|
|
21803
|
+
return chars.slice(0, end).join("");
|
|
21804
|
+
}
|
|
21805
|
+
function hasLetterAndDigit(text16) {
|
|
21806
|
+
return /\p{L}/u.test(text16) && /\p{N}/u.test(text16);
|
|
21807
|
+
}
|
|
21808
|
+
function isIdentifierToken(token) {
|
|
21809
|
+
if (PREFIXED_HEX.test(token) || BARE_HEX.test(token) || BASE58_STRING.test(token)) return true;
|
|
21810
|
+
if (UUID.test(token) || LONG_DIGIT_RUN.test(token)) return true;
|
|
21811
|
+
if (TRUNCATED_ID.test(token) && hasLetterAndDigit(token)) return true;
|
|
21812
|
+
return token.split(/[-_.]/).some((segment) => segment.length >= KEY_SEGMENT_MIN_LENGTH && hasLetterAndDigit(segment));
|
|
21813
|
+
}
|
|
21814
|
+
function containsStructuredPii(name) {
|
|
21815
|
+
return NAME_PII_PATTERNS.some(
|
|
21816
|
+
(pattern) => (name.match(pattern.regex) ?? []).some((match) => pattern.validate?.(match) ?? true)
|
|
21817
|
+
);
|
|
21818
|
+
}
|
|
21819
|
+
function isAmountUnitToken(token) {
|
|
21820
|
+
return NUMERIC_TOKEN.test(token) || TICKER.test(token) || AMOUNT_WORDS.has(token.toLowerCase());
|
|
21821
|
+
}
|
|
21822
|
+
function isAmountWordOrNumber(token) {
|
|
21823
|
+
return NUMERIC_TOKEN.test(token) || AMOUNT_WORDS.has(token.toLowerCase());
|
|
21824
|
+
}
|
|
21825
|
+
function isAmount(tokens) {
|
|
21826
|
+
const start = LEADING_CURRENCY_CODES.has(tokens[0]?.toLowerCase() ?? "") ? 1 : 0;
|
|
21827
|
+
const first = tokens[start];
|
|
21828
|
+
if (first === void 0 || !NUMERIC_TOKEN.test(first)) return false;
|
|
21829
|
+
const units = tokens.slice(start + 1);
|
|
21830
|
+
if (start === 0 && units.length === 0)
|
|
21831
|
+
return !PLAIN_YEAR.test(first) && !SUFFIXED_NAME.test(first);
|
|
21832
|
+
if (!units.every(isAmountUnitToken)) return false;
|
|
21833
|
+
return start === 1 || !BARE_INTEGER.test(first) || units.some(isAmountWordOrNumber);
|
|
21834
|
+
}
|
|
21835
|
+
function hasQuantityPhrase(tokens) {
|
|
21836
|
+
return tokens.some(
|
|
21837
|
+
(token, i) => NUMERIC_TOKEN.test(token) && QUANTITY_UNIT_WORDS.has(tokens[i + 1]?.toLowerCase() ?? "")
|
|
21838
|
+
);
|
|
21839
|
+
}
|
|
21840
|
+
function isIdentifierOrAmountEntityName(name) {
|
|
21841
|
+
const trimmed = name.trim();
|
|
21842
|
+
if (trimmed.length > MAX_ENTITY_NAME_LENGTH) return true;
|
|
21843
|
+
if (containsStructuredPii(trimmed)) return true;
|
|
21844
|
+
const tokens = trimmed.replace(DETACHED_CURRENCY_SYMBOL, "$1$2$3$4").split(/\s+/).map(trimPunctuation).filter((token) => token.length > 0);
|
|
21845
|
+
if (tokens.length === 0) return false;
|
|
21846
|
+
if (tokens.length > MAX_ENTITY_NAME_TOKENS) return true;
|
|
21847
|
+
if (tokens.some(isIdentifierToken)) return true;
|
|
21848
|
+
if (tokens.some((token) => CURRENCY_MARKED.test(token))) return true;
|
|
21849
|
+
return isAmount(tokens) || hasQuantityPhrase(tokens);
|
|
21850
|
+
}
|
|
21851
|
+
function restoreEntityName(name, redactor) {
|
|
21852
|
+
for (const [token, category] of name.matchAll(PLACEHOLDER_TOKEN)) {
|
|
21853
|
+
if (KEPT_PLACEHOLDER_CATEGORIES.has(category.toUpperCase())) continue;
|
|
21854
|
+
if (redactor.restoreForStorage(token).text !== token) return null;
|
|
21855
|
+
}
|
|
21856
|
+
const restored = redactor.restoreForStorage(name);
|
|
21857
|
+
return restored.unresolved || isIdentifierOrAmountEntityName(restored.text) ? null : restored.text;
|
|
21858
|
+
}
|
|
21739
21859
|
|
|
21740
21860
|
// src/lib/memory/injectionClassifier.ts
|
|
21741
21861
|
init_logger();
|
|
@@ -24548,8 +24668,8 @@ function restoreCandidates(candidates, redactor, ownNames) {
|
|
|
24548
24668
|
...c,
|
|
24549
24669
|
content: content.text,
|
|
24550
24670
|
entities: c.entities.flatMap((e) => {
|
|
24551
|
-
const
|
|
24552
|
-
return
|
|
24671
|
+
const name = restoreEntityName(e.name, redactor);
|
|
24672
|
+
return name === null ? [] : [{ ...e, name }];
|
|
24553
24673
|
})
|
|
24554
24674
|
},
|
|
24555
24675
|
unresolved: content.unresolved
|
|
@@ -24817,18 +24937,21 @@ function validateCandidates(parsed, validIds, userIds, fallbackSourceId, ownName
|
|
|
24817
24937
|
}
|
|
24818
24938
|
return out;
|
|
24819
24939
|
}
|
|
24940
|
+
function isAcceptedEntityName(name) {
|
|
24941
|
+
return name.length > 0 && !isGenericEntityName(name) && !isIdentifierOrAmountEntityName(name);
|
|
24942
|
+
}
|
|
24820
24943
|
function parseEntities(raw) {
|
|
24821
24944
|
const out = [];
|
|
24822
24945
|
for (const e of raw) {
|
|
24823
24946
|
if (typeof e === "string") {
|
|
24824
24947
|
const name2 = e.trim();
|
|
24825
|
-
if (
|
|
24948
|
+
if (isAcceptedEntityName(name2)) out.push({ name: name2 });
|
|
24826
24949
|
continue;
|
|
24827
24950
|
}
|
|
24828
24951
|
if (typeof e !== "object" || e === null) continue;
|
|
24829
24952
|
const obj = e;
|
|
24830
24953
|
const name = typeof obj.name === "string" ? obj.name.trim() : "";
|
|
24831
|
-
if (
|
|
24954
|
+
if (!isAcceptedEntityName(name)) continue;
|
|
24832
24955
|
const kind = typeof obj.kind === "string" && ENTITY_KINDS.includes(obj.kind) ? obj.kind : void 0;
|
|
24833
24956
|
const weight = typeof obj.salience === "string" && Object.keys(TOPIC_SALIENCE_WEIGHTS).includes(obj.salience) ? TOPIC_SALIENCE_WEIGHTS[obj.salience] : void 0;
|
|
24834
24957
|
out.push({
|
|
@@ -27018,6 +27141,7 @@ Each memory is a short statement about the user. For each memory, list the NAMED
|
|
|
27018
27141
|
Include only NAMED entities, skip generic/common nouns. A topic must identify a specific thing the user could recognize by name; if it would be equally true of thousands of unrelated memories, leave it out:
|
|
27019
27142
|
- SKIP bare generic nouns even when the memory capitalizes them or a calendar entry is titled that way \u2014 "Home", "Work", "Meeting", "Lunch", "Birthday", "Appointment", "Trip", "Today", "Friday", "March" are NOT topics.
|
|
27020
27143
|
- KEEP the specific thing instead, when the memory names one: "Blue Bottle on Valencia" over "cafe", "Chicago Marathon" over "event", "Hollowpoint Labs" over "work".
|
|
27144
|
+
- SKIP identifiers and numbers \u2014 addresses, hashes, keys, account or order numbers, balances, prices, amounts and position sizes are NOT topics. Use the general subject instead: "Solana" or "trading" rather than "3.5 SOL" or an address.
|
|
27021
27145
|
- Prefer 0 entities over a weak one. A memory whose only candidate is a generic noun has NO entities.
|
|
27022
27146
|
${ENTITY_KIND_GUIDELINES}
|
|
27023
27147
|
|
|
@@ -27123,8 +27247,8 @@ List each memory's named entities.`,
|
|
|
27123
27247
|
}
|
|
27124
27248
|
function restoreEntities(entities, redactor) {
|
|
27125
27249
|
return entities.flatMap((e) => {
|
|
27126
|
-
const
|
|
27127
|
-
return
|
|
27250
|
+
const name = restoreEntityName(e.name, redactor);
|
|
27251
|
+
return name === null ? [] : [{ ...e, name }];
|
|
27128
27252
|
});
|
|
27129
27253
|
}
|
|
27130
27254
|
function parseTopicResponse(parsed, validIds) {
|
package/dist/react/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
INTERNAL_FLOW_MARKER,
|
|
3
|
+
PII_PATTERNS,
|
|
3
4
|
PiiRedactor,
|
|
4
5
|
callPortalJsonCompletion,
|
|
5
6
|
consoleLogger,
|
|
@@ -19,7 +20,7 @@ import {
|
|
|
19
20
|
taskTypeHeader,
|
|
20
21
|
validateEndpointOverride,
|
|
21
22
|
withInternalFlowMarker
|
|
22
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-6QCUNXU6.mjs";
|
|
23
24
|
import {
|
|
24
25
|
BASE_URL,
|
|
25
26
|
MCP_R2_DOMAIN,
|
|
@@ -19852,6 +19853,125 @@ var WEAK_MODIFIERS = /* @__PURE__ */ new Set([
|
|
|
19852
19853
|
"and",
|
|
19853
19854
|
"or"
|
|
19854
19855
|
]);
|
|
19856
|
+
var MAX_ENTITY_NAME_LENGTH = 120;
|
|
19857
|
+
var MAX_ENTITY_NAME_TOKENS = 11;
|
|
19858
|
+
var PREFIXED_HEX = /^0x[0-9a-f]{16,}$/i;
|
|
19859
|
+
var BARE_HEX = /^[0-9a-f]{32,}$/i;
|
|
19860
|
+
var BASE58_STRING = /^[1-9A-HJ-NP-Za-km-z]{32,88}$/;
|
|
19861
|
+
var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
19862
|
+
var TRUNCATED_ID = /^[0-9a-z]{3,}(?:…|\.{2,3})[0-9a-z]{3,}$/i;
|
|
19863
|
+
var KEY_SEGMENT_MIN_LENGTH = 16;
|
|
19864
|
+
var LONG_DIGIT_RUN = /^\d{6,}$/;
|
|
19865
|
+
var CURRENCY_MARKED = /[$€£¥₹₿]\d|\d[$€£¥₹₿]/;
|
|
19866
|
+
var NUMERIC_TOKEN = /^[~≈+\-−]?(?:us\$|[$€£¥₹₿])?\d(?:[\d,.]*\d)?(?:k|mm|m|bn|b|t|x|%|[$€£¥₹₿])?$/i;
|
|
19867
|
+
var PLAIN_YEAR = /^(?:1\d{3}|20\d{2})$/;
|
|
19868
|
+
var SUFFIXED_NAME = /^\d*[1-9][kmb]$/i;
|
|
19869
|
+
var BARE_INTEGER = /^\d+$/;
|
|
19870
|
+
var TICKER = /^\$?[A-Z]{2,6}$/;
|
|
19871
|
+
var DETACHED_CURRENCY_SYMBOL = /(^|\s)([$€£¥₹₿])\s+(?=\d)|(\d)\s+([$€£¥₹₿])(?=\s|$)/gu;
|
|
19872
|
+
var LEADING_PUNCTUATION = /^[^\p{L}\p{N}$€£¥₹₿~≈+\-−]+/u;
|
|
19873
|
+
var TRAILING_KEPT_CHARACTER = /[\p{L}\p{N}$€£¥₹₿%]/u;
|
|
19874
|
+
var LEADING_CURRENCY_CODES = /* @__PURE__ */ new Set(["usd", "eur", "gbp", "jpy", "cad", "aud", "chf", "cny"]);
|
|
19875
|
+
var QUANTITY_UNIT_WORDS = /* @__PURE__ */ new Set([
|
|
19876
|
+
"usd",
|
|
19877
|
+
"usdc",
|
|
19878
|
+
"usdt",
|
|
19879
|
+
"eur",
|
|
19880
|
+
"gbp",
|
|
19881
|
+
"sol",
|
|
19882
|
+
"eth",
|
|
19883
|
+
"btc",
|
|
19884
|
+
"dollar",
|
|
19885
|
+
"dollars",
|
|
19886
|
+
"euro",
|
|
19887
|
+
"euros",
|
|
19888
|
+
"buck",
|
|
19889
|
+
"bucks",
|
|
19890
|
+
"k",
|
|
19891
|
+
"thousand",
|
|
19892
|
+
"million",
|
|
19893
|
+
"billion",
|
|
19894
|
+
"trillion",
|
|
19895
|
+
"share",
|
|
19896
|
+
"shares",
|
|
19897
|
+
"token",
|
|
19898
|
+
"tokens",
|
|
19899
|
+
"coin",
|
|
19900
|
+
"coins",
|
|
19901
|
+
"unit",
|
|
19902
|
+
"units",
|
|
19903
|
+
"position",
|
|
19904
|
+
"balance",
|
|
19905
|
+
"stake",
|
|
19906
|
+
"holdings"
|
|
19907
|
+
]);
|
|
19908
|
+
var AMOUNT_WORDS = /* @__PURE__ */ new Set([...QUANTITY_UNIT_WORDS, "percent", "of"]);
|
|
19909
|
+
var NAME_PII_CATEGORIES = /* @__PURE__ */ new Set(["EMAIL", "PHONE", "SSN", "CREDIT_CARD"]);
|
|
19910
|
+
var NAME_PII_PATTERNS = PII_PATTERNS.filter(
|
|
19911
|
+
(pattern) => NAME_PII_CATEGORIES.has(pattern.category) && pattern.context === void 0
|
|
19912
|
+
);
|
|
19913
|
+
var KEPT_PLACEHOLDER_CATEGORIES = /* @__PURE__ */ new Set(["PERSON", "LOCATION", "ORG"]);
|
|
19914
|
+
var PLACEHOLDER_TOKEN = /\b([A-Za-z]+(?:_[A-Za-z]+)*)_\d+\b/g;
|
|
19915
|
+
function trimPunctuation(token) {
|
|
19916
|
+
const chars = Array.from(token.replace(LEADING_PUNCTUATION, ""));
|
|
19917
|
+
let end = chars.length;
|
|
19918
|
+
while (end > 0 && !TRAILING_KEPT_CHARACTER.test(chars[end - 1])) end--;
|
|
19919
|
+
return chars.slice(0, end).join("");
|
|
19920
|
+
}
|
|
19921
|
+
function hasLetterAndDigit(text16) {
|
|
19922
|
+
return /\p{L}/u.test(text16) && /\p{N}/u.test(text16);
|
|
19923
|
+
}
|
|
19924
|
+
function isIdentifierToken(token) {
|
|
19925
|
+
if (PREFIXED_HEX.test(token) || BARE_HEX.test(token) || BASE58_STRING.test(token)) return true;
|
|
19926
|
+
if (UUID.test(token) || LONG_DIGIT_RUN.test(token)) return true;
|
|
19927
|
+
if (TRUNCATED_ID.test(token) && hasLetterAndDigit(token)) return true;
|
|
19928
|
+
return token.split(/[-_.]/).some((segment) => segment.length >= KEY_SEGMENT_MIN_LENGTH && hasLetterAndDigit(segment));
|
|
19929
|
+
}
|
|
19930
|
+
function containsStructuredPii(name) {
|
|
19931
|
+
return NAME_PII_PATTERNS.some(
|
|
19932
|
+
(pattern) => (name.match(pattern.regex) ?? []).some((match) => pattern.validate?.(match) ?? true)
|
|
19933
|
+
);
|
|
19934
|
+
}
|
|
19935
|
+
function isAmountUnitToken(token) {
|
|
19936
|
+
return NUMERIC_TOKEN.test(token) || TICKER.test(token) || AMOUNT_WORDS.has(token.toLowerCase());
|
|
19937
|
+
}
|
|
19938
|
+
function isAmountWordOrNumber(token) {
|
|
19939
|
+
return NUMERIC_TOKEN.test(token) || AMOUNT_WORDS.has(token.toLowerCase());
|
|
19940
|
+
}
|
|
19941
|
+
function isAmount(tokens) {
|
|
19942
|
+
const start = LEADING_CURRENCY_CODES.has(tokens[0]?.toLowerCase() ?? "") ? 1 : 0;
|
|
19943
|
+
const first = tokens[start];
|
|
19944
|
+
if (first === void 0 || !NUMERIC_TOKEN.test(first)) return false;
|
|
19945
|
+
const units = tokens.slice(start + 1);
|
|
19946
|
+
if (start === 0 && units.length === 0)
|
|
19947
|
+
return !PLAIN_YEAR.test(first) && !SUFFIXED_NAME.test(first);
|
|
19948
|
+
if (!units.every(isAmountUnitToken)) return false;
|
|
19949
|
+
return start === 1 || !BARE_INTEGER.test(first) || units.some(isAmountWordOrNumber);
|
|
19950
|
+
}
|
|
19951
|
+
function hasQuantityPhrase(tokens) {
|
|
19952
|
+
return tokens.some(
|
|
19953
|
+
(token, i) => NUMERIC_TOKEN.test(token) && QUANTITY_UNIT_WORDS.has(tokens[i + 1]?.toLowerCase() ?? "")
|
|
19954
|
+
);
|
|
19955
|
+
}
|
|
19956
|
+
function isIdentifierOrAmountEntityName(name) {
|
|
19957
|
+
const trimmed = name.trim();
|
|
19958
|
+
if (trimmed.length > MAX_ENTITY_NAME_LENGTH) return true;
|
|
19959
|
+
if (containsStructuredPii(trimmed)) return true;
|
|
19960
|
+
const tokens = trimmed.replace(DETACHED_CURRENCY_SYMBOL, "$1$2$3$4").split(/\s+/).map(trimPunctuation).filter((token) => token.length > 0);
|
|
19961
|
+
if (tokens.length === 0) return false;
|
|
19962
|
+
if (tokens.length > MAX_ENTITY_NAME_TOKENS) return true;
|
|
19963
|
+
if (tokens.some(isIdentifierToken)) return true;
|
|
19964
|
+
if (tokens.some((token) => CURRENCY_MARKED.test(token))) return true;
|
|
19965
|
+
return isAmount(tokens) || hasQuantityPhrase(tokens);
|
|
19966
|
+
}
|
|
19967
|
+
function restoreEntityName(name, redactor) {
|
|
19968
|
+
for (const [token, category] of name.matchAll(PLACEHOLDER_TOKEN)) {
|
|
19969
|
+
if (KEPT_PLACEHOLDER_CATEGORIES.has(category.toUpperCase())) continue;
|
|
19970
|
+
if (redactor.restoreForStorage(token).text !== token) return null;
|
|
19971
|
+
}
|
|
19972
|
+
const restored = redactor.restoreForStorage(name);
|
|
19973
|
+
return restored.unresolved || isIdentifierOrAmountEntityName(restored.text) ? null : restored.text;
|
|
19974
|
+
}
|
|
19855
19975
|
|
|
19856
19976
|
// src/lib/memory/injectionClassifier.ts
|
|
19857
19977
|
var DEFAULT_MODEL = "inclusionai/ling-2.6-flash";
|
|
@@ -22354,7 +22474,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
22354
22474
|
content: m.content,
|
|
22355
22475
|
similarity: m.similarity
|
|
22356
22476
|
}));
|
|
22357
|
-
const { consolidateMemory: doConsolidate } = await import("./consolidate-
|
|
22477
|
+
const { consolidateMemory: doConsolidate } = await import("./consolidate-RASCVKD2.mjs");
|
|
22358
22478
|
const decision = await doConsolidate(trimmed, candidates, consolidateOptions);
|
|
22359
22479
|
if (decision.action === "create") return decision.fallbackReason ? null : { create: true };
|
|
22360
22480
|
if (decision.action === "supersede" && decision.content) {
|
|
@@ -22647,8 +22767,8 @@ function restoreCandidates(candidates, redactor, ownNames) {
|
|
|
22647
22767
|
...c,
|
|
22648
22768
|
content: content.text,
|
|
22649
22769
|
entities: c.entities.flatMap((e) => {
|
|
22650
|
-
const
|
|
22651
|
-
return
|
|
22770
|
+
const name = restoreEntityName(e.name, redactor);
|
|
22771
|
+
return name === null ? [] : [{ ...e, name }];
|
|
22652
22772
|
})
|
|
22653
22773
|
},
|
|
22654
22774
|
unresolved: content.unresolved
|
|
@@ -22916,18 +23036,21 @@ function validateCandidates(parsed, validIds, userIds, fallbackSourceId, ownName
|
|
|
22916
23036
|
}
|
|
22917
23037
|
return out;
|
|
22918
23038
|
}
|
|
23039
|
+
function isAcceptedEntityName(name) {
|
|
23040
|
+
return name.length > 0 && !isGenericEntityName(name) && !isIdentifierOrAmountEntityName(name);
|
|
23041
|
+
}
|
|
22919
23042
|
function parseEntities(raw) {
|
|
22920
23043
|
const out = [];
|
|
22921
23044
|
for (const e of raw) {
|
|
22922
23045
|
if (typeof e === "string") {
|
|
22923
23046
|
const name2 = e.trim();
|
|
22924
|
-
if (
|
|
23047
|
+
if (isAcceptedEntityName(name2)) out.push({ name: name2 });
|
|
22925
23048
|
continue;
|
|
22926
23049
|
}
|
|
22927
23050
|
if (typeof e !== "object" || e === null) continue;
|
|
22928
23051
|
const obj = e;
|
|
22929
23052
|
const name = typeof obj.name === "string" ? obj.name.trim() : "";
|
|
22930
|
-
if (
|
|
23053
|
+
if (!isAcceptedEntityName(name)) continue;
|
|
22931
23054
|
const kind = typeof obj.kind === "string" && ENTITY_KINDS.includes(obj.kind) ? obj.kind : void 0;
|
|
22932
23055
|
const weight = typeof obj.salience === "string" && Object.keys(TOPIC_SALIENCE_WEIGHTS).includes(obj.salience) ? TOPIC_SALIENCE_WEIGHTS[obj.salience] : void 0;
|
|
22933
23056
|
out.push({
|
|
@@ -25096,6 +25219,7 @@ Each memory is a short statement about the user. For each memory, list the NAMED
|
|
|
25096
25219
|
Include only NAMED entities, skip generic/common nouns. A topic must identify a specific thing the user could recognize by name; if it would be equally true of thousands of unrelated memories, leave it out:
|
|
25097
25220
|
- SKIP bare generic nouns even when the memory capitalizes them or a calendar entry is titled that way \u2014 "Home", "Work", "Meeting", "Lunch", "Birthday", "Appointment", "Trip", "Today", "Friday", "March" are NOT topics.
|
|
25098
25221
|
- KEEP the specific thing instead, when the memory names one: "Blue Bottle on Valencia" over "cafe", "Chicago Marathon" over "event", "Hollowpoint Labs" over "work".
|
|
25222
|
+
- SKIP identifiers and numbers \u2014 addresses, hashes, keys, account or order numbers, balances, prices, amounts and position sizes are NOT topics. Use the general subject instead: "Solana" or "trading" rather than "3.5 SOL" or an address.
|
|
25099
25223
|
- Prefer 0 entities over a weak one. A memory whose only candidate is a generic noun has NO entities.
|
|
25100
25224
|
${ENTITY_KIND_GUIDELINES}
|
|
25101
25225
|
|
|
@@ -25201,8 +25325,8 @@ List each memory's named entities.`,
|
|
|
25201
25325
|
}
|
|
25202
25326
|
function restoreEntities(entities, redactor) {
|
|
25203
25327
|
return entities.flatMap((e) => {
|
|
25204
|
-
const
|
|
25205
|
-
return
|
|
25328
|
+
const name = restoreEntityName(e.name, redactor);
|
|
25329
|
+
return name === null ? [] : [{ ...e, name }];
|
|
25206
25330
|
});
|
|
25207
25331
|
}
|
|
25208
25332
|
function parseTopicResponse(parsed, validIds) {
|
package/dist/server/index.cjs
CHANGED
|
@@ -30938,6 +30938,7 @@ init_logger();
|
|
|
30938
30938
|
init_redactor();
|
|
30939
30939
|
|
|
30940
30940
|
// src/lib/memory/entitySalience.ts
|
|
30941
|
+
init_patterns();
|
|
30941
30942
|
var GENERIC_ENTITY_NAMES = /* @__PURE__ */ new Set([
|
|
30942
30943
|
"today",
|
|
30943
30944
|
"tomorrow",
|
|
@@ -31083,6 +31084,125 @@ var WEAK_MODIFIERS = /* @__PURE__ */ new Set([
|
|
|
31083
31084
|
"and",
|
|
31084
31085
|
"or"
|
|
31085
31086
|
]);
|
|
31087
|
+
var MAX_ENTITY_NAME_LENGTH = 120;
|
|
31088
|
+
var MAX_ENTITY_NAME_TOKENS = 11;
|
|
31089
|
+
var PREFIXED_HEX = /^0x[0-9a-f]{16,}$/i;
|
|
31090
|
+
var BARE_HEX = /^[0-9a-f]{32,}$/i;
|
|
31091
|
+
var BASE58_STRING = /^[1-9A-HJ-NP-Za-km-z]{32,88}$/;
|
|
31092
|
+
var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
31093
|
+
var TRUNCATED_ID = /^[0-9a-z]{3,}(?:…|\.{2,3})[0-9a-z]{3,}$/i;
|
|
31094
|
+
var KEY_SEGMENT_MIN_LENGTH = 16;
|
|
31095
|
+
var LONG_DIGIT_RUN = /^\d{6,}$/;
|
|
31096
|
+
var CURRENCY_MARKED = /[$€£¥₹₿]\d|\d[$€£¥₹₿]/;
|
|
31097
|
+
var NUMERIC_TOKEN = /^[~≈+\-−]?(?:us\$|[$€£¥₹₿])?\d(?:[\d,.]*\d)?(?:k|mm|m|bn|b|t|x|%|[$€£¥₹₿])?$/i;
|
|
31098
|
+
var PLAIN_YEAR = /^(?:1\d{3}|20\d{2})$/;
|
|
31099
|
+
var SUFFIXED_NAME = /^\d*[1-9][kmb]$/i;
|
|
31100
|
+
var BARE_INTEGER = /^\d+$/;
|
|
31101
|
+
var TICKER = /^\$?[A-Z]{2,6}$/;
|
|
31102
|
+
var DETACHED_CURRENCY_SYMBOL = /(^|\s)([$€£¥₹₿])\s+(?=\d)|(\d)\s+([$€£¥₹₿])(?=\s|$)/gu;
|
|
31103
|
+
var LEADING_PUNCTUATION = /^[^\p{L}\p{N}$€£¥₹₿~≈+\-−]+/u;
|
|
31104
|
+
var TRAILING_KEPT_CHARACTER = /[\p{L}\p{N}$€£¥₹₿%]/u;
|
|
31105
|
+
var LEADING_CURRENCY_CODES = /* @__PURE__ */ new Set(["usd", "eur", "gbp", "jpy", "cad", "aud", "chf", "cny"]);
|
|
31106
|
+
var QUANTITY_UNIT_WORDS = /* @__PURE__ */ new Set([
|
|
31107
|
+
"usd",
|
|
31108
|
+
"usdc",
|
|
31109
|
+
"usdt",
|
|
31110
|
+
"eur",
|
|
31111
|
+
"gbp",
|
|
31112
|
+
"sol",
|
|
31113
|
+
"eth",
|
|
31114
|
+
"btc",
|
|
31115
|
+
"dollar",
|
|
31116
|
+
"dollars",
|
|
31117
|
+
"euro",
|
|
31118
|
+
"euros",
|
|
31119
|
+
"buck",
|
|
31120
|
+
"bucks",
|
|
31121
|
+
"k",
|
|
31122
|
+
"thousand",
|
|
31123
|
+
"million",
|
|
31124
|
+
"billion",
|
|
31125
|
+
"trillion",
|
|
31126
|
+
"share",
|
|
31127
|
+
"shares",
|
|
31128
|
+
"token",
|
|
31129
|
+
"tokens",
|
|
31130
|
+
"coin",
|
|
31131
|
+
"coins",
|
|
31132
|
+
"unit",
|
|
31133
|
+
"units",
|
|
31134
|
+
"position",
|
|
31135
|
+
"balance",
|
|
31136
|
+
"stake",
|
|
31137
|
+
"holdings"
|
|
31138
|
+
]);
|
|
31139
|
+
var AMOUNT_WORDS = /* @__PURE__ */ new Set([...QUANTITY_UNIT_WORDS, "percent", "of"]);
|
|
31140
|
+
var NAME_PII_CATEGORIES = /* @__PURE__ */ new Set(["EMAIL", "PHONE", "SSN", "CREDIT_CARD"]);
|
|
31141
|
+
var NAME_PII_PATTERNS = PII_PATTERNS.filter(
|
|
31142
|
+
(pattern) => NAME_PII_CATEGORIES.has(pattern.category) && pattern.context === void 0
|
|
31143
|
+
);
|
|
31144
|
+
var KEPT_PLACEHOLDER_CATEGORIES = /* @__PURE__ */ new Set(["PERSON", "LOCATION", "ORG"]);
|
|
31145
|
+
var PLACEHOLDER_TOKEN = /\b([A-Za-z]+(?:_[A-Za-z]+)*)_\d+\b/g;
|
|
31146
|
+
function trimPunctuation(token) {
|
|
31147
|
+
const chars = Array.from(token.replace(LEADING_PUNCTUATION, ""));
|
|
31148
|
+
let end = chars.length;
|
|
31149
|
+
while (end > 0 && !TRAILING_KEPT_CHARACTER.test(chars[end - 1])) end--;
|
|
31150
|
+
return chars.slice(0, end).join("");
|
|
31151
|
+
}
|
|
31152
|
+
function hasLetterAndDigit(text12) {
|
|
31153
|
+
return /\p{L}/u.test(text12) && /\p{N}/u.test(text12);
|
|
31154
|
+
}
|
|
31155
|
+
function isIdentifierToken(token) {
|
|
31156
|
+
if (PREFIXED_HEX.test(token) || BARE_HEX.test(token) || BASE58_STRING.test(token)) return true;
|
|
31157
|
+
if (UUID.test(token) || LONG_DIGIT_RUN.test(token)) return true;
|
|
31158
|
+
if (TRUNCATED_ID.test(token) && hasLetterAndDigit(token)) return true;
|
|
31159
|
+
return token.split(/[-_.]/).some((segment) => segment.length >= KEY_SEGMENT_MIN_LENGTH && hasLetterAndDigit(segment));
|
|
31160
|
+
}
|
|
31161
|
+
function containsStructuredPii(name) {
|
|
31162
|
+
return NAME_PII_PATTERNS.some(
|
|
31163
|
+
(pattern) => (name.match(pattern.regex) ?? []).some((match) => pattern.validate?.(match) ?? true)
|
|
31164
|
+
);
|
|
31165
|
+
}
|
|
31166
|
+
function isAmountUnitToken(token) {
|
|
31167
|
+
return NUMERIC_TOKEN.test(token) || TICKER.test(token) || AMOUNT_WORDS.has(token.toLowerCase());
|
|
31168
|
+
}
|
|
31169
|
+
function isAmountWordOrNumber(token) {
|
|
31170
|
+
return NUMERIC_TOKEN.test(token) || AMOUNT_WORDS.has(token.toLowerCase());
|
|
31171
|
+
}
|
|
31172
|
+
function isAmount(tokens) {
|
|
31173
|
+
const start = LEADING_CURRENCY_CODES.has(tokens[0]?.toLowerCase() ?? "") ? 1 : 0;
|
|
31174
|
+
const first = tokens[start];
|
|
31175
|
+
if (first === void 0 || !NUMERIC_TOKEN.test(first)) return false;
|
|
31176
|
+
const units = tokens.slice(start + 1);
|
|
31177
|
+
if (start === 0 && units.length === 0)
|
|
31178
|
+
return !PLAIN_YEAR.test(first) && !SUFFIXED_NAME.test(first);
|
|
31179
|
+
if (!units.every(isAmountUnitToken)) return false;
|
|
31180
|
+
return start === 1 || !BARE_INTEGER.test(first) || units.some(isAmountWordOrNumber);
|
|
31181
|
+
}
|
|
31182
|
+
function hasQuantityPhrase(tokens) {
|
|
31183
|
+
return tokens.some(
|
|
31184
|
+
(token, i) => NUMERIC_TOKEN.test(token) && QUANTITY_UNIT_WORDS.has(tokens[i + 1]?.toLowerCase() ?? "")
|
|
31185
|
+
);
|
|
31186
|
+
}
|
|
31187
|
+
function isIdentifierOrAmountEntityName(name) {
|
|
31188
|
+
const trimmed = name.trim();
|
|
31189
|
+
if (trimmed.length > MAX_ENTITY_NAME_LENGTH) return true;
|
|
31190
|
+
if (containsStructuredPii(trimmed)) return true;
|
|
31191
|
+
const tokens = trimmed.replace(DETACHED_CURRENCY_SYMBOL, "$1$2$3$4").split(/\s+/).map(trimPunctuation).filter((token) => token.length > 0);
|
|
31192
|
+
if (tokens.length === 0) return false;
|
|
31193
|
+
if (tokens.length > MAX_ENTITY_NAME_TOKENS) return true;
|
|
31194
|
+
if (tokens.some(isIdentifierToken)) return true;
|
|
31195
|
+
if (tokens.some((token) => CURRENCY_MARKED.test(token))) return true;
|
|
31196
|
+
return isAmount(tokens) || hasQuantityPhrase(tokens);
|
|
31197
|
+
}
|
|
31198
|
+
function restoreEntityName(name, redactor) {
|
|
31199
|
+
for (const [token, category] of name.matchAll(PLACEHOLDER_TOKEN)) {
|
|
31200
|
+
if (KEPT_PLACEHOLDER_CATEGORIES.has(category.toUpperCase())) continue;
|
|
31201
|
+
if (redactor.restoreForStorage(token).text !== token) return null;
|
|
31202
|
+
}
|
|
31203
|
+
const restored = redactor.restoreForStorage(name);
|
|
31204
|
+
return restored.unresolved || isIdentifierOrAmountEntityName(restored.text) ? null : restored.text;
|
|
31205
|
+
}
|
|
31086
31206
|
|
|
31087
31207
|
// src/lib/memory/injectionClassifier.ts
|
|
31088
31208
|
init_logger();
|
|
@@ -33895,8 +34015,8 @@ function restoreCandidates(candidates, redactor, ownNames) {
|
|
|
33895
34015
|
...c,
|
|
33896
34016
|
content: content.text,
|
|
33897
34017
|
entities: c.entities.flatMap((e) => {
|
|
33898
|
-
const
|
|
33899
|
-
return
|
|
34018
|
+
const name = restoreEntityName(e.name, redactor);
|
|
34019
|
+
return name === null ? [] : [{ ...e, name }];
|
|
33900
34020
|
})
|
|
33901
34021
|
},
|
|
33902
34022
|
unresolved: content.unresolved
|
|
@@ -34164,18 +34284,21 @@ function validateCandidates(parsed, validIds, userIds, fallbackSourceId, ownName
|
|
|
34164
34284
|
}
|
|
34165
34285
|
return out;
|
|
34166
34286
|
}
|
|
34287
|
+
function isAcceptedEntityName(name) {
|
|
34288
|
+
return name.length > 0 && !isGenericEntityName(name) && !isIdentifierOrAmountEntityName(name);
|
|
34289
|
+
}
|
|
34167
34290
|
function parseEntities(raw) {
|
|
34168
34291
|
const out = [];
|
|
34169
34292
|
for (const e of raw) {
|
|
34170
34293
|
if (typeof e === "string") {
|
|
34171
34294
|
const name2 = e.trim();
|
|
34172
|
-
if (
|
|
34295
|
+
if (isAcceptedEntityName(name2)) out.push({ name: name2 });
|
|
34173
34296
|
continue;
|
|
34174
34297
|
}
|
|
34175
34298
|
if (typeof e !== "object" || e === null) continue;
|
|
34176
34299
|
const obj = e;
|
|
34177
34300
|
const name = typeof obj.name === "string" ? obj.name.trim() : "";
|
|
34178
|
-
if (
|
|
34301
|
+
if (!isAcceptedEntityName(name)) continue;
|
|
34179
34302
|
const kind = typeof obj.kind === "string" && ENTITY_KINDS.includes(obj.kind) ? obj.kind : void 0;
|
|
34180
34303
|
const weight = typeof obj.salience === "string" && Object.keys(TOPIC_SALIENCE_WEIGHTS).includes(obj.salience) ? TOPIC_SALIENCE_WEIGHTS[obj.salience] : void 0;
|
|
34181
34304
|
out.push({
|
|
@@ -36365,6 +36488,7 @@ Each memory is a short statement about the user. For each memory, list the NAMED
|
|
|
36365
36488
|
Include only NAMED entities, skip generic/common nouns. A topic must identify a specific thing the user could recognize by name; if it would be equally true of thousands of unrelated memories, leave it out:
|
|
36366
36489
|
- SKIP bare generic nouns even when the memory capitalizes them or a calendar entry is titled that way \u2014 "Home", "Work", "Meeting", "Lunch", "Birthday", "Appointment", "Trip", "Today", "Friday", "March" are NOT topics.
|
|
36367
36490
|
- KEEP the specific thing instead, when the memory names one: "Blue Bottle on Valencia" over "cafe", "Chicago Marathon" over "event", "Hollowpoint Labs" over "work".
|
|
36491
|
+
- SKIP identifiers and numbers \u2014 addresses, hashes, keys, account or order numbers, balances, prices, amounts and position sizes are NOT topics. Use the general subject instead: "Solana" or "trading" rather than "3.5 SOL" or an address.
|
|
36368
36492
|
- Prefer 0 entities over a weak one. A memory whose only candidate is a generic noun has NO entities.
|
|
36369
36493
|
${ENTITY_KIND_GUIDELINES}
|
|
36370
36494
|
|
|
@@ -36470,8 +36594,8 @@ List each memory's named entities.`,
|
|
|
36470
36594
|
}
|
|
36471
36595
|
function restoreEntities(entities, redactor) {
|
|
36472
36596
|
return entities.flatMap((e) => {
|
|
36473
|
-
const
|
|
36474
|
-
return
|
|
36597
|
+
const name = restoreEntityName(e.name, redactor);
|
|
36598
|
+
return name === null ? [] : [{ ...e, name }];
|
|
36475
36599
|
});
|
|
36476
36600
|
}
|
|
36477
36601
|
function parseTopicResponse(parsed, validIds) {
|
package/dist/server/index.mjs
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
INTERNAL_FLOW_MARKER,
|
|
3
|
+
PII_PATTERNS,
|
|
3
4
|
callPortalJsonCompletion,
|
|
4
5
|
createStreamingDeAnonymizer,
|
|
5
6
|
extractCompletionContent,
|
|
@@ -13,7 +14,7 @@ import {
|
|
|
13
14
|
taskTypeHeader,
|
|
14
15
|
validateEndpointOverride,
|
|
15
16
|
withInternalFlowMarker
|
|
16
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-JEY3L7WD.mjs";
|
|
17
18
|
import {
|
|
18
19
|
BASE_URL,
|
|
19
20
|
__commonJS,
|
|
@@ -29337,6 +29338,125 @@ var WEAK_MODIFIERS = /* @__PURE__ */ new Set([
|
|
|
29337
29338
|
"and",
|
|
29338
29339
|
"or"
|
|
29339
29340
|
]);
|
|
29341
|
+
var MAX_ENTITY_NAME_LENGTH = 120;
|
|
29342
|
+
var MAX_ENTITY_NAME_TOKENS = 11;
|
|
29343
|
+
var PREFIXED_HEX = /^0x[0-9a-f]{16,}$/i;
|
|
29344
|
+
var BARE_HEX = /^[0-9a-f]{32,}$/i;
|
|
29345
|
+
var BASE58_STRING = /^[1-9A-HJ-NP-Za-km-z]{32,88}$/;
|
|
29346
|
+
var UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
29347
|
+
var TRUNCATED_ID = /^[0-9a-z]{3,}(?:…|\.{2,3})[0-9a-z]{3,}$/i;
|
|
29348
|
+
var KEY_SEGMENT_MIN_LENGTH = 16;
|
|
29349
|
+
var LONG_DIGIT_RUN = /^\d{6,}$/;
|
|
29350
|
+
var CURRENCY_MARKED = /[$€£¥₹₿]\d|\d[$€£¥₹₿]/;
|
|
29351
|
+
var NUMERIC_TOKEN = /^[~≈+\-−]?(?:us\$|[$€£¥₹₿])?\d(?:[\d,.]*\d)?(?:k|mm|m|bn|b|t|x|%|[$€£¥₹₿])?$/i;
|
|
29352
|
+
var PLAIN_YEAR = /^(?:1\d{3}|20\d{2})$/;
|
|
29353
|
+
var SUFFIXED_NAME = /^\d*[1-9][kmb]$/i;
|
|
29354
|
+
var BARE_INTEGER = /^\d+$/;
|
|
29355
|
+
var TICKER = /^\$?[A-Z]{2,6}$/;
|
|
29356
|
+
var DETACHED_CURRENCY_SYMBOL = /(^|\s)([$€£¥₹₿])\s+(?=\d)|(\d)\s+([$€£¥₹₿])(?=\s|$)/gu;
|
|
29357
|
+
var LEADING_PUNCTUATION = /^[^\p{L}\p{N}$€£¥₹₿~≈+\-−]+/u;
|
|
29358
|
+
var TRAILING_KEPT_CHARACTER = /[\p{L}\p{N}$€£¥₹₿%]/u;
|
|
29359
|
+
var LEADING_CURRENCY_CODES = /* @__PURE__ */ new Set(["usd", "eur", "gbp", "jpy", "cad", "aud", "chf", "cny"]);
|
|
29360
|
+
var QUANTITY_UNIT_WORDS = /* @__PURE__ */ new Set([
|
|
29361
|
+
"usd",
|
|
29362
|
+
"usdc",
|
|
29363
|
+
"usdt",
|
|
29364
|
+
"eur",
|
|
29365
|
+
"gbp",
|
|
29366
|
+
"sol",
|
|
29367
|
+
"eth",
|
|
29368
|
+
"btc",
|
|
29369
|
+
"dollar",
|
|
29370
|
+
"dollars",
|
|
29371
|
+
"euro",
|
|
29372
|
+
"euros",
|
|
29373
|
+
"buck",
|
|
29374
|
+
"bucks",
|
|
29375
|
+
"k",
|
|
29376
|
+
"thousand",
|
|
29377
|
+
"million",
|
|
29378
|
+
"billion",
|
|
29379
|
+
"trillion",
|
|
29380
|
+
"share",
|
|
29381
|
+
"shares",
|
|
29382
|
+
"token",
|
|
29383
|
+
"tokens",
|
|
29384
|
+
"coin",
|
|
29385
|
+
"coins",
|
|
29386
|
+
"unit",
|
|
29387
|
+
"units",
|
|
29388
|
+
"position",
|
|
29389
|
+
"balance",
|
|
29390
|
+
"stake",
|
|
29391
|
+
"holdings"
|
|
29392
|
+
]);
|
|
29393
|
+
var AMOUNT_WORDS = /* @__PURE__ */ new Set([...QUANTITY_UNIT_WORDS, "percent", "of"]);
|
|
29394
|
+
var NAME_PII_CATEGORIES = /* @__PURE__ */ new Set(["EMAIL", "PHONE", "SSN", "CREDIT_CARD"]);
|
|
29395
|
+
var NAME_PII_PATTERNS = PII_PATTERNS.filter(
|
|
29396
|
+
(pattern) => NAME_PII_CATEGORIES.has(pattern.category) && pattern.context === void 0
|
|
29397
|
+
);
|
|
29398
|
+
var KEPT_PLACEHOLDER_CATEGORIES = /* @__PURE__ */ new Set(["PERSON", "LOCATION", "ORG"]);
|
|
29399
|
+
var PLACEHOLDER_TOKEN = /\b([A-Za-z]+(?:_[A-Za-z]+)*)_\d+\b/g;
|
|
29400
|
+
function trimPunctuation(token) {
|
|
29401
|
+
const chars = Array.from(token.replace(LEADING_PUNCTUATION, ""));
|
|
29402
|
+
let end = chars.length;
|
|
29403
|
+
while (end > 0 && !TRAILING_KEPT_CHARACTER.test(chars[end - 1])) end--;
|
|
29404
|
+
return chars.slice(0, end).join("");
|
|
29405
|
+
}
|
|
29406
|
+
function hasLetterAndDigit(text12) {
|
|
29407
|
+
return /\p{L}/u.test(text12) && /\p{N}/u.test(text12);
|
|
29408
|
+
}
|
|
29409
|
+
function isIdentifierToken(token) {
|
|
29410
|
+
if (PREFIXED_HEX.test(token) || BARE_HEX.test(token) || BASE58_STRING.test(token)) return true;
|
|
29411
|
+
if (UUID.test(token) || LONG_DIGIT_RUN.test(token)) return true;
|
|
29412
|
+
if (TRUNCATED_ID.test(token) && hasLetterAndDigit(token)) return true;
|
|
29413
|
+
return token.split(/[-_.]/).some((segment) => segment.length >= KEY_SEGMENT_MIN_LENGTH && hasLetterAndDigit(segment));
|
|
29414
|
+
}
|
|
29415
|
+
function containsStructuredPii(name) {
|
|
29416
|
+
return NAME_PII_PATTERNS.some(
|
|
29417
|
+
(pattern) => (name.match(pattern.regex) ?? []).some((match) => pattern.validate?.(match) ?? true)
|
|
29418
|
+
);
|
|
29419
|
+
}
|
|
29420
|
+
function isAmountUnitToken(token) {
|
|
29421
|
+
return NUMERIC_TOKEN.test(token) || TICKER.test(token) || AMOUNT_WORDS.has(token.toLowerCase());
|
|
29422
|
+
}
|
|
29423
|
+
function isAmountWordOrNumber(token) {
|
|
29424
|
+
return NUMERIC_TOKEN.test(token) || AMOUNT_WORDS.has(token.toLowerCase());
|
|
29425
|
+
}
|
|
29426
|
+
function isAmount(tokens) {
|
|
29427
|
+
const start = LEADING_CURRENCY_CODES.has(tokens[0]?.toLowerCase() ?? "") ? 1 : 0;
|
|
29428
|
+
const first = tokens[start];
|
|
29429
|
+
if (first === void 0 || !NUMERIC_TOKEN.test(first)) return false;
|
|
29430
|
+
const units = tokens.slice(start + 1);
|
|
29431
|
+
if (start === 0 && units.length === 0)
|
|
29432
|
+
return !PLAIN_YEAR.test(first) && !SUFFIXED_NAME.test(first);
|
|
29433
|
+
if (!units.every(isAmountUnitToken)) return false;
|
|
29434
|
+
return start === 1 || !BARE_INTEGER.test(first) || units.some(isAmountWordOrNumber);
|
|
29435
|
+
}
|
|
29436
|
+
function hasQuantityPhrase(tokens) {
|
|
29437
|
+
return tokens.some(
|
|
29438
|
+
(token, i) => NUMERIC_TOKEN.test(token) && QUANTITY_UNIT_WORDS.has(tokens[i + 1]?.toLowerCase() ?? "")
|
|
29439
|
+
);
|
|
29440
|
+
}
|
|
29441
|
+
function isIdentifierOrAmountEntityName(name) {
|
|
29442
|
+
const trimmed = name.trim();
|
|
29443
|
+
if (trimmed.length > MAX_ENTITY_NAME_LENGTH) return true;
|
|
29444
|
+
if (containsStructuredPii(trimmed)) return true;
|
|
29445
|
+
const tokens = trimmed.replace(DETACHED_CURRENCY_SYMBOL, "$1$2$3$4").split(/\s+/).map(trimPunctuation).filter((token) => token.length > 0);
|
|
29446
|
+
if (tokens.length === 0) return false;
|
|
29447
|
+
if (tokens.length > MAX_ENTITY_NAME_TOKENS) return true;
|
|
29448
|
+
if (tokens.some(isIdentifierToken)) return true;
|
|
29449
|
+
if (tokens.some((token) => CURRENCY_MARKED.test(token))) return true;
|
|
29450
|
+
return isAmount(tokens) || hasQuantityPhrase(tokens);
|
|
29451
|
+
}
|
|
29452
|
+
function restoreEntityName(name, redactor) {
|
|
29453
|
+
for (const [token, category] of name.matchAll(PLACEHOLDER_TOKEN)) {
|
|
29454
|
+
if (KEPT_PLACEHOLDER_CATEGORIES.has(category.toUpperCase())) continue;
|
|
29455
|
+
if (redactor.restoreForStorage(token).text !== token) return null;
|
|
29456
|
+
}
|
|
29457
|
+
const restored = redactor.restoreForStorage(name);
|
|
29458
|
+
return restored.unresolved || isIdentifierOrAmountEntityName(restored.text) ? null : restored.text;
|
|
29459
|
+
}
|
|
29340
29460
|
|
|
29341
29461
|
// src/lib/memory/injectionClassifier.ts
|
|
29342
29462
|
var DEFAULT_MODEL = "inclusionai/ling-2.6-flash";
|
|
@@ -31839,7 +31959,7 @@ async function tryConsolidate(trimmed, ctx, options, prepared) {
|
|
|
31839
31959
|
content: m.content,
|
|
31840
31960
|
similarity: m.similarity
|
|
31841
31961
|
}));
|
|
31842
|
-
const { consolidateMemory: doConsolidate } = await import("./consolidate-
|
|
31962
|
+
const { consolidateMemory: doConsolidate } = await import("./consolidate-5DFDLGSS.mjs");
|
|
31843
31963
|
const decision = await doConsolidate(trimmed, candidates, consolidateOptions);
|
|
31844
31964
|
if (decision.action === "create") return decision.fallbackReason ? null : { create: true };
|
|
31845
31965
|
if (decision.action === "supersede" && decision.content) {
|
|
@@ -32132,8 +32252,8 @@ function restoreCandidates(candidates, redactor, ownNames) {
|
|
|
32132
32252
|
...c,
|
|
32133
32253
|
content: content.text,
|
|
32134
32254
|
entities: c.entities.flatMap((e) => {
|
|
32135
|
-
const
|
|
32136
|
-
return
|
|
32255
|
+
const name = restoreEntityName(e.name, redactor);
|
|
32256
|
+
return name === null ? [] : [{ ...e, name }];
|
|
32137
32257
|
})
|
|
32138
32258
|
},
|
|
32139
32259
|
unresolved: content.unresolved
|
|
@@ -32401,18 +32521,21 @@ function validateCandidates(parsed, validIds, userIds, fallbackSourceId, ownName
|
|
|
32401
32521
|
}
|
|
32402
32522
|
return out;
|
|
32403
32523
|
}
|
|
32524
|
+
function isAcceptedEntityName(name) {
|
|
32525
|
+
return name.length > 0 && !isGenericEntityName(name) && !isIdentifierOrAmountEntityName(name);
|
|
32526
|
+
}
|
|
32404
32527
|
function parseEntities(raw) {
|
|
32405
32528
|
const out = [];
|
|
32406
32529
|
for (const e of raw) {
|
|
32407
32530
|
if (typeof e === "string") {
|
|
32408
32531
|
const name2 = e.trim();
|
|
32409
|
-
if (
|
|
32532
|
+
if (isAcceptedEntityName(name2)) out.push({ name: name2 });
|
|
32410
32533
|
continue;
|
|
32411
32534
|
}
|
|
32412
32535
|
if (typeof e !== "object" || e === null) continue;
|
|
32413
32536
|
const obj = e;
|
|
32414
32537
|
const name = typeof obj.name === "string" ? obj.name.trim() : "";
|
|
32415
|
-
if (
|
|
32538
|
+
if (!isAcceptedEntityName(name)) continue;
|
|
32416
32539
|
const kind = typeof obj.kind === "string" && ENTITY_KINDS.includes(obj.kind) ? obj.kind : void 0;
|
|
32417
32540
|
const weight = typeof obj.salience === "string" && Object.keys(TOPIC_SALIENCE_WEIGHTS).includes(obj.salience) ? TOPIC_SALIENCE_WEIGHTS[obj.salience] : void 0;
|
|
32418
32541
|
out.push({
|
|
@@ -34581,6 +34704,7 @@ Each memory is a short statement about the user. For each memory, list the NAMED
|
|
|
34581
34704
|
Include only NAMED entities, skip generic/common nouns. A topic must identify a specific thing the user could recognize by name; if it would be equally true of thousands of unrelated memories, leave it out:
|
|
34582
34705
|
- SKIP bare generic nouns even when the memory capitalizes them or a calendar entry is titled that way \u2014 "Home", "Work", "Meeting", "Lunch", "Birthday", "Appointment", "Trip", "Today", "Friday", "March" are NOT topics.
|
|
34583
34706
|
- KEEP the specific thing instead, when the memory names one: "Blue Bottle on Valencia" over "cafe", "Chicago Marathon" over "event", "Hollowpoint Labs" over "work".
|
|
34707
|
+
- SKIP identifiers and numbers \u2014 addresses, hashes, keys, account or order numbers, balances, prices, amounts and position sizes are NOT topics. Use the general subject instead: "Solana" or "trading" rather than "3.5 SOL" or an address.
|
|
34584
34708
|
- Prefer 0 entities over a weak one. A memory whose only candidate is a generic noun has NO entities.
|
|
34585
34709
|
${ENTITY_KIND_GUIDELINES}
|
|
34586
34710
|
|
|
@@ -34686,8 +34810,8 @@ List each memory's named entities.`,
|
|
|
34686
34810
|
}
|
|
34687
34811
|
function restoreEntities(entities, redactor) {
|
|
34688
34812
|
return entities.flatMap((e) => {
|
|
34689
|
-
const
|
|
34690
|
-
return
|
|
34813
|
+
const name = restoreEntityName(e.name, redactor);
|
|
34814
|
+
return name === null ? [] : [{ ...e, name }];
|
|
34691
34815
|
});
|
|
34692
34816
|
}
|
|
34693
34817
|
function parseTopicResponse(parsed, validIds) {
|