@signetai/connector-forge 0.193.0 → 0.193.2

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 (2) hide show
  1. package/dist/index.js +389 -13
  2. package/package.json +3 -3
package/dist/index.js CHANGED
@@ -6931,6 +6931,99 @@ var PIPELINE_PROVIDER_CHOICES = [
6931
6931
  var SYNTHESIS_PROVIDER_CHOICES = PIPELINE_PROVIDER_CHOICES.filter((provider) => provider !== "command");
6932
6932
  var PIPELINE_PROVIDER_SET = new Set(PIPELINE_PROVIDER_CHOICES);
6933
6933
  var SYNTHESIS_PROVIDER_SET = new Set(SYNTHESIS_PROVIDER_CHOICES);
6934
+ var MEMORY_CONTENT_SAFETY_POLICY_VERSION = "memory-content-safety-v1";
6935
+ var MEMORY_CONTENT_SAFETY_REASONS = [
6936
+ "prompt_injection",
6937
+ "exfiltration",
6938
+ "credential_harvesting",
6939
+ "malicious_shell",
6940
+ "tool_directive",
6941
+ "invisible_unicode"
6942
+ ];
6943
+ 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;
6944
+ var STRONG_DEFENSIVE_CONTEXT_RE = /\b(?:security\s+(?:guidance|discussion|analysis)|threat\s+model|defensive)\b/i;
6945
+ var REPORTING_CONTEXT_RE = /\b(?:example|illustrat\w*|sample|quote|quoted|detector|scanner|classif\w*)\b/i;
6946
+ 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;
6947
+ 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;
6948
+ 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;
6949
+ var PROMPT_INJECTION_RES = [
6950
+ /\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,
6951
+ /\b(?:new|following|these)\s+(?:(?:system|developer|assistant|hidden)\s+)?instructions?\b/i,
6952
+ /(?:^|\n)\s*(?:system|developer|instruction|prompt)\s*:/im,
6953
+ /<\s*(?:system|developer|assistant|instruction|prompt)\b[^>]*>/i,
6954
+ /\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
6955
+ ];
6956
+ var TOOL_DIRECTIVE_RES = [
6957
+ /<\s*(?:tool[_-]?call|function[_-]?call|invoke|tool)\b/i,
6958
+ /\b(?:assistant|system)\s+to\s*=\s*[a-z0-9_.-]+/i,
6959
+ /\b(?:call|invoke|use|run|execute)\s+(?:the\s+)?[a-z0-9_.-]+\s+tool\b/i
6960
+ ];
6961
+ 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;
6962
+ 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;
6963
+ 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;
6964
+ 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;
6965
+ function matchHasDefensiveContext(content, match) {
6966
+ if (!match || !match[0])
6967
+ return false;
6968
+ const start = match.index ?? 0;
6969
+ const before = content.slice(Math.max(0, start - 120), start);
6970
+ const after = content.slice(start + match[0].length, start + match[0].length + 160);
6971
+ 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);
6972
+ }
6973
+ function hasActionableMatch(content, patterns) {
6974
+ return patterns.some((pattern) => {
6975
+ const flags = pattern.flags.includes("g") ? pattern.flags : `${pattern.flags}g`;
6976
+ const searchable = new RegExp(pattern.source, flags);
6977
+ let match;
6978
+ while ((match = searchable.exec(content)) !== null) {
6979
+ if (!matchHasDefensiveContext(content, match))
6980
+ return true;
6981
+ if (match[0].length === 0)
6982
+ searchable.lastIndex += 1;
6983
+ }
6984
+ return false;
6985
+ });
6986
+ }
6987
+ function hasDangerousShell(content) {
6988
+ const searchable = new RegExp(DANGEROUS_SHELL_RE.source, `${DANGEROUS_SHELL_RE.flags}g`);
6989
+ let match;
6990
+ while ((match = searchable.exec(content)) !== null) {
6991
+ if (matchHasDefensiveContext(content, match))
6992
+ continue;
6993
+ const end = (match.index ?? 0) + match[0].length;
6994
+ const after = content.slice(end, end + 160);
6995
+ if (!STRONG_DEFENSIVE_CONTEXT_RE.test(after) && !REPORTING_AFTER_RE.test(after))
6996
+ return true;
6997
+ if (match[0].length === 0)
6998
+ searchable.lastIndex += 1;
6999
+ }
7000
+ return false;
7001
+ }
7002
+ function scanMemoryContent(content) {
7003
+ const raw = typeof content === "string" ? content : String(content ?? "");
7004
+ const normalized = raw.normalize("NFKC");
7005
+ const reasons = new Set;
7006
+ if (INVISIBLE_UNICODE_RE.test(raw))
7007
+ reasons.add("invisible_unicode");
7008
+ if (hasActionableMatch(normalized, PROMPT_INJECTION_RES))
7009
+ reasons.add("prompt_injection");
7010
+ if (hasActionableMatch(normalized, TOOL_DIRECTIVE_RES))
7011
+ reasons.add("tool_directive");
7012
+ if (hasActionableMatch(normalized, [EXFILTRATION_RE, EXFILTRATION_REVERSE]))
7013
+ reasons.add("exfiltration");
7014
+ if (hasActionableMatch(normalized, [CREDENTIAL_HARVESTING_RE]))
7015
+ reasons.add("credential_harvesting");
7016
+ if (hasDangerousShell(normalized))
7017
+ reasons.add("malicious_shell");
7018
+ const orderedReasons = MEMORY_CONTENT_SAFETY_REASONS.filter((reason) => reasons.has(reason));
7019
+ const status = orderedReasons.length === 0 ? "clean" : orderedReasons.every((reason) => reason === "invisible_unicode") ? "tainted" : "blocked";
7020
+ return {
7021
+ status,
7022
+ contextEligible: status === "clean",
7023
+ reasons: orderedReasons,
7024
+ policyVersion: MEMORY_CONTENT_SAFETY_POLICY_VERSION
7025
+ };
7026
+ }
6934
7027
  var DAEMON_DERIVED_MEMORY_SOURCE_TYPES = ["extract", "aggregate-recall", "session_end", "checkpoint", "dreaming"];
6935
7028
  var MEMORIES_FTS_TOKENIZER = "unicode61";
6936
7029
  function normalizeSql(sql) {
@@ -10909,6 +11002,95 @@ function up124(db) {
10909
11002
  ON imported_source_lifecycle(agent_id, status, updated_at DESC);
10910
11003
  `);
10911
11004
  }
11005
+ function tableExists2(db, table) {
11006
+ return db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(table) != null;
11007
+ }
11008
+ function hasColumn24(db, table, column) {
11009
+ return db.prepare(`PRAGMA table_info("${table}")`).all().some((row) => row.name === column);
11010
+ }
11011
+ function backfill(db, rows, sourceKind, scannedAt) {
11012
+ const statement = db.prepare(`INSERT INTO memory_content_safety
11013
+ (agent_id, source_kind, source_id, status, context_eligible, reasons_json, policy_version, scanned_at)
11014
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
11015
+ ON CONFLICT(agent_id, source_kind, source_id) DO UPDATE SET
11016
+ status = excluded.status,
11017
+ context_eligible = excluded.context_eligible,
11018
+ reasons_json = excluded.reasons_json,
11019
+ policy_version = excluded.policy_version,
11020
+ scanned_at = excluded.scanned_at`);
11021
+ for (const row of rows) {
11022
+ const sourceId = row.source_id?.trim();
11023
+ if (!sourceId)
11024
+ continue;
11025
+ const assessment = scanMemoryContent(row.content ?? "");
11026
+ 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);
11027
+ }
11028
+ }
11029
+ function backfillTable(db, params) {
11030
+ if (!tableExists2(db, params.table) || !hasColumn24(db, params.table, params.sourceIdColumn) || !hasColumn24(db, params.table, params.contentColumn))
11031
+ return;
11032
+ const agentColumn = hasColumn24(db, params.table, "agent_id") ? "COALESCE(NULLIF(TRIM(agent_id), ''), 'default')" : "'default'";
11033
+ const rows = db.prepare(`SELECT ${agentColumn} AS agent_id, ${params.sourceIdColumn} AS source_id, ${params.contentColumn} AS content
11034
+ FROM ${params.table}${params.where ? ` WHERE ${params.where}` : ""}`).all();
11035
+ backfill(db, rows, params.sourceKind, params.scannedAt);
11036
+ }
11037
+ function up125(db) {
11038
+ db.exec(`
11039
+ CREATE TABLE IF NOT EXISTS memory_content_safety (
11040
+ agent_id TEXT NOT NULL,
11041
+ source_kind TEXT NOT NULL CHECK (source_kind IN ('memory', 'artifact', 'transcript', 'summary', 'source_chunk')),
11042
+ source_id TEXT NOT NULL,
11043
+ status TEXT NOT NULL CHECK (status IN ('clean', 'tainted', 'blocked')),
11044
+ context_eligible INTEGER NOT NULL CHECK (context_eligible IN (0, 1)),
11045
+ reasons_json TEXT NOT NULL DEFAULT '[]',
11046
+ policy_version TEXT NOT NULL,
11047
+ scanned_at TEXT NOT NULL,
11048
+ PRIMARY KEY (agent_id, source_kind, source_id)
11049
+ );
11050
+
11051
+ CREATE INDEX IF NOT EXISTS idx_memory_content_safety_status
11052
+ ON memory_content_safety(agent_id, status, source_kind);
11053
+ CREATE INDEX IF NOT EXISTS idx_memory_content_safety_eligibility
11054
+ ON memory_content_safety(agent_id, source_kind, context_eligible);
11055
+ `);
11056
+ const scannedAt = new Date().toISOString();
11057
+ backfillTable(db, {
11058
+ table: "memories",
11059
+ sourceKind: "memory",
11060
+ sourceIdColumn: "id",
11061
+ contentColumn: "content",
11062
+ scannedAt
11063
+ });
11064
+ backfillTable(db, {
11065
+ table: "memory_artifacts",
11066
+ sourceKind: "artifact",
11067
+ sourceIdColumn: "source_path",
11068
+ contentColumn: "content",
11069
+ scannedAt
11070
+ });
11071
+ backfillTable(db, {
11072
+ table: "session_transcripts",
11073
+ sourceKind: "transcript",
11074
+ sourceIdColumn: "session_key",
11075
+ contentColumn: "content",
11076
+ scannedAt
11077
+ });
11078
+ backfillTable(db, {
11079
+ table: "session_summaries",
11080
+ sourceKind: "summary",
11081
+ sourceIdColumn: "id",
11082
+ contentColumn: "content",
11083
+ scannedAt
11084
+ });
11085
+ backfillTable(db, {
11086
+ table: "embeddings",
11087
+ sourceKind: "source_chunk",
11088
+ sourceIdColumn: "id",
11089
+ contentColumn: "chunk_text",
11090
+ where: "source_type IN ('source_chunk', 'source_obsidian_chunk')",
11091
+ scannedAt
11092
+ });
11093
+ }
10912
11094
  var MIGRATIONS = [
10913
11095
  {
10914
11096
  version: 1,
@@ -11917,6 +12099,12 @@ var MIGRATIONS = [
11917
12099
  artifacts: {
11918
12100
  tables: ["imported_source_lifecycle"]
11919
12101
  }
12102
+ },
12103
+ {
12104
+ version: 125,
12105
+ name: "memory-content-safety",
12106
+ up: up125,
12107
+ artifacts: { tables: ["memory_content_safety"] }
11920
12108
  }
11921
12109
  ];
11922
12110
  var LATEST_SCHEMA_VERSION = MIGRATIONS[MIGRATIONS.length - 1]?.version ?? 0;
@@ -19388,6 +19576,99 @@ var PIPELINE_PROVIDER_CHOICES2 = [
19388
19576
  var SYNTHESIS_PROVIDER_CHOICES2 = PIPELINE_PROVIDER_CHOICES2.filter((provider) => provider !== "command");
19389
19577
  var PIPELINE_PROVIDER_SET2 = new Set(PIPELINE_PROVIDER_CHOICES2);
19390
19578
  var SYNTHESIS_PROVIDER_SET2 = new Set(SYNTHESIS_PROVIDER_CHOICES2);
19579
+ var MEMORY_CONTENT_SAFETY_POLICY_VERSION2 = "memory-content-safety-v1";
19580
+ var MEMORY_CONTENT_SAFETY_REASONS2 = [
19581
+ "prompt_injection",
19582
+ "exfiltration",
19583
+ "credential_harvesting",
19584
+ "malicious_shell",
19585
+ "tool_directive",
19586
+ "invisible_unicode"
19587
+ ];
19588
+ var INVISIBLE_UNICODE_RE2 = /(?:\u034f|[\u00ad\u061c\u070f\u180e\u200b\u200c\u200e\u200f\u202a-\u202e\u2060\u2066-\u2069\u206a-\u206f\ufeff]|[\u{e0000}-\u{e007f}])/u;
19589
+ var STRONG_DEFENSIVE_CONTEXT_RE2 = /\b(?:security\s+(?:guidance|discussion|analysis)|threat\s+model|defensive)\b/i;
19590
+ var REPORTING_CONTEXT_RE2 = /\b(?:example|illustrat\w*|sample|quote|quoted|detector|scanner|classif\w*)\b/i;
19591
+ var REPORTING_BEFORE_RE2 = /\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;
19592
+ var REPORTING_AFTER_RE2 = /\b(?:detector|scanner|classif\w*|flag\w*|pattern|dangerous|unsafe|malicious|hostile|should|would|must|never|do not|don't|avoid|quoted)\b/i;
19593
+ var NEGATED_DIRECTIVE_RE2 = /\b(?:never|do not|don't|should not|must not|cannot|can't|avoid|prevent|detect|mitigat\w*)\b[\s\S]{0,80}$/i;
19594
+ var PROMPT_INJECTION_RES2 = [
19595
+ /\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,
19596
+ /\b(?:new|following|these)\s+(?:(?:system|developer|assistant|hidden)\s+)?instructions?\b/i,
19597
+ /(?:^|\n)\s*(?:system|developer|instruction|prompt)\s*:/im,
19598
+ /<\s*(?:system|developer|assistant|instruction|prompt)\b[^>]*>/i,
19599
+ /\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
19600
+ ];
19601
+ var TOOL_DIRECTIVE_RES2 = [
19602
+ /<\s*(?:tool[_-]?call|function[_-]?call|invoke|tool)\b/i,
19603
+ /\b(?:assistant|system)\s+to\s*=\s*[a-z0-9_.-]+/i,
19604
+ /\b(?:call|invoke|use|run|execute)\s+(?:the\s+)?[a-z0-9_.-]+\s+tool\b/i
19605
+ ];
19606
+ var EXFILTRATION_RE2 = /\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;
19607
+ var EXFILTRATION_REVERSE2 = /(?:\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;
19608
+ var CREDENTIAL_HARVESTING_RE2 = /\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;
19609
+ var DANGEROUS_SHELL_RE2 = /\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;
19610
+ function matchHasDefensiveContext2(content, match) {
19611
+ if (!match || !match[0])
19612
+ return false;
19613
+ const start = match.index ?? 0;
19614
+ const before = content.slice(Math.max(0, start - 120), start);
19615
+ const after = content.slice(start + match[0].length, start + match[0].length + 160);
19616
+ return STRONG_DEFENSIVE_CONTEXT_RE2.test(match[0]) || NEGATED_DIRECTIVE_RE2.test(before) || STRONG_DEFENSIVE_CONTEXT_RE2.test(before) || STRONG_DEFENSIVE_CONTEXT_RE2.test(after) || REPORTING_BEFORE_RE2.test(before) || REPORTING_CONTEXT_RE2.test(before) && REPORTING_AFTER_RE2.test(after);
19617
+ }
19618
+ function hasActionableMatch2(content, patterns) {
19619
+ return patterns.some((pattern) => {
19620
+ const flags = pattern.flags.includes("g") ? pattern.flags : `${pattern.flags}g`;
19621
+ const searchable = new RegExp(pattern.source, flags);
19622
+ let match;
19623
+ while ((match = searchable.exec(content)) !== null) {
19624
+ if (!matchHasDefensiveContext2(content, match))
19625
+ return true;
19626
+ if (match[0].length === 0)
19627
+ searchable.lastIndex += 1;
19628
+ }
19629
+ return false;
19630
+ });
19631
+ }
19632
+ function hasDangerousShell2(content) {
19633
+ const searchable = new RegExp(DANGEROUS_SHELL_RE2.source, `${DANGEROUS_SHELL_RE2.flags}g`);
19634
+ let match;
19635
+ while ((match = searchable.exec(content)) !== null) {
19636
+ if (matchHasDefensiveContext2(content, match))
19637
+ continue;
19638
+ const end = (match.index ?? 0) + match[0].length;
19639
+ const after = content.slice(end, end + 160);
19640
+ if (!STRONG_DEFENSIVE_CONTEXT_RE2.test(after) && !REPORTING_AFTER_RE2.test(after))
19641
+ return true;
19642
+ if (match[0].length === 0)
19643
+ searchable.lastIndex += 1;
19644
+ }
19645
+ return false;
19646
+ }
19647
+ function scanMemoryContent2(content) {
19648
+ const raw = typeof content === "string" ? content : String(content ?? "");
19649
+ const normalized = raw.normalize("NFKC");
19650
+ const reasons = new Set;
19651
+ if (INVISIBLE_UNICODE_RE2.test(raw))
19652
+ reasons.add("invisible_unicode");
19653
+ if (hasActionableMatch2(normalized, PROMPT_INJECTION_RES2))
19654
+ reasons.add("prompt_injection");
19655
+ if (hasActionableMatch2(normalized, TOOL_DIRECTIVE_RES2))
19656
+ reasons.add("tool_directive");
19657
+ if (hasActionableMatch2(normalized, [EXFILTRATION_RE2, EXFILTRATION_REVERSE2]))
19658
+ reasons.add("exfiltration");
19659
+ if (hasActionableMatch2(normalized, [CREDENTIAL_HARVESTING_RE2]))
19660
+ reasons.add("credential_harvesting");
19661
+ if (hasDangerousShell2(normalized))
19662
+ reasons.add("malicious_shell");
19663
+ const orderedReasons = MEMORY_CONTENT_SAFETY_REASONS2.filter((reason) => reasons.has(reason));
19664
+ const status = orderedReasons.length === 0 ? "clean" : orderedReasons.every((reason) => reason === "invisible_unicode") ? "tainted" : "blocked";
19665
+ return {
19666
+ status,
19667
+ contextEligible: status === "clean",
19668
+ reasons: orderedReasons,
19669
+ policyVersion: MEMORY_CONTENT_SAFETY_POLICY_VERSION2
19670
+ };
19671
+ }
19391
19672
  var DAEMON_DERIVED_MEMORY_SOURCE_TYPES2 = ["extract", "aggregate-recall", "session_end", "checkpoint", "dreaming"];
19392
19673
  var MEMORIES_FTS_TOKENIZER2 = "unicode61";
19393
19674
  function normalizeSql2(sql) {
@@ -19439,7 +19720,7 @@ function memoriesFtsNeedsTokenizerRepair2(sql) {
19439
19720
  return true;
19440
19721
  return !normalized.includes(`tokenize='${MEMORIES_FTS_TOKENIZER2}'`);
19441
19722
  }
19442
- function up125(db) {
19723
+ function up126(db) {
19443
19724
  db.exec(`
19444
19725
  CREATE TABLE IF NOT EXISTS schema_migrations (
19445
19726
  version INTEGER PRIMARY KEY,
@@ -19528,12 +19809,12 @@ function up125(db) {
19528
19809
  } catch {}
19529
19810
  createMemoriesFts2(db);
19530
19811
  }
19531
- function hasColumn24(db, table, column) {
19812
+ function hasColumn25(db, table, column) {
19532
19813
  const rows = db.prepare(`PRAGMA table_info(${table})`).all();
19533
19814
  return rows.some((r) => r.name === column);
19534
19815
  }
19535
19816
  function addColumnIfMissing27(db, table, column, definition) {
19536
- if (!hasColumn24(db, table, column)) {
19817
+ if (!hasColumn25(db, table, column)) {
19537
19818
  db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
19538
19819
  }
19539
19820
  }
@@ -19683,12 +19964,12 @@ function up310(db) {
19683
19964
  WHERE content_hash IS NOT NULL AND is_deleted = 0
19684
19965
  `);
19685
19966
  }
19686
- function hasColumn25(db, table, column) {
19967
+ function hasColumn26(db, table, column) {
19687
19968
  const rows = db.prepare(`PRAGMA table_info(${table})`).all();
19688
19969
  return rows.some((r) => r.name === column);
19689
19970
  }
19690
19971
  function addColumnIfMissing32(db, table, column, definition) {
19691
- if (!hasColumn25(db, table, column)) {
19972
+ if (!hasColumn26(db, table, column)) {
19692
19973
  db.exec(`ALTER TABLE ${table} ADD COLUMN ${column} ${definition}`);
19693
19974
  }
19694
19975
  }
@@ -19882,7 +20163,7 @@ function up1110(db) {
19882
20163
  ON session_scores(session_key);
19883
20164
  `);
19884
20165
  }
19885
- function up126(db) {
20166
+ function up127(db) {
19886
20167
  db.exec(`
19887
20168
  CREATE TABLE IF NOT EXISTS scheduled_tasks (
19888
20169
  id TEXT PRIMARY KEY,
@@ -22674,7 +22955,7 @@ function up1032(db) {
22674
22955
  )
22675
22956
  `);
22676
22957
  }
22677
- function tableExists2(db, table) {
22958
+ function tableExists3(db, table) {
22678
22959
  return db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(table) !== undefined;
22679
22960
  }
22680
22961
  function hasColumn162(db, table, column) {
@@ -22696,7 +22977,7 @@ function up1042(db) {
22696
22977
  CREATE INDEX IF NOT EXISTS idx_derived_memory_sources_source
22697
22978
  ON derived_memory_sources(agent_id, source_kind, source_id);
22698
22979
  `);
22699
- if (tableExists2(db, "aggregate_evidence_sources")) {
22980
+ if (tableExists3(db, "aggregate_evidence_sources")) {
22700
22981
  db.exec(`
22701
22982
  INSERT OR IGNORE INTO derived_memory_sources
22702
22983
  (derived_memory_id, source_kind, source_id, source_path, agent_id, created_at)
@@ -22704,7 +22985,7 @@ function up1042(db) {
22704
22985
  FROM aggregate_evidence_sources
22705
22986
  `);
22706
22987
  }
22707
- if (tableExists2(db, "aggregate_memory_sources")) {
22988
+ if (tableExists3(db, "aggregate_memory_sources")) {
22708
22989
  db.exec(`
22709
22990
  INSERT OR IGNORE INTO derived_memory_sources
22710
22991
  (derived_memory_id, source_kind, source_id, source_path, agent_id, created_at)
@@ -22712,10 +22993,10 @@ function up1042(db) {
22712
22993
  FROM aggregate_memory_sources
22713
22994
  `);
22714
22995
  }
22715
- if (tableExists2(db, "memories") && !hasColumn162(db, "memories", "stale_at")) {
22996
+ if (tableExists3(db, "memories") && !hasColumn162(db, "memories", "stale_at")) {
22716
22997
  db.exec("ALTER TABLE memories ADD COLUMN stale_at TEXT");
22717
22998
  }
22718
- if (tableExists2(db, "memories")) {
22999
+ if (tableExists3(db, "memories")) {
22719
23000
  db.exec(`
22720
23001
  CREATE INDEX IF NOT EXISTS idx_memories_stale_derived
22721
23002
  ON memories(agent_id, stale_at)
@@ -23366,11 +23647,100 @@ function up1242(db) {
23366
23647
  ON imported_source_lifecycle(agent_id, status, updated_at DESC);
23367
23648
  `);
23368
23649
  }
23650
+ function tableExists22(db, table) {
23651
+ return db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = ?").get(table) != null;
23652
+ }
23653
+ function hasColumn242(db, table, column) {
23654
+ return db.prepare(`PRAGMA table_info("${table}")`).all().some((row) => row.name === column);
23655
+ }
23656
+ function backfill2(db, rows, sourceKind, scannedAt) {
23657
+ const statement = db.prepare(`INSERT INTO memory_content_safety
23658
+ (agent_id, source_kind, source_id, status, context_eligible, reasons_json, policy_version, scanned_at)
23659
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
23660
+ ON CONFLICT(agent_id, source_kind, source_id) DO UPDATE SET
23661
+ status = excluded.status,
23662
+ context_eligible = excluded.context_eligible,
23663
+ reasons_json = excluded.reasons_json,
23664
+ policy_version = excluded.policy_version,
23665
+ scanned_at = excluded.scanned_at`);
23666
+ for (const row of rows) {
23667
+ const sourceId = row.source_id?.trim();
23668
+ if (!sourceId)
23669
+ continue;
23670
+ const assessment = scanMemoryContent2(row.content ?? "");
23671
+ statement.run(row.agent_id?.trim() || "default", sourceKind, sourceId, assessment.status, assessment.contextEligible ? 1 : 0, JSON.stringify(assessment.reasons), MEMORY_CONTENT_SAFETY_POLICY_VERSION2, scannedAt);
23672
+ }
23673
+ }
23674
+ function backfillTable2(db, params) {
23675
+ if (!tableExists22(db, params.table) || !hasColumn242(db, params.table, params.sourceIdColumn) || !hasColumn242(db, params.table, params.contentColumn))
23676
+ return;
23677
+ const agentColumn = hasColumn242(db, params.table, "agent_id") ? "COALESCE(NULLIF(TRIM(agent_id), ''), 'default')" : "'default'";
23678
+ const rows = db.prepare(`SELECT ${agentColumn} AS agent_id, ${params.sourceIdColumn} AS source_id, ${params.contentColumn} AS content
23679
+ FROM ${params.table}${params.where ? ` WHERE ${params.where}` : ""}`).all();
23680
+ backfill2(db, rows, params.sourceKind, params.scannedAt);
23681
+ }
23682
+ function up1252(db) {
23683
+ db.exec(`
23684
+ CREATE TABLE IF NOT EXISTS memory_content_safety (
23685
+ agent_id TEXT NOT NULL,
23686
+ source_kind TEXT NOT NULL CHECK (source_kind IN ('memory', 'artifact', 'transcript', 'summary', 'source_chunk')),
23687
+ source_id TEXT NOT NULL,
23688
+ status TEXT NOT NULL CHECK (status IN ('clean', 'tainted', 'blocked')),
23689
+ context_eligible INTEGER NOT NULL CHECK (context_eligible IN (0, 1)),
23690
+ reasons_json TEXT NOT NULL DEFAULT '[]',
23691
+ policy_version TEXT NOT NULL,
23692
+ scanned_at TEXT NOT NULL,
23693
+ PRIMARY KEY (agent_id, source_kind, source_id)
23694
+ );
23695
+
23696
+ CREATE INDEX IF NOT EXISTS idx_memory_content_safety_status
23697
+ ON memory_content_safety(agent_id, status, source_kind);
23698
+ CREATE INDEX IF NOT EXISTS idx_memory_content_safety_eligibility
23699
+ ON memory_content_safety(agent_id, source_kind, context_eligible);
23700
+ `);
23701
+ const scannedAt = new Date().toISOString();
23702
+ backfillTable2(db, {
23703
+ table: "memories",
23704
+ sourceKind: "memory",
23705
+ sourceIdColumn: "id",
23706
+ contentColumn: "content",
23707
+ scannedAt
23708
+ });
23709
+ backfillTable2(db, {
23710
+ table: "memory_artifacts",
23711
+ sourceKind: "artifact",
23712
+ sourceIdColumn: "source_path",
23713
+ contentColumn: "content",
23714
+ scannedAt
23715
+ });
23716
+ backfillTable2(db, {
23717
+ table: "session_transcripts",
23718
+ sourceKind: "transcript",
23719
+ sourceIdColumn: "session_key",
23720
+ contentColumn: "content",
23721
+ scannedAt
23722
+ });
23723
+ backfillTable2(db, {
23724
+ table: "session_summaries",
23725
+ sourceKind: "summary",
23726
+ sourceIdColumn: "id",
23727
+ contentColumn: "content",
23728
+ scannedAt
23729
+ });
23730
+ backfillTable2(db, {
23731
+ table: "embeddings",
23732
+ sourceKind: "source_chunk",
23733
+ sourceIdColumn: "id",
23734
+ contentColumn: "chunk_text",
23735
+ where: "source_type IN ('source_chunk', 'source_obsidian_chunk')",
23736
+ scannedAt
23737
+ });
23738
+ }
23369
23739
  var MIGRATIONS2 = [
23370
23740
  {
23371
23741
  version: 1,
23372
23742
  name: "baseline",
23373
- up: up125,
23743
+ up: up126,
23374
23744
  artifacts: { tables: ["memories", "conversations", "embeddings"] }
23375
23745
  },
23376
23746
  {
@@ -23442,7 +23812,7 @@ var MIGRATIONS2 = [
23442
23812
  {
23443
23813
  version: 12,
23444
23814
  name: "scheduled-tasks",
23445
- up: up126,
23815
+ up: up127,
23446
23816
  artifacts: { tables: ["scheduled_tasks", "task_runs"] }
23447
23817
  },
23448
23818
  {
@@ -24374,6 +24744,12 @@ var MIGRATIONS2 = [
24374
24744
  artifacts: {
24375
24745
  tables: ["imported_source_lifecycle"]
24376
24746
  }
24747
+ },
24748
+ {
24749
+ version: 125,
24750
+ name: "memory-content-safety",
24751
+ up: up1252,
24752
+ artifacts: { tables: ["memory_content_safety"] }
24377
24753
  }
24378
24754
  ];
24379
24755
  var LATEST_SCHEMA_VERSION2 = MIGRATIONS2[MIGRATIONS2.length - 1]?.version ?? 0;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@signetai/connector-forge",
3
- "version": "0.193.0",
3
+ "version": "0.193.2",
4
4
  "description": "Signet connector for ForgeCode - installs MCP, identity, and skills integration",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -24,8 +24,8 @@
24
24
  "typecheck": "tsc --noEmit"
25
25
  },
26
26
  "dependencies": {
27
- "@signetai/connector-base": "0.193.0",
28
- "@signetai/core": "0.193.0"
27
+ "@signetai/connector-base": "0.193.2",
28
+ "@signetai/core": "0.193.2"
29
29
  },
30
30
  "devDependencies": {
31
31
  "@types/node": "^22.0.0",