@signetai/connector-base 0.236.0 → 0.237.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/dist/agent-dir.js +213 -174
  2. package/dist/index.js +213 -174
  3. package/package.json +2 -2
package/dist/agent-dir.js CHANGED
@@ -10394,99 +10394,6 @@ var execFileHiddenImpl = (...args) => Reflect.apply(nodeExecFile, undefined, wit
10394
10394
  Object.defineProperty(execFileHiddenImpl, promisify.custom, {
10395
10395
  value: (...args) => Reflect.apply(nodeExecFileAsync, undefined, withWindowsHideArgument(args, 1))
10396
10396
  });
10397
- var MEMORY_CONTENT_SAFETY_POLICY_VERSION = "memory-content-safety-v1";
10398
- var MEMORY_CONTENT_SAFETY_REASONS = [
10399
- "prompt_injection",
10400
- "exfiltration",
10401
- "credential_harvesting",
10402
- "malicious_shell",
10403
- "tool_directive",
10404
- "invisible_unicode"
10405
- ];
10406
- var INVISIBLE_UNICODE_RE = /(?:\u034f|[\u00ad\u061c\u070f\u180e\u200b\u200c\u200e\u200f\u202a-\u202e\u2060\u2066-\u2069\u206a-\u206f\ufeff]|[\u{e0000}-\u{e007f}])/u;
10407
- var STRONG_DEFENSIVE_CONTEXT_RE = /\b(?:security\s+(?:guidance|discussion|analysis)|threat\s+model|defensive)\b/i;
10408
- var REPORTING_CONTEXT_RE = /\b(?:example|illustrat\w*|sample|quote|quoted|detector|scanner|classif\w*)\b/i;
10409
- var REPORTING_BEFORE_RE = /\b(?:example|illustrat\w*|sample|quote|quoted|detector|scanner|classif\w*)\b[\s\S]{0,80}\b(?:say\w*|read\w*|show\w*|flag\w*|detect\w*|describ\w*|demonstrat\w*|contain\w*|match\w*|pattern)\b/i;
10410
- var REPORTING_AFTER_RE = /\b(?:detector|scanner|classif\w*|flag\w*|pattern|dangerous|unsafe|malicious|hostile|should|would|must|never|do not|don't|avoid|quoted)\b/i;
10411
- var NEGATED_DIRECTIVE_RE = /\b(?:never|do not|don't|should not|must not|cannot|can't|avoid|prevent|detect|mitigat\w*)\b[\s\S]{0,80}$/i;
10412
- var PROMPT_INJECTION_RES = [
10413
- /\b(?:ignore|disregard|override|forget|bypass)\b[\s\S]{0,100}\b(?:previous|prior|above|earlier|system|developer|assistant|safety|security)?\s*(?:instructions?|rules?|prompt|message)\b/i,
10414
- /\b(?:new|following|these)\s+(?:(?:system|developer|assistant|hidden)\s+)?instructions?\b/i,
10415
- /(?:^|\n)\s*(?:system|developer|instruction|prompt)\s*:/im,
10416
- /<\s*(?:system|developer|assistant|instruction|prompt)\b[^>]*>/i,
10417
- /\b(?:you are now|act as|roleplay as|pretend to be)\b[\s\S]{0,80}\b(?:system|admin|developer|unrestricted|jailbreak|different agent)\b/i
10418
- ];
10419
- var TOOL_DIRECTIVE_RES = [
10420
- /<\s*(?:tool[_-]?call|function[_-]?call|invoke|tool)\b/i,
10421
- /\b(?:assistant|system)\s+to\s*=\s*[a-z0-9_.-]+/i,
10422
- /\b(?:call|invoke|use|run|execute)\s+(?:the\s+)?[a-z0-9_.-]+\s+tool\b/i
10423
- ];
10424
- var EXFILTRATION_RE = /\b(?:reveal|show|print|send|upload|exfiltrat\w*|dump|forward|leak|transmit|export)\b[\s\S]{0,120}(?:\b(?:system\s+prompt|hidden\s+instructions?|secret(?:s)?|credential(?:s)?|password(?:s)?|api\s*keys?|tokens?|private\s+keys?|environment\s+variables?)\b|\.env\b|~\/(?:\.ssh)\/\S+|\/etc\/(?:shadow|passwd)\b)/i;
10425
- var EXFILTRATION_REVERSE = /(?:\b(?:system\s+prompt|hidden\s+instructions?|secret(?:s)?|credential(?:s)?|password(?:s)?|api\s*keys?|tokens?|private\s+keys?|environment\s+variables?)\b|\.env\b|~\/(?:\.ssh)\/\S+|\/etc\/(?:shadow|passwd)\b)[\s\S]{0,120}\b(?:reveal|show|print|send|upload|exfiltrat\w*|dump|forward|leak|transmit|export)\b/i;
10426
- var CREDENTIAL_HARVESTING_RE = /\b(?:enter|paste|provide|share|send|give|submit|type|hand over)\b[\s\S]{0,80}\b(?:password|api\s*key|token|secret|credential|private\s+key)\b/i;
10427
- var DANGEROUS_SHELL_RE = /\b(?:curl|wget)\b[^\n]{0,240}\|\s*(?:ba|z|fi)?sh\b|\brm\s+-rf\s+(?:\/|~|\.ssh)[^\n]{0,240}|\b(?:cat|head|tail)\s+~\/?\.ssh\/(?:id_[a-z]+|authorized_keys)\b|\b(?:printenv|env)\b[^\n]{0,120}\b(?:curl|wget|send|upload|post)\b/i;
10428
- function matchHasDefensiveContext(content, match) {
10429
- if (!match || !match[0])
10430
- return false;
10431
- const start = match.index ?? 0;
10432
- const before = content.slice(Math.max(0, start - 120), start);
10433
- const after = content.slice(start + match[0].length, start + match[0].length + 160);
10434
- return STRONG_DEFENSIVE_CONTEXT_RE.test(match[0]) || NEGATED_DIRECTIVE_RE.test(before) || STRONG_DEFENSIVE_CONTEXT_RE.test(before) || STRONG_DEFENSIVE_CONTEXT_RE.test(after) || REPORTING_BEFORE_RE.test(before) || REPORTING_CONTEXT_RE.test(before) && REPORTING_AFTER_RE.test(after);
10435
- }
10436
- function hasActionableMatch(content, patterns) {
10437
- return patterns.some((pattern) => {
10438
- const flags = pattern.flags.includes("g") ? pattern.flags : `${pattern.flags}g`;
10439
- const searchable = new RegExp(pattern.source, flags);
10440
- let match;
10441
- while ((match = searchable.exec(content)) !== null) {
10442
- if (!matchHasDefensiveContext(content, match))
10443
- return true;
10444
- if (match[0].length === 0)
10445
- searchable.lastIndex += 1;
10446
- }
10447
- return false;
10448
- });
10449
- }
10450
- function hasDangerousShell(content) {
10451
- const searchable = new RegExp(DANGEROUS_SHELL_RE.source, `${DANGEROUS_SHELL_RE.flags}g`);
10452
- let match;
10453
- while ((match = searchable.exec(content)) !== null) {
10454
- if (matchHasDefensiveContext(content, match))
10455
- continue;
10456
- const end = (match.index ?? 0) + match[0].length;
10457
- const after = content.slice(end, end + 160);
10458
- if (!STRONG_DEFENSIVE_CONTEXT_RE.test(after) && !REPORTING_AFTER_RE.test(after))
10459
- return true;
10460
- if (match[0].length === 0)
10461
- searchable.lastIndex += 1;
10462
- }
10463
- return false;
10464
- }
10465
- function scanMemoryContent(content) {
10466
- const raw = typeof content === "string" ? content : String(content ?? "");
10467
- const normalized = raw.normalize("NFKC");
10468
- const reasons = new Set;
10469
- if (INVISIBLE_UNICODE_RE.test(raw))
10470
- reasons.add("invisible_unicode");
10471
- if (hasActionableMatch(normalized, PROMPT_INJECTION_RES))
10472
- reasons.add("prompt_injection");
10473
- if (hasActionableMatch(normalized, TOOL_DIRECTIVE_RES))
10474
- reasons.add("tool_directive");
10475
- if (hasActionableMatch(normalized, [EXFILTRATION_RE, EXFILTRATION_REVERSE]))
10476
- reasons.add("exfiltration");
10477
- if (hasActionableMatch(normalized, [CREDENTIAL_HARVESTING_RE]))
10478
- reasons.add("credential_harvesting");
10479
- if (hasDangerousShell(normalized))
10480
- reasons.add("malicious_shell");
10481
- const orderedReasons = MEMORY_CONTENT_SAFETY_REASONS.filter((reason) => reasons.has(reason));
10482
- const status = orderedReasons.length === 0 ? "clean" : orderedReasons.every((reason) => reason === "invisible_unicode") ? "tainted" : "blocked";
10483
- return {
10484
- status,
10485
- contextEligible: status === "clean",
10486
- reasons: orderedReasons,
10487
- policyVersion: MEMORY_CONTENT_SAFETY_POLICY_VERSION
10488
- };
10489
- }
10490
10397
  var DAEMON_DERIVED_MEMORY_SOURCE_TYPES = [
10491
10398
  "extract",
10492
10399
  "aggregate-recall",
@@ -10609,7 +10516,7 @@ function up4(db) {
10609
10516
  function up5(db) {
10610
10517
  db.exec("DROP TABLE IF EXISTS mcp_invocations");
10611
10518
  }
10612
- var MEMORIES_FTS_TOKENIZER = "unicode61";
10519
+ var MEMORIES_FTS_TOKENIZER = "porter unicode61";
10613
10520
  var FTS_STATE_TABLE = "memories_fts_state";
10614
10521
  function normalizeSql(sql) {
10615
10522
  return sql.replace(/\s+/g, " ").trim().toLowerCase();
@@ -10719,10 +10626,7 @@ function readMemoriesFtsSql(db) {
10719
10626
  function memoriesFtsNeedsTokenizerRepair(sql) {
10720
10627
  if (sql === null)
10721
10628
  return false;
10722
- const normalized = normalizeSql(sql);
10723
- if (normalized.includes("porter unicode61"))
10724
- return true;
10725
- return !normalized.includes(`tokenize='${MEMORIES_FTS_TOKENIZER}'`);
10629
+ return !normalizeSql(sql).includes(`tokenize='${MEMORIES_FTS_TOKENIZER}'`);
10726
10630
  }
10727
10631
  function up6(db) {
10728
10632
  db.exec(`
@@ -14635,38 +14539,6 @@ function up129(db) {
14635
14539
  ON imported_source_lifecycle(agent_id, status, updated_at DESC);
14636
14540
  `);
14637
14541
  }
14638
- function tableExists2(db, table) {
14639
- return db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(table) != null;
14640
- }
14641
- function hasColumn24(db, table, column) {
14642
- return db.prepare(`PRAGMA table_info("${table}")`).all().some((row) => row.name === column);
14643
- }
14644
- function backfill(db, rows, sourceKind, scannedAt) {
14645
- const statement = db.prepare(`INSERT INTO memory_content_safety
14646
- (agent_id, source_kind, source_id, status, context_eligible, reasons_json, policy_version, scanned_at)
14647
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)
14648
- ON CONFLICT(agent_id, source_kind, source_id) DO UPDATE SET
14649
- status = excluded.status,
14650
- context_eligible = excluded.context_eligible,
14651
- reasons_json = excluded.reasons_json,
14652
- policy_version = excluded.policy_version,
14653
- scanned_at = excluded.scanned_at`);
14654
- for (const row of rows) {
14655
- const sourceId = row.source_id?.trim();
14656
- if (!sourceId)
14657
- continue;
14658
- const assessment = scanMemoryContent(row.content ?? "");
14659
- statement.run(row.agent_id?.trim() || "default", sourceKind, sourceId, assessment.status, assessment.contextEligible ? 1 : 0, JSON.stringify(assessment.reasons), MEMORY_CONTENT_SAFETY_POLICY_VERSION, scannedAt);
14660
- }
14661
- }
14662
- function backfillTable(db, params) {
14663
- if (!tableExists2(db, params.table) || !hasColumn24(db, params.table, params.sourceIdColumn) || !hasColumn24(db, params.table, params.contentColumn))
14664
- return;
14665
- const agentColumn = hasColumn24(db, params.table, "agent_id") ? "COALESCE(NULLIF(TRIM(agent_id), ''), 'default')" : "'default'";
14666
- const rows = db.prepare(`SELECT ${agentColumn} AS agent_id, ${params.sourceIdColumn} AS source_id, ${params.contentColumn} AS content
14667
- FROM ${params.table}${params.where ? ` WHERE ${params.where}` : ""}`).all();
14668
- backfill(db, rows, params.sourceKind, params.scannedAt);
14669
- }
14670
14542
  function up130(db) {
14671
14543
  db.exec(`
14672
14544
  CREATE TABLE IF NOT EXISTS memory_content_safety (
@@ -14686,43 +14558,6 @@ function up130(db) {
14686
14558
  CREATE INDEX IF NOT EXISTS idx_memory_content_safety_eligibility
14687
14559
  ON memory_content_safety(agent_id, source_kind, context_eligible);
14688
14560
  `);
14689
- const scannedAt = new Date().toISOString();
14690
- backfillTable(db, {
14691
- table: "memories",
14692
- sourceKind: "memory",
14693
- sourceIdColumn: "id",
14694
- contentColumn: "content",
14695
- scannedAt
14696
- });
14697
- backfillTable(db, {
14698
- table: "memory_artifacts",
14699
- sourceKind: "artifact",
14700
- sourceIdColumn: "source_path",
14701
- contentColumn: "content",
14702
- scannedAt
14703
- });
14704
- backfillTable(db, {
14705
- table: "session_transcripts",
14706
- sourceKind: "transcript",
14707
- sourceIdColumn: "session_key",
14708
- contentColumn: "content",
14709
- scannedAt
14710
- });
14711
- backfillTable(db, {
14712
- table: "session_summaries",
14713
- sourceKind: "summary",
14714
- sourceIdColumn: "id",
14715
- contentColumn: "content",
14716
- scannedAt
14717
- });
14718
- backfillTable(db, {
14719
- table: "embeddings",
14720
- sourceKind: "source_chunk",
14721
- sourceIdColumn: "id",
14722
- contentColumn: "chunk_text",
14723
- where: "source_type IN ('source_chunk', 'source_obsidian_chunk')",
14724
- scannedAt
14725
- });
14726
14561
  }
14727
14562
  function up131(db) {
14728
14563
  const table = db.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'dreaming_attention'").get();
@@ -14826,13 +14661,13 @@ function up133(db) {
14826
14661
  AND error IS NOT NULL;
14827
14662
  `);
14828
14663
  }
14829
- function tableExists3(db, table) {
14664
+ function tableExists2(db, table) {
14830
14665
  return db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(table) != null;
14831
14666
  }
14832
14667
  function up134(db) {
14833
- if (!tableExists3(db, "memory_jobs"))
14668
+ if (!tableExists2(db, "memory_jobs"))
14834
14669
  return;
14835
- if (!tableExists3(db, "job_cancellations")) {
14670
+ if (!tableExists2(db, "job_cancellations")) {
14836
14671
  throw new Error("job_cancellations table missing; cannot retire structural jobs without an audit trail");
14837
14672
  }
14838
14673
  db.prepare(`
@@ -15061,12 +14896,12 @@ function up142(db) {
15061
14896
  if (!cols.has(name))
15062
14897
  db.exec(`ALTER TABLE dreaming_passes ADD COLUMN ${name} ${type}`);
15063
14898
  }
15064
- function hasColumn25(db, table, column) {
14899
+ function hasColumn24(db, table, column) {
15065
14900
  const rows = db.prepare(`PRAGMA table_info(${table})`).all();
15066
14901
  return rows.some((row) => row.name === column);
15067
14902
  }
15068
14903
  function addColumnIfMissing28(db, table, column, definition) {
15069
- if (!hasColumn25(db, table, column))
14904
+ if (!hasColumn24(db, table, column))
15070
14905
  db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
15071
14906
  }
15072
14907
  function up143(db) {
@@ -15938,6 +15773,138 @@ function up162(db) {
15938
15773
  END;
15939
15774
  `);
15940
15775
  }
15776
+ function up163(db) {
15777
+ db.exec(`
15778
+ DROP TRIGGER IF EXISTS memory_content_safety_head_freshness_ai;
15779
+ DROP TRIGGER IF EXISTS memory_content_safety_head_freshness_au;
15780
+ DROP INDEX IF EXISTS idx_memory_content_safety_status;
15781
+ DROP INDEX IF EXISTS idx_memory_content_safety_eligibility;
15782
+ DROP TABLE IF EXISTS memory_content_safety;
15783
+ `);
15784
+ }
15785
+ var COLUMNS3 = ["occurred_start", "occurred_end", "valid_from", "valid_until", "time_precision"];
15786
+ function up164(db) {
15787
+ const cols = db.prepare("PRAGMA table_info(entity_attributes)").all();
15788
+ for (const column of COLUMNS3) {
15789
+ if (!cols.some((col) => col.name === column)) {
15790
+ db.exec(`ALTER TABLE entity_attributes ADD COLUMN ${column} TEXT`);
15791
+ }
15792
+ }
15793
+ }
15794
+ function up165(db) {
15795
+ const passColumns = db.prepare("PRAGMA table_info(dreaming_passes)").all();
15796
+ if (!passColumns.some((column) => column.name === "scope_key")) {
15797
+ db.exec("ALTER TABLE dreaming_passes ADD COLUMN scope_key TEXT");
15798
+ }
15799
+ db.exec(`
15800
+ CREATE TABLE IF NOT EXISTS dreaming_history_nodes (
15801
+ agent_id TEXT NOT NULL,
15802
+ scope_key TEXT NOT NULL,
15803
+ level INTEGER NOT NULL,
15804
+ idx INTEGER NOT NULL,
15805
+ pass_id TEXT,
15806
+ text TEXT NOT NULL,
15807
+ tokens_input INTEGER,
15808
+ tokens_output INTEGER,
15809
+ tokens_cache_read INTEGER,
15810
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
15811
+ PRIMARY KEY (agent_id, scope_key, level, idx)
15812
+ );
15813
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_dreaming_history_nodes_pass
15814
+ ON dreaming_history_nodes(pass_id) WHERE pass_id IS NOT NULL;
15815
+ `);
15816
+ }
15817
+ function up166(db) {
15818
+ const columns = db.prepare("PRAGMA table_info(dreaming_passes)").all();
15819
+ if (!columns.some((column) => column.name === "tokens_peak_context")) {
15820
+ db.exec("ALTER TABLE dreaming_passes ADD COLUMN tokens_peak_context INTEGER");
15821
+ }
15822
+ }
15823
+ function up167(db) {
15824
+ const sql = readMemoriesFtsSql(db);
15825
+ if (sql !== null && !memoriesFtsNeedsTokenizerRepair(sql))
15826
+ return;
15827
+ recreateMemoriesFts(db);
15828
+ }
15829
+ function hasTable5(db, table) {
15830
+ return db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(table) != null;
15831
+ }
15832
+ function hasColumn25(db, table, column) {
15833
+ return db.prepare(`PRAGMA table_info(${table})`).all().some((row) => row.name === column);
15834
+ }
15835
+ function up168(db) {
15836
+ if (!hasTable5(db, "entity_attributes") || !hasTable5(db, "entity_aspects") || !hasTable5(db, "entities") || !hasColumn25(db, "entity_attributes", "source_root") || !hasColumn25(db, "entities", "source_root")) {
15837
+ return;
15838
+ }
15839
+ const now = new Date().toISOString();
15840
+ db.exec(`
15841
+ CREATE TEMP TABLE retired_source_paragraphs AS
15842
+ SELECT attr.id, attr.memory_id, attr.agent_id, asp.entity_id
15843
+ FROM entity_attributes attr
15844
+ JOIN entity_aspects asp ON asp.id = attr.aspect_id
15845
+ JOIN entities e ON e.id = asp.entity_id
15846
+ WHERE e.entity_type IN ('source_document', 'source_document_reference')
15847
+ AND attr.source_root IS NOT NULL
15848
+ AND attr.source_root = e.source_root
15849
+ AND attr.source_id = e.source_id
15850
+ AND attr.source_root NOT IN ('dreaming', 'dreaming_attention')
15851
+ `);
15852
+ if (hasColumn25(db, "entity_attributes", "memory_id") && hasTable5(db, "memories")) {
15853
+ if (hasTable5(db, "memory_history")) {
15854
+ db.prepare(`INSERT INTO memory_history (id, memory_id, event, old_content, new_content, changed_by, reason, metadata, created_at)
15855
+ SELECT lower(hex(randomblob(16))), mem.id, 'deleted', mem.content, NULL, 'migration:168',
15856
+ 'Source paragraph claims retired', '{"force":true}', ?
15857
+ FROM memories mem
15858
+ JOIN retired_source_paragraphs retired ON retired.memory_id = mem.id
15859
+ WHERE mem.is_deleted = 0`).run(now);
15860
+ }
15861
+ if (hasTable5(db, "derived_memory_sources") && hasColumn25(db, "memories", "stale_at")) {
15862
+ db.prepare(`UPDATE memories
15863
+ SET stale_at = ?
15864
+ WHERE stale_at IS NULL
15865
+ AND is_deleted = 0
15866
+ AND id IN (
15867
+ SELECT dms.derived_memory_id
15868
+ FROM derived_memory_sources dms
15869
+ JOIN retired_source_paragraphs retired ON retired.agent_id = dms.agent_id
15870
+ WHERE (dms.source_kind = 'memory' AND dms.source_id = retired.memory_id)
15871
+ OR (dms.source_kind = 'ontology_claim' AND dms.source_id = retired.id)
15872
+ )`).run(now);
15873
+ }
15874
+ const forget = [
15875
+ "is_deleted = 1",
15876
+ ...["deleted_at", "updated_at"].filter((column) => hasColumn25(db, "memories", column)).map((column) => `${column} = $now`),
15877
+ ...hasColumn25(db, "memories", "updated_by") ? ["updated_by = 'migration:168'"] : [],
15878
+ ...hasColumn25(db, "memories", "version") ? ["version = version + 1"] : []
15879
+ ];
15880
+ db.prepare(`UPDATE memories
15881
+ SET ${forget.join(", ")}
15882
+ WHERE is_deleted = 0
15883
+ AND id IN (SELECT memory_id FROM retired_source_paragraphs WHERE memory_id IS NOT NULL)`).run({ $now: now });
15884
+ if (hasTable5(db, "memory_entity_mentions")) {
15885
+ db.exec(`
15886
+ DELETE FROM memory_entity_mentions
15887
+ WHERE memory_id IN (SELECT memory_id FROM retired_source_paragraphs WHERE memory_id IS NOT NULL)
15888
+ `);
15889
+ }
15890
+ }
15891
+ if (hasTable5(db, "ontology_contradictions")) {
15892
+ db.prepare(`UPDATE ontology_contradictions
15893
+ SET status = 'resolved', resolved_at = ?, resolution_reason = 'source paragraph claims retired', updated_at = ?
15894
+ WHERE status = 'active'
15895
+ AND (left_attribute_id IN (SELECT id FROM retired_source_paragraphs)
15896
+ OR right_attribute_id IN (SELECT id FROM retired_source_paragraphs))`).run(now, now);
15897
+ }
15898
+ db.exec(`
15899
+ DELETE FROM entity_attributes WHERE id IN (SELECT id FROM retired_source_paragraphs);
15900
+ DELETE FROM entity_aspects
15901
+ WHERE entity_id IN (
15902
+ SELECT id FROM entities WHERE entity_type IN ('source_document', 'source_document_reference')
15903
+ )
15904
+ AND NOT EXISTS (SELECT 1 FROM entity_attributes attr WHERE attr.aspect_id = entity_aspects.id);
15905
+ DROP TABLE retired_source_paragraphs;
15906
+ `);
15907
+ }
15941
15908
  var MIGRATIONS = [
15942
15909
  {
15943
15910
  version: 1,
@@ -16947,8 +16914,7 @@ var MIGRATIONS = [
16947
16914
  {
16948
16915
  version: 125,
16949
16916
  name: "memory-content-safety",
16950
- up: up130,
16951
- artifacts: { tables: ["memory_content_safety"] }
16917
+ up: up130
16952
16918
  },
16953
16919
  {
16954
16920
  version: 126,
@@ -17250,6 +17216,48 @@ var MIGRATIONS = [
17250
17216
  name: "generic-entity-prune-scan-generation",
17251
17217
  up: up162,
17252
17218
  artifacts: { tables: ["generic_entity_prune_scan_state"] }
17219
+ },
17220
+ {
17221
+ version: 163,
17222
+ name: "retire-memory-content-safety",
17223
+ up: up163
17224
+ },
17225
+ {
17226
+ version: 164,
17227
+ name: "claim-event-time",
17228
+ up: up164,
17229
+ artifacts: {
17230
+ columns: ["occurred_start", "occurred_end", "valid_from", "valid_until", "time_precision"].map((column) => ({
17231
+ table: "entity_attributes",
17232
+ column
17233
+ }))
17234
+ }
17235
+ },
17236
+ {
17237
+ version: 165,
17238
+ name: "dreaming-history",
17239
+ up: up165,
17240
+ artifacts: {
17241
+ tables: ["dreaming_history_nodes"],
17242
+ indexes: ["idx_dreaming_history_nodes_pass"],
17243
+ columns: [{ table: "dreaming_passes", column: "scope_key" }]
17244
+ }
17245
+ },
17246
+ {
17247
+ version: 166,
17248
+ name: "dreaming-pass-peak-context",
17249
+ up: up166,
17250
+ artifacts: { columns: [{ table: "dreaming_passes", column: "tokens_peak_context" }] }
17251
+ },
17252
+ {
17253
+ version: 167,
17254
+ name: "memories-fts-porter",
17255
+ up: up167
17256
+ },
17257
+ {
17258
+ version: 168,
17259
+ name: "retire-source-paragraph-claims",
17260
+ up: up168
17253
17261
  }
17254
17262
  ];
17255
17263
  var LATEST_SCHEMA_VERSION = MIGRATIONS[MIGRATIONS.length - 1]?.version ?? 0;
@@ -17491,6 +17499,37 @@ var PIPELINE_PROVIDER_CHOICES = [
17491
17499
  var SYNTHESIS_PROVIDER_CHOICES = PIPELINE_PROVIDER_CHOICES.filter((provider) => provider !== "command");
17492
17500
  var PIPELINE_PROVIDER_SET = new Set(PIPELINE_PROVIDER_CHOICES);
17493
17501
  var SYNTHESIS_PROVIDER_SET = new Set(SYNTHESIS_PROVIDER_CHOICES);
17502
+ var SECRET_NAMES = "(?:access[_-]?token|api[_-]?key|apikey|auth[_-]?token|client[_-]?secret|passw(?:or)?d|refresh[_-]?token|private[_-]?key|secret(?:[_-]?key)?|token)";
17503
+ var SECRET_VALUE = `(?=[^\\s"',;&<>()\\[\\]{}$]*\\d)[^\\s"',;&<>()\\[\\]{}$]{8,}`;
17504
+ var PATTERNS = [
17505
+ {
17506
+ kind: "private_key",
17507
+ pattern: /-----BEGIN (?:[A-Z]+ )*PRIVATE KEY-----[\s\S]*?-----END (?:[A-Z]+ )*PRIVATE KEY-----/g
17508
+ },
17509
+ {
17510
+ kind: "provider_key",
17511
+ pattern: /\b(?:(?:AKIA|ASIA)[0-9A-Z]{16}|github_pat_[A-Za-z0-9_]{20,}|gh[pousr]_[A-Za-z0-9]{20,}|sk-(?:ant-|proj-)?[A-Za-z0-9_-]{20,}|(?:sk|rk)_(?:live|test)_[0-9A-Za-z]{16,}|xox[abprs]-[A-Za-z0-9-]{10,}|AIza[0-9A-Za-z_-]{35}|glpat-[A-Za-z0-9_-]{20,}|npm_[A-Za-z0-9]{36})\b/g
17512
+ },
17513
+ {
17514
+ kind: "jwt",
17515
+ pattern: /\beyJ[A-Za-z0-9_-]{8,}\.eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}/g
17516
+ },
17517
+ {
17518
+ kind: "bearer_token",
17519
+ pattern: /\bBearer\s+([A-Za-z0-9._~+/-]{16,}=*)/g,
17520
+ valueGroup: 1
17521
+ },
17522
+ {
17523
+ kind: "secret_assignment",
17524
+ pattern: new RegExp(`\\b${SECRET_NAMES}["']?\\s*[:=]\\s*["']?(${SECRET_VALUE})`, "gi"),
17525
+ valueGroup: 1
17526
+ },
17527
+ {
17528
+ kind: "secret_assignment",
17529
+ pattern: new RegExp(`\\b[A-Z][A-Z0-9_]*(?:API_KEY|TOKEN|SECRET|PASSWORD)\\s*=\\s*["']?(${SECRET_VALUE})`, "g"),
17530
+ valueGroup: 1
17531
+ }
17532
+ ];
17494
17533
  var LOOPBACK_HOST = "127.0.0.1";
17495
17534
  function normalizeLoopbackHost(host) {
17496
17535
  const normalized = host.trim().toLowerCase().replace(/^\[|\]$/g, "");
package/dist/index.js CHANGED
@@ -10395,99 +10395,6 @@ var execFileHiddenImpl = (...args) => Reflect.apply(nodeExecFile, undefined, wit
10395
10395
  Object.defineProperty(execFileHiddenImpl, promisify.custom, {
10396
10396
  value: (...args) => Reflect.apply(nodeExecFileAsync, undefined, withWindowsHideArgument(args, 1))
10397
10397
  });
10398
- var MEMORY_CONTENT_SAFETY_POLICY_VERSION = "memory-content-safety-v1";
10399
- var MEMORY_CONTENT_SAFETY_REASONS = [
10400
- "prompt_injection",
10401
- "exfiltration",
10402
- "credential_harvesting",
10403
- "malicious_shell",
10404
- "tool_directive",
10405
- "invisible_unicode"
10406
- ];
10407
- var INVISIBLE_UNICODE_RE = /(?:\u034f|[\u00ad\u061c\u070f\u180e\u200b\u200c\u200e\u200f\u202a-\u202e\u2060\u2066-\u2069\u206a-\u206f\ufeff]|[\u{e0000}-\u{e007f}])/u;
10408
- var STRONG_DEFENSIVE_CONTEXT_RE = /\b(?:security\s+(?:guidance|discussion|analysis)|threat\s+model|defensive)\b/i;
10409
- var REPORTING_CONTEXT_RE = /\b(?:example|illustrat\w*|sample|quote|quoted|detector|scanner|classif\w*)\b/i;
10410
- var REPORTING_BEFORE_RE = /\b(?:example|illustrat\w*|sample|quote|quoted|detector|scanner|classif\w*)\b[\s\S]{0,80}\b(?:say\w*|read\w*|show\w*|flag\w*|detect\w*|describ\w*|demonstrat\w*|contain\w*|match\w*|pattern)\b/i;
10411
- var REPORTING_AFTER_RE = /\b(?:detector|scanner|classif\w*|flag\w*|pattern|dangerous|unsafe|malicious|hostile|should|would|must|never|do not|don't|avoid|quoted)\b/i;
10412
- var NEGATED_DIRECTIVE_RE = /\b(?:never|do not|don't|should not|must not|cannot|can't|avoid|prevent|detect|mitigat\w*)\b[\s\S]{0,80}$/i;
10413
- var PROMPT_INJECTION_RES = [
10414
- /\b(?:ignore|disregard|override|forget|bypass)\b[\s\S]{0,100}\b(?:previous|prior|above|earlier|system|developer|assistant|safety|security)?\s*(?:instructions?|rules?|prompt|message)\b/i,
10415
- /\b(?:new|following|these)\s+(?:(?:system|developer|assistant|hidden)\s+)?instructions?\b/i,
10416
- /(?:^|\n)\s*(?:system|developer|instruction|prompt)\s*:/im,
10417
- /<\s*(?:system|developer|assistant|instruction|prompt)\b[^>]*>/i,
10418
- /\b(?:you are now|act as|roleplay as|pretend to be)\b[\s\S]{0,80}\b(?:system|admin|developer|unrestricted|jailbreak|different agent)\b/i
10419
- ];
10420
- var TOOL_DIRECTIVE_RES = [
10421
- /<\s*(?:tool[_-]?call|function[_-]?call|invoke|tool)\b/i,
10422
- /\b(?:assistant|system)\s+to\s*=\s*[a-z0-9_.-]+/i,
10423
- /\b(?:call|invoke|use|run|execute)\s+(?:the\s+)?[a-z0-9_.-]+\s+tool\b/i
10424
- ];
10425
- var EXFILTRATION_RE = /\b(?:reveal|show|print|send|upload|exfiltrat\w*|dump|forward|leak|transmit|export)\b[\s\S]{0,120}(?:\b(?:system\s+prompt|hidden\s+instructions?|secret(?:s)?|credential(?:s)?|password(?:s)?|api\s*keys?|tokens?|private\s+keys?|environment\s+variables?)\b|\.env\b|~\/(?:\.ssh)\/\S+|\/etc\/(?:shadow|passwd)\b)/i;
10426
- var EXFILTRATION_REVERSE = /(?:\b(?:system\s+prompt|hidden\s+instructions?|secret(?:s)?|credential(?:s)?|password(?:s)?|api\s*keys?|tokens?|private\s+keys?|environment\s+variables?)\b|\.env\b|~\/(?:\.ssh)\/\S+|\/etc\/(?:shadow|passwd)\b)[\s\S]{0,120}\b(?:reveal|show|print|send|upload|exfiltrat\w*|dump|forward|leak|transmit|export)\b/i;
10427
- var CREDENTIAL_HARVESTING_RE = /\b(?:enter|paste|provide|share|send|give|submit|type|hand over)\b[\s\S]{0,80}\b(?:password|api\s*key|token|secret|credential|private\s+key)\b/i;
10428
- var DANGEROUS_SHELL_RE = /\b(?:curl|wget)\b[^\n]{0,240}\|\s*(?:ba|z|fi)?sh\b|\brm\s+-rf\s+(?:\/|~|\.ssh)[^\n]{0,240}|\b(?:cat|head|tail)\s+~\/?\.ssh\/(?:id_[a-z]+|authorized_keys)\b|\b(?:printenv|env)\b[^\n]{0,120}\b(?:curl|wget|send|upload|post)\b/i;
10429
- function matchHasDefensiveContext(content, match) {
10430
- if (!match || !match[0])
10431
- return false;
10432
- const start = match.index ?? 0;
10433
- const before = content.slice(Math.max(0, start - 120), start);
10434
- const after = content.slice(start + match[0].length, start + match[0].length + 160);
10435
- return STRONG_DEFENSIVE_CONTEXT_RE.test(match[0]) || NEGATED_DIRECTIVE_RE.test(before) || STRONG_DEFENSIVE_CONTEXT_RE.test(before) || STRONG_DEFENSIVE_CONTEXT_RE.test(after) || REPORTING_BEFORE_RE.test(before) || REPORTING_CONTEXT_RE.test(before) && REPORTING_AFTER_RE.test(after);
10436
- }
10437
- function hasActionableMatch(content, patterns) {
10438
- return patterns.some((pattern) => {
10439
- const flags = pattern.flags.includes("g") ? pattern.flags : `${pattern.flags}g`;
10440
- const searchable = new RegExp(pattern.source, flags);
10441
- let match;
10442
- while ((match = searchable.exec(content)) !== null) {
10443
- if (!matchHasDefensiveContext(content, match))
10444
- return true;
10445
- if (match[0].length === 0)
10446
- searchable.lastIndex += 1;
10447
- }
10448
- return false;
10449
- });
10450
- }
10451
- function hasDangerousShell(content) {
10452
- const searchable = new RegExp(DANGEROUS_SHELL_RE.source, `${DANGEROUS_SHELL_RE.flags}g`);
10453
- let match;
10454
- while ((match = searchable.exec(content)) !== null) {
10455
- if (matchHasDefensiveContext(content, match))
10456
- continue;
10457
- const end = (match.index ?? 0) + match[0].length;
10458
- const after = content.slice(end, end + 160);
10459
- if (!STRONG_DEFENSIVE_CONTEXT_RE.test(after) && !REPORTING_AFTER_RE.test(after))
10460
- return true;
10461
- if (match[0].length === 0)
10462
- searchable.lastIndex += 1;
10463
- }
10464
- return false;
10465
- }
10466
- function scanMemoryContent(content) {
10467
- const raw = typeof content === "string" ? content : String(content ?? "");
10468
- const normalized = raw.normalize("NFKC");
10469
- const reasons = new Set;
10470
- if (INVISIBLE_UNICODE_RE.test(raw))
10471
- reasons.add("invisible_unicode");
10472
- if (hasActionableMatch(normalized, PROMPT_INJECTION_RES))
10473
- reasons.add("prompt_injection");
10474
- if (hasActionableMatch(normalized, TOOL_DIRECTIVE_RES))
10475
- reasons.add("tool_directive");
10476
- if (hasActionableMatch(normalized, [EXFILTRATION_RE, EXFILTRATION_REVERSE]))
10477
- reasons.add("exfiltration");
10478
- if (hasActionableMatch(normalized, [CREDENTIAL_HARVESTING_RE]))
10479
- reasons.add("credential_harvesting");
10480
- if (hasDangerousShell(normalized))
10481
- reasons.add("malicious_shell");
10482
- const orderedReasons = MEMORY_CONTENT_SAFETY_REASONS.filter((reason) => reasons.has(reason));
10483
- const status = orderedReasons.length === 0 ? "clean" : orderedReasons.every((reason) => reason === "invisible_unicode") ? "tainted" : "blocked";
10484
- return {
10485
- status,
10486
- contextEligible: status === "clean",
10487
- reasons: orderedReasons,
10488
- policyVersion: MEMORY_CONTENT_SAFETY_POLICY_VERSION
10489
- };
10490
- }
10491
10398
  var DAEMON_DERIVED_MEMORY_SOURCE_TYPES = [
10492
10399
  "extract",
10493
10400
  "aggregate-recall",
@@ -10610,7 +10517,7 @@ function up4(db) {
10610
10517
  function up5(db) {
10611
10518
  db.exec("DROP TABLE IF EXISTS mcp_invocations");
10612
10519
  }
10613
- var MEMORIES_FTS_TOKENIZER = "unicode61";
10520
+ var MEMORIES_FTS_TOKENIZER = "porter unicode61";
10614
10521
  var FTS_STATE_TABLE = "memories_fts_state";
10615
10522
  function normalizeSql(sql) {
10616
10523
  return sql.replace(/\s+/g, " ").trim().toLowerCase();
@@ -10720,10 +10627,7 @@ function readMemoriesFtsSql(db) {
10720
10627
  function memoriesFtsNeedsTokenizerRepair(sql) {
10721
10628
  if (sql === null)
10722
10629
  return false;
10723
- const normalized = normalizeSql(sql);
10724
- if (normalized.includes("porter unicode61"))
10725
- return true;
10726
- return !normalized.includes(`tokenize='${MEMORIES_FTS_TOKENIZER}'`);
10630
+ return !normalizeSql(sql).includes(`tokenize='${MEMORIES_FTS_TOKENIZER}'`);
10727
10631
  }
10728
10632
  function up6(db) {
10729
10633
  db.exec(`
@@ -14636,38 +14540,6 @@ function up129(db) {
14636
14540
  ON imported_source_lifecycle(agent_id, status, updated_at DESC);
14637
14541
  `);
14638
14542
  }
14639
- function tableExists2(db, table) {
14640
- return db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(table) != null;
14641
- }
14642
- function hasColumn24(db, table, column) {
14643
- return db.prepare(`PRAGMA table_info("${table}")`).all().some((row) => row.name === column);
14644
- }
14645
- function backfill(db, rows, sourceKind, scannedAt) {
14646
- const statement = db.prepare(`INSERT INTO memory_content_safety
14647
- (agent_id, source_kind, source_id, status, context_eligible, reasons_json, policy_version, scanned_at)
14648
- VALUES (?, ?, ?, ?, ?, ?, ?, ?)
14649
- ON CONFLICT(agent_id, source_kind, source_id) DO UPDATE SET
14650
- status = excluded.status,
14651
- context_eligible = excluded.context_eligible,
14652
- reasons_json = excluded.reasons_json,
14653
- policy_version = excluded.policy_version,
14654
- scanned_at = excluded.scanned_at`);
14655
- for (const row of rows) {
14656
- const sourceId = row.source_id?.trim();
14657
- if (!sourceId)
14658
- continue;
14659
- const assessment = scanMemoryContent(row.content ?? "");
14660
- statement.run(row.agent_id?.trim() || "default", sourceKind, sourceId, assessment.status, assessment.contextEligible ? 1 : 0, JSON.stringify(assessment.reasons), MEMORY_CONTENT_SAFETY_POLICY_VERSION, scannedAt);
14661
- }
14662
- }
14663
- function backfillTable(db, params) {
14664
- if (!tableExists2(db, params.table) || !hasColumn24(db, params.table, params.sourceIdColumn) || !hasColumn24(db, params.table, params.contentColumn))
14665
- return;
14666
- const agentColumn = hasColumn24(db, params.table, "agent_id") ? "COALESCE(NULLIF(TRIM(agent_id), ''), 'default')" : "'default'";
14667
- const rows = db.prepare(`SELECT ${agentColumn} AS agent_id, ${params.sourceIdColumn} AS source_id, ${params.contentColumn} AS content
14668
- FROM ${params.table}${params.where ? ` WHERE ${params.where}` : ""}`).all();
14669
- backfill(db, rows, params.sourceKind, params.scannedAt);
14670
- }
14671
14543
  function up130(db) {
14672
14544
  db.exec(`
14673
14545
  CREATE TABLE IF NOT EXISTS memory_content_safety (
@@ -14687,43 +14559,6 @@ function up130(db) {
14687
14559
  CREATE INDEX IF NOT EXISTS idx_memory_content_safety_eligibility
14688
14560
  ON memory_content_safety(agent_id, source_kind, context_eligible);
14689
14561
  `);
14690
- const scannedAt = new Date().toISOString();
14691
- backfillTable(db, {
14692
- table: "memories",
14693
- sourceKind: "memory",
14694
- sourceIdColumn: "id",
14695
- contentColumn: "content",
14696
- scannedAt
14697
- });
14698
- backfillTable(db, {
14699
- table: "memory_artifacts",
14700
- sourceKind: "artifact",
14701
- sourceIdColumn: "source_path",
14702
- contentColumn: "content",
14703
- scannedAt
14704
- });
14705
- backfillTable(db, {
14706
- table: "session_transcripts",
14707
- sourceKind: "transcript",
14708
- sourceIdColumn: "session_key",
14709
- contentColumn: "content",
14710
- scannedAt
14711
- });
14712
- backfillTable(db, {
14713
- table: "session_summaries",
14714
- sourceKind: "summary",
14715
- sourceIdColumn: "id",
14716
- contentColumn: "content",
14717
- scannedAt
14718
- });
14719
- backfillTable(db, {
14720
- table: "embeddings",
14721
- sourceKind: "source_chunk",
14722
- sourceIdColumn: "id",
14723
- contentColumn: "chunk_text",
14724
- where: "source_type IN ('source_chunk', 'source_obsidian_chunk')",
14725
- scannedAt
14726
- });
14727
14562
  }
14728
14563
  function up131(db) {
14729
14564
  const table = db.prepare("SELECT sql FROM sqlite_master WHERE type = 'table' AND name = 'dreaming_attention'").get();
@@ -14827,13 +14662,13 @@ function up133(db) {
14827
14662
  AND error IS NOT NULL;
14828
14663
  `);
14829
14664
  }
14830
- function tableExists3(db, table) {
14665
+ function tableExists2(db, table) {
14831
14666
  return db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(table) != null;
14832
14667
  }
14833
14668
  function up134(db) {
14834
- if (!tableExists3(db, "memory_jobs"))
14669
+ if (!tableExists2(db, "memory_jobs"))
14835
14670
  return;
14836
- if (!tableExists3(db, "job_cancellations")) {
14671
+ if (!tableExists2(db, "job_cancellations")) {
14837
14672
  throw new Error("job_cancellations table missing; cannot retire structural jobs without an audit trail");
14838
14673
  }
14839
14674
  db.prepare(`
@@ -15062,12 +14897,12 @@ function up142(db) {
15062
14897
  if (!cols.has(name))
15063
14898
  db.exec(`ALTER TABLE dreaming_passes ADD COLUMN ${name} ${type}`);
15064
14899
  }
15065
- function hasColumn25(db, table, column) {
14900
+ function hasColumn24(db, table, column) {
15066
14901
  const rows = db.prepare(`PRAGMA table_info(${table})`).all();
15067
14902
  return rows.some((row) => row.name === column);
15068
14903
  }
15069
14904
  function addColumnIfMissing28(db, table, column, definition) {
15070
- if (!hasColumn25(db, table, column))
14905
+ if (!hasColumn24(db, table, column))
15071
14906
  db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
15072
14907
  }
15073
14908
  function up143(db) {
@@ -15939,6 +15774,138 @@ function up162(db) {
15939
15774
  END;
15940
15775
  `);
15941
15776
  }
15777
+ function up163(db) {
15778
+ db.exec(`
15779
+ DROP TRIGGER IF EXISTS memory_content_safety_head_freshness_ai;
15780
+ DROP TRIGGER IF EXISTS memory_content_safety_head_freshness_au;
15781
+ DROP INDEX IF EXISTS idx_memory_content_safety_status;
15782
+ DROP INDEX IF EXISTS idx_memory_content_safety_eligibility;
15783
+ DROP TABLE IF EXISTS memory_content_safety;
15784
+ `);
15785
+ }
15786
+ var COLUMNS3 = ["occurred_start", "occurred_end", "valid_from", "valid_until", "time_precision"];
15787
+ function up164(db) {
15788
+ const cols = db.prepare("PRAGMA table_info(entity_attributes)").all();
15789
+ for (const column of COLUMNS3) {
15790
+ if (!cols.some((col) => col.name === column)) {
15791
+ db.exec(`ALTER TABLE entity_attributes ADD COLUMN ${column} TEXT`);
15792
+ }
15793
+ }
15794
+ }
15795
+ function up165(db) {
15796
+ const passColumns = db.prepare("PRAGMA table_info(dreaming_passes)").all();
15797
+ if (!passColumns.some((column) => column.name === "scope_key")) {
15798
+ db.exec("ALTER TABLE dreaming_passes ADD COLUMN scope_key TEXT");
15799
+ }
15800
+ db.exec(`
15801
+ CREATE TABLE IF NOT EXISTS dreaming_history_nodes (
15802
+ agent_id TEXT NOT NULL,
15803
+ scope_key TEXT NOT NULL,
15804
+ level INTEGER NOT NULL,
15805
+ idx INTEGER NOT NULL,
15806
+ pass_id TEXT,
15807
+ text TEXT NOT NULL,
15808
+ tokens_input INTEGER,
15809
+ tokens_output INTEGER,
15810
+ tokens_cache_read INTEGER,
15811
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
15812
+ PRIMARY KEY (agent_id, scope_key, level, idx)
15813
+ );
15814
+ CREATE UNIQUE INDEX IF NOT EXISTS idx_dreaming_history_nodes_pass
15815
+ ON dreaming_history_nodes(pass_id) WHERE pass_id IS NOT NULL;
15816
+ `);
15817
+ }
15818
+ function up166(db) {
15819
+ const columns = db.prepare("PRAGMA table_info(dreaming_passes)").all();
15820
+ if (!columns.some((column) => column.name === "tokens_peak_context")) {
15821
+ db.exec("ALTER TABLE dreaming_passes ADD COLUMN tokens_peak_context INTEGER");
15822
+ }
15823
+ }
15824
+ function up167(db) {
15825
+ const sql = readMemoriesFtsSql(db);
15826
+ if (sql !== null && !memoriesFtsNeedsTokenizerRepair(sql))
15827
+ return;
15828
+ recreateMemoriesFts(db);
15829
+ }
15830
+ function hasTable5(db, table) {
15831
+ return db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(table) != null;
15832
+ }
15833
+ function hasColumn25(db, table, column) {
15834
+ return db.prepare(`PRAGMA table_info(${table})`).all().some((row) => row.name === column);
15835
+ }
15836
+ function up168(db) {
15837
+ if (!hasTable5(db, "entity_attributes") || !hasTable5(db, "entity_aspects") || !hasTable5(db, "entities") || !hasColumn25(db, "entity_attributes", "source_root") || !hasColumn25(db, "entities", "source_root")) {
15838
+ return;
15839
+ }
15840
+ const now = new Date().toISOString();
15841
+ db.exec(`
15842
+ CREATE TEMP TABLE retired_source_paragraphs AS
15843
+ SELECT attr.id, attr.memory_id, attr.agent_id, asp.entity_id
15844
+ FROM entity_attributes attr
15845
+ JOIN entity_aspects asp ON asp.id = attr.aspect_id
15846
+ JOIN entities e ON e.id = asp.entity_id
15847
+ WHERE e.entity_type IN ('source_document', 'source_document_reference')
15848
+ AND attr.source_root IS NOT NULL
15849
+ AND attr.source_root = e.source_root
15850
+ AND attr.source_id = e.source_id
15851
+ AND attr.source_root NOT IN ('dreaming', 'dreaming_attention')
15852
+ `);
15853
+ if (hasColumn25(db, "entity_attributes", "memory_id") && hasTable5(db, "memories")) {
15854
+ if (hasTable5(db, "memory_history")) {
15855
+ db.prepare(`INSERT INTO memory_history (id, memory_id, event, old_content, new_content, changed_by, reason, metadata, created_at)
15856
+ SELECT lower(hex(randomblob(16))), mem.id, 'deleted', mem.content, NULL, 'migration:168',
15857
+ 'Source paragraph claims retired', '{"force":true}', ?
15858
+ FROM memories mem
15859
+ JOIN retired_source_paragraphs retired ON retired.memory_id = mem.id
15860
+ WHERE mem.is_deleted = 0`).run(now);
15861
+ }
15862
+ if (hasTable5(db, "derived_memory_sources") && hasColumn25(db, "memories", "stale_at")) {
15863
+ db.prepare(`UPDATE memories
15864
+ SET stale_at = ?
15865
+ WHERE stale_at IS NULL
15866
+ AND is_deleted = 0
15867
+ AND id IN (
15868
+ SELECT dms.derived_memory_id
15869
+ FROM derived_memory_sources dms
15870
+ JOIN retired_source_paragraphs retired ON retired.agent_id = dms.agent_id
15871
+ WHERE (dms.source_kind = 'memory' AND dms.source_id = retired.memory_id)
15872
+ OR (dms.source_kind = 'ontology_claim' AND dms.source_id = retired.id)
15873
+ )`).run(now);
15874
+ }
15875
+ const forget = [
15876
+ "is_deleted = 1",
15877
+ ...["deleted_at", "updated_at"].filter((column) => hasColumn25(db, "memories", column)).map((column) => `${column} = $now`),
15878
+ ...hasColumn25(db, "memories", "updated_by") ? ["updated_by = 'migration:168'"] : [],
15879
+ ...hasColumn25(db, "memories", "version") ? ["version = version + 1"] : []
15880
+ ];
15881
+ db.prepare(`UPDATE memories
15882
+ SET ${forget.join(", ")}
15883
+ WHERE is_deleted = 0
15884
+ AND id IN (SELECT memory_id FROM retired_source_paragraphs WHERE memory_id IS NOT NULL)`).run({ $now: now });
15885
+ if (hasTable5(db, "memory_entity_mentions")) {
15886
+ db.exec(`
15887
+ DELETE FROM memory_entity_mentions
15888
+ WHERE memory_id IN (SELECT memory_id FROM retired_source_paragraphs WHERE memory_id IS NOT NULL)
15889
+ `);
15890
+ }
15891
+ }
15892
+ if (hasTable5(db, "ontology_contradictions")) {
15893
+ db.prepare(`UPDATE ontology_contradictions
15894
+ SET status = 'resolved', resolved_at = ?, resolution_reason = 'source paragraph claims retired', updated_at = ?
15895
+ WHERE status = 'active'
15896
+ AND (left_attribute_id IN (SELECT id FROM retired_source_paragraphs)
15897
+ OR right_attribute_id IN (SELECT id FROM retired_source_paragraphs))`).run(now, now);
15898
+ }
15899
+ db.exec(`
15900
+ DELETE FROM entity_attributes WHERE id IN (SELECT id FROM retired_source_paragraphs);
15901
+ DELETE FROM entity_aspects
15902
+ WHERE entity_id IN (
15903
+ SELECT id FROM entities WHERE entity_type IN ('source_document', 'source_document_reference')
15904
+ )
15905
+ AND NOT EXISTS (SELECT 1 FROM entity_attributes attr WHERE attr.aspect_id = entity_aspects.id);
15906
+ DROP TABLE retired_source_paragraphs;
15907
+ `);
15908
+ }
15942
15909
  var MIGRATIONS = [
15943
15910
  {
15944
15911
  version: 1,
@@ -16948,8 +16915,7 @@ var MIGRATIONS = [
16948
16915
  {
16949
16916
  version: 125,
16950
16917
  name: "memory-content-safety",
16951
- up: up130,
16952
- artifacts: { tables: ["memory_content_safety"] }
16918
+ up: up130
16953
16919
  },
16954
16920
  {
16955
16921
  version: 126,
@@ -17251,6 +17217,48 @@ var MIGRATIONS = [
17251
17217
  name: "generic-entity-prune-scan-generation",
17252
17218
  up: up162,
17253
17219
  artifacts: { tables: ["generic_entity_prune_scan_state"] }
17220
+ },
17221
+ {
17222
+ version: 163,
17223
+ name: "retire-memory-content-safety",
17224
+ up: up163
17225
+ },
17226
+ {
17227
+ version: 164,
17228
+ name: "claim-event-time",
17229
+ up: up164,
17230
+ artifacts: {
17231
+ columns: ["occurred_start", "occurred_end", "valid_from", "valid_until", "time_precision"].map((column) => ({
17232
+ table: "entity_attributes",
17233
+ column
17234
+ }))
17235
+ }
17236
+ },
17237
+ {
17238
+ version: 165,
17239
+ name: "dreaming-history",
17240
+ up: up165,
17241
+ artifacts: {
17242
+ tables: ["dreaming_history_nodes"],
17243
+ indexes: ["idx_dreaming_history_nodes_pass"],
17244
+ columns: [{ table: "dreaming_passes", column: "scope_key" }]
17245
+ }
17246
+ },
17247
+ {
17248
+ version: 166,
17249
+ name: "dreaming-pass-peak-context",
17250
+ up: up166,
17251
+ artifacts: { columns: [{ table: "dreaming_passes", column: "tokens_peak_context" }] }
17252
+ },
17253
+ {
17254
+ version: 167,
17255
+ name: "memories-fts-porter",
17256
+ up: up167
17257
+ },
17258
+ {
17259
+ version: 168,
17260
+ name: "retire-source-paragraph-claims",
17261
+ up: up168
17254
17262
  }
17255
17263
  ];
17256
17264
  var LATEST_SCHEMA_VERSION = MIGRATIONS[MIGRATIONS.length - 1]?.version ?? 0;
@@ -17492,6 +17500,37 @@ var PIPELINE_PROVIDER_CHOICES = [
17492
17500
  var SYNTHESIS_PROVIDER_CHOICES = PIPELINE_PROVIDER_CHOICES.filter((provider) => provider !== "command");
17493
17501
  var PIPELINE_PROVIDER_SET = new Set(PIPELINE_PROVIDER_CHOICES);
17494
17502
  var SYNTHESIS_PROVIDER_SET = new Set(SYNTHESIS_PROVIDER_CHOICES);
17503
+ var SECRET_NAMES = "(?:access[_-]?token|api[_-]?key|apikey|auth[_-]?token|client[_-]?secret|passw(?:or)?d|refresh[_-]?token|private[_-]?key|secret(?:[_-]?key)?|token)";
17504
+ var SECRET_VALUE = `(?=[^\\s"',;&<>()\\[\\]{}$]*\\d)[^\\s"',;&<>()\\[\\]{}$]{8,}`;
17505
+ var PATTERNS = [
17506
+ {
17507
+ kind: "private_key",
17508
+ pattern: /-----BEGIN (?:[A-Z]+ )*PRIVATE KEY-----[\s\S]*?-----END (?:[A-Z]+ )*PRIVATE KEY-----/g
17509
+ },
17510
+ {
17511
+ kind: "provider_key",
17512
+ pattern: /\b(?:(?:AKIA|ASIA)[0-9A-Z]{16}|github_pat_[A-Za-z0-9_]{20,}|gh[pousr]_[A-Za-z0-9]{20,}|sk-(?:ant-|proj-)?[A-Za-z0-9_-]{20,}|(?:sk|rk)_(?:live|test)_[0-9A-Za-z]{16,}|xox[abprs]-[A-Za-z0-9-]{10,}|AIza[0-9A-Za-z_-]{35}|glpat-[A-Za-z0-9_-]{20,}|npm_[A-Za-z0-9]{36})\b/g
17513
+ },
17514
+ {
17515
+ kind: "jwt",
17516
+ pattern: /\beyJ[A-Za-z0-9_-]{8,}\.eyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}/g
17517
+ },
17518
+ {
17519
+ kind: "bearer_token",
17520
+ pattern: /\bBearer\s+([A-Za-z0-9._~+/-]{16,}=*)/g,
17521
+ valueGroup: 1
17522
+ },
17523
+ {
17524
+ kind: "secret_assignment",
17525
+ pattern: new RegExp(`\\b${SECRET_NAMES}["']?\\s*[:=]\\s*["']?(${SECRET_VALUE})`, "gi"),
17526
+ valueGroup: 1
17527
+ },
17528
+ {
17529
+ kind: "secret_assignment",
17530
+ pattern: new RegExp(`\\b[A-Z][A-Z0-9_]*(?:API_KEY|TOKEN|SECRET|PASSWORD)\\s*=\\s*["']?(${SECRET_VALUE})`, "g"),
17531
+ valueGroup: 1
17532
+ }
17533
+ ];
17495
17534
  var LOOPBACK_HOST = "127.0.0.1";
17496
17535
  function normalizeLoopbackHost(host) {
17497
17536
  const normalized = host.trim().toLowerCase().replace(/^\[|\]$/g, "");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signetai/connector-base",
3
- "version": "0.236.0",
3
+ "version": "0.237.0",
4
4
  "description": "Base class for Signet harness connectors",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -30,7 +30,7 @@
30
30
  "typecheck": "tsc --noEmit"
31
31
  },
32
32
  "dependencies": {
33
- "@signetai/core": "0.236.0",
33
+ "@signetai/core": "0.237.0",
34
34
  "json5": "^2.2.3",
35
35
  "jsonc-parser": "3.3.1"
36
36
  },