@anuma/sdk 10.0.2 → 10.0.4
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 +281 -226
- package/dist/expo/index.mjs +227 -172
- package/dist/react/index.cjs +304 -249
- package/dist/react/index.mjs +235 -180
- package/dist/server/index.cjs +1430 -1375
- package/dist/server/index.d.mts +1 -8
- package/dist/server/index.d.ts +1 -8
- package/dist/server/index.mjs +263 -208
- package/package.json +1 -1
package/dist/server/index.cjs
CHANGED
|
@@ -14346,1183 +14346,1183 @@ var init_logger = __esm({
|
|
|
14346
14346
|
}
|
|
14347
14347
|
});
|
|
14348
14348
|
|
|
14349
|
-
//
|
|
14350
|
-
var
|
|
14351
|
-
|
|
14352
|
-
BASE_URL: () => BASE_URL,
|
|
14353
|
-
MCP_R2_DOMAIN: () => MCP_R2_DOMAIN,
|
|
14354
|
-
createClientConfig: () => createClientConfig,
|
|
14355
|
-
resolveBaseUrl: () => resolveBaseUrl
|
|
14356
|
-
});
|
|
14357
|
-
function readGlobal(key) {
|
|
14358
|
-
if (typeof globalThis === "undefined") return void 0;
|
|
14359
|
-
const value = globalThis[key];
|
|
14360
|
-
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
14361
|
-
}
|
|
14362
|
-
function resolveBaseUrl() {
|
|
14363
|
-
const fromProcess = typeof process !== "undefined" ? process.env.API_URL || process.env.NEXT_PUBLIC_API_URL || process.env.EXPO_PUBLIC_API_URL : void 0;
|
|
14364
|
-
const fromGlobal = readGlobal("API_URL") ?? readGlobal("NEXT_PUBLIC_API_URL") ?? readGlobal("EXPO_PUBLIC_API_URL");
|
|
14365
|
-
return (fromProcess || fromGlobal || DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
14366
|
-
}
|
|
14367
|
-
var DEFAULT_BASE_URL, BASE_URL, MCP_R2_DOMAIN, createClientConfig;
|
|
14368
|
-
var init_clientConfig = __esm({
|
|
14369
|
-
"src/clientConfig.ts"() {
|
|
14349
|
+
// node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/action/index.js
|
|
14350
|
+
var require_action = __commonJS({
|
|
14351
|
+
"node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/action/index.js"(exports2) {
|
|
14370
14352
|
"use strict";
|
|
14371
|
-
|
|
14372
|
-
|
|
14373
|
-
|
|
14374
|
-
|
|
14375
|
-
|
|
14376
|
-
|
|
14377
|
-
|
|
14353
|
+
var _interopRequireDefault = require_interopRequireDefault();
|
|
14354
|
+
exports2.__esModule = true;
|
|
14355
|
+
exports2.reader = reader;
|
|
14356
|
+
exports2.writer = writer;
|
|
14357
|
+
var _extends2 = _interopRequireDefault(require_extends());
|
|
14358
|
+
function writer(target, key, descriptor) {
|
|
14359
|
+
var actionName = "".concat(target.table || target.constructor.name, ".").concat(key);
|
|
14360
|
+
return (0, _extends2.default)({}, descriptor, {
|
|
14361
|
+
value: function(...args) {
|
|
14362
|
+
var _this = this;
|
|
14363
|
+
return this.database.write(function() {
|
|
14364
|
+
return descriptor.value.apply(_this, args);
|
|
14365
|
+
}, actionName);
|
|
14366
|
+
}
|
|
14367
|
+
});
|
|
14368
|
+
}
|
|
14369
|
+
function reader(target, key, descriptor) {
|
|
14370
|
+
var actionName = "".concat(target.table || target.constructor.name, ".").concat(key);
|
|
14371
|
+
return (0, _extends2.default)({}, descriptor, {
|
|
14372
|
+
value: function(...args) {
|
|
14373
|
+
var _this2 = this;
|
|
14374
|
+
return this.database.read(function() {
|
|
14375
|
+
return descriptor.value.apply(_this2, args);
|
|
14376
|
+
}, actionName);
|
|
14377
|
+
}
|
|
14378
|
+
});
|
|
14379
|
+
}
|
|
14378
14380
|
}
|
|
14379
14381
|
});
|
|
14380
14382
|
|
|
14381
|
-
//
|
|
14382
|
-
|
|
14383
|
-
|
|
14384
|
-
}
|
|
14385
|
-
var TASK_TYPE_HEADER;
|
|
14386
|
-
var init_taskType = __esm({
|
|
14387
|
-
"src/lib/taskType.ts"() {
|
|
14383
|
+
// node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/children/index.js
|
|
14384
|
+
var require_children = __commonJS({
|
|
14385
|
+
"node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/children/index.js"(exports2) {
|
|
14388
14386
|
"use strict";
|
|
14389
|
-
|
|
14387
|
+
var _interopRequireDefault = require_interopRequireDefault();
|
|
14388
|
+
exports2.__esModule = true;
|
|
14389
|
+
exports2.default = void 0;
|
|
14390
|
+
var _makeDecorator = _interopRequireDefault(require_makeDecorator());
|
|
14391
|
+
var _logError = _interopRequireDefault(require_logError());
|
|
14392
|
+
var _invariant = _interopRequireDefault(require_invariant());
|
|
14393
|
+
var Q13 = _interopRequireWildcard(require_QueryDescription());
|
|
14394
|
+
function _getRequireWildcardCache(e) {
|
|
14395
|
+
if ("function" != typeof WeakMap) return null;
|
|
14396
|
+
var r = /* @__PURE__ */ new WeakMap(), t = /* @__PURE__ */ new WeakMap();
|
|
14397
|
+
return (_getRequireWildcardCache = function _getRequireWildcardCache2(e2) {
|
|
14398
|
+
return e2 ? t : r;
|
|
14399
|
+
})(e);
|
|
14400
|
+
}
|
|
14401
|
+
function _interopRequireWildcard(e, r) {
|
|
14402
|
+
if (!r && e && e.__esModule) return e;
|
|
14403
|
+
if (null === e || "object" != typeof e && "function" != typeof e) return { default: e };
|
|
14404
|
+
var t = _getRequireWildcardCache(r);
|
|
14405
|
+
if (t && t.has(e)) return t.get(e);
|
|
14406
|
+
var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
14407
|
+
for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) {
|
|
14408
|
+
var i = a ? Object.getOwnPropertyDescriptor(e, u) : null;
|
|
14409
|
+
i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u];
|
|
14410
|
+
}
|
|
14411
|
+
return n.default = e, t && t.set(e, n), n;
|
|
14412
|
+
}
|
|
14413
|
+
var children = (0, _makeDecorator.default)(function(childTable) {
|
|
14414
|
+
return function() {
|
|
14415
|
+
return {
|
|
14416
|
+
get: function() {
|
|
14417
|
+
var that = this;
|
|
14418
|
+
that._childrenQueryCache = that._childrenQueryCache || {};
|
|
14419
|
+
var cachedQuery = that._childrenQueryCache[childTable];
|
|
14420
|
+
if (cachedQuery) {
|
|
14421
|
+
return cachedQuery;
|
|
14422
|
+
}
|
|
14423
|
+
var model = that.asModel;
|
|
14424
|
+
var childCollection = model.collections.get(childTable);
|
|
14425
|
+
var association = model.constructor.associations[childTable];
|
|
14426
|
+
(0, _invariant.default)(association && "has_many" === association.type, "@children decorator used for a table that's not has_many");
|
|
14427
|
+
var query = childCollection.query(Q13.where(association.foreignKey, model.id));
|
|
14428
|
+
that._childrenQueryCache[childTable] = query;
|
|
14429
|
+
return query;
|
|
14430
|
+
},
|
|
14431
|
+
set: function() {
|
|
14432
|
+
(0, _logError.default)("Setter called on a @children-marked property");
|
|
14433
|
+
}
|
|
14434
|
+
};
|
|
14435
|
+
};
|
|
14436
|
+
});
|
|
14437
|
+
var _default = exports2.default = children;
|
|
14390
14438
|
}
|
|
14391
14439
|
});
|
|
14392
14440
|
|
|
14393
|
-
//
|
|
14394
|
-
|
|
14395
|
-
|
|
14396
|
-
let alternate = false;
|
|
14397
|
-
for (let i = digits.length - 1; i >= 0; i--) {
|
|
14398
|
-
let n = parseInt(digits[i], 10);
|
|
14399
|
-
if (alternate) {
|
|
14400
|
-
n *= 2;
|
|
14401
|
-
if (n > 9) n -= 9;
|
|
14402
|
-
}
|
|
14403
|
-
sum += n;
|
|
14404
|
-
alternate = !alternate;
|
|
14405
|
-
}
|
|
14406
|
-
return sum % 10 === 0;
|
|
14407
|
-
}
|
|
14408
|
-
var PII_PATTERNS;
|
|
14409
|
-
var init_patterns = __esm({
|
|
14410
|
-
"src/lib/pii/patterns.ts"() {
|
|
14441
|
+
// node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/common.js
|
|
14442
|
+
var require_common2 = __commonJS({
|
|
14443
|
+
"node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/common.js"(exports2) {
|
|
14411
14444
|
"use strict";
|
|
14412
|
-
|
|
14413
|
-
|
|
14414
|
-
|
|
14415
|
-
|
|
14416
|
-
|
|
14417
|
-
|
|
14418
|
-
|
|
14419
|
-
|
|
14420
|
-
|
|
14421
|
-
const parts = match.split("-");
|
|
14422
|
-
const area = parseInt(parts[0], 10);
|
|
14423
|
-
return area !== 0 && area !== 666 && area < 900;
|
|
14424
|
-
}
|
|
14425
|
-
},
|
|
14426
|
-
{
|
|
14427
|
-
category: "SSN",
|
|
14428
|
-
regex: /\b\d{3}[ ]?\d{2}[ ]?\d{4}\b/g,
|
|
14429
|
-
context: /(?:\bssn\b|\bsocial\s+security(?:\s+(?:number|no\.?|#))?\b)[^\d\n]{0,12}$/i,
|
|
14430
|
-
validate: (match) => {
|
|
14431
|
-
const digits = match.replace(/\D/g, "");
|
|
14432
|
-
if (digits.length !== 9) return false;
|
|
14433
|
-
const area = parseInt(digits.slice(0, 3), 10);
|
|
14434
|
-
return area !== 0 && area !== 666 && area < 900;
|
|
14435
|
-
}
|
|
14436
|
-
},
|
|
14437
|
-
{
|
|
14438
|
-
category: "CREDIT_CARD",
|
|
14439
|
-
regex: /\b\d{4}[\s-]\d{4}[\s-]\d{4}[\s-]\d{1,7}\b|\b\d{13,19}\b/g,
|
|
14440
|
-
validate: (match) => {
|
|
14441
|
-
const digits = match.replace(/\D/g, "");
|
|
14442
|
-
if (digits.length < 13 || digits.length > 19) return false;
|
|
14443
|
-
return luhnCheck(digits);
|
|
14444
|
-
}
|
|
14445
|
-
},
|
|
14446
|
-
{
|
|
14447
|
-
category: "IP_ADDRESS",
|
|
14448
|
-
regex: /\b(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\b/g,
|
|
14449
|
-
validate: (match) => {
|
|
14450
|
-
return match !== "0.0.0.0" && match !== "127.0.0.1" && match !== "255.255.255.255";
|
|
14451
|
-
}
|
|
14452
|
-
},
|
|
14453
|
-
{
|
|
14454
|
-
category: "IP_ADDRESS",
|
|
14455
|
-
regex: /(?:(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?::[0-9a-fA-F]{1,4}){1,6}|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:))/g,
|
|
14456
|
-
validate: (match) => match !== "::1" && match !== "::"
|
|
14457
|
-
},
|
|
14458
|
-
{
|
|
14459
|
-
category: "PHONE",
|
|
14460
|
-
regex: /(?:\+\d{1,3}[\s.-])?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}\b|\+\d{10,15}\b/g
|
|
14461
|
-
},
|
|
14462
|
-
{
|
|
14463
|
-
category: "API_KEY",
|
|
14464
|
-
regex: /\b(?:sk|pk|api|key|token|secret|bearer|access)[_-]?[a-zA-Z0-9_-]{20,}\b/gi,
|
|
14465
|
-
validate: (match) => {
|
|
14466
|
-
const hasDigit = /\d/.test(match);
|
|
14467
|
-
const hasMixedCase = /[a-z]/.test(match) && /[A-Z]/.test(match);
|
|
14468
|
-
return hasDigit || hasMixedCase;
|
|
14469
|
-
}
|
|
14470
|
-
},
|
|
14471
|
-
{
|
|
14472
|
-
category: "US_ADDRESS",
|
|
14473
|
-
regex: /\b\d{1,5}[ \t]+(?:[A-Z][a-z]+[ \t]+){1,3}(?:St(?:reet)?|Ave(?:nue)?|Blvd|Boulevard|Dr(?:ive)?|Ln|Lane|Rd|Road|Ct|Court|Pl(?:ace)?|Way|Cir(?:cle)?|Pkwy|Parkway|Hwy|Highway)\.?(?=[\s,.;:!?)]|$)/g,
|
|
14474
|
-
validate: (match) => {
|
|
14475
|
-
return !/^0/.test(match.trim());
|
|
14476
|
-
}
|
|
14477
|
-
},
|
|
14478
|
-
{
|
|
14479
|
-
category: "DATE_OF_BIRTH",
|
|
14480
|
-
regex: /\b(?:(?:0?[1-9]|1[0-2])[/-](?:0?[1-9]|[12]\d|3[01])[/-](?:19|20)\d{2})\b/g,
|
|
14481
|
-
context: /(?:\bdob\b|\bd\.?o\.?b\.?|\bborn\b|\bbirth\s?date\b|\bbirthdate\b|\bbirthday\b|\bdate\s+of\s+birth\b)[^\d\n]{0,12}$/i,
|
|
14482
|
-
validate: (match) => {
|
|
14483
|
-
const m = match.match(/(\d{1,2})[/-](\d{1,2})[/-](\d{4})/);
|
|
14484
|
-
if (!m) return false;
|
|
14485
|
-
const month = parseInt(m[1], 10);
|
|
14486
|
-
const day = parseInt(m[2], 10);
|
|
14487
|
-
const year = parseInt(m[3], 10);
|
|
14488
|
-
const isLeap = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
14489
|
-
const daysInMonth = [31, isLeap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
14490
|
-
return month >= 1 && month <= 12 && day >= 1 && day <= daysInMonth[month - 1];
|
|
14491
|
-
}
|
|
14445
|
+
var _interopRequireDefault = require_interopRequireDefault();
|
|
14446
|
+
exports2.__esModule = true;
|
|
14447
|
+
exports2.ensureDecoratorUsedProperly = ensureDecoratorUsedProperly;
|
|
14448
|
+
var _invariant = _interopRequireDefault(require_invariant());
|
|
14449
|
+
function ensureDecoratorUsedProperly(columnName, target, key, descriptor) {
|
|
14450
|
+
(0, _invariant.default)(columnName, "Pass column name (raw field name) to the decorator - error in ".concat(target.constructor.name, ".prototype.").concat(key, " given."));
|
|
14451
|
+
if (descriptor) {
|
|
14452
|
+
(0, _invariant.default)("initializer" in descriptor, "Model field decorators can only be used for simple properties - method, setter or getter ".concat(target.constructor.name, ".prototype.").concat(key, " given."));
|
|
14453
|
+
(0, _invariant.default)("function" !== typeof descriptor.initializer, 'Model field decorators must not be used on properties with a default value - error in "'.concat(target.constructor.name, ".prototype.").concat(key, '".'));
|
|
14492
14454
|
}
|
|
14493
|
-
|
|
14455
|
+
}
|
|
14494
14456
|
}
|
|
14495
14457
|
});
|
|
14496
14458
|
|
|
14497
|
-
//
|
|
14498
|
-
|
|
14499
|
-
|
|
14500
|
-
}
|
|
14501
|
-
function isWordChar(ch) {
|
|
14502
|
-
return /[A-Za-z0-9_]/.test(ch) || ch.charCodeAt(0) > 127;
|
|
14503
|
-
}
|
|
14504
|
-
function isPiiRedactor(value) {
|
|
14505
|
-
return typeof value === "object" && value !== null && typeof value.redactMessages === "function" && typeof value.deAnonymize === "function";
|
|
14506
|
-
}
|
|
14507
|
-
function resolvePiiRedactor(piiRedaction) {
|
|
14508
|
-
if (piiRedaction === true) return new PiiRedactor();
|
|
14509
|
-
if (!piiRedaction) return void 0;
|
|
14510
|
-
if (isPiiRedactor(piiRedaction)) return piiRedaction;
|
|
14511
|
-
console.warn(
|
|
14512
|
-
"[PiiRedactor] `piiRedaction` is neither `true` nor a PiiRedactor instance; PII redaction is DISABLED for this request."
|
|
14513
|
-
);
|
|
14514
|
-
return void 0;
|
|
14515
|
-
}
|
|
14516
|
-
function createStreamingDeAnonymizer(redactor, emit) {
|
|
14517
|
-
let buffer = "";
|
|
14518
|
-
const trailingFragment = /\[[A-Za-z0-9_]*$/;
|
|
14519
|
-
return {
|
|
14520
|
-
push(chunk) {
|
|
14521
|
-
if (!chunk) return;
|
|
14522
|
-
buffer += chunk;
|
|
14523
|
-
const m = buffer.match(trailingFragment);
|
|
14524
|
-
if (!m || m.index === void 0) {
|
|
14525
|
-
emit(redactor.deAnonymize(buffer));
|
|
14526
|
-
buffer = "";
|
|
14527
|
-
} else if (m.index > 0) {
|
|
14528
|
-
emit(redactor.deAnonymize(buffer.slice(0, m.index)));
|
|
14529
|
-
buffer = buffer.slice(m.index);
|
|
14530
|
-
}
|
|
14531
|
-
},
|
|
14532
|
-
flush() {
|
|
14533
|
-
if (buffer) {
|
|
14534
|
-
emit(redactor.deAnonymize(buffer));
|
|
14535
|
-
buffer = "";
|
|
14536
|
-
}
|
|
14537
|
-
}
|
|
14538
|
-
};
|
|
14539
|
-
}
|
|
14540
|
-
var PiiRedactor;
|
|
14541
|
-
var init_redactor = __esm({
|
|
14542
|
-
"src/lib/pii/redactor.ts"() {
|
|
14459
|
+
// node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/json/index.js
|
|
14460
|
+
var require_json = __commonJS({
|
|
14461
|
+
"node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/json/index.js"(exports2) {
|
|
14543
14462
|
"use strict";
|
|
14544
|
-
|
|
14545
|
-
|
|
14546
|
-
|
|
14547
|
-
|
|
14548
|
-
|
|
14549
|
-
|
|
14550
|
-
this.placeholderToValue = /* @__PURE__ */ new Map();
|
|
14551
|
-
/** Next index per category for placeholder numbering. */
|
|
14552
|
-
this.categoryCounters = /* @__PURE__ */ new Map();
|
|
14553
|
-
/**
|
|
14554
|
-
* Matches any placeholder-shaped token for this redactor's categories —
|
|
14555
|
-
* bracketed `[EMAIL_1]` OR bare `EMAIL_1`, case-insensitive — capturing the
|
|
14556
|
-
* body. Drives {@link restoreForStorage}: the extraction / consolidation
|
|
14557
|
-
* models echo placeholders mangled (brackets dropped, re-cased), and a single
|
|
14558
|
-
* pass with this matcher restores the assigned ones and flags the rest in one
|
|
14559
|
-
* go. Built lazily from the union of pattern categories AND any categories
|
|
14560
|
-
* minted at runtime (e.g. NER `PERSON`/`LOCATION`/`ORG`): `undefined` = stale
|
|
14561
|
-
* (rebuild on next use), `null` = built but there are no categories.
|
|
14562
|
-
*/
|
|
14563
|
-
this.storagePattern = void 0;
|
|
14564
|
-
/**
|
|
14565
|
-
* Cached body→value lookups for {@link restoreForStorage}, built lazily from
|
|
14566
|
-
* the assigned placeholders and invalidated on each mint. `exact` is keyed by
|
|
14567
|
-
* the literal body (collision-proof); `ci` by upper-cased body for re-cased
|
|
14568
|
-
* echoes, minus any `ciCollisions` where two distinct bodies share a form.
|
|
14569
|
-
*/
|
|
14570
|
-
this.storageLookup = null;
|
|
14571
|
-
/** Whether the non-text-content bypass warning has already been emitted. */
|
|
14572
|
-
this.warnedNonText = false;
|
|
14573
|
-
/** Whether the NER-detector-failure warning has already been emitted. */
|
|
14574
|
-
this.warnedNerFailure = false;
|
|
14575
|
-
this.nerDetector = options.nerDetector;
|
|
14576
|
-
if (options.patterns) {
|
|
14577
|
-
this.patterns = options.patterns;
|
|
14578
|
-
} else {
|
|
14579
|
-
let base = PII_PATTERNS;
|
|
14580
|
-
if (options.excludeCategories?.length) {
|
|
14581
|
-
const excluded = new Set(options.excludeCategories);
|
|
14582
|
-
base = base.filter((p) => !excluded.has(p.category));
|
|
14583
|
-
}
|
|
14584
|
-
this.patterns = options.extraPatterns ? [...base, ...options.extraPatterns] : base;
|
|
14585
|
-
}
|
|
14586
|
-
this.patternCategories = [...new Set(this.patterns.map((p) => String(p.category)))];
|
|
14587
|
-
}
|
|
14588
|
-
/**
|
|
14589
|
-
* Build the {@link storagePattern} from the union of pattern categories and
|
|
14590
|
-
* any categories minted at runtime (NER entities arrive only when redaction
|
|
14591
|
-
* runs, so this can't be fixed at construction). Bracketed `[EMAIL_1]` OR
|
|
14592
|
-
* bare `EMAIL_1`, capturing the body, case-insensitive, global. `\d+` (not a
|
|
14593
|
-
* fixed body) spans any index; `\b` on the bare arm keeps it off prose like
|
|
14594
|
-
* "email 1 of 3".
|
|
14595
|
-
*/
|
|
14596
|
-
buildStoragePattern() {
|
|
14597
|
-
const categories = [.../* @__PURE__ */ new Set([...this.patternCategories, ...this.categoryCounters.keys()])];
|
|
14598
|
-
if (categories.length === 0) return null;
|
|
14599
|
-
const categoryAlt = categories.sort((a, b) => b.length - a.length).map(escapeRegExp).join("|");
|
|
14600
|
-
return new RegExp(`\\[((?:${categoryAlt})_\\d+)\\]|\\b((?:${categoryAlt})_\\d+)\\b`, "gi");
|
|
14601
|
-
}
|
|
14602
|
-
/**
|
|
14603
|
-
* Returns the current number of unique PII values tracked.
|
|
14604
|
-
*/
|
|
14605
|
-
get size() {
|
|
14606
|
-
return this.valueToPlaceholder.size;
|
|
14607
|
-
}
|
|
14608
|
-
/**
|
|
14609
|
-
* Returns a snapshot of all placeholder → original value mappings.
|
|
14610
|
-
* Useful for debugging or UI display. This is a copy — mutating it (or
|
|
14611
|
-
* later redactions) does not affect the returned map and vice versa.
|
|
14612
|
-
*/
|
|
14613
|
-
getMappings() {
|
|
14614
|
-
return new Map(this.placeholderToValue);
|
|
14463
|
+
exports2.__esModule = true;
|
|
14464
|
+
exports2.jsonDecorator = exports2.default = void 0;
|
|
14465
|
+
var _common = require_common2();
|
|
14466
|
+
var parseJSON = function(value) {
|
|
14467
|
+
if (null === value || value === void 0 || "" === value) {
|
|
14468
|
+
return void 0;
|
|
14615
14469
|
}
|
|
14616
|
-
|
|
14617
|
-
|
|
14618
|
-
|
|
14619
|
-
|
|
14620
|
-
getPlaceholder(category, value) {
|
|
14621
|
-
const normalizedValue = value.trim();
|
|
14622
|
-
const existing = this.valueToPlaceholder.get(normalizedValue);
|
|
14623
|
-
if (existing) return existing;
|
|
14624
|
-
const existingCount = this.categoryCounters.get(category);
|
|
14625
|
-
const count = (existingCount ?? 0) + 1;
|
|
14626
|
-
this.categoryCounters.set(category, count);
|
|
14627
|
-
if (existingCount === void 0) this.storagePattern = void 0;
|
|
14628
|
-
const placeholder = `[${category}_${count}]`;
|
|
14629
|
-
this.valueToPlaceholder.set(normalizedValue, placeholder);
|
|
14630
|
-
this.placeholderToValue.set(placeholder, normalizedValue);
|
|
14631
|
-
this.storageLookup = null;
|
|
14632
|
-
return placeholder;
|
|
14470
|
+
try {
|
|
14471
|
+
return JSON.parse(value);
|
|
14472
|
+
} catch (_) {
|
|
14473
|
+
return void 0;
|
|
14633
14474
|
}
|
|
14634
|
-
|
|
14635
|
-
|
|
14636
|
-
|
|
14637
|
-
|
|
14638
|
-
|
|
14639
|
-
|
|
14640
|
-
|
|
14641
|
-
|
|
14642
|
-
|
|
14643
|
-
|
|
14644
|
-
|
|
14645
|
-
|
|
14646
|
-
|
|
14647
|
-
|
|
14648
|
-
|
|
14649
|
-
|
|
14650
|
-
|
|
14475
|
+
};
|
|
14476
|
+
var defaultOptions = {
|
|
14477
|
+
memo: false
|
|
14478
|
+
};
|
|
14479
|
+
var jsonDecorator = exports2.jsonDecorator = function(rawFieldName, sanitizer, options = defaultOptions) {
|
|
14480
|
+
return function(target, key, descriptor) {
|
|
14481
|
+
(0, _common.ensureDecoratorUsedProperly)(rawFieldName, target, key, descriptor);
|
|
14482
|
+
return {
|
|
14483
|
+
configurable: true,
|
|
14484
|
+
enumerable: true,
|
|
14485
|
+
get: function get() {
|
|
14486
|
+
var model = this;
|
|
14487
|
+
var rawValue = model.asModel._getRaw(rawFieldName);
|
|
14488
|
+
if (options.memo) {
|
|
14489
|
+
model._jsonDecoratorCache = model._jsonDecoratorCache || {};
|
|
14490
|
+
var cachedEntry = model._jsonDecoratorCache[rawFieldName];
|
|
14491
|
+
if (cachedEntry && cachedEntry[0] === rawValue) {
|
|
14492
|
+
return cachedEntry[1];
|
|
14493
|
+
}
|
|
14494
|
+
}
|
|
14495
|
+
var parsedValue = parseJSON(rawValue);
|
|
14496
|
+
var sanitized = sanitizer(parsedValue, model);
|
|
14497
|
+
if (options.memo) {
|
|
14498
|
+
model._jsonDecoratorCache[rawFieldName] = [rawValue, sanitized];
|
|
14499
|
+
}
|
|
14500
|
+
return sanitized;
|
|
14501
|
+
},
|
|
14502
|
+
set: function set(json4) {
|
|
14503
|
+
var model = this;
|
|
14504
|
+
var sanitizedValue = sanitizer(json4, model);
|
|
14505
|
+
var stringifiedValue = null != sanitizedValue ? JSON.stringify(sanitizedValue) : null;
|
|
14506
|
+
model.asModel._setRaw(rawFieldName, stringifiedValue);
|
|
14651
14507
|
}
|
|
14652
|
-
|
|
14653
|
-
|
|
14654
|
-
|
|
14655
|
-
|
|
14656
|
-
|
|
14657
|
-
|
|
14658
|
-
|
|
14659
|
-
|
|
14660
|
-
|
|
14661
|
-
|
|
14662
|
-
|
|
14663
|
-
|
|
14664
|
-
|
|
14665
|
-
|
|
14666
|
-
|
|
14667
|
-
|
|
14668
|
-
|
|
14669
|
-
|
|
14670
|
-
|
|
14671
|
-
|
|
14672
|
-
|
|
14673
|
-
|
|
14674
|
-
|
|
14675
|
-
|
|
14676
|
-
|
|
14677
|
-
|
|
14678
|
-
}
|
|
14679
|
-
result += redacted.slice(cursor);
|
|
14680
|
-
redacted = result;
|
|
14681
|
-
}
|
|
14682
|
-
return { text: redacted, matches };
|
|
14683
|
-
}
|
|
14684
|
-
/**
|
|
14685
|
-
* Scan and redact PII from a single text string, using numbered, reversible
|
|
14686
|
-
* placeholders ([EMAIL_1], …) tracked on this instance.
|
|
14687
|
-
*/
|
|
14688
|
-
redactText(text12) {
|
|
14689
|
-
return this.scan(text12, (category, value) => this.getPlaceholder(category, value));
|
|
14690
|
-
}
|
|
14691
|
-
/**
|
|
14692
|
-
* Mask PII with unnumbered, NON-reversible tokens ([EMAIL], [SSN], …) without
|
|
14693
|
-
* mutating this instance's state. Use for one-way purposes where the value is
|
|
14694
|
-
* never restored — notably embedding inputs: it keeps real PII off the
|
|
14695
|
-
* embeddings endpoint while staying deterministic, so the same content always
|
|
14696
|
-
* masks identically and search stays consistent across conversations.
|
|
14697
|
-
*/
|
|
14698
|
-
maskText(text12) {
|
|
14699
|
-
return this.scan(text12, (category) => `[${category}]`).text;
|
|
14700
|
-
}
|
|
14701
|
-
/** All regex matches as spans on the ORIGINAL text (priority 0). Uses the
|
|
14702
|
-
* same {@link findMatches} guards as the sync scan. */
|
|
14703
|
-
collectRegexSpans(text12) {
|
|
14704
|
-
const spans = [];
|
|
14705
|
-
this.patterns.forEach((pattern, patternIndex) => {
|
|
14706
|
-
for (const { match, index } of this.findMatches(text12, pattern)) {
|
|
14707
|
-
spans.push({
|
|
14708
|
-
start: index,
|
|
14709
|
-
end: index + match.length,
|
|
14710
|
-
category: pattern.category,
|
|
14711
|
-
priority: 0,
|
|
14712
|
-
order: patternIndex
|
|
14713
|
-
});
|
|
14508
|
+
};
|
|
14509
|
+
};
|
|
14510
|
+
};
|
|
14511
|
+
var _default = exports2.default = jsonDecorator;
|
|
14512
|
+
}
|
|
14513
|
+
});
|
|
14514
|
+
|
|
14515
|
+
// node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/nochange/index.js
|
|
14516
|
+
var require_nochange = __commonJS({
|
|
14517
|
+
"node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/nochange/index.js"(exports2) {
|
|
14518
|
+
"use strict";
|
|
14519
|
+
var _interopRequireDefault = require_interopRequireDefault();
|
|
14520
|
+
exports2.__esModule = true;
|
|
14521
|
+
exports2.default = void 0;
|
|
14522
|
+
var _extends2 = _interopRequireDefault(require_extends());
|
|
14523
|
+
var _makeDecorator = _interopRequireDefault(require_makeDecorator());
|
|
14524
|
+
var _invariant = _interopRequireDefault(require_invariant());
|
|
14525
|
+
var nochange = (0, _makeDecorator.default)(function() {
|
|
14526
|
+
return function(target, key, descriptor) {
|
|
14527
|
+
(0, _invariant.default)(descriptor.set, "@nochange can only be applied to model fields (to properties with a setter)");
|
|
14528
|
+
var errorMessage = "Attempt to set a new value on a @nochange field: ".concat(target.constructor.name, ".prototype.").concat(key);
|
|
14529
|
+
return (0, _extends2.default)({}, descriptor, {
|
|
14530
|
+
set: function(value) {
|
|
14531
|
+
var model = this;
|
|
14532
|
+
(0, _invariant.default)("create" === model.asModel._preparedState, errorMessage);
|
|
14533
|
+
descriptor.set.call(model, value);
|
|
14714
14534
|
}
|
|
14715
14535
|
});
|
|
14716
|
-
|
|
14717
|
-
|
|
14718
|
-
|
|
14719
|
-
* Normalize raw NER spans: clamp to the text bounds, drop empty/categoryless
|
|
14720
|
-
* spans, and snap each to whole-word boundaries. Snapping prevents a detector
|
|
14721
|
-
* that tagged only part of a word (a common WordPiece artifact — e.g. "Strip"
|
|
14722
|
-
* of "Stripe") from producing a corrupting partial placeholder like
|
|
14723
|
-
* `[ORG_1]e`.
|
|
14724
|
-
*/
|
|
14725
|
-
normalizeNerSpans(text12, raw) {
|
|
14726
|
-
if (!Array.isArray(raw)) return [];
|
|
14727
|
-
const out = [];
|
|
14728
|
-
raw.forEach((s, i) => {
|
|
14729
|
-
if (!Number.isFinite(s.start) || !Number.isFinite(s.end)) return;
|
|
14730
|
-
let start = Math.max(0, Math.min(Math.trunc(s.start), text12.length));
|
|
14731
|
-
let end = Math.max(0, Math.min(Math.trunc(s.end), text12.length));
|
|
14732
|
-
if (end <= start) return;
|
|
14733
|
-
while (start > 0 && isWordChar(text12[start - 1])) start--;
|
|
14734
|
-
while (end < text12.length && isWordChar(text12[end])) end++;
|
|
14735
|
-
const category = String(s.category ?? "").trim();
|
|
14736
|
-
if (!category) return;
|
|
14737
|
-
out.push({ start, end, category, priority: 1, order: i });
|
|
14738
|
-
});
|
|
14739
|
-
return out;
|
|
14740
|
-
}
|
|
14741
|
-
/** Run the configured detector defensively: failures degrade to regex-only
|
|
14742
|
-
* (fail-open on detection, not on protection) with a one-time warning. */
|
|
14743
|
-
async detectNerSpans(text12) {
|
|
14744
|
-
if (!this.nerDetector) return [];
|
|
14745
|
-
try {
|
|
14746
|
-
return this.normalizeNerSpans(text12, await this.nerDetector.detect(text12));
|
|
14747
|
-
} catch (err) {
|
|
14748
|
-
this.warnNerFailure(err);
|
|
14749
|
-
return [];
|
|
14750
|
-
}
|
|
14751
|
-
}
|
|
14752
|
-
/**
|
|
14753
|
-
* Resolve overlaps by placing higher-priority spans first and dropping any
|
|
14754
|
-
* span that overlaps one already placed. Regex (priority 0) is placed before
|
|
14755
|
-
* NER (priority 1), and within regex by ascending pattern index — so regex
|
|
14756
|
-
* always wins on overlap and the regex-only result reproduces the sync scan's
|
|
14757
|
-
* sequential "earlier pattern wins". O(n²) but n (spans per message) is tiny.
|
|
14758
|
-
*
|
|
14759
|
-
* The returned spans stay in `(priority, order, start)` order — i.e. mint
|
|
14760
|
-
* order — which {@link rebuildSpans} relies on.
|
|
14761
|
-
*/
|
|
14762
|
-
resolveOverlaps(spans) {
|
|
14763
|
-
const ordered = [...spans].sort(
|
|
14764
|
-
(a, b) => a.priority - b.priority || a.order - b.order || a.start - b.start
|
|
14765
|
-
);
|
|
14766
|
-
const placed = [];
|
|
14767
|
-
for (const s of ordered) {
|
|
14768
|
-
if (!placed.some((p) => s.start < p.end && p.start < s.end)) placed.push(s);
|
|
14769
|
-
}
|
|
14770
|
-
return placed;
|
|
14771
|
-
}
|
|
14772
|
-
/**
|
|
14773
|
-
* Rebuild `text` from resolved (non-overlapping) spans. `spans` must arrive in
|
|
14774
|
-
* mint order — `(priority, order, start)`, as {@link resolveOverlaps} returns —
|
|
14775
|
-
* so placeholders are MINTED by iterating it directly (regex categories first,
|
|
14776
|
-
* in pattern then document order, matching the sync scan's numbering). The
|
|
14777
|
-
* string is then EMITTED in document order.
|
|
14778
|
-
*/
|
|
14779
|
-
rebuildSpans(text12, spans, makeReplacement) {
|
|
14780
|
-
const placeholderByStart = /* @__PURE__ */ new Map();
|
|
14781
|
-
const matches = [];
|
|
14782
|
-
for (const s of spans) {
|
|
14783
|
-
const value = text12.slice(s.start, s.end);
|
|
14784
|
-
const placeholder = makeReplacement(s.category, value);
|
|
14785
|
-
placeholderByStart.set(s.start, placeholder);
|
|
14786
|
-
matches.push({ category: s.category, original: value, placeholder });
|
|
14787
|
-
}
|
|
14788
|
-
const emitOrder = [...spans].sort((a, b) => a.start - b.start);
|
|
14789
|
-
let result = "";
|
|
14790
|
-
let cursor = 0;
|
|
14791
|
-
for (const s of emitOrder) {
|
|
14792
|
-
result += text12.slice(cursor, s.start) + (placeholderByStart.get(s.start) ?? "");
|
|
14793
|
-
cursor = s.end;
|
|
14794
|
-
}
|
|
14795
|
-
result += text12.slice(cursor);
|
|
14796
|
-
return { text: result, matches };
|
|
14797
|
-
}
|
|
14798
|
-
/** Merge regex + NER spans for `text` into a resolved, non-overlapping set. */
|
|
14799
|
-
async detectAllSpans(text12) {
|
|
14800
|
-
const nerPromise = this.detectNerSpans(text12);
|
|
14801
|
-
const regexSpans = this.collectRegexSpans(text12);
|
|
14802
|
-
const ner = await nerPromise;
|
|
14803
|
-
return this.resolveOverlaps([...regexSpans, ...ner]);
|
|
14804
|
-
}
|
|
14805
|
-
/**
|
|
14806
|
-
* Async counterpart to {@link redactText}: redacts structured PII (regex) AND
|
|
14807
|
-
* unstructured PII (the configured {@link NerDetector}) with numbered,
|
|
14808
|
-
* reversible placeholders. With no detector, identical to `redactText`.
|
|
14809
|
-
*/
|
|
14810
|
-
async redactTextAsync(text12) {
|
|
14811
|
-
if (!this.nerDetector) return this.redactText(text12);
|
|
14812
|
-
const spans = await this.detectAllSpans(text12);
|
|
14813
|
-
return this.rebuildSpans(
|
|
14814
|
-
text12,
|
|
14815
|
-
spans,
|
|
14816
|
-
(category, value) => this.getPlaceholder(category, value)
|
|
14817
|
-
);
|
|
14818
|
-
}
|
|
14819
|
-
/**
|
|
14820
|
-
* Async counterpart to {@link maskText}: stateless `[CATEGORY]` masking over
|
|
14821
|
-
* regex + NER matches. With no detector, identical to `maskText`.
|
|
14822
|
-
*/
|
|
14823
|
-
async maskTextAsync(text12) {
|
|
14824
|
-
if (!this.nerDetector) return this.maskText(text12);
|
|
14825
|
-
const spans = await this.detectAllSpans(text12);
|
|
14826
|
-
return this.rebuildSpans(text12, spans, (category) => `[${category}]`).text;
|
|
14827
|
-
}
|
|
14828
|
-
/**
|
|
14829
|
-
* Async counterpart to {@link redactMessages}. Text parts are redacted
|
|
14830
|
-
* sequentially so placeholder numbering stays deterministic across the
|
|
14831
|
-
* conversation. With no detector, identical to `redactMessages`.
|
|
14832
|
-
*/
|
|
14833
|
-
async redactMessagesAsync(messages) {
|
|
14834
|
-
if (!this.nerDetector) return this.redactMessages(messages);
|
|
14835
|
-
const allMatches = [];
|
|
14836
|
-
const redactedMessages = [];
|
|
14837
|
-
for (const msg of messages) {
|
|
14838
|
-
if (!msg.content) {
|
|
14839
|
-
redactedMessages.push(msg);
|
|
14840
|
-
continue;
|
|
14841
|
-
}
|
|
14842
|
-
const newContent = [];
|
|
14843
|
-
for (const part of msg.content) {
|
|
14844
|
-
if (part.type === "text" && part.text) {
|
|
14845
|
-
const result = await this.redactTextAsync(part.text);
|
|
14846
|
-
allMatches.push(...result.matches);
|
|
14847
|
-
newContent.push(result.matches.length > 0 ? { ...part, text: result.text } : part);
|
|
14848
|
-
} else {
|
|
14849
|
-
if (part.type !== "text") this.warnNonTextBypass();
|
|
14850
|
-
newContent.push(part);
|
|
14851
|
-
}
|
|
14852
|
-
}
|
|
14853
|
-
redactedMessages.push({ ...msg, content: newContent });
|
|
14854
|
-
}
|
|
14855
|
-
return { messages: redactedMessages, matches: allMatches };
|
|
14856
|
-
}
|
|
14857
|
-
/**
|
|
14858
|
-
* Redact PII from an array of LlmapiMessage objects.
|
|
14859
|
-
* Returns new message objects — originals are not mutated.
|
|
14860
|
-
*
|
|
14861
|
-
* All roles' text content is redacted, not just user/system: tool results
|
|
14862
|
-
* can return PII fetched from external systems, and assistant history is
|
|
14863
|
-
* persisted with original (de-anonymized) values, so both must be re-redacted
|
|
14864
|
-
* before they go back over the wire. Placeholders the model already emitted
|
|
14865
|
-
* are inert here (they don't match any PII pattern), so re-redaction is safe.
|
|
14866
|
-
*/
|
|
14867
|
-
redactMessages(messages) {
|
|
14868
|
-
const allMatches = [];
|
|
14869
|
-
const redactedMessages = messages.map((msg) => {
|
|
14870
|
-
if (!msg.content) return msg;
|
|
14871
|
-
const newContent = msg.content.map((part) => {
|
|
14872
|
-
if (part.type === "text" && part.text) {
|
|
14873
|
-
const result = this.redactText(part.text);
|
|
14874
|
-
allMatches.push(...result.matches);
|
|
14875
|
-
if (result.matches.length > 0) {
|
|
14876
|
-
return { ...part, text: result.text };
|
|
14877
|
-
}
|
|
14878
|
-
} else if (part.type !== "text") {
|
|
14879
|
-
this.warnNonTextBypass();
|
|
14880
|
-
}
|
|
14881
|
-
return part;
|
|
14882
|
-
});
|
|
14883
|
-
return { ...msg, content: newContent };
|
|
14884
|
-
});
|
|
14885
|
-
return { messages: redactedMessages, matches: allMatches };
|
|
14886
|
-
}
|
|
14887
|
-
/** Emit the non-text bypass warning at most once per redactor instance. */
|
|
14888
|
-
warnNonTextBypass() {
|
|
14889
|
-
if (this.warnedNonText) return;
|
|
14890
|
-
this.warnedNonText = true;
|
|
14891
|
-
console.warn(
|
|
14892
|
-
"[PiiRedactor] A message contains non-text content (images, files, or attachments) that is NOT scanned for PII \u2014 only text parts are redacted."
|
|
14893
|
-
);
|
|
14894
|
-
}
|
|
14895
|
-
/** Emit the NER-detector-failure warning at most once per redactor instance. */
|
|
14896
|
-
warnNerFailure(err) {
|
|
14897
|
-
if (this.warnedNerFailure) return;
|
|
14898
|
-
this.warnedNerFailure = true;
|
|
14899
|
-
console.warn(
|
|
14900
|
-
"[PiiRedactor] The NER detector threw; falling back to regex-only redaction for this call's unstructured PII. The detector is still retried on subsequent calls; this warning is emitted only once.",
|
|
14901
|
-
err
|
|
14902
|
-
);
|
|
14903
|
-
}
|
|
14904
|
-
/**
|
|
14905
|
-
* Restore original PII values in text that contains placeholders.
|
|
14906
|
-
* Used to de-anonymize LLM responses before displaying to the user.
|
|
14907
|
-
*
|
|
14908
|
-
* Exact: matches the literal `[EMAIL_1]` form only. The storage paths use
|
|
14909
|
-
* {@link restoreForStorage} instead, which tolerates the mangled echoes the
|
|
14910
|
-
* extraction models produce.
|
|
14911
|
-
*/
|
|
14912
|
-
deAnonymize(text12) {
|
|
14913
|
-
if (!text12.includes("[")) return text12;
|
|
14914
|
-
let restored = text12;
|
|
14915
|
-
for (const [placeholder, original] of this.placeholderToValue) {
|
|
14916
|
-
if (restored.includes(placeholder)) {
|
|
14917
|
-
restored = restored.split(placeholder).join(original);
|
|
14918
|
-
}
|
|
14919
|
-
}
|
|
14920
|
-
return restored;
|
|
14921
|
-
}
|
|
14922
|
-
/**
|
|
14923
|
-
* De-anonymize for PERSISTENCE (auto-extraction / consolidation), tolerant of
|
|
14924
|
-
* the ways the extraction models mangle a placeholder when echoing it back:
|
|
14925
|
-
* dropped brackets (`EMAIL_1`) and changed case (`email_1` / `Email_1`).
|
|
14926
|
-
*
|
|
14927
|
-
* Returns the restored text plus `unresolved` — true when a placeholder-shaped
|
|
14928
|
-
* token for one of this redactor's categories was NOT assigned during
|
|
14929
|
-
* redaction (a model hallucination, or an ambiguous re-cased collision).
|
|
14930
|
-
* Callers drop/degrade such facts so an opaque token never reaches the vault.
|
|
14931
|
-
*
|
|
14932
|
-
* One left-to-right pass over the ORIGINAL text. Two properties matter:
|
|
14933
|
-
* - a restored value is never re-scanned — so a real value that happens to
|
|
14934
|
-
* contain a `<CATEGORY>_<n>` substring (e.g. the email `ssn_1@example.com`,
|
|
14935
|
-
* or an API key containing `EMAIL_1`) is neither corrupted nor false-flagged;
|
|
14936
|
-
* - `unresolved` is derived from the lookup miss during this pass, not from a
|
|
14937
|
-
* regex re-scan of the output — so it can't trip over a restored value.
|
|
14938
|
-
*/
|
|
14939
|
-
restoreForStorage(text12) {
|
|
14940
|
-
if (this.storagePattern === void 0) this.storagePattern = this.buildStoragePattern();
|
|
14941
|
-
if (!this.storagePattern || this.placeholderToValue.size === 0) {
|
|
14942
|
-
return { text: text12, unresolved: false };
|
|
14943
|
-
}
|
|
14944
|
-
this.storageLookup ?? (this.storageLookup = this.buildStorageLookup());
|
|
14945
|
-
const { exact, ci, ciCollisions } = this.storageLookup;
|
|
14946
|
-
let unresolved = false;
|
|
14947
|
-
const restored = text12.replace(
|
|
14948
|
-
this.storagePattern,
|
|
14949
|
-
(match, bracketed, bare) => {
|
|
14950
|
-
const body = bracketed ?? bare ?? "";
|
|
14951
|
-
const exactHit = exact.get(body);
|
|
14952
|
-
if (exactHit !== void 0) return exactHit;
|
|
14953
|
-
const key = body.toUpperCase();
|
|
14954
|
-
if (!ciCollisions.has(key)) {
|
|
14955
|
-
const ciHit = ci.get(key);
|
|
14956
|
-
if (ciHit !== void 0) return ciHit;
|
|
14957
|
-
}
|
|
14958
|
-
unresolved = true;
|
|
14959
|
-
return match;
|
|
14960
|
-
}
|
|
14961
|
-
);
|
|
14962
|
-
return { text: restored, unresolved };
|
|
14963
|
-
}
|
|
14964
|
-
/**
|
|
14965
|
-
* Build the {@link restoreForStorage} body→value lookups from the assigned
|
|
14966
|
-
* placeholders. `exact` (literal body) is collision-proof; `ci` (upper-cased
|
|
14967
|
-
* body) handles re-cased echoes, except where two distinct bodies share an
|
|
14968
|
-
* upper-cased form — those are recorded in `ciCollisions` so a re-cased echo
|
|
14969
|
-
* of them is left unresolved rather than resolved to the wrong value.
|
|
14970
|
-
*/
|
|
14971
|
-
buildStorageLookup() {
|
|
14972
|
-
const exact = /* @__PURE__ */ new Map();
|
|
14973
|
-
const ci = /* @__PURE__ */ new Map();
|
|
14974
|
-
const ciCollisions = /* @__PURE__ */ new Set();
|
|
14975
|
-
for (const [placeholder, value] of this.placeholderToValue) {
|
|
14976
|
-
const body = placeholder.slice(1, -1);
|
|
14977
|
-
exact.set(body, value);
|
|
14978
|
-
const key = body.toUpperCase();
|
|
14979
|
-
if (ci.has(key) && ci.get(key) !== value) ciCollisions.add(key);
|
|
14980
|
-
else ci.set(key, value);
|
|
14981
|
-
}
|
|
14982
|
-
return { exact, ci, ciCollisions };
|
|
14983
|
-
}
|
|
14984
|
-
/**
|
|
14985
|
-
* Reset all state. Useful for testing or when starting a fresh conversation.
|
|
14986
|
-
*/
|
|
14987
|
-
clear() {
|
|
14988
|
-
this.valueToPlaceholder.clear();
|
|
14989
|
-
this.placeholderToValue.clear();
|
|
14990
|
-
this.categoryCounters.clear();
|
|
14991
|
-
this.storageLookup = null;
|
|
14992
|
-
this.storagePattern = void 0;
|
|
14993
|
-
this.warnedNonText = false;
|
|
14994
|
-
this.warnedNerFailure = false;
|
|
14995
|
-
}
|
|
14996
|
-
};
|
|
14997
|
-
}
|
|
14998
|
-
});
|
|
14999
|
-
|
|
15000
|
-
// src/lib/chat/endpointOverride.ts
|
|
15001
|
-
function validateEndpointOverride(override) {
|
|
15002
|
-
const trimmed = override.trim();
|
|
15003
|
-
if (trimmed === "") {
|
|
15004
|
-
return {
|
|
15005
|
-
valid: false,
|
|
15006
|
-
message: 'endpointOverride must be a non-empty, root-relative path (e.g. "/api/v1/utility/responses"); received an empty or whitespace-only string'
|
|
15007
|
-
};
|
|
15008
|
-
}
|
|
15009
|
-
if (trimmed.startsWith("//") || trimmed.includes("://")) {
|
|
15010
|
-
return {
|
|
15011
|
-
valid: false,
|
|
15012
|
-
message: `endpointOverride must be a root-relative path (e.g. "/api/v1/utility/responses"), not a protocol-relative or absolute URL; received "${trimmed}"`
|
|
15013
|
-
};
|
|
15014
|
-
}
|
|
15015
|
-
return { valid: true, endpoint: trimmed.startsWith("/") ? trimmed : `/${trimmed}` };
|
|
15016
|
-
}
|
|
15017
|
-
var init_endpointOverride = __esm({
|
|
15018
|
-
"src/lib/chat/endpointOverride.ts"() {
|
|
15019
|
-
"use strict";
|
|
14536
|
+
};
|
|
14537
|
+
});
|
|
14538
|
+
var _default = exports2.default = nochange;
|
|
15020
14539
|
}
|
|
15021
14540
|
});
|
|
15022
14541
|
|
|
15023
|
-
//
|
|
15024
|
-
|
|
15025
|
-
|
|
15026
|
-
return `${INTERNAL_FLOW_MARKER}
|
|
15027
|
-
${systemPrompt}`;
|
|
15028
|
-
}
|
|
15029
|
-
var INTERNAL_FLOW_MARKER;
|
|
15030
|
-
var init_internalFlowMarker = __esm({
|
|
15031
|
-
"src/lib/internalFlowMarker.ts"() {
|
|
14542
|
+
// node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/field/index.js
|
|
14543
|
+
var require_field = __commonJS({
|
|
14544
|
+
"node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/field/index.js"(exports2) {
|
|
15032
14545
|
"use strict";
|
|
15033
|
-
|
|
14546
|
+
var _interopRequireDefault = require_interopRequireDefault();
|
|
14547
|
+
exports2.__esModule = true;
|
|
14548
|
+
exports2.default = void 0;
|
|
14549
|
+
var _makeDecorator = _interopRequireDefault(require_makeDecorator());
|
|
14550
|
+
var _common = require_common2();
|
|
14551
|
+
var field10 = (0, _makeDecorator.default)(function(columnName) {
|
|
14552
|
+
return function(target, key, descriptor) {
|
|
14553
|
+
(0, _common.ensureDecoratorUsedProperly)(columnName, target, key, descriptor);
|
|
14554
|
+
return {
|
|
14555
|
+
configurable: true,
|
|
14556
|
+
enumerable: true,
|
|
14557
|
+
get: function() {
|
|
14558
|
+
return this.asModel._getRaw(columnName);
|
|
14559
|
+
},
|
|
14560
|
+
set: function(value) {
|
|
14561
|
+
this.asModel._setRaw(columnName, value);
|
|
14562
|
+
}
|
|
14563
|
+
};
|
|
14564
|
+
};
|
|
14565
|
+
});
|
|
14566
|
+
var _default = exports2.default = field10;
|
|
15034
14567
|
}
|
|
15035
14568
|
});
|
|
15036
14569
|
|
|
15037
|
-
// node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/
|
|
15038
|
-
var
|
|
15039
|
-
"node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/
|
|
14570
|
+
// node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/utils/common/memory/index.js
|
|
14571
|
+
var require_memory = __commonJS({
|
|
14572
|
+
"node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/utils/common/memory/index.js"(exports2) {
|
|
15040
14573
|
"use strict";
|
|
15041
|
-
var _interopRequireDefault = require_interopRequireDefault();
|
|
15042
14574
|
exports2.__esModule = true;
|
|
15043
|
-
exports2.
|
|
15044
|
-
exports2.
|
|
15045
|
-
var
|
|
15046
|
-
function
|
|
15047
|
-
|
|
15048
|
-
return (0, _extends2.default)({}, descriptor, {
|
|
15049
|
-
value: function(...args) {
|
|
15050
|
-
var _this = this;
|
|
15051
|
-
return this.database.write(function() {
|
|
15052
|
-
return descriptor.value.apply(_this, args);
|
|
15053
|
-
}, actionName);
|
|
15054
|
-
}
|
|
15055
|
-
});
|
|
14575
|
+
exports2._triggerOnLowMemory = _triggerOnLowMemory;
|
|
14576
|
+
exports2.onLowMemory = onLowMemory;
|
|
14577
|
+
var lowMemoryCallbacks = [];
|
|
14578
|
+
function onLowMemory(callback) {
|
|
14579
|
+
lowMemoryCallbacks.push(callback);
|
|
15056
14580
|
}
|
|
15057
|
-
function
|
|
15058
|
-
|
|
15059
|
-
|
|
15060
|
-
value: function(...args) {
|
|
15061
|
-
var _this2 = this;
|
|
15062
|
-
return this.database.read(function() {
|
|
15063
|
-
return descriptor.value.apply(_this2, args);
|
|
15064
|
-
}, actionName);
|
|
15065
|
-
}
|
|
14581
|
+
function _triggerOnLowMemory() {
|
|
14582
|
+
lowMemoryCallbacks.forEach(function(callback) {
|
|
14583
|
+
return callback();
|
|
15066
14584
|
});
|
|
15067
14585
|
}
|
|
15068
14586
|
}
|
|
15069
14587
|
});
|
|
15070
14588
|
|
|
15071
|
-
// node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/
|
|
15072
|
-
var
|
|
15073
|
-
"node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/
|
|
14589
|
+
// node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/date/index.js
|
|
14590
|
+
var require_date = __commonJS({
|
|
14591
|
+
"node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/date/index.js"(exports2) {
|
|
15074
14592
|
"use strict";
|
|
15075
14593
|
var _interopRequireDefault = require_interopRequireDefault();
|
|
15076
14594
|
exports2.__esModule = true;
|
|
15077
14595
|
exports2.default = void 0;
|
|
15078
14596
|
var _makeDecorator = _interopRequireDefault(require_makeDecorator());
|
|
15079
|
-
var
|
|
15080
|
-
var
|
|
15081
|
-
var
|
|
15082
|
-
|
|
15083
|
-
|
|
15084
|
-
|
|
15085
|
-
|
|
15086
|
-
|
|
15087
|
-
|
|
15088
|
-
}
|
|
15089
|
-
function _interopRequireWildcard(e, r) {
|
|
15090
|
-
if (!r && e && e.__esModule) return e;
|
|
15091
|
-
if (null === e || "object" != typeof e && "function" != typeof e) return { default: e };
|
|
15092
|
-
var t = _getRequireWildcardCache(r);
|
|
15093
|
-
if (t && t.has(e)) return t.get(e);
|
|
15094
|
-
var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
15095
|
-
for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) {
|
|
15096
|
-
var i = a ? Object.getOwnPropertyDescriptor(e, u) : null;
|
|
15097
|
-
i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u];
|
|
15098
|
-
}
|
|
15099
|
-
return n.default = e, t && t.set(e, n), n;
|
|
15100
|
-
}
|
|
15101
|
-
var children = (0, _makeDecorator.default)(function(childTable) {
|
|
15102
|
-
return function() {
|
|
14597
|
+
var _memory = require_memory();
|
|
14598
|
+
var _common = require_common2();
|
|
14599
|
+
var cache = /* @__PURE__ */ new Map();
|
|
14600
|
+
(0, _memory.onLowMemory)(function() {
|
|
14601
|
+
return cache.clear();
|
|
14602
|
+
});
|
|
14603
|
+
var dateDecorator = (0, _makeDecorator.default)(function(columnName) {
|
|
14604
|
+
return function(target, key, descriptor) {
|
|
14605
|
+
(0, _common.ensureDecoratorUsedProperly)(columnName, target, key, descriptor);
|
|
15103
14606
|
return {
|
|
14607
|
+
configurable: true,
|
|
14608
|
+
enumerable: true,
|
|
15104
14609
|
get: function() {
|
|
15105
|
-
var
|
|
15106
|
-
|
|
15107
|
-
|
|
15108
|
-
|
|
15109
|
-
|
|
14610
|
+
var rawValue = this.asModel._getRaw(columnName);
|
|
14611
|
+
if ("number" === typeof rawValue) {
|
|
14612
|
+
var cached = cache.get(rawValue);
|
|
14613
|
+
if (cached) {
|
|
14614
|
+
return cached;
|
|
14615
|
+
}
|
|
14616
|
+
var date10 = new Date(rawValue);
|
|
14617
|
+
cache.set(rawValue, date10);
|
|
14618
|
+
return date10;
|
|
15110
14619
|
}
|
|
15111
|
-
|
|
15112
|
-
var childCollection = model.collections.get(childTable);
|
|
15113
|
-
var association = model.constructor.associations[childTable];
|
|
15114
|
-
(0, _invariant.default)(association && "has_many" === association.type, "@children decorator used for a table that's not has_many");
|
|
15115
|
-
var query = childCollection.query(Q13.where(association.foreignKey, model.id));
|
|
15116
|
-
that._childrenQueryCache[childTable] = query;
|
|
15117
|
-
return query;
|
|
14620
|
+
return null;
|
|
15118
14621
|
},
|
|
15119
|
-
set: function() {
|
|
15120
|
-
|
|
14622
|
+
set: function(date10) {
|
|
14623
|
+
var rawValue = date10 ? +new Date(date10) : null;
|
|
14624
|
+
if (rawValue && date10) {
|
|
14625
|
+
cache.set(rawValue, new Date(date10));
|
|
14626
|
+
}
|
|
14627
|
+
this.asModel._setRaw(columnName, rawValue);
|
|
15121
14628
|
}
|
|
15122
14629
|
};
|
|
15123
14630
|
};
|
|
15124
14631
|
});
|
|
15125
|
-
var _default = exports2.default =
|
|
14632
|
+
var _default = exports2.default = dateDecorator;
|
|
15126
14633
|
}
|
|
15127
14634
|
});
|
|
15128
14635
|
|
|
15129
|
-
// node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/
|
|
15130
|
-
var
|
|
15131
|
-
"node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/
|
|
14636
|
+
// node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/text/index.js
|
|
14637
|
+
var require_text = __commonJS({
|
|
14638
|
+
"node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/text/index.js"(exports2) {
|
|
15132
14639
|
"use strict";
|
|
15133
14640
|
var _interopRequireDefault = require_interopRequireDefault();
|
|
15134
14641
|
exports2.__esModule = true;
|
|
15135
|
-
exports2.
|
|
14642
|
+
exports2.default = void 0;
|
|
14643
|
+
var _makeDecorator = _interopRequireDefault(require_makeDecorator());
|
|
14644
|
+
var _common = require_common2();
|
|
14645
|
+
var text12 = (0, _makeDecorator.default)(function(columnName) {
|
|
14646
|
+
return function(target, key, descriptor) {
|
|
14647
|
+
(0, _common.ensureDecoratorUsedProperly)(columnName, target, key, descriptor);
|
|
14648
|
+
return {
|
|
14649
|
+
configurable: true,
|
|
14650
|
+
enumerable: true,
|
|
14651
|
+
get: function() {
|
|
14652
|
+
return this.asModel._getRaw(columnName);
|
|
14653
|
+
},
|
|
14654
|
+
set: function(value) {
|
|
14655
|
+
this.asModel._setRaw(columnName, "string" === typeof value ? value.trim() : null);
|
|
14656
|
+
}
|
|
14657
|
+
};
|
|
14658
|
+
};
|
|
14659
|
+
});
|
|
14660
|
+
var _default = exports2.default = text12;
|
|
14661
|
+
}
|
|
14662
|
+
});
|
|
14663
|
+
|
|
14664
|
+
// node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/readonly/index.js
|
|
14665
|
+
var require_readonly = __commonJS({
|
|
14666
|
+
"node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/readonly/index.js"(exports2) {
|
|
14667
|
+
"use strict";
|
|
14668
|
+
var _interopRequireDefault = require_interopRequireDefault();
|
|
14669
|
+
exports2.__esModule = true;
|
|
14670
|
+
exports2.default = void 0;
|
|
14671
|
+
var _extends2 = _interopRequireDefault(require_extends());
|
|
14672
|
+
var _makeDecorator = _interopRequireDefault(require_makeDecorator());
|
|
15136
14673
|
var _invariant = _interopRequireDefault(require_invariant());
|
|
15137
|
-
|
|
15138
|
-
|
|
15139
|
-
|
|
15140
|
-
|
|
15141
|
-
|
|
15142
|
-
|
|
15143
|
-
|
|
14674
|
+
var readonly8 = (0, _makeDecorator.default)(function() {
|
|
14675
|
+
return function(target, key, descriptor) {
|
|
14676
|
+
if (descriptor.get || descriptor.set) {
|
|
14677
|
+
return (0, _extends2.default)({}, descriptor, {
|
|
14678
|
+
set: function() {
|
|
14679
|
+
(0, _invariant.default)(false, "Attempt to set new value on a property ".concat(target.constructor.name, ".prototype.").concat(key, " marked as @readonly"));
|
|
14680
|
+
}
|
|
14681
|
+
});
|
|
14682
|
+
}
|
|
14683
|
+
descriptor.writable = false;
|
|
14684
|
+
return descriptor;
|
|
14685
|
+
};
|
|
14686
|
+
});
|
|
14687
|
+
var _default = exports2.default = readonly8;
|
|
15144
14688
|
}
|
|
15145
14689
|
});
|
|
15146
14690
|
|
|
15147
|
-
// node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/
|
|
15148
|
-
var
|
|
15149
|
-
"node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/
|
|
14691
|
+
// node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/relation/index.js
|
|
14692
|
+
var require_relation = __commonJS({
|
|
14693
|
+
"node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/relation/index.js"(exports2) {
|
|
15150
14694
|
"use strict";
|
|
14695
|
+
var _interopRequireDefault = require_interopRequireDefault();
|
|
15151
14696
|
exports2.__esModule = true;
|
|
15152
|
-
exports2.
|
|
14697
|
+
exports2.default = void 0;
|
|
15153
14698
|
var _common = require_common2();
|
|
15154
|
-
var
|
|
15155
|
-
|
|
15156
|
-
return void 0;
|
|
15157
|
-
}
|
|
15158
|
-
try {
|
|
15159
|
-
return JSON.parse(value);
|
|
15160
|
-
} catch (_) {
|
|
15161
|
-
return void 0;
|
|
15162
|
-
}
|
|
15163
|
-
};
|
|
15164
|
-
var defaultOptions = {
|
|
15165
|
-
memo: false
|
|
15166
|
-
};
|
|
15167
|
-
var jsonDecorator = exports2.jsonDecorator = function(rawFieldName, sanitizer, options = defaultOptions) {
|
|
14699
|
+
var _Relation = _interopRequireDefault(require_Relation());
|
|
14700
|
+
var relation = function(relationTable, relationIdColumn, options) {
|
|
15168
14701
|
return function(target, key, descriptor) {
|
|
15169
|
-
(0, _common.ensureDecoratorUsedProperly)(
|
|
14702
|
+
(0, _common.ensureDecoratorUsedProperly)(relationIdColumn, target, key, descriptor);
|
|
15170
14703
|
return {
|
|
15171
|
-
|
|
15172
|
-
enumerable: true,
|
|
15173
|
-
get: function get() {
|
|
14704
|
+
get: function() {
|
|
15174
14705
|
var model = this;
|
|
15175
|
-
|
|
15176
|
-
|
|
15177
|
-
|
|
15178
|
-
|
|
15179
|
-
if (cachedEntry && cachedEntry[0] === rawValue) {
|
|
15180
|
-
return cachedEntry[1];
|
|
15181
|
-
}
|
|
15182
|
-
}
|
|
15183
|
-
var parsedValue = parseJSON(rawValue);
|
|
15184
|
-
var sanitized = sanitizer(parsedValue, model);
|
|
15185
|
-
if (options.memo) {
|
|
15186
|
-
model._jsonDecoratorCache[rawFieldName] = [rawValue, sanitized];
|
|
14706
|
+
model._relationCache = model._relationCache || {};
|
|
14707
|
+
var cachedRelation = model._relationCache[key];
|
|
14708
|
+
if (cachedRelation) {
|
|
14709
|
+
return cachedRelation;
|
|
15187
14710
|
}
|
|
15188
|
-
|
|
14711
|
+
var newRelation = new _Relation.default(model.asModel, relationTable, relationIdColumn, options || {
|
|
14712
|
+
isImmutable: false
|
|
14713
|
+
});
|
|
14714
|
+
model._relationCache[key] = newRelation;
|
|
14715
|
+
return newRelation;
|
|
15189
14716
|
},
|
|
15190
|
-
set: function
|
|
15191
|
-
|
|
15192
|
-
var sanitizedValue = sanitizer(json4, model);
|
|
15193
|
-
var stringifiedValue = null != sanitizedValue ? JSON.stringify(sanitizedValue) : null;
|
|
15194
|
-
model.asModel._setRaw(rawFieldName, stringifiedValue);
|
|
14717
|
+
set: function() {
|
|
14718
|
+
throw new Error("Don't set relation directly. Use relation.set() instead");
|
|
15195
14719
|
}
|
|
15196
14720
|
};
|
|
15197
14721
|
};
|
|
15198
14722
|
};
|
|
15199
|
-
var _default = exports2.default =
|
|
14723
|
+
var _default = exports2.default = relation;
|
|
14724
|
+
}
|
|
14725
|
+
});
|
|
14726
|
+
|
|
14727
|
+
// node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/immutableRelation/index.js
|
|
14728
|
+
var require_immutableRelation = __commonJS({
|
|
14729
|
+
"node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/immutableRelation/index.js"(exports2) {
|
|
14730
|
+
"use strict";
|
|
14731
|
+
var _interopRequireDefault = require_interopRequireDefault();
|
|
14732
|
+
exports2.__esModule = true;
|
|
14733
|
+
exports2.default = void 0;
|
|
14734
|
+
var _relation = _interopRequireDefault(require_relation());
|
|
14735
|
+
var immutableRelation = function(relationTable, relationIdColumn) {
|
|
14736
|
+
return (0, _relation.default)(relationTable, relationIdColumn, {
|
|
14737
|
+
isImmutable: true
|
|
14738
|
+
});
|
|
14739
|
+
};
|
|
14740
|
+
var _default = exports2.default = immutableRelation;
|
|
15200
14741
|
}
|
|
15201
14742
|
});
|
|
15202
14743
|
|
|
15203
|
-
// node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/
|
|
15204
|
-
var
|
|
15205
|
-
"node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/
|
|
14744
|
+
// node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/experimentalFailsafe/index.js
|
|
14745
|
+
var require_experimentalFailsafe = __commonJS({
|
|
14746
|
+
"node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/experimentalFailsafe/index.js"(exports2) {
|
|
15206
14747
|
"use strict";
|
|
15207
14748
|
var _interopRequireDefault = require_interopRequireDefault();
|
|
15208
14749
|
exports2.__esModule = true;
|
|
15209
14750
|
exports2.default = void 0;
|
|
15210
14751
|
var _extends2 = _interopRequireDefault(require_extends());
|
|
15211
|
-
var
|
|
15212
|
-
var
|
|
15213
|
-
var
|
|
14752
|
+
var _fp = require_fp();
|
|
14753
|
+
var _rx = require_rx();
|
|
14754
|
+
var failsafe = function(fallback = void 0) {
|
|
15214
14755
|
return function(target, key, descriptor) {
|
|
15215
|
-
(0, _invariant.default)(descriptor.set, "@nochange can only be applied to model fields (to properties with a setter)");
|
|
15216
|
-
var errorMessage = "Attempt to set a new value on a @nochange field: ".concat(target.constructor.name, ".prototype.").concat(key);
|
|
15217
14756
|
return (0, _extends2.default)({}, descriptor, {
|
|
15218
|
-
|
|
15219
|
-
var
|
|
15220
|
-
|
|
15221
|
-
|
|
14757
|
+
get: function() {
|
|
14758
|
+
var value;
|
|
14759
|
+
var unsafeThis = this;
|
|
14760
|
+
if ("value" in descriptor) {
|
|
14761
|
+
value = descriptor.value;
|
|
14762
|
+
} else if ("get" in descriptor) {
|
|
14763
|
+
value = descriptor.get.call(unsafeThis);
|
|
14764
|
+
} else if ("initializer" in descriptor) {
|
|
14765
|
+
value = descriptor.initializer.call(unsafeThis);
|
|
14766
|
+
}
|
|
14767
|
+
if (value && (0, _fp.isObj)(value)) {
|
|
14768
|
+
var originalFetch = value.fetch;
|
|
14769
|
+
var originalObserve = value.observe;
|
|
14770
|
+
if ("function" === typeof originalFetch) {
|
|
14771
|
+
value.fetch = function(...args) {
|
|
14772
|
+
var result = originalFetch.apply(value, args);
|
|
14773
|
+
if ((0, _fp.isObj)(result) && "function" === typeof result.catch) {
|
|
14774
|
+
return result.catch(function() {
|
|
14775
|
+
return fallback;
|
|
14776
|
+
});
|
|
14777
|
+
}
|
|
14778
|
+
return result;
|
|
14779
|
+
};
|
|
14780
|
+
}
|
|
14781
|
+
if ("function" === typeof originalObserve) {
|
|
14782
|
+
value.observe = function(...args) {
|
|
14783
|
+
var result = originalObserve.apply(value, args);
|
|
14784
|
+
if ((0, _fp.isObj)(result) && "function" === typeof result.pipe) {
|
|
14785
|
+
return result.pipe((0, _rx.catchError)(function() {
|
|
14786
|
+
return (0, _rx.of)(fallback);
|
|
14787
|
+
}));
|
|
14788
|
+
}
|
|
14789
|
+
return result;
|
|
14790
|
+
};
|
|
14791
|
+
}
|
|
14792
|
+
}
|
|
14793
|
+
Object.defineProperty(unsafeThis, key, {
|
|
14794
|
+
value,
|
|
14795
|
+
enumerable: descriptor.enumerable
|
|
14796
|
+
});
|
|
14797
|
+
return value;
|
|
15222
14798
|
}
|
|
15223
14799
|
});
|
|
15224
14800
|
};
|
|
15225
|
-
}
|
|
15226
|
-
var _default = exports2.default =
|
|
14801
|
+
};
|
|
14802
|
+
var _default = exports2.default = failsafe;
|
|
15227
14803
|
}
|
|
15228
14804
|
});
|
|
15229
14805
|
|
|
15230
|
-
// node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/
|
|
15231
|
-
var
|
|
15232
|
-
"node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/
|
|
14806
|
+
// node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/index.js
|
|
14807
|
+
var require_decorators = __commonJS({
|
|
14808
|
+
"node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/index.js"(exports2) {
|
|
15233
14809
|
"use strict";
|
|
15234
14810
|
var _interopRequireDefault = require_interopRequireDefault();
|
|
15235
14811
|
exports2.__esModule = true;
|
|
15236
|
-
exports2.
|
|
15237
|
-
var
|
|
15238
|
-
|
|
15239
|
-
|
|
15240
|
-
|
|
15241
|
-
|
|
15242
|
-
|
|
15243
|
-
|
|
15244
|
-
|
|
15245
|
-
|
|
15246
|
-
|
|
15247
|
-
|
|
15248
|
-
|
|
15249
|
-
|
|
15250
|
-
|
|
15251
|
-
|
|
15252
|
-
|
|
14812
|
+
exports2.writer = exports2.text = exports2.relation = exports2.readonly = exports2.reader = exports2.nochange = exports2.lazy = exports2.json = exports2.immutableRelation = exports2.field = exports2.experimentalFailsafe = exports2.date = exports2.children = void 0;
|
|
14813
|
+
var _action = require_action();
|
|
14814
|
+
exports2.writer = _action.writer;
|
|
14815
|
+
exports2.reader = _action.reader;
|
|
14816
|
+
var _children = _interopRequireDefault(require_children());
|
|
14817
|
+
exports2.children = _children.default;
|
|
14818
|
+
var _json = _interopRequireDefault(require_json());
|
|
14819
|
+
exports2.json = _json.default;
|
|
14820
|
+
var _nochange = _interopRequireDefault(require_nochange());
|
|
14821
|
+
exports2.nochange = _nochange.default;
|
|
14822
|
+
var _field = _interopRequireDefault(require_field());
|
|
14823
|
+
exports2.field = _field.default;
|
|
14824
|
+
var _date = _interopRequireDefault(require_date());
|
|
14825
|
+
exports2.date = _date.default;
|
|
14826
|
+
var _text = _interopRequireDefault(require_text());
|
|
14827
|
+
exports2.text = _text.default;
|
|
14828
|
+
var _readonly = _interopRequireDefault(require_readonly());
|
|
14829
|
+
exports2.readonly = _readonly.default;
|
|
14830
|
+
var _lazy = _interopRequireDefault(require_lazy());
|
|
14831
|
+
exports2.lazy = _lazy.default;
|
|
14832
|
+
var _relation = _interopRequireDefault(require_relation());
|
|
14833
|
+
exports2.relation = _relation.default;
|
|
14834
|
+
var _immutableRelation = _interopRequireDefault(require_immutableRelation());
|
|
14835
|
+
exports2.immutableRelation = _immutableRelation.default;
|
|
14836
|
+
var _experimentalFailsafe = _interopRequireDefault(require_experimentalFailsafe());
|
|
14837
|
+
exports2.experimentalFailsafe = _experimentalFailsafe.default;
|
|
14838
|
+
}
|
|
14839
|
+
});
|
|
14840
|
+
|
|
14841
|
+
// src/clientConfig.ts
|
|
14842
|
+
var clientConfig_exports = {};
|
|
14843
|
+
__export(clientConfig_exports, {
|
|
14844
|
+
BASE_URL: () => BASE_URL,
|
|
14845
|
+
MCP_R2_DOMAIN: () => MCP_R2_DOMAIN,
|
|
14846
|
+
createClientConfig: () => createClientConfig,
|
|
14847
|
+
resolveBaseUrl: () => resolveBaseUrl
|
|
14848
|
+
});
|
|
14849
|
+
function readGlobal(key) {
|
|
14850
|
+
if (typeof globalThis === "undefined") return void 0;
|
|
14851
|
+
const value = globalThis[key];
|
|
14852
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
14853
|
+
}
|
|
14854
|
+
function resolveBaseUrl() {
|
|
14855
|
+
const fromProcess = typeof process !== "undefined" ? process.env.API_URL || process.env.NEXT_PUBLIC_API_URL || process.env.EXPO_PUBLIC_API_URL : void 0;
|
|
14856
|
+
const fromGlobal = readGlobal("API_URL") ?? readGlobal("NEXT_PUBLIC_API_URL") ?? readGlobal("EXPO_PUBLIC_API_URL");
|
|
14857
|
+
return (fromProcess || fromGlobal || DEFAULT_BASE_URL).replace(/\/+$/, "");
|
|
14858
|
+
}
|
|
14859
|
+
var DEFAULT_BASE_URL, BASE_URL, MCP_R2_DOMAIN, createClientConfig;
|
|
14860
|
+
var init_clientConfig = __esm({
|
|
14861
|
+
"src/clientConfig.ts"() {
|
|
14862
|
+
"use strict";
|
|
14863
|
+
DEFAULT_BASE_URL = "https://portal.anuma-dev.ai";
|
|
14864
|
+
BASE_URL = resolveBaseUrl();
|
|
14865
|
+
MCP_R2_DOMAIN = "4cf0e0ea50b97e72386fcf2f92a2d4e8.r2.cloudflarestorage.com";
|
|
14866
|
+
createClientConfig = (config) => ({
|
|
14867
|
+
...config,
|
|
14868
|
+
baseUrl: BASE_URL
|
|
15253
14869
|
});
|
|
15254
|
-
var _default = exports2.default = field10;
|
|
15255
14870
|
}
|
|
15256
14871
|
});
|
|
15257
14872
|
|
|
15258
|
-
//
|
|
15259
|
-
|
|
15260
|
-
|
|
15261
|
-
|
|
15262
|
-
|
|
15263
|
-
|
|
15264
|
-
|
|
15265
|
-
|
|
15266
|
-
|
|
15267
|
-
|
|
15268
|
-
|
|
15269
|
-
|
|
15270
|
-
|
|
15271
|
-
|
|
15272
|
-
|
|
14873
|
+
// src/lib/taskType.ts
|
|
14874
|
+
function taskTypeHeader(taskType) {
|
|
14875
|
+
return taskType ? { [TASK_TYPE_HEADER]: taskType } : {};
|
|
14876
|
+
}
|
|
14877
|
+
var TASK_TYPE_HEADER;
|
|
14878
|
+
var init_taskType = __esm({
|
|
14879
|
+
"src/lib/taskType.ts"() {
|
|
14880
|
+
"use strict";
|
|
14881
|
+
TASK_TYPE_HEADER = "X-Anuma-Task-Type";
|
|
14882
|
+
}
|
|
14883
|
+
});
|
|
14884
|
+
|
|
14885
|
+
// src/lib/pii/patterns.ts
|
|
14886
|
+
function luhnCheck(digits) {
|
|
14887
|
+
let sum = 0;
|
|
14888
|
+
let alternate = false;
|
|
14889
|
+
for (let i = digits.length - 1; i >= 0; i--) {
|
|
14890
|
+
let n = parseInt(digits[i], 10);
|
|
14891
|
+
if (alternate) {
|
|
14892
|
+
n *= 2;
|
|
14893
|
+
if (n > 9) n -= 9;
|
|
14894
|
+
}
|
|
14895
|
+
sum += n;
|
|
14896
|
+
alternate = !alternate;
|
|
14897
|
+
}
|
|
14898
|
+
return sum % 10 === 0;
|
|
14899
|
+
}
|
|
14900
|
+
var PII_PATTERNS;
|
|
14901
|
+
var init_patterns = __esm({
|
|
14902
|
+
"src/lib/pii/patterns.ts"() {
|
|
14903
|
+
"use strict";
|
|
14904
|
+
PII_PATTERNS = [
|
|
14905
|
+
{
|
|
14906
|
+
category: "EMAIL",
|
|
14907
|
+
regex: /\b[a-zA-Z0-9._%+-]{1,64}@[a-zA-Z0-9.-]{1,255}\.[a-zA-Z]{2,24}\b/g
|
|
14908
|
+
},
|
|
14909
|
+
{
|
|
14910
|
+
category: "SSN",
|
|
14911
|
+
regex: /\b\d{3}-\d{2}-\d{4}\b/g,
|
|
14912
|
+
validate: (match) => {
|
|
14913
|
+
const parts = match.split("-");
|
|
14914
|
+
const area = parseInt(parts[0], 10);
|
|
14915
|
+
return area !== 0 && area !== 666 && area < 900;
|
|
14916
|
+
}
|
|
14917
|
+
},
|
|
14918
|
+
{
|
|
14919
|
+
category: "SSN",
|
|
14920
|
+
regex: /\b\d{3}[ ]?\d{2}[ ]?\d{4}\b/g,
|
|
14921
|
+
context: /(?:\bssn\b|\bsocial\s+security(?:\s+(?:number|no\.?|#))?\b)[^\d\n]{0,12}$/i,
|
|
14922
|
+
validate: (match) => {
|
|
14923
|
+
const digits = match.replace(/\D/g, "");
|
|
14924
|
+
if (digits.length !== 9) return false;
|
|
14925
|
+
const area = parseInt(digits.slice(0, 3), 10);
|
|
14926
|
+
return area !== 0 && area !== 666 && area < 900;
|
|
14927
|
+
}
|
|
14928
|
+
},
|
|
14929
|
+
{
|
|
14930
|
+
category: "CREDIT_CARD",
|
|
14931
|
+
regex: /\b\d{4}[\s-]\d{4}[\s-]\d{4}[\s-]\d{1,7}\b|\b\d{13,19}\b/g,
|
|
14932
|
+
validate: (match) => {
|
|
14933
|
+
const digits = match.replace(/\D/g, "");
|
|
14934
|
+
if (digits.length < 13 || digits.length > 19) return false;
|
|
14935
|
+
return luhnCheck(digits);
|
|
14936
|
+
}
|
|
14937
|
+
},
|
|
14938
|
+
{
|
|
14939
|
+
category: "IP_ADDRESS",
|
|
14940
|
+
regex: /\b(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\b/g,
|
|
14941
|
+
validate: (match) => {
|
|
14942
|
+
return match !== "0.0.0.0" && match !== "127.0.0.1" && match !== "255.255.255.255";
|
|
14943
|
+
}
|
|
14944
|
+
},
|
|
14945
|
+
{
|
|
14946
|
+
category: "IP_ADDRESS",
|
|
14947
|
+
regex: /(?:(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,7}:|(?:[0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|(?:[0-9a-fA-F]{1,4}:){1,5}(?::[0-9a-fA-F]{1,4}){1,2}|(?:[0-9a-fA-F]{1,4}:){1,4}(?::[0-9a-fA-F]{1,4}){1,3}|(?:[0-9a-fA-F]{1,4}:){1,3}(?::[0-9a-fA-F]{1,4}){1,4}|(?:[0-9a-fA-F]{1,4}:){1,2}(?::[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:(?::[0-9a-fA-F]{1,4}){1,6}|:(?:(?::[0-9a-fA-F]{1,4}){1,7}|:))/g,
|
|
14948
|
+
validate: (match) => match !== "::1" && match !== "::"
|
|
14949
|
+
},
|
|
14950
|
+
{
|
|
14951
|
+
category: "PHONE",
|
|
14952
|
+
regex: /(?:\+\d{1,3}[\s.-])?\(?\d{3}\)?[\s.-]\d{3}[\s.-]\d{4}\b|\+\d{10,15}\b/g
|
|
14953
|
+
},
|
|
14954
|
+
{
|
|
14955
|
+
category: "API_KEY",
|
|
14956
|
+
regex: /\b(?:sk|pk|api|key|token|secret|bearer|access)[_-]?[a-zA-Z0-9_-]{20,}\b/gi,
|
|
14957
|
+
validate: (match) => {
|
|
14958
|
+
const hasDigit = /\d/.test(match);
|
|
14959
|
+
const hasMixedCase = /[a-z]/.test(match) && /[A-Z]/.test(match);
|
|
14960
|
+
return hasDigit || hasMixedCase;
|
|
14961
|
+
}
|
|
14962
|
+
},
|
|
14963
|
+
{
|
|
14964
|
+
category: "US_ADDRESS",
|
|
14965
|
+
regex: /\b\d{1,5}[ \t]+(?:[A-Z][a-z]+[ \t]+){1,3}(?:St(?:reet)?|Ave(?:nue)?|Blvd|Boulevard|Dr(?:ive)?|Ln|Lane|Rd|Road|Ct|Court|Pl(?:ace)?|Way|Cir(?:cle)?|Pkwy|Parkway|Hwy|Highway)\.?(?=[\s,.;:!?)]|$)/g,
|
|
14966
|
+
validate: (match) => {
|
|
14967
|
+
return !/^0/.test(match.trim());
|
|
14968
|
+
}
|
|
14969
|
+
},
|
|
14970
|
+
{
|
|
14971
|
+
category: "DATE_OF_BIRTH",
|
|
14972
|
+
regex: /\b(?:(?:0?[1-9]|1[0-2])[/-](?:0?[1-9]|[12]\d|3[01])[/-](?:19|20)\d{2})\b/g,
|
|
14973
|
+
context: /(?:\bdob\b|\bd\.?o\.?b\.?|\bborn\b|\bbirth\s?date\b|\bbirthdate\b|\bbirthday\b|\bdate\s+of\s+birth\b)[^\d\n]{0,12}$/i,
|
|
14974
|
+
validate: (match) => {
|
|
14975
|
+
const m = match.match(/(\d{1,2})[/-](\d{1,2})[/-](\d{4})/);
|
|
14976
|
+
if (!m) return false;
|
|
14977
|
+
const month = parseInt(m[1], 10);
|
|
14978
|
+
const day = parseInt(m[2], 10);
|
|
14979
|
+
const year = parseInt(m[3], 10);
|
|
14980
|
+
const isLeap = year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
|
|
14981
|
+
const daysInMonth = [31, isLeap ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
|
|
14982
|
+
return month >= 1 && month <= 12 && day >= 1 && day <= daysInMonth[month - 1];
|
|
14983
|
+
}
|
|
14984
|
+
}
|
|
14985
|
+
];
|
|
14986
|
+
}
|
|
14987
|
+
});
|
|
14988
|
+
|
|
14989
|
+
// src/lib/pii/redactor.ts
|
|
14990
|
+
function escapeRegExp(value) {
|
|
14991
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
14992
|
+
}
|
|
14993
|
+
function isWordChar(ch) {
|
|
14994
|
+
return /[A-Za-z0-9_]/.test(ch) || ch.charCodeAt(0) > 127;
|
|
14995
|
+
}
|
|
14996
|
+
function isPiiRedactor(value) {
|
|
14997
|
+
return typeof value === "object" && value !== null && typeof value.redactMessages === "function" && typeof value.deAnonymize === "function";
|
|
14998
|
+
}
|
|
14999
|
+
function resolvePiiRedactor(piiRedaction) {
|
|
15000
|
+
if (piiRedaction === true) return new PiiRedactor();
|
|
15001
|
+
if (!piiRedaction) return void 0;
|
|
15002
|
+
if (isPiiRedactor(piiRedaction)) return piiRedaction;
|
|
15003
|
+
console.warn(
|
|
15004
|
+
"[PiiRedactor] `piiRedaction` is neither `true` nor a PiiRedactor instance; PII redaction is DISABLED for this request."
|
|
15005
|
+
);
|
|
15006
|
+
return void 0;
|
|
15007
|
+
}
|
|
15008
|
+
function createStreamingDeAnonymizer(redactor, emit) {
|
|
15009
|
+
let buffer = "";
|
|
15010
|
+
const trailingFragment = /\[[A-Za-z0-9_]*$/;
|
|
15011
|
+
return {
|
|
15012
|
+
push(chunk) {
|
|
15013
|
+
if (!chunk) return;
|
|
15014
|
+
buffer += chunk;
|
|
15015
|
+
const m = buffer.match(trailingFragment);
|
|
15016
|
+
if (!m || m.index === void 0) {
|
|
15017
|
+
emit(redactor.deAnonymize(buffer));
|
|
15018
|
+
buffer = "";
|
|
15019
|
+
} else if (m.index > 0) {
|
|
15020
|
+
emit(redactor.deAnonymize(buffer.slice(0, m.index)));
|
|
15021
|
+
buffer = buffer.slice(m.index);
|
|
15022
|
+
}
|
|
15023
|
+
},
|
|
15024
|
+
flush() {
|
|
15025
|
+
if (buffer) {
|
|
15026
|
+
emit(redactor.deAnonymize(buffer));
|
|
15027
|
+
buffer = "";
|
|
15028
|
+
}
|
|
15273
15029
|
}
|
|
15274
|
-
}
|
|
15275
|
-
}
|
|
15276
|
-
|
|
15277
|
-
|
|
15278
|
-
|
|
15279
|
-
"node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/date/index.js"(exports2) {
|
|
15030
|
+
};
|
|
15031
|
+
}
|
|
15032
|
+
var PiiRedactor;
|
|
15033
|
+
var init_redactor = __esm({
|
|
15034
|
+
"src/lib/pii/redactor.ts"() {
|
|
15280
15035
|
"use strict";
|
|
15281
|
-
|
|
15282
|
-
|
|
15283
|
-
|
|
15284
|
-
|
|
15285
|
-
|
|
15286
|
-
|
|
15287
|
-
|
|
15288
|
-
|
|
15289
|
-
|
|
15290
|
-
|
|
15291
|
-
|
|
15292
|
-
|
|
15293
|
-
|
|
15294
|
-
|
|
15295
|
-
|
|
15296
|
-
|
|
15297
|
-
|
|
15298
|
-
|
|
15299
|
-
|
|
15300
|
-
|
|
15301
|
-
|
|
15302
|
-
|
|
15303
|
-
|
|
15304
|
-
|
|
15305
|
-
|
|
15306
|
-
|
|
15307
|
-
|
|
15308
|
-
|
|
15309
|
-
|
|
15310
|
-
|
|
15311
|
-
|
|
15312
|
-
|
|
15313
|
-
|
|
15314
|
-
|
|
15315
|
-
|
|
15036
|
+
init_patterns();
|
|
15037
|
+
PiiRedactor = class {
|
|
15038
|
+
constructor(options = {}) {
|
|
15039
|
+
/** Maps original PII value → placeholder tag. */
|
|
15040
|
+
this.valueToPlaceholder = /* @__PURE__ */ new Map();
|
|
15041
|
+
/** Maps placeholder tag → original PII value (reverse lookup for de-anonymization). */
|
|
15042
|
+
this.placeholderToValue = /* @__PURE__ */ new Map();
|
|
15043
|
+
/** Next index per category for placeholder numbering. */
|
|
15044
|
+
this.categoryCounters = /* @__PURE__ */ new Map();
|
|
15045
|
+
/**
|
|
15046
|
+
* Matches any placeholder-shaped token for this redactor's categories —
|
|
15047
|
+
* bracketed `[EMAIL_1]` OR bare `EMAIL_1`, case-insensitive — capturing the
|
|
15048
|
+
* body. Drives {@link restoreForStorage}: the extraction / consolidation
|
|
15049
|
+
* models echo placeholders mangled (brackets dropped, re-cased), and a single
|
|
15050
|
+
* pass with this matcher restores the assigned ones and flags the rest in one
|
|
15051
|
+
* go. Built lazily from the union of pattern categories AND any categories
|
|
15052
|
+
* minted at runtime (e.g. NER `PERSON`/`LOCATION`/`ORG`): `undefined` = stale
|
|
15053
|
+
* (rebuild on next use), `null` = built but there are no categories.
|
|
15054
|
+
*/
|
|
15055
|
+
this.storagePattern = void 0;
|
|
15056
|
+
/**
|
|
15057
|
+
* Cached body→value lookups for {@link restoreForStorage}, built lazily from
|
|
15058
|
+
* the assigned placeholders and invalidated on each mint. `exact` is keyed by
|
|
15059
|
+
* the literal body (collision-proof); `ci` by upper-cased body for re-cased
|
|
15060
|
+
* echoes, minus any `ciCollisions` where two distinct bodies share a form.
|
|
15061
|
+
*/
|
|
15062
|
+
this.storageLookup = null;
|
|
15063
|
+
/** Whether the non-text-content bypass warning has already been emitted. */
|
|
15064
|
+
this.warnedNonText = false;
|
|
15065
|
+
/** Whether the NER-detector-failure warning has already been emitted. */
|
|
15066
|
+
this.warnedNerFailure = false;
|
|
15067
|
+
this.nerDetector = options.nerDetector;
|
|
15068
|
+
if (options.patterns) {
|
|
15069
|
+
this.patterns = options.patterns;
|
|
15070
|
+
} else {
|
|
15071
|
+
let base = PII_PATTERNS;
|
|
15072
|
+
if (options.excludeCategories?.length) {
|
|
15073
|
+
const excluded = new Set(options.excludeCategories);
|
|
15074
|
+
base = base.filter((p) => !excluded.has(p.category));
|
|
15316
15075
|
}
|
|
15317
|
-
|
|
15318
|
-
|
|
15319
|
-
|
|
15320
|
-
|
|
15321
|
-
|
|
15322
|
-
}
|
|
15323
|
-
|
|
15324
|
-
|
|
15325
|
-
|
|
15326
|
-
|
|
15327
|
-
|
|
15328
|
-
|
|
15329
|
-
|
|
15330
|
-
|
|
15331
|
-
|
|
15332
|
-
|
|
15333
|
-
|
|
15334
|
-
|
|
15335
|
-
|
|
15336
|
-
|
|
15337
|
-
|
|
15338
|
-
|
|
15339
|
-
|
|
15340
|
-
|
|
15341
|
-
|
|
15342
|
-
|
|
15343
|
-
|
|
15076
|
+
this.patterns = options.extraPatterns ? [...base, ...options.extraPatterns] : base;
|
|
15077
|
+
}
|
|
15078
|
+
this.patternCategories = [...new Set(this.patterns.map((p) => String(p.category)))];
|
|
15079
|
+
}
|
|
15080
|
+
/**
|
|
15081
|
+
* Build the {@link storagePattern} from the union of pattern categories and
|
|
15082
|
+
* any categories minted at runtime (NER entities arrive only when redaction
|
|
15083
|
+
* runs, so this can't be fixed at construction). Bracketed `[EMAIL_1]` OR
|
|
15084
|
+
* bare `EMAIL_1`, capturing the body, case-insensitive, global. `\d+` (not a
|
|
15085
|
+
* fixed body) spans any index; `\b` on the bare arm keeps it off prose like
|
|
15086
|
+
* "email 1 of 3".
|
|
15087
|
+
*/
|
|
15088
|
+
buildStoragePattern() {
|
|
15089
|
+
const categories = [.../* @__PURE__ */ new Set([...this.patternCategories, ...this.categoryCounters.keys()])];
|
|
15090
|
+
if (categories.length === 0) return null;
|
|
15091
|
+
const categoryAlt = categories.sort((a, b) => b.length - a.length).map(escapeRegExp).join("|");
|
|
15092
|
+
return new RegExp(`\\[((?:${categoryAlt})_\\d+)\\]|\\b((?:${categoryAlt})_\\d+)\\b`, "gi");
|
|
15093
|
+
}
|
|
15094
|
+
/**
|
|
15095
|
+
* Returns the current number of unique PII values tracked.
|
|
15096
|
+
*/
|
|
15097
|
+
get size() {
|
|
15098
|
+
return this.valueToPlaceholder.size;
|
|
15099
|
+
}
|
|
15100
|
+
/**
|
|
15101
|
+
* Returns a snapshot of all placeholder → original value mappings.
|
|
15102
|
+
* Useful for debugging or UI display. This is a copy — mutating it (or
|
|
15103
|
+
* later redactions) does not affect the returned map and vice versa.
|
|
15104
|
+
*/
|
|
15105
|
+
getMappings() {
|
|
15106
|
+
return new Map(this.placeholderToValue);
|
|
15107
|
+
}
|
|
15108
|
+
/**
|
|
15109
|
+
* Get or create a placeholder for a PII value.
|
|
15110
|
+
* The same value always gets the same placeholder within a redactor instance.
|
|
15111
|
+
*/
|
|
15112
|
+
getPlaceholder(category, value) {
|
|
15113
|
+
const normalizedValue = value.trim();
|
|
15114
|
+
const existing = this.valueToPlaceholder.get(normalizedValue);
|
|
15115
|
+
if (existing) return existing;
|
|
15116
|
+
const existingCount = this.categoryCounters.get(category);
|
|
15117
|
+
const count = (existingCount ?? 0) + 1;
|
|
15118
|
+
this.categoryCounters.set(category, count);
|
|
15119
|
+
if (existingCount === void 0) this.storagePattern = void 0;
|
|
15120
|
+
const placeholder = `[${category}_${count}]`;
|
|
15121
|
+
this.valueToPlaceholder.set(normalizedValue, placeholder);
|
|
15122
|
+
this.placeholderToValue.set(placeholder, normalizedValue);
|
|
15123
|
+
this.storageLookup = null;
|
|
15124
|
+
return placeholder;
|
|
15125
|
+
}
|
|
15126
|
+
/**
|
|
15127
|
+
* Find all matches of a single pattern in `text`, applying its `validate` and
|
|
15128
|
+
* `context` guards. Matches are non-overlapping and ascending (the global
|
|
15129
|
+
* regex advances `lastIndex` past each match). Shared by the sync {@link scan}
|
|
15130
|
+
* (sequential, per-pattern) and the async {@link collectRegexSpans} (span)
|
|
15131
|
+
* paths so the detection rules live in exactly one place.
|
|
15132
|
+
*/
|
|
15133
|
+
findMatches(text12, pattern) {
|
|
15134
|
+
const regex = new RegExp(pattern.regex.source, pattern.regex.flags);
|
|
15135
|
+
const found = [];
|
|
15136
|
+
let m;
|
|
15137
|
+
while ((m = regex.exec(text12)) !== null) {
|
|
15138
|
+
const value = m[0];
|
|
15139
|
+
if (pattern.validate && !pattern.validate(value)) continue;
|
|
15140
|
+
if (pattern.context) {
|
|
15141
|
+
const before = text12.slice(Math.max(0, m.index - 40), m.index);
|
|
15142
|
+
if (!pattern.context.test(before)) continue;
|
|
15143
|
+
}
|
|
15144
|
+
found.push({ match: value, index: m.index });
|
|
15145
|
+
}
|
|
15146
|
+
return found;
|
|
15147
|
+
}
|
|
15148
|
+
/**
|
|
15149
|
+
* Scan text for PII and rebuild it, replacing each match with whatever
|
|
15150
|
+
* `makeReplacement(category, value)` returns. Shared by `redactText`
|
|
15151
|
+
* (numbered, stateful placeholders) and `maskText` (unnumbered, stateless).
|
|
15152
|
+
*
|
|
15153
|
+
* Patterns are applied sequentially: each scans the text already rewritten by
|
|
15154
|
+
* earlier patterns, so an earlier (more specific) pattern claims a region
|
|
15155
|
+
* before a later one can — placeholders are inert and match no pattern.
|
|
15156
|
+
*/
|
|
15157
|
+
scan(text12, makeReplacement) {
|
|
15158
|
+
const matches = [];
|
|
15159
|
+
let redacted = text12;
|
|
15160
|
+
for (const pattern of this.patterns) {
|
|
15161
|
+
const found = this.findMatches(redacted, pattern);
|
|
15162
|
+
if (found.length === 0) continue;
|
|
15163
|
+
let result = "";
|
|
15164
|
+
let cursor = 0;
|
|
15165
|
+
for (const { match, index } of found) {
|
|
15166
|
+
const placeholder = makeReplacement(pattern.category, match);
|
|
15167
|
+
matches.push({ category: pattern.category, original: match, placeholder });
|
|
15168
|
+
result += redacted.slice(cursor, index) + placeholder;
|
|
15169
|
+
cursor = index + match.length;
|
|
15344
15170
|
}
|
|
15345
|
-
|
|
15346
|
-
|
|
15347
|
-
});
|
|
15348
|
-
var _default = exports2.default = text12;
|
|
15349
|
-
}
|
|
15350
|
-
});
|
|
15351
|
-
|
|
15352
|
-
// node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/readonly/index.js
|
|
15353
|
-
var require_readonly = __commonJS({
|
|
15354
|
-
"node_modules/.pnpm/@nozbe+watermelondb@0.28.0/node_modules/@nozbe/watermelondb/decorators/readonly/index.js"(exports2) {
|
|
15355
|
-
"use strict";
|
|
15356
|
-
var _interopRequireDefault = require_interopRequireDefault();
|
|
15357
|
-
exports2.__esModule = true;
|
|
15358
|
-
exports2.default = void 0;
|
|
15359
|
-
var _extends2 = _interopRequireDefault(require_extends());
|
|
15360
|
-
var _makeDecorator = _interopRequireDefault(require_makeDecorator());
|
|
15361
|
-
var _invariant = _interopRequireDefault(require_invariant());
|
|
15362
|
-
var readonly8 = (0, _makeDecorator.default)(function() {
|
|
15363
|
-
return function(target, key, descriptor) {
|
|
15364
|
-
if (descriptor.get || descriptor.set) {
|
|
15365
|
-
return (0, _extends2.default)({}, descriptor, {
|
|
15366
|
-
set: function() {
|
|
15367
|
-
(0, _invariant.default)(false, "Attempt to set new value on a property ".concat(target.constructor.name, ".prototype.").concat(key, " marked as @readonly"));
|
|
15368
|
-
}
|
|
15369
|
-
});
|
|
15171
|
+
result += redacted.slice(cursor);
|
|
15172
|
+
redacted = result;
|
|
15370
15173
|
}
|
|
15371
|
-
|
|
15372
|
-
|
|
15373
|
-
|
|
15374
|
-
|
|
15375
|
-
|
|
15376
|
-
|
|
15377
|
-
|
|
15378
|
-
|
|
15379
|
-
|
|
15380
|
-
|
|
15381
|
-
|
|
15382
|
-
|
|
15383
|
-
|
|
15384
|
-
|
|
15385
|
-
|
|
15386
|
-
|
|
15387
|
-
|
|
15388
|
-
|
|
15389
|
-
|
|
15390
|
-
|
|
15391
|
-
|
|
15392
|
-
|
|
15393
|
-
|
|
15394
|
-
|
|
15395
|
-
|
|
15396
|
-
|
|
15397
|
-
|
|
15398
|
-
|
|
15399
|
-
|
|
15400
|
-
|
|
15174
|
+
return { text: redacted, matches };
|
|
15175
|
+
}
|
|
15176
|
+
/**
|
|
15177
|
+
* Scan and redact PII from a single text string, using numbered, reversible
|
|
15178
|
+
* placeholders ([EMAIL_1], …) tracked on this instance.
|
|
15179
|
+
*/
|
|
15180
|
+
redactText(text12) {
|
|
15181
|
+
return this.scan(text12, (category, value) => this.getPlaceholder(category, value));
|
|
15182
|
+
}
|
|
15183
|
+
/**
|
|
15184
|
+
* Mask PII with unnumbered, NON-reversible tokens ([EMAIL], [SSN], …) without
|
|
15185
|
+
* mutating this instance's state. Use for one-way purposes where the value is
|
|
15186
|
+
* never restored — notably embedding inputs: it keeps real PII off the
|
|
15187
|
+
* embeddings endpoint while staying deterministic, so the same content always
|
|
15188
|
+
* masks identically and search stays consistent across conversations.
|
|
15189
|
+
*/
|
|
15190
|
+
maskText(text12) {
|
|
15191
|
+
return this.scan(text12, (category) => `[${category}]`).text;
|
|
15192
|
+
}
|
|
15193
|
+
/** All regex matches as spans on the ORIGINAL text (priority 0). Uses the
|
|
15194
|
+
* same {@link findMatches} guards as the sync scan. */
|
|
15195
|
+
collectRegexSpans(text12) {
|
|
15196
|
+
const spans = [];
|
|
15197
|
+
this.patterns.forEach((pattern, patternIndex) => {
|
|
15198
|
+
for (const { match, index } of this.findMatches(text12, pattern)) {
|
|
15199
|
+
spans.push({
|
|
15200
|
+
start: index,
|
|
15201
|
+
end: index + match.length,
|
|
15202
|
+
category: pattern.category,
|
|
15203
|
+
priority: 0,
|
|
15204
|
+
order: patternIndex
|
|
15401
15205
|
});
|
|
15402
|
-
model._relationCache[key] = newRelation;
|
|
15403
|
-
return newRelation;
|
|
15404
|
-
},
|
|
15405
|
-
set: function() {
|
|
15406
|
-
throw new Error("Don't set relation directly. Use relation.set() instead");
|
|
15407
15206
|
}
|
|
15408
|
-
};
|
|
15409
|
-
|
|
15410
|
-
|
|
15411
|
-
|
|
15412
|
-
|
|
15413
|
-
|
|
15414
|
-
|
|
15415
|
-
|
|
15416
|
-
|
|
15417
|
-
|
|
15418
|
-
|
|
15419
|
-
|
|
15420
|
-
|
|
15421
|
-
|
|
15422
|
-
|
|
15423
|
-
|
|
15424
|
-
|
|
15425
|
-
|
|
15426
|
-
|
|
15427
|
-
|
|
15428
|
-
|
|
15429
|
-
|
|
15430
|
-
});
|
|
15431
|
-
|
|
15432
|
-
|
|
15433
|
-
|
|
15434
|
-
|
|
15435
|
-
|
|
15436
|
-
|
|
15437
|
-
|
|
15438
|
-
|
|
15439
|
-
|
|
15440
|
-
|
|
15441
|
-
|
|
15442
|
-
|
|
15443
|
-
|
|
15444
|
-
|
|
15445
|
-
|
|
15446
|
-
|
|
15447
|
-
|
|
15448
|
-
|
|
15449
|
-
|
|
15450
|
-
|
|
15451
|
-
|
|
15452
|
-
|
|
15453
|
-
|
|
15207
|
+
});
|
|
15208
|
+
return spans;
|
|
15209
|
+
}
|
|
15210
|
+
/**
|
|
15211
|
+
* Normalize raw NER spans: clamp to the text bounds, drop empty/categoryless
|
|
15212
|
+
* spans, and snap each to whole-word boundaries. Snapping prevents a detector
|
|
15213
|
+
* that tagged only part of a word (a common WordPiece artifact — e.g. "Strip"
|
|
15214
|
+
* of "Stripe") from producing a corrupting partial placeholder like
|
|
15215
|
+
* `[ORG_1]e`.
|
|
15216
|
+
*/
|
|
15217
|
+
normalizeNerSpans(text12, raw) {
|
|
15218
|
+
if (!Array.isArray(raw)) return [];
|
|
15219
|
+
const out = [];
|
|
15220
|
+
raw.forEach((s, i) => {
|
|
15221
|
+
if (!Number.isFinite(s.start) || !Number.isFinite(s.end)) return;
|
|
15222
|
+
let start = Math.max(0, Math.min(Math.trunc(s.start), text12.length));
|
|
15223
|
+
let end = Math.max(0, Math.min(Math.trunc(s.end), text12.length));
|
|
15224
|
+
if (end <= start) return;
|
|
15225
|
+
while (start > 0 && isWordChar(text12[start - 1])) start--;
|
|
15226
|
+
while (end < text12.length && isWordChar(text12[end])) end++;
|
|
15227
|
+
const category = String(s.category ?? "").trim();
|
|
15228
|
+
if (!category) return;
|
|
15229
|
+
out.push({ start, end, category, priority: 1, order: i });
|
|
15230
|
+
});
|
|
15231
|
+
return out;
|
|
15232
|
+
}
|
|
15233
|
+
/** Run the configured detector defensively: failures degrade to regex-only
|
|
15234
|
+
* (fail-open on detection, not on protection) with a one-time warning. */
|
|
15235
|
+
async detectNerSpans(text12) {
|
|
15236
|
+
if (!this.nerDetector) return [];
|
|
15237
|
+
try {
|
|
15238
|
+
return this.normalizeNerSpans(text12, await this.nerDetector.detect(text12));
|
|
15239
|
+
} catch (err) {
|
|
15240
|
+
this.warnNerFailure(err);
|
|
15241
|
+
return [];
|
|
15242
|
+
}
|
|
15243
|
+
}
|
|
15244
|
+
/**
|
|
15245
|
+
* Resolve overlaps by placing higher-priority spans first and dropping any
|
|
15246
|
+
* span that overlaps one already placed. Regex (priority 0) is placed before
|
|
15247
|
+
* NER (priority 1), and within regex by ascending pattern index — so regex
|
|
15248
|
+
* always wins on overlap and the regex-only result reproduces the sync scan's
|
|
15249
|
+
* sequential "earlier pattern wins". O(n²) but n (spans per message) is tiny.
|
|
15250
|
+
*
|
|
15251
|
+
* The returned spans stay in `(priority, order, start)` order — i.e. mint
|
|
15252
|
+
* order — which {@link rebuildSpans} relies on.
|
|
15253
|
+
*/
|
|
15254
|
+
resolveOverlaps(spans) {
|
|
15255
|
+
const ordered = [...spans].sort(
|
|
15256
|
+
(a, b) => a.priority - b.priority || a.order - b.order || a.start - b.start
|
|
15257
|
+
);
|
|
15258
|
+
const placed = [];
|
|
15259
|
+
for (const s of ordered) {
|
|
15260
|
+
if (!placed.some((p) => s.start < p.end && p.start < s.end)) placed.push(s);
|
|
15261
|
+
}
|
|
15262
|
+
return placed;
|
|
15263
|
+
}
|
|
15264
|
+
/**
|
|
15265
|
+
* Rebuild `text` from resolved (non-overlapping) spans. `spans` must arrive in
|
|
15266
|
+
* mint order — `(priority, order, start)`, as {@link resolveOverlaps} returns —
|
|
15267
|
+
* so placeholders are MINTED by iterating it directly (regex categories first,
|
|
15268
|
+
* in pattern then document order, matching the sync scan's numbering). The
|
|
15269
|
+
* string is then EMITTED in document order.
|
|
15270
|
+
*/
|
|
15271
|
+
rebuildSpans(text12, spans, makeReplacement) {
|
|
15272
|
+
const placeholderByStart = /* @__PURE__ */ new Map();
|
|
15273
|
+
const matches = [];
|
|
15274
|
+
for (const s of spans) {
|
|
15275
|
+
const value = text12.slice(s.start, s.end);
|
|
15276
|
+
const placeholder = makeReplacement(s.category, value);
|
|
15277
|
+
placeholderByStart.set(s.start, placeholder);
|
|
15278
|
+
matches.push({ category: s.category, original: value, placeholder });
|
|
15279
|
+
}
|
|
15280
|
+
const emitOrder = [...spans].sort((a, b) => a.start - b.start);
|
|
15281
|
+
let result = "";
|
|
15282
|
+
let cursor = 0;
|
|
15283
|
+
for (const s of emitOrder) {
|
|
15284
|
+
result += text12.slice(cursor, s.start) + (placeholderByStart.get(s.start) ?? "");
|
|
15285
|
+
cursor = s.end;
|
|
15286
|
+
}
|
|
15287
|
+
result += text12.slice(cursor);
|
|
15288
|
+
return { text: result, matches };
|
|
15289
|
+
}
|
|
15290
|
+
/** Merge regex + NER spans for `text` into a resolved, non-overlapping set. */
|
|
15291
|
+
async detectAllSpans(text12) {
|
|
15292
|
+
const nerPromise = this.detectNerSpans(text12);
|
|
15293
|
+
const regexSpans = this.collectRegexSpans(text12);
|
|
15294
|
+
const ner = await nerPromise;
|
|
15295
|
+
return this.resolveOverlaps([...regexSpans, ...ner]);
|
|
15296
|
+
}
|
|
15297
|
+
/**
|
|
15298
|
+
* Async counterpart to {@link redactText}: redacts structured PII (regex) AND
|
|
15299
|
+
* unstructured PII (the configured {@link NerDetector}) with numbered,
|
|
15300
|
+
* reversible placeholders. With no detector, identical to `redactText`.
|
|
15301
|
+
*/
|
|
15302
|
+
async redactTextAsync(text12) {
|
|
15303
|
+
if (!this.nerDetector) return this.redactText(text12);
|
|
15304
|
+
const spans = await this.detectAllSpans(text12);
|
|
15305
|
+
return this.rebuildSpans(
|
|
15306
|
+
text12,
|
|
15307
|
+
spans,
|
|
15308
|
+
(category, value) => this.getPlaceholder(category, value)
|
|
15309
|
+
);
|
|
15310
|
+
}
|
|
15311
|
+
/**
|
|
15312
|
+
* Async counterpart to {@link maskText}: stateless `[CATEGORY]` masking over
|
|
15313
|
+
* regex + NER matches. With no detector, identical to `maskText`.
|
|
15314
|
+
*/
|
|
15315
|
+
async maskTextAsync(text12) {
|
|
15316
|
+
if (!this.nerDetector) return this.maskText(text12);
|
|
15317
|
+
const spans = await this.detectAllSpans(text12);
|
|
15318
|
+
return this.rebuildSpans(text12, spans, (category) => `[${category}]`).text;
|
|
15319
|
+
}
|
|
15320
|
+
/**
|
|
15321
|
+
* Async counterpart to {@link redactMessages}. Text parts are redacted
|
|
15322
|
+
* sequentially so placeholder numbering stays deterministic across the
|
|
15323
|
+
* conversation. With no detector, identical to `redactMessages`.
|
|
15324
|
+
*/
|
|
15325
|
+
async redactMessagesAsync(messages) {
|
|
15326
|
+
if (!this.nerDetector) return this.redactMessages(messages);
|
|
15327
|
+
const allMatches = [];
|
|
15328
|
+
const redactedMessages = [];
|
|
15329
|
+
for (const msg of messages) {
|
|
15330
|
+
if (!msg.content) {
|
|
15331
|
+
redactedMessages.push(msg);
|
|
15332
|
+
continue;
|
|
15333
|
+
}
|
|
15334
|
+
const newContent = [];
|
|
15335
|
+
for (const part of msg.content) {
|
|
15336
|
+
if (part.type === "text" && part.text) {
|
|
15337
|
+
const result = await this.redactTextAsync(part.text);
|
|
15338
|
+
allMatches.push(...result.matches);
|
|
15339
|
+
newContent.push(result.matches.length > 0 ? { ...part, text: result.text } : part);
|
|
15340
|
+
} else {
|
|
15341
|
+
if (part.type !== "text") this.warnNonTextBypass();
|
|
15342
|
+
newContent.push(part);
|
|
15454
15343
|
}
|
|
15455
|
-
|
|
15456
|
-
|
|
15457
|
-
|
|
15458
|
-
|
|
15459
|
-
|
|
15460
|
-
|
|
15461
|
-
|
|
15462
|
-
|
|
15463
|
-
|
|
15464
|
-
|
|
15465
|
-
|
|
15466
|
-
|
|
15467
|
-
|
|
15468
|
-
|
|
15469
|
-
|
|
15470
|
-
|
|
15471
|
-
|
|
15472
|
-
|
|
15473
|
-
|
|
15474
|
-
|
|
15475
|
-
|
|
15476
|
-
|
|
15477
|
-
|
|
15478
|
-
|
|
15344
|
+
}
|
|
15345
|
+
redactedMessages.push({ ...msg, content: newContent });
|
|
15346
|
+
}
|
|
15347
|
+
return { messages: redactedMessages, matches: allMatches };
|
|
15348
|
+
}
|
|
15349
|
+
/**
|
|
15350
|
+
* Redact PII from an array of LlmapiMessage objects.
|
|
15351
|
+
* Returns new message objects — originals are not mutated.
|
|
15352
|
+
*
|
|
15353
|
+
* All roles' text content is redacted, not just user/system: tool results
|
|
15354
|
+
* can return PII fetched from external systems, and assistant history is
|
|
15355
|
+
* persisted with original (de-anonymized) values, so both must be re-redacted
|
|
15356
|
+
* before they go back over the wire. Placeholders the model already emitted
|
|
15357
|
+
* are inert here (they don't match any PII pattern), so re-redaction is safe.
|
|
15358
|
+
*/
|
|
15359
|
+
redactMessages(messages) {
|
|
15360
|
+
const allMatches = [];
|
|
15361
|
+
const redactedMessages = messages.map((msg) => {
|
|
15362
|
+
if (!msg.content) return msg;
|
|
15363
|
+
const newContent = msg.content.map((part) => {
|
|
15364
|
+
if (part.type === "text" && part.text) {
|
|
15365
|
+
const result = this.redactText(part.text);
|
|
15366
|
+
allMatches.push(...result.matches);
|
|
15367
|
+
if (result.matches.length > 0) {
|
|
15368
|
+
return { ...part, text: result.text };
|
|
15479
15369
|
}
|
|
15370
|
+
} else if (part.type !== "text") {
|
|
15371
|
+
this.warnNonTextBypass();
|
|
15480
15372
|
}
|
|
15481
|
-
|
|
15482
|
-
|
|
15483
|
-
|
|
15484
|
-
});
|
|
15485
|
-
return value;
|
|
15486
|
-
}
|
|
15373
|
+
return part;
|
|
15374
|
+
});
|
|
15375
|
+
return { ...msg, content: newContent };
|
|
15487
15376
|
});
|
|
15488
|
-
|
|
15377
|
+
return { messages: redactedMessages, matches: allMatches };
|
|
15378
|
+
}
|
|
15379
|
+
/** Emit the non-text bypass warning at most once per redactor instance. */
|
|
15380
|
+
warnNonTextBypass() {
|
|
15381
|
+
if (this.warnedNonText) return;
|
|
15382
|
+
this.warnedNonText = true;
|
|
15383
|
+
console.warn(
|
|
15384
|
+
"[PiiRedactor] A message contains non-text content (images, files, or attachments) that is NOT scanned for PII \u2014 only text parts are redacted."
|
|
15385
|
+
);
|
|
15386
|
+
}
|
|
15387
|
+
/** Emit the NER-detector-failure warning at most once per redactor instance. */
|
|
15388
|
+
warnNerFailure(err) {
|
|
15389
|
+
if (this.warnedNerFailure) return;
|
|
15390
|
+
this.warnedNerFailure = true;
|
|
15391
|
+
console.warn(
|
|
15392
|
+
"[PiiRedactor] The NER detector threw; falling back to regex-only redaction for this call's unstructured PII. The detector is still retried on subsequent calls; this warning is emitted only once.",
|
|
15393
|
+
err
|
|
15394
|
+
);
|
|
15395
|
+
}
|
|
15396
|
+
/**
|
|
15397
|
+
* Restore original PII values in text that contains placeholders.
|
|
15398
|
+
* Used to de-anonymize LLM responses before displaying to the user.
|
|
15399
|
+
*
|
|
15400
|
+
* Exact: matches the literal `[EMAIL_1]` form only. The storage paths use
|
|
15401
|
+
* {@link restoreForStorage} instead, which tolerates the mangled echoes the
|
|
15402
|
+
* extraction models produce.
|
|
15403
|
+
*/
|
|
15404
|
+
deAnonymize(text12) {
|
|
15405
|
+
if (!text12.includes("[")) return text12;
|
|
15406
|
+
let restored = text12;
|
|
15407
|
+
for (const [placeholder, original] of this.placeholderToValue) {
|
|
15408
|
+
if (restored.includes(placeholder)) {
|
|
15409
|
+
restored = restored.split(placeholder).join(original);
|
|
15410
|
+
}
|
|
15411
|
+
}
|
|
15412
|
+
return restored;
|
|
15413
|
+
}
|
|
15414
|
+
/**
|
|
15415
|
+
* De-anonymize for PERSISTENCE (auto-extraction / consolidation), tolerant of
|
|
15416
|
+
* the ways the extraction models mangle a placeholder when echoing it back:
|
|
15417
|
+
* dropped brackets (`EMAIL_1`) and changed case (`email_1` / `Email_1`).
|
|
15418
|
+
*
|
|
15419
|
+
* Returns the restored text plus `unresolved` — true when a placeholder-shaped
|
|
15420
|
+
* token for one of this redactor's categories was NOT assigned during
|
|
15421
|
+
* redaction (a model hallucination, or an ambiguous re-cased collision).
|
|
15422
|
+
* Callers drop/degrade such facts so an opaque token never reaches the vault.
|
|
15423
|
+
*
|
|
15424
|
+
* One left-to-right pass over the ORIGINAL text. Two properties matter:
|
|
15425
|
+
* - a restored value is never re-scanned — so a real value that happens to
|
|
15426
|
+
* contain a `<CATEGORY>_<n>` substring (e.g. the email `ssn_1@example.com`,
|
|
15427
|
+
* or an API key containing `EMAIL_1`) is neither corrupted nor false-flagged;
|
|
15428
|
+
* - `unresolved` is derived from the lookup miss during this pass, not from a
|
|
15429
|
+
* regex re-scan of the output — so it can't trip over a restored value.
|
|
15430
|
+
*/
|
|
15431
|
+
restoreForStorage(text12) {
|
|
15432
|
+
if (this.storagePattern === void 0) this.storagePattern = this.buildStoragePattern();
|
|
15433
|
+
if (!this.storagePattern || this.placeholderToValue.size === 0) {
|
|
15434
|
+
return { text: text12, unresolved: false };
|
|
15435
|
+
}
|
|
15436
|
+
this.storageLookup ?? (this.storageLookup = this.buildStorageLookup());
|
|
15437
|
+
const { exact, ci, ciCollisions } = this.storageLookup;
|
|
15438
|
+
let unresolved = false;
|
|
15439
|
+
const restored = text12.replace(
|
|
15440
|
+
this.storagePattern,
|
|
15441
|
+
(match, bracketed, bare) => {
|
|
15442
|
+
const body = bracketed ?? bare ?? "";
|
|
15443
|
+
const exactHit = exact.get(body);
|
|
15444
|
+
if (exactHit !== void 0) return exactHit;
|
|
15445
|
+
const key = body.toUpperCase();
|
|
15446
|
+
if (!ciCollisions.has(key)) {
|
|
15447
|
+
const ciHit = ci.get(key);
|
|
15448
|
+
if (ciHit !== void 0) return ciHit;
|
|
15449
|
+
}
|
|
15450
|
+
unresolved = true;
|
|
15451
|
+
return match;
|
|
15452
|
+
}
|
|
15453
|
+
);
|
|
15454
|
+
return { text: restored, unresolved };
|
|
15455
|
+
}
|
|
15456
|
+
/**
|
|
15457
|
+
* Build the {@link restoreForStorage} body→value lookups from the assigned
|
|
15458
|
+
* placeholders. `exact` (literal body) is collision-proof; `ci` (upper-cased
|
|
15459
|
+
* body) handles re-cased echoes, except where two distinct bodies share an
|
|
15460
|
+
* upper-cased form — those are recorded in `ciCollisions` so a re-cased echo
|
|
15461
|
+
* of them is left unresolved rather than resolved to the wrong value.
|
|
15462
|
+
*/
|
|
15463
|
+
buildStorageLookup() {
|
|
15464
|
+
const exact = /* @__PURE__ */ new Map();
|
|
15465
|
+
const ci = /* @__PURE__ */ new Map();
|
|
15466
|
+
const ciCollisions = /* @__PURE__ */ new Set();
|
|
15467
|
+
for (const [placeholder, value] of this.placeholderToValue) {
|
|
15468
|
+
const body = placeholder.slice(1, -1);
|
|
15469
|
+
exact.set(body, value);
|
|
15470
|
+
const key = body.toUpperCase();
|
|
15471
|
+
if (ci.has(key) && ci.get(key) !== value) ciCollisions.add(key);
|
|
15472
|
+
else ci.set(key, value);
|
|
15473
|
+
}
|
|
15474
|
+
return { exact, ci, ciCollisions };
|
|
15475
|
+
}
|
|
15476
|
+
/**
|
|
15477
|
+
* Reset all state. Useful for testing or when starting a fresh conversation.
|
|
15478
|
+
*/
|
|
15479
|
+
clear() {
|
|
15480
|
+
this.valueToPlaceholder.clear();
|
|
15481
|
+
this.placeholderToValue.clear();
|
|
15482
|
+
this.categoryCounters.clear();
|
|
15483
|
+
this.storageLookup = null;
|
|
15484
|
+
this.storagePattern = void 0;
|
|
15485
|
+
this.warnedNonText = false;
|
|
15486
|
+
this.warnedNerFailure = false;
|
|
15487
|
+
}
|
|
15489
15488
|
};
|
|
15490
|
-
var _default = exports2.default = failsafe;
|
|
15491
15489
|
}
|
|
15492
15490
|
});
|
|
15493
15491
|
|
|
15494
|
-
//
|
|
15495
|
-
|
|
15496
|
-
|
|
15497
|
-
|
|
15498
|
-
|
|
15499
|
-
|
|
15500
|
-
|
|
15501
|
-
|
|
15502
|
-
|
|
15503
|
-
|
|
15504
|
-
|
|
15505
|
-
|
|
15506
|
-
|
|
15507
|
-
|
|
15508
|
-
|
|
15509
|
-
|
|
15510
|
-
|
|
15511
|
-
|
|
15512
|
-
|
|
15513
|
-
|
|
15514
|
-
|
|
15515
|
-
|
|
15516
|
-
|
|
15517
|
-
|
|
15518
|
-
|
|
15519
|
-
|
|
15520
|
-
|
|
15521
|
-
|
|
15522
|
-
|
|
15523
|
-
|
|
15524
|
-
|
|
15525
|
-
|
|
15492
|
+
// src/lib/chat/endpointOverride.ts
|
|
15493
|
+
function validateEndpointOverride(override) {
|
|
15494
|
+
const trimmed = override.trim();
|
|
15495
|
+
if (trimmed === "") {
|
|
15496
|
+
return {
|
|
15497
|
+
valid: false,
|
|
15498
|
+
message: 'endpointOverride must be a non-empty, root-relative path (e.g. "/api/v1/utility/responses"); received an empty or whitespace-only string'
|
|
15499
|
+
};
|
|
15500
|
+
}
|
|
15501
|
+
if (trimmed.startsWith("//") || trimmed.includes("://")) {
|
|
15502
|
+
return {
|
|
15503
|
+
valid: false,
|
|
15504
|
+
message: `endpointOverride must be a root-relative path (e.g. "/api/v1/utility/responses"), not a protocol-relative or absolute URL; received "${trimmed}"`
|
|
15505
|
+
};
|
|
15506
|
+
}
|
|
15507
|
+
return { valid: true, endpoint: trimmed.startsWith("/") ? trimmed : `/${trimmed}` };
|
|
15508
|
+
}
|
|
15509
|
+
var init_endpointOverride = __esm({
|
|
15510
|
+
"src/lib/chat/endpointOverride.ts"() {
|
|
15511
|
+
"use strict";
|
|
15512
|
+
}
|
|
15513
|
+
});
|
|
15514
|
+
|
|
15515
|
+
// src/lib/internalFlowMarker.ts
|
|
15516
|
+
function withInternalFlowMarker(systemPrompt) {
|
|
15517
|
+
if (systemPrompt.includes(INTERNAL_FLOW_MARKER)) return systemPrompt;
|
|
15518
|
+
return `${INTERNAL_FLOW_MARKER}
|
|
15519
|
+
${systemPrompt}`;
|
|
15520
|
+
}
|
|
15521
|
+
var INTERNAL_FLOW_MARKER;
|
|
15522
|
+
var init_internalFlowMarker = __esm({
|
|
15523
|
+
"src/lib/internalFlowMarker.ts"() {
|
|
15524
|
+
"use strict";
|
|
15525
|
+
INTERNAL_FLOW_MARKER = "Anuma internal first-party flow (not user chat).";
|
|
15526
15526
|
}
|
|
15527
15527
|
});
|
|
15528
15528
|
|
|
@@ -16831,7 +16831,7 @@ ${line}`;
|
|
|
16831
16831
|
}
|
|
16832
16832
|
|
|
16833
16833
|
// src/lib/db/chat/operations.ts
|
|
16834
|
-
var
|
|
16834
|
+
var import_watermelondb3 = __toESM(require_watermelondb());
|
|
16835
16835
|
var import_uuid2 = require("uuid");
|
|
16836
16836
|
|
|
16837
16837
|
// src/react/useEncryption.ts
|
|
@@ -18010,106 +18010,260 @@ function worseDecryptStatus(a, b) {
|
|
|
18010
18010
|
};
|
|
18011
18011
|
return rank(b) >= rank(a) ? b : a;
|
|
18012
18012
|
}
|
|
18013
|
-
async function decryptMessageFields(message, address, signMessage, embeddedWalletSigner) {
|
|
18014
|
-
if (!address) {
|
|
18015
|
-
return message;
|
|
18016
|
-
}
|
|
18017
|
-
if (signMessage) {
|
|
18018
|
-
try {
|
|
18019
|
-
await requestEncryptionKey(address, signMessage, embeddedWalletSigner);
|
|
18020
|
-
} catch (error) {
|
|
18021
|
-
getLogger().warn("Failed to request encryption key for decryption:", error);
|
|
18022
|
-
}
|
|
18023
|
-
}
|
|
18024
|
-
let assembled = await assembleDecryptedMessage(message, address);
|
|
18025
|
-
const needsRefresh = assembled.decryptionStatus === "auth_mismatch" || assembled.decryptionStatus === "key_missing";
|
|
18026
|
-
if (needsRefresh && signMessage && assembled.refreshProbe) {
|
|
18027
|
-
try {
|
|
18028
|
-
const refreshed = await refreshEncryptionKeyIfMatches(
|
|
18029
|
-
address,
|
|
18030
|
-
assembled.refreshProbe,
|
|
18031
|
-
signMessage,
|
|
18032
|
-
embeddedWalletSigner
|
|
18033
|
-
);
|
|
18034
|
-
if (refreshed) {
|
|
18035
|
-
assembled = await assembleDecryptedMessage(message, address);
|
|
18036
|
-
}
|
|
18037
|
-
} catch (error) {
|
|
18038
|
-
getLogger().warn("Failed to refresh encryption key after decrypt failure:", error);
|
|
18039
|
-
}
|
|
18013
|
+
async function decryptMessageFields(message, address, signMessage, embeddedWalletSigner) {
|
|
18014
|
+
if (!address) {
|
|
18015
|
+
return message;
|
|
18016
|
+
}
|
|
18017
|
+
if (signMessage) {
|
|
18018
|
+
try {
|
|
18019
|
+
await requestEncryptionKey(address, signMessage, embeddedWalletSigner);
|
|
18020
|
+
} catch (error) {
|
|
18021
|
+
getLogger().warn("Failed to request encryption key for decryption:", error);
|
|
18022
|
+
}
|
|
18023
|
+
}
|
|
18024
|
+
let assembled = await assembleDecryptedMessage(message, address);
|
|
18025
|
+
const needsRefresh = assembled.decryptionStatus === "auth_mismatch" || assembled.decryptionStatus === "key_missing";
|
|
18026
|
+
if (needsRefresh && signMessage && assembled.refreshProbe) {
|
|
18027
|
+
try {
|
|
18028
|
+
const refreshed = await refreshEncryptionKeyIfMatches(
|
|
18029
|
+
address,
|
|
18030
|
+
assembled.refreshProbe,
|
|
18031
|
+
signMessage,
|
|
18032
|
+
embeddedWalletSigner
|
|
18033
|
+
);
|
|
18034
|
+
if (refreshed) {
|
|
18035
|
+
assembled = await assembleDecryptedMessage(message, address);
|
|
18036
|
+
}
|
|
18037
|
+
} catch (error) {
|
|
18038
|
+
getLogger().warn("Failed to refresh encryption key after decrypt failure:", error);
|
|
18039
|
+
}
|
|
18040
|
+
}
|
|
18041
|
+
const { refreshProbe: _probe, ...result } = assembled;
|
|
18042
|
+
return result;
|
|
18043
|
+
}
|
|
18044
|
+
async function assembleDecryptedMessage(message, address) {
|
|
18045
|
+
const contentResult = await decryptFieldDetailed(message.content, address);
|
|
18046
|
+
const thinkingResult = message.thinking ? await decryptFieldDetailed(message.thinking, address) : null;
|
|
18047
|
+
const vectorResult = await decryptMaybeJsonFieldDetailed(
|
|
18048
|
+
message.vector,
|
|
18049
|
+
address
|
|
18050
|
+
);
|
|
18051
|
+
const chunksResult = await decryptMaybeJsonFieldDetailed(
|
|
18052
|
+
message.chunks,
|
|
18053
|
+
address
|
|
18054
|
+
);
|
|
18055
|
+
const sourcesResult = await decryptMaybeJsonFieldDetailed(
|
|
18056
|
+
message.sources,
|
|
18057
|
+
address
|
|
18058
|
+
);
|
|
18059
|
+
const thoughtProcessResult = await decryptMaybeJsonFieldDetailed(
|
|
18060
|
+
message.thoughtProcess,
|
|
18061
|
+
address
|
|
18062
|
+
);
|
|
18063
|
+
const toolCallEventsResult = await decryptMaybeJsonFieldDetailed(
|
|
18064
|
+
message.toolCallEvents,
|
|
18065
|
+
address
|
|
18066
|
+
);
|
|
18067
|
+
let decryptionStatus;
|
|
18068
|
+
let refreshProbe;
|
|
18069
|
+
const consider = (status, probe) => {
|
|
18070
|
+
decryptionStatus = worseDecryptStatus(decryptionStatus, status);
|
|
18071
|
+
if (!refreshProbe && probe && (status === "auth_mismatch" || status === "key_missing")) {
|
|
18072
|
+
refreshProbe = probe;
|
|
18073
|
+
}
|
|
18074
|
+
};
|
|
18075
|
+
consider(contentResult.status, isEncrypted(message.content) ? message.content : void 0);
|
|
18076
|
+
if (thinkingResult && message.thinking && typeof message.thinking === "string") {
|
|
18077
|
+
consider(thinkingResult.status, isEncrypted(message.thinking) ? message.thinking : void 0);
|
|
18078
|
+
}
|
|
18079
|
+
if (vectorResult.probe) consider(vectorResult.status, vectorResult.probe);
|
|
18080
|
+
if (chunksResult.probe) consider(chunksResult.status, chunksResult.probe);
|
|
18081
|
+
if (sourcesResult.probe) consider(sourcesResult.status, sourcesResult.probe);
|
|
18082
|
+
if (thoughtProcessResult.probe) {
|
|
18083
|
+
consider(thoughtProcessResult.status, thoughtProcessResult.probe);
|
|
18084
|
+
}
|
|
18085
|
+
if (toolCallEventsResult.probe) {
|
|
18086
|
+
consider(toolCallEventsResult.status, toolCallEventsResult.probe);
|
|
18087
|
+
}
|
|
18088
|
+
const toolCallEvents = Array.isArray(toolCallEventsResult.value) ? await mapToolCallPayloads(toolCallEventsResult.value, async (value) => {
|
|
18089
|
+
const detailed = await decryptFieldDetailed(value, address);
|
|
18090
|
+
consider(detailed.status, isEncrypted(value) ? value : void 0);
|
|
18091
|
+
return detailed.value;
|
|
18092
|
+
}) : void 0;
|
|
18093
|
+
const statusForConsumer = decryptionStatus === "ok" || decryptionStatus === "plaintext" || !decryptionStatus ? void 0 : decryptionStatus;
|
|
18094
|
+
const result = {
|
|
18095
|
+
...message,
|
|
18096
|
+
content: contentResult.value,
|
|
18097
|
+
thinking: thinkingResult ? thinkingResult.value : message.thinking,
|
|
18098
|
+
vector: vectorResult.value,
|
|
18099
|
+
chunks: chunksResult.value,
|
|
18100
|
+
sources: sourcesResult.value,
|
|
18101
|
+
thoughtProcess: thoughtProcessResult.value,
|
|
18102
|
+
toolCallEvents
|
|
18103
|
+
};
|
|
18104
|
+
if (statusForConsumer) {
|
|
18105
|
+
result.decryptionStatus = statusForConsumer;
|
|
18106
|
+
} else {
|
|
18107
|
+
delete result.decryptionStatus;
|
|
18108
|
+
}
|
|
18109
|
+
if (refreshProbe) {
|
|
18110
|
+
result.refreshProbe = refreshProbe;
|
|
18111
|
+
}
|
|
18112
|
+
return result;
|
|
18113
|
+
}
|
|
18114
|
+
|
|
18115
|
+
// src/lib/db/chat/models.ts
|
|
18116
|
+
var import_watermelondb2 = __toESM(require_watermelondb());
|
|
18117
|
+
var import_decorators = __toESM(require_decorators());
|
|
18118
|
+
var Message = class extends import_watermelondb2.Model {
|
|
18119
|
+
};
|
|
18120
|
+
Message.table = "history";
|
|
18121
|
+
Message.associations = {
|
|
18122
|
+
conversations: { type: "belongs_to", key: "conversation_id" },
|
|
18123
|
+
media: { type: "has_many", foreignKey: "message_id" }
|
|
18124
|
+
};
|
|
18125
|
+
__decorateClass([
|
|
18126
|
+
(0, import_decorators.field)("message_id")
|
|
18127
|
+
], Message.prototype, "messageId", 2);
|
|
18128
|
+
__decorateClass([
|
|
18129
|
+
(0, import_decorators.text)("conversation_id")
|
|
18130
|
+
], Message.prototype, "conversationId", 2);
|
|
18131
|
+
__decorateClass([
|
|
18132
|
+
(0, import_decorators.text)("role")
|
|
18133
|
+
], Message.prototype, "role", 2);
|
|
18134
|
+
__decorateClass([
|
|
18135
|
+
(0, import_decorators.text)("content")
|
|
18136
|
+
], Message.prototype, "content", 2);
|
|
18137
|
+
__decorateClass([
|
|
18138
|
+
(0, import_decorators.text)("model")
|
|
18139
|
+
], Message.prototype, "model", 2);
|
|
18140
|
+
__decorateClass([
|
|
18141
|
+
(0, import_decorators.text)("image_model")
|
|
18142
|
+
], Message.prototype, "imageModel", 2);
|
|
18143
|
+
__decorateClass([
|
|
18144
|
+
(0, import_decorators.json)("files", (raw) => raw)
|
|
18145
|
+
], Message.prototype, "files", 2);
|
|
18146
|
+
__decorateClass([
|
|
18147
|
+
(0, import_decorators.json)("file_ids", (raw) => raw)
|
|
18148
|
+
], Message.prototype, "fileIds", 2);
|
|
18149
|
+
__decorateClass([
|
|
18150
|
+
(0, import_decorators.date)("created_at")
|
|
18151
|
+
], Message.prototype, "createdAt", 2);
|
|
18152
|
+
__decorateClass([
|
|
18153
|
+
(0, import_decorators.date)("updated_at")
|
|
18154
|
+
], Message.prototype, "updatedAt", 2);
|
|
18155
|
+
__decorateClass([
|
|
18156
|
+
(0, import_decorators.json)("vector", (raw) => raw)
|
|
18157
|
+
], Message.prototype, "vector", 2);
|
|
18158
|
+
__decorateClass([
|
|
18159
|
+
(0, import_decorators.text)("embedding_model")
|
|
18160
|
+
], Message.prototype, "embeddingModel", 2);
|
|
18161
|
+
__decorateClass([
|
|
18162
|
+
(0, import_decorators.json)("chunks", (raw) => raw)
|
|
18163
|
+
], Message.prototype, "chunks", 2);
|
|
18164
|
+
__decorateClass([
|
|
18165
|
+
(0, import_decorators.json)("usage", (raw) => raw)
|
|
18166
|
+
], Message.prototype, "usage", 2);
|
|
18167
|
+
__decorateClass([
|
|
18168
|
+
(0, import_decorators.json)("sources", (raw) => raw)
|
|
18169
|
+
], Message.prototype, "sources", 2);
|
|
18170
|
+
__decorateClass([
|
|
18171
|
+
(0, import_decorators.field)("response_duration")
|
|
18172
|
+
], Message.prototype, "responseDuration", 2);
|
|
18173
|
+
__decorateClass([
|
|
18174
|
+
(0, import_decorators.field)("was_stopped")
|
|
18175
|
+
], Message.prototype, "wasStopped", 2);
|
|
18176
|
+
__decorateClass([
|
|
18177
|
+
(0, import_decorators.text)("error")
|
|
18178
|
+
], Message.prototype, "error", 2);
|
|
18179
|
+
__decorateClass([
|
|
18180
|
+
(0, import_decorators.json)("thought_process", (raw) => raw)
|
|
18181
|
+
], Message.prototype, "thoughtProcess", 2);
|
|
18182
|
+
__decorateClass([
|
|
18183
|
+
(0, import_decorators.text)("thinking")
|
|
18184
|
+
], Message.prototype, "thinking", 2);
|
|
18185
|
+
__decorateClass([
|
|
18186
|
+
(0, import_decorators.text)("parent_message_id")
|
|
18187
|
+
], Message.prototype, "parentMessageId", 2);
|
|
18188
|
+
__decorateClass([
|
|
18189
|
+
(0, import_decorators.text)("feedback")
|
|
18190
|
+
], Message.prototype, "feedback", 2);
|
|
18191
|
+
__decorateClass([
|
|
18192
|
+
(0, import_decorators.json)("tool_call_events", (raw) => raw)
|
|
18193
|
+
], Message.prototype, "toolCallEvents", 2);
|
|
18194
|
+
__decorateClass([
|
|
18195
|
+
(0, import_decorators.text)("origin")
|
|
18196
|
+
], Message.prototype, "origin", 2);
|
|
18197
|
+
var Conversation = class extends import_watermelondb2.Model {
|
|
18198
|
+
};
|
|
18199
|
+
Conversation.table = "conversations";
|
|
18200
|
+
Conversation.associations = {
|
|
18201
|
+
history: { type: "has_many", foreignKey: "conversation_id" },
|
|
18202
|
+
projects: { type: "belongs_to", key: "project_id" }
|
|
18203
|
+
};
|
|
18204
|
+
__decorateClass([
|
|
18205
|
+
(0, import_decorators.text)("conversation_id")
|
|
18206
|
+
], Conversation.prototype, "conversationId", 2);
|
|
18207
|
+
__decorateClass([
|
|
18208
|
+
(0, import_decorators.text)("title")
|
|
18209
|
+
], Conversation.prototype, "title", 2);
|
|
18210
|
+
__decorateClass([
|
|
18211
|
+
(0, import_decorators.text)("project_id")
|
|
18212
|
+
], Conversation.prototype, "projectId", 2);
|
|
18213
|
+
__decorateClass([
|
|
18214
|
+
(0, import_decorators.date)("created_at")
|
|
18215
|
+
], Conversation.prototype, "createdAt", 2);
|
|
18216
|
+
__decorateClass([
|
|
18217
|
+
(0, import_decorators.date)("updated_at")
|
|
18218
|
+
], Conversation.prototype, "updatedAt", 2);
|
|
18219
|
+
__decorateClass([
|
|
18220
|
+
(0, import_decorators.field)("is_deleted")
|
|
18221
|
+
], Conversation.prototype, "isDeleted", 2);
|
|
18222
|
+
__decorateClass([
|
|
18223
|
+
(0, import_decorators.date)("pinned_at")
|
|
18224
|
+
], Conversation.prototype, "pinnedAt", 2);
|
|
18225
|
+
var ConversationSummary = class extends import_watermelondb2.Model {
|
|
18226
|
+
};
|
|
18227
|
+
ConversationSummary.table = "conversation_summaries";
|
|
18228
|
+
ConversationSummary.associations = {
|
|
18229
|
+
conversations: { type: "belongs_to", key: "conversation_id" }
|
|
18230
|
+
};
|
|
18231
|
+
__decorateClass([
|
|
18232
|
+
(0, import_decorators.text)("conversation_id")
|
|
18233
|
+
], ConversationSummary.prototype, "conversationId", 2);
|
|
18234
|
+
__decorateClass([
|
|
18235
|
+
(0, import_decorators.text)("summary")
|
|
18236
|
+
], ConversationSummary.prototype, "summary", 2);
|
|
18237
|
+
__decorateClass([
|
|
18238
|
+
(0, import_decorators.text)("summarized_up_to")
|
|
18239
|
+
], ConversationSummary.prototype, "summarizedUpTo", 2);
|
|
18240
|
+
__decorateClass([
|
|
18241
|
+
(0, import_decorators.field)("token_count")
|
|
18242
|
+
], ConversationSummary.prototype, "tokenCount", 2);
|
|
18243
|
+
__decorateClass([
|
|
18244
|
+
(0, import_decorators.date)("created_at")
|
|
18245
|
+
], ConversationSummary.prototype, "createdAt", 2);
|
|
18246
|
+
__decorateClass([
|
|
18247
|
+
(0, import_decorators.date)("updated_at")
|
|
18248
|
+
], ConversationSummary.prototype, "updatedAt", 2);
|
|
18249
|
+
|
|
18250
|
+
// src/lib/db/chat/summaryRevision.ts
|
|
18251
|
+
var conversationRevisions = /* @__PURE__ */ new WeakMap();
|
|
18252
|
+
function getConversationRevision(database, conversationId) {
|
|
18253
|
+
return conversationRevisions.get(database)?.get(conversationId) ?? 0;
|
|
18254
|
+
}
|
|
18255
|
+
function advanceConversationRevision(database, conversationId) {
|
|
18256
|
+
let revisions = conversationRevisions.get(database);
|
|
18257
|
+
if (!revisions) {
|
|
18258
|
+
revisions = /* @__PURE__ */ new Map();
|
|
18259
|
+
conversationRevisions.set(database, revisions);
|
|
18040
18260
|
}
|
|
18041
|
-
|
|
18042
|
-
return result;
|
|
18261
|
+
revisions.set(conversationId, getConversationRevision(database, conversationId) + 1);
|
|
18043
18262
|
}
|
|
18044
|
-
|
|
18045
|
-
|
|
18046
|
-
|
|
18047
|
-
const vectorResult = await decryptMaybeJsonFieldDetailed(
|
|
18048
|
-
message.vector,
|
|
18049
|
-
address
|
|
18050
|
-
);
|
|
18051
|
-
const chunksResult = await decryptMaybeJsonFieldDetailed(
|
|
18052
|
-
message.chunks,
|
|
18053
|
-
address
|
|
18054
|
-
);
|
|
18055
|
-
const sourcesResult = await decryptMaybeJsonFieldDetailed(
|
|
18056
|
-
message.sources,
|
|
18057
|
-
address
|
|
18058
|
-
);
|
|
18059
|
-
const thoughtProcessResult = await decryptMaybeJsonFieldDetailed(
|
|
18060
|
-
message.thoughtProcess,
|
|
18061
|
-
address
|
|
18062
|
-
);
|
|
18063
|
-
const toolCallEventsResult = await decryptMaybeJsonFieldDetailed(
|
|
18064
|
-
message.toolCallEvents,
|
|
18065
|
-
address
|
|
18066
|
-
);
|
|
18067
|
-
let decryptionStatus;
|
|
18068
|
-
let refreshProbe;
|
|
18069
|
-
const consider = (status, probe) => {
|
|
18070
|
-
decryptionStatus = worseDecryptStatus(decryptionStatus, status);
|
|
18071
|
-
if (!refreshProbe && probe && (status === "auth_mismatch" || status === "key_missing")) {
|
|
18072
|
-
refreshProbe = probe;
|
|
18073
|
-
}
|
|
18074
|
-
};
|
|
18075
|
-
consider(contentResult.status, isEncrypted(message.content) ? message.content : void 0);
|
|
18076
|
-
if (thinkingResult && message.thinking && typeof message.thinking === "string") {
|
|
18077
|
-
consider(thinkingResult.status, isEncrypted(message.thinking) ? message.thinking : void 0);
|
|
18078
|
-
}
|
|
18079
|
-
if (vectorResult.probe) consider(vectorResult.status, vectorResult.probe);
|
|
18080
|
-
if (chunksResult.probe) consider(chunksResult.status, chunksResult.probe);
|
|
18081
|
-
if (sourcesResult.probe) consider(sourcesResult.status, sourcesResult.probe);
|
|
18082
|
-
if (thoughtProcessResult.probe) {
|
|
18083
|
-
consider(thoughtProcessResult.status, thoughtProcessResult.probe);
|
|
18084
|
-
}
|
|
18085
|
-
if (toolCallEventsResult.probe) {
|
|
18086
|
-
consider(toolCallEventsResult.status, toolCallEventsResult.probe);
|
|
18087
|
-
}
|
|
18088
|
-
const toolCallEvents = Array.isArray(toolCallEventsResult.value) ? await mapToolCallPayloads(toolCallEventsResult.value, async (value) => {
|
|
18089
|
-
const detailed = await decryptFieldDetailed(value, address);
|
|
18090
|
-
consider(detailed.status, isEncrypted(value) ? value : void 0);
|
|
18091
|
-
return detailed.value;
|
|
18092
|
-
}) : void 0;
|
|
18093
|
-
const statusForConsumer = decryptionStatus === "ok" || decryptionStatus === "plaintext" || !decryptionStatus ? void 0 : decryptionStatus;
|
|
18094
|
-
const result = {
|
|
18095
|
-
...message,
|
|
18096
|
-
content: contentResult.value,
|
|
18097
|
-
thinking: thinkingResult ? thinkingResult.value : message.thinking,
|
|
18098
|
-
vector: vectorResult.value,
|
|
18099
|
-
chunks: chunksResult.value,
|
|
18100
|
-
sources: sourcesResult.value,
|
|
18101
|
-
thoughtProcess: thoughtProcessResult.value,
|
|
18102
|
-
toolCallEvents
|
|
18103
|
-
};
|
|
18104
|
-
if (statusForConsumer) {
|
|
18105
|
-
result.decryptionStatus = statusForConsumer;
|
|
18106
|
-
} else {
|
|
18107
|
-
delete result.decryptionStatus;
|
|
18108
|
-
}
|
|
18109
|
-
if (refreshProbe) {
|
|
18110
|
-
result.refreshProbe = refreshProbe;
|
|
18263
|
+
function assertConversationRevision(database, conversationId, revision) {
|
|
18264
|
+
if (getConversationRevision(database, conversationId) !== revision) {
|
|
18265
|
+
throw new Error("The conversation changed during summarization. Retry the request.");
|
|
18111
18266
|
}
|
|
18112
|
-
return result;
|
|
18113
18267
|
}
|
|
18114
18268
|
|
|
18115
18269
|
// src/lib/db/chat/types.ts
|
|
@@ -18354,7 +18508,7 @@ async function createConversationOp(ctx, opts, defaultTitle = "New Conversation"
|
|
|
18354
18508
|
);
|
|
18355
18509
|
}
|
|
18356
18510
|
async function getConversationOp(ctx, id) {
|
|
18357
|
-
const results = await ctx.conversationsCollection.query(
|
|
18511
|
+
const results = await ctx.conversationsCollection.query(import_watermelondb3.Q.where("conversation_id", id), import_watermelondb3.Q.where("is_deleted", false)).fetch();
|
|
18358
18512
|
return results.length > 0 ? await conversationToStored(
|
|
18359
18513
|
results[0],
|
|
18360
18514
|
ctx.walletAddress,
|
|
@@ -18363,7 +18517,7 @@ async function getConversationOp(ctx, id) {
|
|
|
18363
18517
|
) : null;
|
|
18364
18518
|
}
|
|
18365
18519
|
async function getConversationsOp(ctx) {
|
|
18366
|
-
const results = await ctx.conversationsCollection.query(
|
|
18520
|
+
const results = await ctx.conversationsCollection.query(import_watermelondb3.Q.where("is_deleted", false), import_watermelondb3.Q.sortBy("created_at", import_watermelondb3.Q.desc)).unsafeFetchRaw();
|
|
18367
18521
|
return Promise.all(
|
|
18368
18522
|
results.map(
|
|
18369
18523
|
(raw) => conversationRawToStored(raw, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner)
|
|
@@ -18384,33 +18538,33 @@ function conversationRawToLazyStored(raw) {
|
|
|
18384
18538
|
};
|
|
18385
18539
|
}
|
|
18386
18540
|
async function getConversationsLazyOp(ctx) {
|
|
18387
|
-
const results = await ctx.conversationsCollection.query(
|
|
18541
|
+
const results = await ctx.conversationsCollection.query(import_watermelondb3.Q.where("is_deleted", false), import_watermelondb3.Q.sortBy("created_at", import_watermelondb3.Q.desc)).unsafeFetchRaw();
|
|
18388
18542
|
return results.map(conversationRawToLazyStored);
|
|
18389
18543
|
}
|
|
18390
18544
|
async function getConversationsPageOp(ctx, options) {
|
|
18391
18545
|
const limit = Math.floor(options?.limit ?? 200);
|
|
18392
18546
|
if (!Number.isFinite(limit) || limit < 1) return [];
|
|
18393
18547
|
const exclude = new Set(options?.boundaryExcludeUniqueIds ?? []);
|
|
18394
|
-
const clauses = [
|
|
18548
|
+
const clauses = [import_watermelondb3.Q.where("is_deleted", false)];
|
|
18395
18549
|
if (options?.before !== void 0) {
|
|
18396
18550
|
clauses.push(
|
|
18397
|
-
exclude.size > 0 ?
|
|
18551
|
+
exclude.size > 0 ? import_watermelondb3.Q.where("created_at", import_watermelondb3.Q.lte(options.before)) : import_watermelondb3.Q.where("created_at", import_watermelondb3.Q.lt(options.before))
|
|
18398
18552
|
);
|
|
18399
18553
|
}
|
|
18400
|
-
const fetched = await ctx.conversationsCollection.query(...clauses,
|
|
18554
|
+
const fetched = await ctx.conversationsCollection.query(...clauses, import_watermelondb3.Q.sortBy("created_at", import_watermelondb3.Q.desc), import_watermelondb3.Q.take(limit + exclude.size)).unsafeFetchRaw();
|
|
18401
18555
|
const results = exclude.size > 0 ? fetched.filter((raw) => !exclude.has(raw.id)) : fetched;
|
|
18402
18556
|
return results.slice(0, limit).map(conversationRawToLazyStored);
|
|
18403
18557
|
}
|
|
18404
18558
|
async function getConversationsByProjectLazyOp(ctx, projectId) {
|
|
18405
18559
|
const results = await ctx.conversationsCollection.query(
|
|
18406
|
-
|
|
18407
|
-
|
|
18408
|
-
|
|
18560
|
+
import_watermelondb3.Q.where("project_id", projectId === null ? "" : projectId),
|
|
18561
|
+
import_watermelondb3.Q.where("is_deleted", false),
|
|
18562
|
+
import_watermelondb3.Q.sortBy("created_at", import_watermelondb3.Q.desc)
|
|
18409
18563
|
).unsafeFetchRaw();
|
|
18410
18564
|
return results.map(conversationRawToLazyStored);
|
|
18411
18565
|
}
|
|
18412
18566
|
async function updateConversationTitleOp(ctx, id, title) {
|
|
18413
|
-
const results = await ctx.conversationsCollection.query(
|
|
18567
|
+
const results = await ctx.conversationsCollection.query(import_watermelondb3.Q.where("conversation_id", id), import_watermelondb3.Q.where("is_deleted", false)).fetch();
|
|
18414
18568
|
if (results.length > 0) {
|
|
18415
18569
|
const encryptedOpts = ctx.walletAddress && ctx.signMessage ? await encryptConversationFields(
|
|
18416
18570
|
{ title },
|
|
@@ -18429,13 +18583,13 @@ async function updateConversationTitleOp(ctx, id, title) {
|
|
|
18429
18583
|
return false;
|
|
18430
18584
|
}
|
|
18431
18585
|
async function deleteConversationOp(ctx, id) {
|
|
18432
|
-
const results = await ctx.conversationsCollection.query(
|
|
18586
|
+
const results = await ctx.conversationsCollection.query(import_watermelondb3.Q.where("conversation_id", id), import_watermelondb3.Q.where("is_deleted", false)).fetch();
|
|
18433
18587
|
if (results.length > 0) {
|
|
18434
18588
|
await ctx.database.write(async () => {
|
|
18435
18589
|
await results[0].update((conv) => {
|
|
18436
18590
|
conv._setRaw("is_deleted", true);
|
|
18437
18591
|
});
|
|
18438
|
-
const jobs = ctx.database.schema?.tables[ExtractionJob.table] ? await ctx.database.get(ExtractionJob.table).query(
|
|
18592
|
+
const jobs = ctx.database.schema?.tables[ExtractionJob.table] ? await ctx.database.get(ExtractionJob.table).query(import_watermelondb3.Q.where("conversation_id", id)).fetch() : [];
|
|
18439
18593
|
for (const job of jobs) await job.destroyPermanently();
|
|
18440
18594
|
});
|
|
18441
18595
|
return true;
|
|
@@ -18443,7 +18597,7 @@ async function deleteConversationOp(ctx, id) {
|
|
|
18443
18597
|
return false;
|
|
18444
18598
|
}
|
|
18445
18599
|
async function updateConversationProjectOp(ctx, id, projectId) {
|
|
18446
|
-
const results = await ctx.conversationsCollection.query(
|
|
18600
|
+
const results = await ctx.conversationsCollection.query(import_watermelondb3.Q.where("conversation_id", id), import_watermelondb3.Q.where("is_deleted", false)).fetch();
|
|
18447
18601
|
if (results.length > 0) {
|
|
18448
18602
|
await ctx.database.write(async () => {
|
|
18449
18603
|
await results[0].update((conv) => {
|
|
@@ -18456,9 +18610,9 @@ async function updateConversationProjectOp(ctx, id, projectId) {
|
|
|
18456
18610
|
}
|
|
18457
18611
|
async function getConversationsByProjectOp(ctx, projectId) {
|
|
18458
18612
|
const results = await ctx.conversationsCollection.query(
|
|
18459
|
-
|
|
18460
|
-
|
|
18461
|
-
|
|
18613
|
+
import_watermelondb3.Q.where("project_id", projectId === null ? "" : projectId),
|
|
18614
|
+
import_watermelondb3.Q.where("is_deleted", false),
|
|
18615
|
+
import_watermelondb3.Q.sortBy("created_at", import_watermelondb3.Q.desc)
|
|
18462
18616
|
).unsafeFetchRaw();
|
|
18463
18617
|
return Promise.all(
|
|
18464
18618
|
results.map(
|
|
@@ -18467,7 +18621,7 @@ async function getConversationsByProjectOp(ctx, projectId) {
|
|
|
18467
18621
|
);
|
|
18468
18622
|
}
|
|
18469
18623
|
async function getMessagesOp(ctx, convId, opts) {
|
|
18470
|
-
const fetched = await ctx.messagesCollection.query(
|
|
18624
|
+
const fetched = await ctx.messagesCollection.query(import_watermelondb3.Q.where("conversation_id", convId), import_watermelondb3.Q.sortBy("message_id", import_watermelondb3.Q.asc)).unsafeFetchRaw();
|
|
18471
18625
|
const results = opts?.rawFilter ? fetched.filter(opts.rawFilter) : fetched;
|
|
18472
18626
|
return Promise.all(
|
|
18473
18627
|
results.map(
|
|
@@ -18475,10 +18629,22 @@ async function getMessagesOp(ctx, convId, opts) {
|
|
|
18475
18629
|
)
|
|
18476
18630
|
);
|
|
18477
18631
|
}
|
|
18632
|
+
async function invalidateConversationSummary(ctx, conversationId, changedMessageId) {
|
|
18633
|
+
if (!ctx.database.schema?.tables[ConversationSummary.table]) return;
|
|
18634
|
+
const summaries = await ctx.database.get(ConversationSummary.table).query(import_watermelondb3.Q.where("conversation_id", conversationId)).fetch();
|
|
18635
|
+
for (const summary of summaries) {
|
|
18636
|
+
if (changedMessageId !== void 0) {
|
|
18637
|
+
const [boundary] = await ctx.messagesCollection.query(import_watermelondb3.Q.where("id", summary.summarizedUpTo), import_watermelondb3.Q.where("conversation_id", conversationId)).fetch();
|
|
18638
|
+
if (boundary && changedMessageId > boundary.messageId) continue;
|
|
18639
|
+
}
|
|
18640
|
+
await summary.destroyPermanently();
|
|
18641
|
+
}
|
|
18642
|
+
}
|
|
18478
18643
|
async function clearMessagesOp(ctx, convId) {
|
|
18479
18644
|
await ctx.database.write(async () => {
|
|
18480
|
-
|
|
18481
|
-
const
|
|
18645
|
+
await invalidateConversationSummary(ctx, convId);
|
|
18646
|
+
const messages = await ctx.messagesCollection.query(import_watermelondb3.Q.where("conversation_id", convId)).fetch();
|
|
18647
|
+
const jobs = ctx.database.schema?.tables[ExtractionJob.table] ? await ctx.database.get(ExtractionJob.table).query(import_watermelondb3.Q.where("conversation_id", convId)).fetch() : [];
|
|
18482
18648
|
for (const job of jobs) {
|
|
18483
18649
|
await job.update((row) => {
|
|
18484
18650
|
row._setRaw("message_ids", "[]");
|
|
@@ -18488,11 +18654,12 @@ async function clearMessagesOp(ctx, convId) {
|
|
|
18488
18654
|
}
|
|
18489
18655
|
for (const message of messages) {
|
|
18490
18656
|
await message.update((msg) => {
|
|
18491
|
-
msg._setRaw("file_ids", null);
|
|
18657
|
+
if (ctx.messagesCollection.schema.columns.file_ids) msg._setRaw("file_ids", null);
|
|
18492
18658
|
msg._setRaw("files", null);
|
|
18493
18659
|
});
|
|
18494
18660
|
await message.destroyPermanently();
|
|
18495
18661
|
}
|
|
18662
|
+
advanceConversationRevision(ctx.database, convId);
|
|
18496
18663
|
});
|
|
18497
18664
|
}
|
|
18498
18665
|
async function deleteMessageOp(ctx, uniqueId) {
|
|
@@ -18503,7 +18670,8 @@ async function deleteMessageOp(ctx, uniqueId) {
|
|
|
18503
18670
|
return null;
|
|
18504
18671
|
}
|
|
18505
18672
|
await ctx.database.write(async () => {
|
|
18506
|
-
|
|
18673
|
+
await invalidateConversationSummary(ctx, message.conversationId, message.messageId);
|
|
18674
|
+
const jobs = ctx.database.schema?.tables[ExtractionJob.table] ? await ctx.database.get(ExtractionJob.table).query(import_watermelondb3.Q.where("conversation_id", message.conversationId)).fetch() : [];
|
|
18507
18675
|
for (const job of jobs) {
|
|
18508
18676
|
const ids = JSON.parse(String(job._getRaw("message_ids")));
|
|
18509
18677
|
await job.update((row) => {
|
|
@@ -18512,10 +18680,11 @@ async function deleteMessageOp(ctx, uniqueId) {
|
|
|
18512
18680
|
});
|
|
18513
18681
|
}
|
|
18514
18682
|
await message.update((msg) => {
|
|
18515
|
-
msg._setRaw("file_ids", null);
|
|
18683
|
+
if (ctx.messagesCollection.schema.columns.file_ids) msg._setRaw("file_ids", null);
|
|
18516
18684
|
msg._setRaw("files", null);
|
|
18517
18685
|
});
|
|
18518
18686
|
await message.destroyPermanently();
|
|
18687
|
+
advanceConversationRevision(ctx.database, message.conversationId);
|
|
18519
18688
|
});
|
|
18520
18689
|
return uniqueId;
|
|
18521
18690
|
}
|
|
@@ -18576,9 +18745,9 @@ async function createMessageOp(ctx, opts) {
|
|
|
18576
18745
|
}
|
|
18577
18746
|
}
|
|
18578
18747
|
const newest = await ctx.messagesCollection.query(
|
|
18579
|
-
|
|
18580
|
-
|
|
18581
|
-
|
|
18748
|
+
import_watermelondb3.Q.where("conversation_id", opts.conversationId),
|
|
18749
|
+
import_watermelondb3.Q.sortBy("message_id", import_watermelondb3.Q.desc),
|
|
18750
|
+
import_watermelondb3.Q.take(1)
|
|
18582
18751
|
).fetch();
|
|
18583
18752
|
const messageId = (newest[0]?.messageId ?? 0) + 1;
|
|
18584
18753
|
const encryptedOpts = await encryptMessageOptsIfNeeded(ctx, opts);
|
|
@@ -18592,7 +18761,7 @@ async function createMessageOp(ctx, opts) {
|
|
|
18592
18761
|
return messageToStored(created, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
18593
18762
|
}
|
|
18594
18763
|
async function upsertMessageOp(ctx, opts) {
|
|
18595
|
-
const results = await ctx.messagesCollection.query(
|
|
18764
|
+
const results = await ctx.messagesCollection.query(import_watermelondb3.Q.where("id", opts.uniqueId)).fetch();
|
|
18596
18765
|
const existing = results.length > 0 ? results[0] : null;
|
|
18597
18766
|
if (!existing) {
|
|
18598
18767
|
return createMessageOp(ctx, opts);
|
|
@@ -18700,13 +18869,13 @@ async function decryptMessageEmbeddingFields(raw, walletAddress) {
|
|
|
18700
18869
|
async function sealLegacyMessageEmbeddingsOp(ctx) {
|
|
18701
18870
|
if (!ctx.walletAddress) return 0;
|
|
18702
18871
|
const candidateIds = await ctx.messagesCollection.query(
|
|
18703
|
-
|
|
18704
|
-
|
|
18872
|
+
import_watermelondb3.Q.where("content", import_watermelondb3.Q.like("enc:%")),
|
|
18873
|
+
import_watermelondb3.Q.or(
|
|
18705
18874
|
...["vector", "chunks"].map(
|
|
18706
|
-
(column) =>
|
|
18707
|
-
|
|
18708
|
-
|
|
18709
|
-
|
|
18875
|
+
(column) => import_watermelondb3.Q.and(
|
|
18876
|
+
import_watermelondb3.Q.where(column, import_watermelondb3.Q.notEq(null)),
|
|
18877
|
+
import_watermelondb3.Q.where(column, import_watermelondb3.Q.notEq("")),
|
|
18878
|
+
import_watermelondb3.Q.where(column, import_watermelondb3.Q.notLike("enc:%"))
|
|
18710
18879
|
)
|
|
18711
18880
|
)
|
|
18712
18881
|
)
|
|
@@ -18716,7 +18885,7 @@ async function sealLegacyMessageEmbeddingsOp(ctx) {
|
|
|
18716
18885
|
for (let start = 0; start < candidateIds.length; start += 50) {
|
|
18717
18886
|
const pageIds = candidateIds.slice(start, start + 50);
|
|
18718
18887
|
await ctx.database.write(async () => {
|
|
18719
|
-
const pageMessages = await ctx.messagesCollection.query(
|
|
18888
|
+
const pageMessages = await ctx.messagesCollection.query(import_watermelondb3.Q.where("id", import_watermelondb3.Q.oneOf(pageIds))).fetch();
|
|
18720
18889
|
for (const message of pageMessages) {
|
|
18721
18890
|
if (!isEncrypted(message.content)) continue;
|
|
18722
18891
|
const content = await decryptFieldDetailed(message.content, ctx.walletAddress);
|
|
@@ -18797,15 +18966,15 @@ function chunksWithoutText(raw) {
|
|
|
18797
18966
|
});
|
|
18798
18967
|
}
|
|
18799
18968
|
async function stripLegacyChunkTextOp(ctx) {
|
|
18800
|
-
const candidateIds = await ctx.messagesCollection.query(
|
|
18969
|
+
const candidateIds = await ctx.messagesCollection.query(import_watermelondb3.Q.where("chunks", import_watermelondb3.Q.like(`%${import_watermelondb3.Q.sanitizeLikeString('"text":')}%`))).fetchIds();
|
|
18801
18970
|
let stripped = 0;
|
|
18802
18971
|
for (let start = 0; start < candidateIds.length; start += RAW_REPAIR_PAGE_SIZE) {
|
|
18803
18972
|
const pageIds = candidateIds.slice(start, start + RAW_REPAIR_PAGE_SIZE);
|
|
18804
|
-
const rows = await ctx.messagesCollection.query(
|
|
18973
|
+
const rows = await ctx.messagesCollection.query(import_watermelondb3.Q.where("id", import_watermelondb3.Q.oneOf(pageIds))).unsafeFetchRaw();
|
|
18805
18974
|
const changedIds = rows.filter((row) => chunksWithoutText(row.chunks) !== null).map((row) => String(row.id));
|
|
18806
18975
|
if (changedIds.length === 0) continue;
|
|
18807
18976
|
await ctx.database.write(async () => {
|
|
18808
|
-
const messages = await ctx.messagesCollection.query(
|
|
18977
|
+
const messages = await ctx.messagesCollection.query(import_watermelondb3.Q.where("id", import_watermelondb3.Q.oneOf(changedIds))).fetch();
|
|
18809
18978
|
const updates = messages.flatMap((message) => {
|
|
18810
18979
|
const raw = message._raw;
|
|
18811
18980
|
const chunks = chunksWithoutText(raw.chunks);
|
|
@@ -18852,13 +19021,13 @@ async function encryptToolCallEventsOp(ctx) {
|
|
|
18852
19021
|
return 0;
|
|
18853
19022
|
}
|
|
18854
19023
|
const candidateIds = await ctx.messagesCollection.query(
|
|
18855
|
-
|
|
18856
|
-
|
|
19024
|
+
import_watermelondb3.Q.where("tool_call_events", import_watermelondb3.Q.notEq(null)),
|
|
19025
|
+
import_watermelondb3.Q.where("tool_call_events", import_watermelondb3.Q.notIn(["", "[]"]))
|
|
18857
19026
|
).fetchIds();
|
|
18858
19027
|
let encrypted = 0;
|
|
18859
19028
|
for (let start = 0; start < candidateIds.length; start += RAW_REPAIR_PAGE_SIZE) {
|
|
18860
19029
|
const pageIds = candidateIds.slice(start, start + RAW_REPAIR_PAGE_SIZE);
|
|
18861
|
-
const rows = await ctx.messagesCollection.query(
|
|
19030
|
+
const rows = await ctx.messagesCollection.query(import_watermelondb3.Q.where("id", import_watermelondb3.Q.oneOf(pageIds))).unsafeFetchRaw();
|
|
18862
19031
|
const repairs = /* @__PURE__ */ new Map();
|
|
18863
19032
|
for (const row of rows) {
|
|
18864
19033
|
const column = await encryptedToolCallEventsColumn(
|
|
@@ -18871,12 +19040,12 @@ async function encryptToolCallEventsOp(ctx) {
|
|
|
18871
19040
|
}
|
|
18872
19041
|
if (repairs.size === 0) continue;
|
|
18873
19042
|
await ctx.database.write(async () => {
|
|
18874
|
-
const messages = (await ctx.messagesCollection.query(
|
|
19043
|
+
const messages = (await ctx.messagesCollection.query(import_watermelondb3.Q.where("id", import_watermelondb3.Q.oneOf([...repairs.keys()]))).fetch()).filter(
|
|
18875
19044
|
(message) => message._raw.tool_call_events === repairs.get(message.id)?.raw
|
|
18876
19045
|
);
|
|
18877
19046
|
if (messages.length === 0) return;
|
|
18878
19047
|
const conversationIds = [...new Set(messages.map((message) => message.conversationId))];
|
|
18879
|
-
const conversations = await ctx.conversationsCollection.query(
|
|
19048
|
+
const conversations = await ctx.conversationsCollection.query(import_watermelondb3.Q.where("conversation_id", import_watermelondb3.Q.oneOf(conversationIds))).fetch();
|
|
18880
19049
|
await ctx.database.batch(
|
|
18881
19050
|
...messages.map(
|
|
18882
19051
|
(message) => message.prepareUpdate((msg) => {
|
|
@@ -18903,7 +19072,7 @@ async function savedKeyOpensExistingData(ctx, address, signMessage, embeddedWall
|
|
|
18903
19072
|
return refreshEncryptionKeyIfMatches(address, v2Probe, signMessage, embeddedWalletSigner);
|
|
18904
19073
|
}
|
|
18905
19074
|
async function findEncryptedContent(ctx, pattern) {
|
|
18906
|
-
const [row] = await ctx.messagesCollection.query(
|
|
19075
|
+
const [row] = await ctx.messagesCollection.query(import_watermelondb3.Q.where("content", import_watermelondb3.Q.like(pattern)), import_watermelondb3.Q.take(1)).unsafeFetchRaw();
|
|
18907
19076
|
return row ? String(row.content) : null;
|
|
18908
19077
|
}
|
|
18909
19078
|
async function updateMessageErrorOp(ctx, uniqueId, error) {
|
|
@@ -18948,6 +19117,14 @@ async function _updateMessageOp(ctx, uniqueId, opts) {
|
|
|
18948
19117
|
ctx.embeddedWalletSigner
|
|
18949
19118
|
) : opts;
|
|
18950
19119
|
await ctx.database.write(async () => {
|
|
19120
|
+
let contentChanged = false;
|
|
19121
|
+
if (opts.content !== void 0) {
|
|
19122
|
+
const originalContent = ctx.walletAddress ? await decryptField(message.content, ctx.walletAddress) : message.content;
|
|
19123
|
+
contentChanged = opts.content !== originalContent;
|
|
19124
|
+
if (contentChanged) {
|
|
19125
|
+
await invalidateConversationSummary(ctx, message.conversationId, message.messageId);
|
|
19126
|
+
}
|
|
19127
|
+
}
|
|
18951
19128
|
await message.update((msg) => {
|
|
18952
19129
|
if (encryptedOpts.content !== void 0)
|
|
18953
19130
|
msg._setRaw("content", encryptedOpts.content);
|
|
@@ -18992,6 +19169,7 @@ async function _updateMessageOp(ctx, uniqueId, opts) {
|
|
|
18992
19169
|
msg._setRaw("tool_call_events", tceValue);
|
|
18993
19170
|
}
|
|
18994
19171
|
});
|
|
19172
|
+
if (contentChanged) advanceConversationRevision(ctx.database, message.conversationId);
|
|
18995
19173
|
});
|
|
18996
19174
|
return messageToStored(message, ctx.walletAddress, ctx.signMessage, ctx.embeddedWalletSigner);
|
|
18997
19175
|
}
|
|
@@ -19019,11 +19197,11 @@ async function readRawJsonField(raw, column, walletAddress) {
|
|
|
19019
19197
|
}
|
|
19020
19198
|
async function searchMessagesOp(ctx, queryVector, options) {
|
|
19021
19199
|
const { limit = 10, minSimilarity = 0.5, conversationId } = options || {};
|
|
19022
|
-
const activeConversations = await ctx.conversationsCollection.query(
|
|
19200
|
+
const activeConversations = await ctx.conversationsCollection.query(import_watermelondb3.Q.where("is_deleted", false)).fetch();
|
|
19023
19201
|
const activeConversationIds = new Set(
|
|
19024
19202
|
activeConversations.map((c) => String(c._getRaw("conversation_id")))
|
|
19025
19203
|
);
|
|
19026
|
-
const queryConditions = conversationId ? [
|
|
19204
|
+
const queryConditions = conversationId ? [import_watermelondb3.Q.where("conversation_id", conversationId)] : [];
|
|
19027
19205
|
const messages = await ctx.messagesCollection.query(...queryConditions).unsafeFetchRaw();
|
|
19028
19206
|
const candidates = [];
|
|
19029
19207
|
for (const message of messages) {
|
|
@@ -19062,7 +19240,7 @@ function toChunkCandidateKey(raw) {
|
|
|
19062
19240
|
}
|
|
19063
19241
|
async function fetchRowsByIds(ctx, ids) {
|
|
19064
19242
|
if (ids.length === 0) return [];
|
|
19065
|
-
return await ctx.messagesCollection.query(
|
|
19243
|
+
return await ctx.messagesCollection.query(import_watermelondb3.Q.where("id", import_watermelondb3.Q.oneOf(ids))).unsafeFetchRaw();
|
|
19066
19244
|
}
|
|
19067
19245
|
async function projectedChunkRowSource(ctx, filter) {
|
|
19068
19246
|
const clauses = [
|
|
@@ -19080,7 +19258,7 @@ async function projectedChunkRowSource(ctx, filter) {
|
|
|
19080
19258
|
args.push(filter.excludeConversationId);
|
|
19081
19259
|
}
|
|
19082
19260
|
const keyRows = await ctx.messagesCollection.query(
|
|
19083
|
-
|
|
19261
|
+
import_watermelondb3.Q.unsafeSqlQuery(
|
|
19084
19262
|
`select "id", "conversation_id", "updated_at", "embedding_model" from "history" where ${clauses.join(" and ")}`,
|
|
19085
19263
|
args
|
|
19086
19264
|
)
|
|
@@ -19090,7 +19268,7 @@ async function projectedChunkRowSource(ctx, filter) {
|
|
|
19090
19268
|
loadVectorRows: async (ids) => {
|
|
19091
19269
|
if (ids.length === 0) return [];
|
|
19092
19270
|
return await ctx.messagesCollection.query(
|
|
19093
|
-
|
|
19271
|
+
import_watermelondb3.Q.unsafeSqlQuery(
|
|
19094
19272
|
`select "id", "updated_at", "chunks", "vector" from "history" where "_status" is not 'deleted' and "id" in (${ids.map(() => "?").join(",")})`,
|
|
19095
19273
|
ids
|
|
19096
19274
|
)
|
|
@@ -19100,11 +19278,11 @@ async function projectedChunkRowSource(ctx, filter) {
|
|
|
19100
19278
|
};
|
|
19101
19279
|
}
|
|
19102
19280
|
async function fullScanChunkRowSource(ctx, filter) {
|
|
19103
|
-
const activeConversations = await ctx.conversationsCollection.query(
|
|
19281
|
+
const activeConversations = await ctx.conversationsCollection.query(import_watermelondb3.Q.where("is_deleted", false)).fetch();
|
|
19104
19282
|
const activeConversationIds = new Set(
|
|
19105
19283
|
activeConversations.map((c) => String(c._getRaw("conversation_id")))
|
|
19106
19284
|
);
|
|
19107
|
-
const queryConditions = filter.conversationId !== void 0 ? [
|
|
19285
|
+
const queryConditions = filter.conversationId !== void 0 ? [import_watermelondb3.Q.where("conversation_id", filter.conversationId)] : [];
|
|
19108
19286
|
const rows = await ctx.messagesCollection.query(...queryConditions).unsafeFetchRaw();
|
|
19109
19287
|
const rowsById = /* @__PURE__ */ new Map();
|
|
19110
19288
|
for (const row of rows) {
|
|
@@ -19311,12 +19489,12 @@ async function searchChunksOp(ctx, queryVector, options) {
|
|
|
19311
19489
|
}
|
|
19312
19490
|
async function getAllFilesOp(ctx, options) {
|
|
19313
19491
|
const { conversationId, limit } = options || {};
|
|
19314
|
-
const activeConversations = await ctx.conversationsCollection.query(
|
|
19492
|
+
const activeConversations = await ctx.conversationsCollection.query(import_watermelondb3.Q.where("is_deleted", false)).fetch();
|
|
19315
19493
|
const activeConversationIds = new Set(
|
|
19316
19494
|
activeConversations.map((c) => String(c._getRaw("conversation_id")))
|
|
19317
19495
|
);
|
|
19318
|
-
const queryConditions = conversationId ? [
|
|
19319
|
-
const messages = await ctx.messagesCollection.query(...queryConditions,
|
|
19496
|
+
const queryConditions = conversationId ? [import_watermelondb3.Q.where("conversation_id", conversationId)] : [];
|
|
19497
|
+
const messages = await ctx.messagesCollection.query(...queryConditions, import_watermelondb3.Q.sortBy("created_at", import_watermelondb3.Q.desc)).fetch();
|
|
19320
19498
|
const filesWithContext = [];
|
|
19321
19499
|
for (const message of messages) {
|
|
19322
19500
|
const msgConvId = String(message._getRaw("conversation_id"));
|
|
@@ -25301,7 +25479,7 @@ function createStockPricePreProcessor(options = {}) {
|
|
|
25301
25479
|
init_clientConfig();
|
|
25302
25480
|
|
|
25303
25481
|
// src/lib/db/chat/summaryOperations.ts
|
|
25304
|
-
var
|
|
25482
|
+
var import_watermelondb4 = __toESM(require_watermelondb());
|
|
25305
25483
|
function createSummaryContext(database) {
|
|
25306
25484
|
return {
|
|
25307
25485
|
database,
|
|
@@ -25320,14 +25498,14 @@ function modelToStored(record) {
|
|
|
25320
25498
|
};
|
|
25321
25499
|
}
|
|
25322
25500
|
async function getConversationSummaryOp(ctx, conversationId) {
|
|
25323
|
-
const results = await ctx.summariesCollection.query(
|
|
25501
|
+
const results = await ctx.summariesCollection.query(import_watermelondb4.Q.where("conversation_id", conversationId)).fetch();
|
|
25324
25502
|
if (results.length === 0) return null;
|
|
25325
25503
|
return modelToStored(results[0]);
|
|
25326
25504
|
}
|
|
25327
25505
|
async function upsertConversationSummaryOp(ctx, conversationId, summary, summarizedUpTo, tokenCount) {
|
|
25328
25506
|
let record;
|
|
25329
25507
|
await ctx.database.write(async () => {
|
|
25330
|
-
const existing = await ctx.summariesCollection.query(
|
|
25508
|
+
const existing = await ctx.summariesCollection.query(import_watermelondb4.Q.where("conversation_id", conversationId)).fetch();
|
|
25331
25509
|
if (existing.length > 0) {
|
|
25332
25510
|
record = await existing[0].update((rec) => {
|
|
25333
25511
|
rec.summary = summary;
|
|
@@ -25347,7 +25525,7 @@ async function upsertConversationSummaryOp(ctx, conversationId, summary, summari
|
|
|
25347
25525
|
}
|
|
25348
25526
|
async function deleteConversationSummaryOp(ctx, conversationId) {
|
|
25349
25527
|
await ctx.database.write(async () => {
|
|
25350
|
-
const existing = await ctx.summariesCollection.query(
|
|
25528
|
+
const existing = await ctx.summariesCollection.query(import_watermelondb4.Q.where("conversation_id", conversationId)).fetch();
|
|
25351
25529
|
for (const record of existing) {
|
|
25352
25530
|
await record.destroyPermanently();
|
|
25353
25531
|
}
|
|
@@ -25591,6 +25769,13 @@ var lastCompactionTime = /* @__PURE__ */ new Map();
|
|
|
25591
25769
|
var COMPACTION_COOLDOWN_MS = 6e4;
|
|
25592
25770
|
var MAX_SUMMARY_TOKEN_RATIO = 0.8;
|
|
25593
25771
|
async function maybeSummarizeHistory(options) {
|
|
25772
|
+
const { database, conversationId } = options;
|
|
25773
|
+
const revision = getConversationRevision(database, conversationId);
|
|
25774
|
+
const result = await summarizeHistoryAtRevision(options, revision);
|
|
25775
|
+
assertConversationRevision(database, conversationId, revision);
|
|
25776
|
+
return result;
|
|
25777
|
+
}
|
|
25778
|
+
async function summarizeHistoryAtRevision(options, revision) {
|
|
25594
25779
|
const { database, conversationId, messages, summarizeHistory, summaryMinWindowMessages, token } = options;
|
|
25595
25780
|
if (!summarizeHistory) {
|
|
25596
25781
|
return { messagesToConvert: messages, summarySystemMessage: null };
|
|
@@ -25631,7 +25816,7 @@ async function maybeSummarizeHistory(options) {
|
|
|
25631
25816
|
clearTimeout(staleGuardTimerId);
|
|
25632
25817
|
}
|
|
25633
25818
|
}
|
|
25634
|
-
const promise = doSummarizeHistory(options);
|
|
25819
|
+
const promise = doSummarizeHistory(options, revision);
|
|
25635
25820
|
summarizationLocks.set(conversationId, promise);
|
|
25636
25821
|
try {
|
|
25637
25822
|
return await promise;
|
|
@@ -25645,7 +25830,7 @@ Summary to condense:
|
|
|
25645
25830
|
{summary}
|
|
25646
25831
|
|
|
25647
25832
|
Condensed summary:`;
|
|
25648
|
-
async function doSummarizeHistory(options) {
|
|
25833
|
+
async function doSummarizeHistory(options, revision) {
|
|
25649
25834
|
const {
|
|
25650
25835
|
database,
|
|
25651
25836
|
conversationId,
|
|
@@ -25660,7 +25845,20 @@ async function doSummarizeHistory(options) {
|
|
|
25660
25845
|
} = options;
|
|
25661
25846
|
try {
|
|
25662
25847
|
const summaryCtx = createSummaryContext(database);
|
|
25848
|
+
const persistSummary = (summary, summarizedUpTo, tokenCount) => database.write(async (writer) => {
|
|
25849
|
+
assertConversationRevision(database, conversationId, revision);
|
|
25850
|
+
await writer.callWriter(
|
|
25851
|
+
() => upsertConversationSummaryOp(
|
|
25852
|
+
summaryCtx,
|
|
25853
|
+
conversationId,
|
|
25854
|
+
summary,
|
|
25855
|
+
summarizedUpTo,
|
|
25856
|
+
tokenCount
|
|
25857
|
+
)
|
|
25858
|
+
);
|
|
25859
|
+
});
|
|
25663
25860
|
let cachedSummary = await getConversationSummaryOp(summaryCtx, conversationId);
|
|
25861
|
+
assertConversationRevision(database, conversationId, revision);
|
|
25664
25862
|
const lastCompacted = lastCompactionTime.get(conversationId) ?? 0;
|
|
25665
25863
|
const compactionCooledDown = Date.now() - lastCompacted > COMPACTION_COOLDOWN_MS;
|
|
25666
25864
|
if (cachedSummary && cachedSummary.tokenCount > summaryTokenThreshold * MAX_SUMMARY_TOKEN_RATIO && compactionCooledDown) {
|
|
@@ -25676,13 +25874,7 @@ async function doSummarizeHistory(options) {
|
|
|
25676
25874
|
);
|
|
25677
25875
|
const compactedSummary = redactor ? redactor.deAnonymize(rawCompacted) : rawCompacted;
|
|
25678
25876
|
const compactedTokens = estimateTokens(compactedSummary);
|
|
25679
|
-
await
|
|
25680
|
-
summaryCtx,
|
|
25681
|
-
conversationId,
|
|
25682
|
-
compactedSummary,
|
|
25683
|
-
cachedSummary.summarizedUpTo,
|
|
25684
|
-
compactedTokens
|
|
25685
|
-
);
|
|
25877
|
+
await persistSummary(compactedSummary, cachedSummary.summarizedUpTo, compactedTokens);
|
|
25686
25878
|
cachedSummary = {
|
|
25687
25879
|
...cachedSummary,
|
|
25688
25880
|
summary: compactedSummary,
|
|
@@ -25690,6 +25882,7 @@ async function doSummarizeHistory(options) {
|
|
|
25690
25882
|
};
|
|
25691
25883
|
lastCompactionTime.set(conversationId, Date.now());
|
|
25692
25884
|
} catch {
|
|
25885
|
+
assertConversationRevision(database, conversationId, revision);
|
|
25693
25886
|
lastCompactionTime.set(conversationId, Date.now());
|
|
25694
25887
|
getLogger().warn(
|
|
25695
25888
|
"[summarize] Summary compaction failed, proceeding with oversized summary"
|
|
@@ -25721,10 +25914,9 @@ async function doSummarizeHistory(options) {
|
|
|
25721
25914
|
redactor,
|
|
25722
25915
|
onPiiRedacted
|
|
25723
25916
|
});
|
|
25917
|
+
assertConversationRevision(database, conversationId, revision);
|
|
25724
25918
|
if (summarizeResult.didSummarize && summarizeResult.summary && summarizeResult.summarizedUpTo) {
|
|
25725
|
-
await
|
|
25726
|
-
summaryCtx,
|
|
25727
|
-
conversationId,
|
|
25919
|
+
await persistSummary(
|
|
25728
25920
|
summarizeResult.summary,
|
|
25729
25921
|
summarizeResult.summarizedUpTo,
|
|
25730
25922
|
summarizeResult.summaryTokenCount
|
|
@@ -25743,6 +25935,7 @@ async function doSummarizeHistory(options) {
|
|
|
25743
25935
|
summarySystemMessage: summarizeResult.summary ? summaryToSystemMessage(summarizeResult.summary) : null
|
|
25744
25936
|
};
|
|
25745
25937
|
} catch (err) {
|
|
25938
|
+
assertConversationRevision(database, conversationId, revision);
|
|
25746
25939
|
getLogger().warn("[summarize] Summarization failed, falling back to verbatim:", err);
|
|
25747
25940
|
return { messagesToConvert: messages, summarySystemMessage: null };
|
|
25748
25941
|
}
|
|
@@ -25901,141 +26094,6 @@ async function decryptConversationTitle(encryptedTitle, address) {
|
|
|
25901
26094
|
}
|
|
25902
26095
|
}
|
|
25903
26096
|
|
|
25904
|
-
// src/lib/db/chat/models.ts
|
|
25905
|
-
var import_watermelondb4 = __toESM(require_watermelondb());
|
|
25906
|
-
var import_decorators = __toESM(require_decorators());
|
|
25907
|
-
var Message = class extends import_watermelondb4.Model {
|
|
25908
|
-
};
|
|
25909
|
-
Message.table = "history";
|
|
25910
|
-
Message.associations = {
|
|
25911
|
-
conversations: { type: "belongs_to", key: "conversation_id" },
|
|
25912
|
-
media: { type: "has_many", foreignKey: "message_id" }
|
|
25913
|
-
};
|
|
25914
|
-
__decorateClass([
|
|
25915
|
-
(0, import_decorators.field)("message_id")
|
|
25916
|
-
], Message.prototype, "messageId", 2);
|
|
25917
|
-
__decorateClass([
|
|
25918
|
-
(0, import_decorators.text)("conversation_id")
|
|
25919
|
-
], Message.prototype, "conversationId", 2);
|
|
25920
|
-
__decorateClass([
|
|
25921
|
-
(0, import_decorators.text)("role")
|
|
25922
|
-
], Message.prototype, "role", 2);
|
|
25923
|
-
__decorateClass([
|
|
25924
|
-
(0, import_decorators.text)("content")
|
|
25925
|
-
], Message.prototype, "content", 2);
|
|
25926
|
-
__decorateClass([
|
|
25927
|
-
(0, import_decorators.text)("model")
|
|
25928
|
-
], Message.prototype, "model", 2);
|
|
25929
|
-
__decorateClass([
|
|
25930
|
-
(0, import_decorators.text)("image_model")
|
|
25931
|
-
], Message.prototype, "imageModel", 2);
|
|
25932
|
-
__decorateClass([
|
|
25933
|
-
(0, import_decorators.json)("files", (raw) => raw)
|
|
25934
|
-
], Message.prototype, "files", 2);
|
|
25935
|
-
__decorateClass([
|
|
25936
|
-
(0, import_decorators.json)("file_ids", (raw) => raw)
|
|
25937
|
-
], Message.prototype, "fileIds", 2);
|
|
25938
|
-
__decorateClass([
|
|
25939
|
-
(0, import_decorators.date)("created_at")
|
|
25940
|
-
], Message.prototype, "createdAt", 2);
|
|
25941
|
-
__decorateClass([
|
|
25942
|
-
(0, import_decorators.date)("updated_at")
|
|
25943
|
-
], Message.prototype, "updatedAt", 2);
|
|
25944
|
-
__decorateClass([
|
|
25945
|
-
(0, import_decorators.json)("vector", (raw) => raw)
|
|
25946
|
-
], Message.prototype, "vector", 2);
|
|
25947
|
-
__decorateClass([
|
|
25948
|
-
(0, import_decorators.text)("embedding_model")
|
|
25949
|
-
], Message.prototype, "embeddingModel", 2);
|
|
25950
|
-
__decorateClass([
|
|
25951
|
-
(0, import_decorators.json)("chunks", (raw) => raw)
|
|
25952
|
-
], Message.prototype, "chunks", 2);
|
|
25953
|
-
__decorateClass([
|
|
25954
|
-
(0, import_decorators.json)("usage", (raw) => raw)
|
|
25955
|
-
], Message.prototype, "usage", 2);
|
|
25956
|
-
__decorateClass([
|
|
25957
|
-
(0, import_decorators.json)("sources", (raw) => raw)
|
|
25958
|
-
], Message.prototype, "sources", 2);
|
|
25959
|
-
__decorateClass([
|
|
25960
|
-
(0, import_decorators.field)("response_duration")
|
|
25961
|
-
], Message.prototype, "responseDuration", 2);
|
|
25962
|
-
__decorateClass([
|
|
25963
|
-
(0, import_decorators.field)("was_stopped")
|
|
25964
|
-
], Message.prototype, "wasStopped", 2);
|
|
25965
|
-
__decorateClass([
|
|
25966
|
-
(0, import_decorators.text)("error")
|
|
25967
|
-
], Message.prototype, "error", 2);
|
|
25968
|
-
__decorateClass([
|
|
25969
|
-
(0, import_decorators.json)("thought_process", (raw) => raw)
|
|
25970
|
-
], Message.prototype, "thoughtProcess", 2);
|
|
25971
|
-
__decorateClass([
|
|
25972
|
-
(0, import_decorators.text)("thinking")
|
|
25973
|
-
], Message.prototype, "thinking", 2);
|
|
25974
|
-
__decorateClass([
|
|
25975
|
-
(0, import_decorators.text)("parent_message_id")
|
|
25976
|
-
], Message.prototype, "parentMessageId", 2);
|
|
25977
|
-
__decorateClass([
|
|
25978
|
-
(0, import_decorators.text)("feedback")
|
|
25979
|
-
], Message.prototype, "feedback", 2);
|
|
25980
|
-
__decorateClass([
|
|
25981
|
-
(0, import_decorators.json)("tool_call_events", (raw) => raw)
|
|
25982
|
-
], Message.prototype, "toolCallEvents", 2);
|
|
25983
|
-
__decorateClass([
|
|
25984
|
-
(0, import_decorators.text)("origin")
|
|
25985
|
-
], Message.prototype, "origin", 2);
|
|
25986
|
-
var Conversation = class extends import_watermelondb4.Model {
|
|
25987
|
-
};
|
|
25988
|
-
Conversation.table = "conversations";
|
|
25989
|
-
Conversation.associations = {
|
|
25990
|
-
history: { type: "has_many", foreignKey: "conversation_id" },
|
|
25991
|
-
projects: { type: "belongs_to", key: "project_id" }
|
|
25992
|
-
};
|
|
25993
|
-
__decorateClass([
|
|
25994
|
-
(0, import_decorators.text)("conversation_id")
|
|
25995
|
-
], Conversation.prototype, "conversationId", 2);
|
|
25996
|
-
__decorateClass([
|
|
25997
|
-
(0, import_decorators.text)("title")
|
|
25998
|
-
], Conversation.prototype, "title", 2);
|
|
25999
|
-
__decorateClass([
|
|
26000
|
-
(0, import_decorators.text)("project_id")
|
|
26001
|
-
], Conversation.prototype, "projectId", 2);
|
|
26002
|
-
__decorateClass([
|
|
26003
|
-
(0, import_decorators.date)("created_at")
|
|
26004
|
-
], Conversation.prototype, "createdAt", 2);
|
|
26005
|
-
__decorateClass([
|
|
26006
|
-
(0, import_decorators.date)("updated_at")
|
|
26007
|
-
], Conversation.prototype, "updatedAt", 2);
|
|
26008
|
-
__decorateClass([
|
|
26009
|
-
(0, import_decorators.field)("is_deleted")
|
|
26010
|
-
], Conversation.prototype, "isDeleted", 2);
|
|
26011
|
-
__decorateClass([
|
|
26012
|
-
(0, import_decorators.date)("pinned_at")
|
|
26013
|
-
], Conversation.prototype, "pinnedAt", 2);
|
|
26014
|
-
var ConversationSummary = class extends import_watermelondb4.Model {
|
|
26015
|
-
};
|
|
26016
|
-
ConversationSummary.table = "conversation_summaries";
|
|
26017
|
-
ConversationSummary.associations = {
|
|
26018
|
-
conversations: { type: "belongs_to", key: "conversation_id" }
|
|
26019
|
-
};
|
|
26020
|
-
__decorateClass([
|
|
26021
|
-
(0, import_decorators.text)("conversation_id")
|
|
26022
|
-
], ConversationSummary.prototype, "conversationId", 2);
|
|
26023
|
-
__decorateClass([
|
|
26024
|
-
(0, import_decorators.text)("summary")
|
|
26025
|
-
], ConversationSummary.prototype, "summary", 2);
|
|
26026
|
-
__decorateClass([
|
|
26027
|
-
(0, import_decorators.text)("summarized_up_to")
|
|
26028
|
-
], ConversationSummary.prototype, "summarizedUpTo", 2);
|
|
26029
|
-
__decorateClass([
|
|
26030
|
-
(0, import_decorators.field)("token_count")
|
|
26031
|
-
], ConversationSummary.prototype, "tokenCount", 2);
|
|
26032
|
-
__decorateClass([
|
|
26033
|
-
(0, import_decorators.date)("created_at")
|
|
26034
|
-
], ConversationSummary.prototype, "createdAt", 2);
|
|
26035
|
-
__decorateClass([
|
|
26036
|
-
(0, import_decorators.date)("updated_at")
|
|
26037
|
-
], ConversationSummary.prototype, "updatedAt", 2);
|
|
26038
|
-
|
|
26039
26097
|
// src/lib/db/manager.ts
|
|
26040
26098
|
var import_watermelondb16 = __toESM(require_watermelondb());
|
|
26041
26099
|
|
|
@@ -36910,10 +36968,7 @@ async function computeStaleFacetKeys(ctx, memories, facets, previous, watermark,
|
|
|
36910
36968
|
for (const facet of facets) {
|
|
36911
36969
|
if (!previous.sections.some((s) => s.key === facet.key)) stale.add(facet.key);
|
|
36912
36970
|
}
|
|
36913
|
-
|
|
36914
|
-
let toAttribute = changed.filter(
|
|
36915
|
-
(m) => !m.isDeleted && !m.supersededBy && !citedIds.has(m.uniqueId)
|
|
36916
|
-
);
|
|
36971
|
+
let toAttribute = changed.filter((m) => !m.isDeleted && !m.supersededBy);
|
|
36917
36972
|
if (reviewedMemoryIds !== void 0) {
|
|
36918
36973
|
const allowed = new Set(reviewedMemoryIds);
|
|
36919
36974
|
toAttribute = toAttribute.filter((m) => allowed.has(m.uniqueId));
|