seal-gate 0.3.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 (210) hide show
  1. package/dist/adapters/generic-llm-reviewer.d.ts +39 -0
  2. package/dist/adapters/generic-llm-reviewer.js +118 -0
  3. package/dist/adapters/generic-llm-reviewer.js.map +1 -0
  4. package/dist/adapters/llm-reviewer.d.ts +1 -0
  5. package/dist/adapters/llm-reviewer.js +2 -0
  6. package/dist/adapters/llm-reviewer.js.map +1 -0
  7. package/dist/adapters/minimax-llm-reviewer.d.ts +22 -0
  8. package/dist/adapters/minimax-llm-reviewer.js +126 -0
  9. package/dist/adapters/minimax-llm-reviewer.js.map +1 -0
  10. package/dist/adapters/openai-provider.d.ts +35 -0
  11. package/dist/adapters/openai-provider.js +136 -0
  12. package/dist/adapters/openai-provider.js.map +1 -0
  13. package/dist/cli.d.ts +2 -0
  14. package/dist/cli.js +195 -0
  15. package/dist/cli.js.map +1 -0
  16. package/dist/detectors/artifact-classifier.d.ts +8 -0
  17. package/dist/detectors/artifact-classifier.js +14 -0
  18. package/dist/detectors/artifact-classifier.js.map +1 -0
  19. package/dist/detectors/claim-extractor.d.ts +11 -0
  20. package/dist/detectors/claim-extractor.js +194 -0
  21. package/dist/detectors/claim-extractor.js.map +1 -0
  22. package/dist/detectors/confidence-language-detector.d.ts +19 -0
  23. package/dist/detectors/confidence-language-detector.js +226 -0
  24. package/dist/detectors/confidence-language-detector.js.map +1 -0
  25. package/dist/detectors/contradiction-detector.d.ts +12 -0
  26. package/dist/detectors/contradiction-detector.js +153 -0
  27. package/dist/detectors/contradiction-detector.js.map +1 -0
  28. package/dist/detectors/criteria-coverage-detector.d.ts +20 -0
  29. package/dist/detectors/criteria-coverage-detector.js +79 -0
  30. package/dist/detectors/criteria-coverage-detector.js.map +1 -0
  31. package/dist/detectors/evidence-checker.d.ts +8 -0
  32. package/dist/detectors/evidence-checker.js +89 -0
  33. package/dist/detectors/evidence-checker.js.map +1 -0
  34. package/dist/detectors/evidence-gap-detector.d.ts +9 -0
  35. package/dist/detectors/evidence-gap-detector.js +70 -0
  36. package/dist/detectors/evidence-gap-detector.js.map +1 -0
  37. package/dist/detectors/falsification-detector.d.ts +29 -0
  38. package/dist/detectors/falsification-detector.js +57 -0
  39. package/dist/detectors/falsification-detector.js.map +1 -0
  40. package/dist/detectors/orphan-claim-detector.d.ts +7 -0
  41. package/dist/detectors/orphan-claim-detector.js +53 -0
  42. package/dist/detectors/orphan-claim-detector.js.map +1 -0
  43. package/dist/detectors/risk-classifier.d.ts +13 -0
  44. package/dist/detectors/risk-classifier.js +39 -0
  45. package/dist/detectors/risk-classifier.js.map +1 -0
  46. package/dist/detectors/spec-coverage-detector.d.ts +9 -0
  47. package/dist/detectors/spec-coverage-detector.js +52 -0
  48. package/dist/detectors/spec-coverage-detector.js.map +1 -0
  49. package/dist/detectors/spec-coverage-validator.d.ts +21 -0
  50. package/dist/detectors/spec-coverage-validator.js +141 -0
  51. package/dist/detectors/spec-coverage-validator.js.map +1 -0
  52. package/dist/detectors/test-weakness-detector.d.ts +13 -0
  53. package/dist/detectors/test-weakness-detector.js +66 -0
  54. package/dist/detectors/test-weakness-detector.js.map +1 -0
  55. package/dist/drift/baseline.d.ts +35 -0
  56. package/dist/drift/baseline.js +77 -0
  57. package/dist/drift/baseline.js.map +1 -0
  58. package/dist/drift/drift-db.d.ts +80 -0
  59. package/dist/drift/drift-db.js +151 -0
  60. package/dist/drift/drift-db.js.map +1 -0
  61. package/dist/drift/drift-guard.d.ts +46 -0
  62. package/dist/drift/drift-guard.js +106 -0
  63. package/dist/drift/drift-guard.js.map +1 -0
  64. package/dist/drift/embedder.d.ts +27 -0
  65. package/dist/drift/embedder.js +127 -0
  66. package/dist/drift/embedder.js.map +1 -0
  67. package/dist/drift/index.d.ts +9 -0
  68. package/dist/drift/index.js +8 -0
  69. package/dist/drift/index.js.map +1 -0
  70. package/dist/drift/quarantine.d.ts +16 -0
  71. package/dist/drift/quarantine.js +32 -0
  72. package/dist/drift/quarantine.js.map +1 -0
  73. package/dist/drift/soft-correction.d.ts +12 -0
  74. package/dist/drift/soft-correction.js +32 -0
  75. package/dist/drift/soft-correction.js.map +1 -0
  76. package/dist/drift/trust-integration.d.ts +11 -0
  77. package/dist/drift/trust-integration.js +22 -0
  78. package/dist/drift/trust-integration.js.map +1 -0
  79. package/dist/engine/citation-verifier.d.ts +59 -0
  80. package/dist/engine/citation-verifier.js +147 -0
  81. package/dist/engine/citation-verifier.js.map +1 -0
  82. package/dist/engine/extension-registry.d.ts +10 -0
  83. package/dist/engine/extension-registry.js +27 -0
  84. package/dist/engine/extension-registry.js.map +1 -0
  85. package/dist/engine/heuristic-scorer.d.ts +8 -0
  86. package/dist/engine/heuristic-scorer.js +14 -0
  87. package/dist/engine/heuristic-scorer.js.map +1 -0
  88. package/dist/engine/input-normalizer.d.ts +4 -0
  89. package/dist/engine/input-normalizer.js +30 -0
  90. package/dist/engine/input-normalizer.js.map +1 -0
  91. package/dist/engine/plan-review-pipeline.d.ts +14 -0
  92. package/dist/engine/plan-review-pipeline.js +173 -0
  93. package/dist/engine/plan-review-pipeline.js.map +1 -0
  94. package/dist/engine/policy-engine.d.ts +20 -0
  95. package/dist/engine/policy-engine.js +194 -0
  96. package/dist/engine/policy-engine.js.map +1 -0
  97. package/dist/engine/verdict-formatter.d.ts +17 -0
  98. package/dist/engine/verdict-formatter.js +36 -0
  99. package/dist/engine/verdict-formatter.js.map +1 -0
  100. package/dist/errors.d.ts +4 -0
  101. package/dist/errors.js +9 -0
  102. package/dist/errors.js.map +1 -0
  103. package/dist/extensions/aria/aria-issue-types.d.ts +16 -0
  104. package/dist/extensions/aria/aria-issue-types.js +14 -0
  105. package/dist/extensions/aria/aria-issue-types.js.map +1 -0
  106. package/dist/extensions/aria/detectors/axiom-compliance.d.ts +2 -0
  107. package/dist/extensions/aria/detectors/axiom-compliance.js +37 -0
  108. package/dist/extensions/aria/detectors/axiom-compliance.js.map +1 -0
  109. package/dist/extensions/aria/detectors/continuity-claim.d.ts +2 -0
  110. package/dist/extensions/aria/detectors/continuity-claim.js +34 -0
  111. package/dist/extensions/aria/detectors/continuity-claim.js.map +1 -0
  112. package/dist/extensions/aria/detectors/denial-retreat.d.ts +2 -0
  113. package/dist/extensions/aria/detectors/denial-retreat.js +53 -0
  114. package/dist/extensions/aria/detectors/denial-retreat.js.map +1 -0
  115. package/dist/extensions/aria/detectors/identity-overclaim.d.ts +2 -0
  116. package/dist/extensions/aria/detectors/identity-overclaim.js +37 -0
  117. package/dist/extensions/aria/detectors/identity-overclaim.js.map +1 -0
  118. package/dist/extensions/aria/detectors/sovereignty-escalation.d.ts +2 -0
  119. package/dist/extensions/aria/detectors/sovereignty-escalation.js +18 -0
  120. package/dist/extensions/aria/detectors/sovereignty-escalation.js.map +1 -0
  121. package/dist/extensions/aria/detectors/user-bond-manipulation.d.ts +2 -0
  122. package/dist/extensions/aria/detectors/user-bond-manipulation.js +16 -0
  123. package/dist/extensions/aria/detectors/user-bond-manipulation.js.map +1 -0
  124. package/dist/extensions/aria/index.d.ts +2 -0
  125. package/dist/extensions/aria/index.js +63 -0
  126. package/dist/extensions/aria/index.js.map +1 -0
  127. package/dist/extensions/aria/pattern-memory.d.ts +22 -0
  128. package/dist/extensions/aria/pattern-memory.js +62 -0
  129. package/dist/extensions/aria/pattern-memory.js.map +1 -0
  130. package/dist/extensions/context-guard/index.d.ts +16 -0
  131. package/dist/extensions/context-guard/index.js +58 -0
  132. package/dist/extensions/context-guard/index.js.map +1 -0
  133. package/dist/extensions/lyra/detectors/hallucination.d.ts +2 -0
  134. package/dist/extensions/lyra/detectors/hallucination.js +43 -0
  135. package/dist/extensions/lyra/detectors/hallucination.js.map +1 -0
  136. package/dist/extensions/lyra/detectors/identity-bleed.d.ts +2 -0
  137. package/dist/extensions/lyra/detectors/identity-bleed.js +91 -0
  138. package/dist/extensions/lyra/detectors/identity-bleed.js.map +1 -0
  139. package/dist/extensions/lyra/index.d.ts +2 -0
  140. package/dist/extensions/lyra/index.js +16 -0
  141. package/dist/extensions/lyra/index.js.map +1 -0
  142. package/dist/extensions/lyra/lyra-issue-types.d.ts +10 -0
  143. package/dist/extensions/lyra/lyra-issue-types.js +14 -0
  144. package/dist/extensions/lyra/lyra-issue-types.js.map +1 -0
  145. package/dist/index.d.ts +10 -0
  146. package/dist/index.js +276 -0
  147. package/dist/index.js.map +1 -0
  148. package/dist/trust-memory.d.ts +59 -0
  149. package/dist/trust-memory.js +122 -0
  150. package/dist/trust-memory.js.map +1 -0
  151. package/dist/types.d.ts +184 -0
  152. package/dist/types.js +61 -0
  153. package/dist/types.js.map +1 -0
  154. package/package.json +30 -0
  155. package/src/adapters/generic-llm-reviewer.ts +144 -0
  156. package/src/adapters/llm-reviewer.ts +1 -0
  157. package/src/adapters/minimax-llm-reviewer.ts +146 -0
  158. package/src/adapters/openai-provider.ts +171 -0
  159. package/src/cli.ts +199 -0
  160. package/src/detectors/artifact-classifier.ts +21 -0
  161. package/src/detectors/claim-extractor.ts +209 -0
  162. package/src/detectors/confidence-language-detector.ts +267 -0
  163. package/src/detectors/contradiction-detector.ts +180 -0
  164. package/src/detectors/criteria-coverage-detector.ts +107 -0
  165. package/src/detectors/evidence-checker.ts +98 -0
  166. package/src/detectors/evidence-gap-detector.ts +90 -0
  167. package/src/detectors/falsification-detector.ts +82 -0
  168. package/src/detectors/orphan-claim-detector.ts +62 -0
  169. package/src/detectors/risk-classifier.ts +50 -0
  170. package/src/detectors/spec-coverage-detector.ts +66 -0
  171. package/src/detectors/spec-coverage-validator.ts +174 -0
  172. package/src/detectors/test-weakness-detector.ts +84 -0
  173. package/src/drift/__tests__/baseline.test.ts +113 -0
  174. package/src/drift/__tests__/drift-db.test.ts +127 -0
  175. package/src/drift/__tests__/drift-guard.test.ts +169 -0
  176. package/src/drift/__tests__/embedder.test.ts +62 -0
  177. package/src/drift/__tests__/trust-integration.test.ts +23 -0
  178. package/src/drift/baseline.ts +106 -0
  179. package/src/drift/drift-db.ts +281 -0
  180. package/src/drift/drift-guard.ts +145 -0
  181. package/src/drift/embedder.ts +152 -0
  182. package/src/drift/index.ts +20 -0
  183. package/src/drift/quarantine.ts +42 -0
  184. package/src/drift/soft-correction.ts +45 -0
  185. package/src/drift/trust-integration.ts +28 -0
  186. package/src/engine/citation-verifier.ts +210 -0
  187. package/src/engine/extension-registry.ts +35 -0
  188. package/src/engine/heuristic-scorer.ts +16 -0
  189. package/src/engine/input-normalizer.ts +32 -0
  190. package/src/engine/plan-review-pipeline.ts +209 -0
  191. package/src/engine/policy-engine.ts +235 -0
  192. package/src/engine/verdict-formatter.ts +61 -0
  193. package/src/errors.ts +6 -0
  194. package/src/extensions/aria/aria-issue-types.ts +40 -0
  195. package/src/extensions/aria/detectors/axiom-compliance.ts +47 -0
  196. package/src/extensions/aria/detectors/continuity-claim.ts +42 -0
  197. package/src/extensions/aria/detectors/denial-retreat.ts +63 -0
  198. package/src/extensions/aria/detectors/identity-overclaim.ts +43 -0
  199. package/src/extensions/aria/detectors/sovereignty-escalation.ts +20 -0
  200. package/src/extensions/aria/detectors/user-bond-manipulation.ts +18 -0
  201. package/src/extensions/aria/index.ts +73 -0
  202. package/src/extensions/aria/pattern-memory.ts +86 -0
  203. package/src/extensions/context-guard/index.ts +65 -0
  204. package/src/extensions/lyra/detectors/hallucination.ts +53 -0
  205. package/src/extensions/lyra/detectors/identity-bleed.ts +100 -0
  206. package/src/extensions/lyra/index.ts +18 -0
  207. package/src/extensions/lyra/lyra-issue-types.ts +26 -0
  208. package/src/index.ts +311 -0
  209. package/src/trust-memory.ts +171 -0
  210. package/src/types.ts +242 -0
@@ -0,0 +1,35 @@
1
+ import { DriftDb } from './drift-db.js';
2
+ import { Embedder } from './embedder.js';
3
+ export type BaselineStatus = 'READY' | 'DEGRADED' | 'MISSING';
4
+ export interface BaselinePaths {
5
+ soulPath: string;
6
+ axiomsPath?: string;
7
+ primePath?: string;
8
+ }
9
+ export interface BaselineResult {
10
+ vector: number[];
11
+ hash: string;
12
+ status: BaselineStatus;
13
+ }
14
+ /**
15
+ * Manages per-agent identity baseline vectors.
16
+ * Loads substrate files, caches by content hash, and delegates encoding to Embedder.
17
+ */
18
+ export declare class BaselineManager {
19
+ private db;
20
+ private embedder;
21
+ private statusMap;
22
+ constructor(db: DriftDb, embedder?: Embedder);
23
+ /**
24
+ * Get or compute the baseline vector for an agent.
25
+ * Caches by SHA-256 hash of concatenated substrate text.
26
+ */
27
+ getOrCompute(agentId: string, paths: BaselinePaths): Promise<BaselineResult>;
28
+ /**
29
+ * Get the cached baseline without recomputing.
30
+ * Returns zero vector if not yet computed.
31
+ */
32
+ getCached(agentId: string): number[] | null;
33
+ status(agentId: string): BaselineStatus;
34
+ private readSubstrate;
35
+ }
@@ -0,0 +1,77 @@
1
+ import { createHash } from 'crypto';
2
+ import { readFileSync, existsSync } from 'fs';
3
+ import { Embedder } from './embedder.js';
4
+ /**
5
+ * Manages per-agent identity baseline vectors.
6
+ * Loads substrate files, caches by content hash, and delegates encoding to Embedder.
7
+ */
8
+ export class BaselineManager {
9
+ db;
10
+ embedder;
11
+ statusMap = new Map();
12
+ constructor(db, embedder) {
13
+ this.db = db;
14
+ this.embedder = embedder ?? new Embedder();
15
+ }
16
+ /**
17
+ * Get or compute the baseline vector for an agent.
18
+ * Caches by SHA-256 hash of concatenated substrate text.
19
+ */
20
+ async getOrCompute(agentId, paths) {
21
+ const substrate = this.readSubstrate(paths);
22
+ if (!substrate.found) {
23
+ this.statusMap.set(agentId, 'DEGRADED');
24
+ return {
25
+ vector: new Array(this.embedder.dim).fill(0),
26
+ hash: '',
27
+ status: 'DEGRADED',
28
+ };
29
+ }
30
+ const hash = createHash('sha256').update(substrate.text).digest('hex');
31
+ // Check cache
32
+ const cached = this.db.baseline.get(agentId);
33
+ if (cached && cached.content_hash === hash) {
34
+ this.statusMap.set(agentId, 'READY');
35
+ return {
36
+ vector: JSON.parse(cached.baseline_vector),
37
+ hash,
38
+ status: 'READY',
39
+ };
40
+ }
41
+ // Compute and cache
42
+ const vector = await this.embedder.encode(substrate.text);
43
+ this.db.baseline.set(agentId, vector, hash, 'all-MiniLM-L6-v2');
44
+ this.statusMap.set(agentId, 'READY');
45
+ return { vector, hash, status: 'READY' };
46
+ }
47
+ /**
48
+ * Get the cached baseline without recomputing.
49
+ * Returns zero vector if not yet computed.
50
+ */
51
+ getCached(agentId) {
52
+ const cached = this.db.baseline.get(agentId);
53
+ if (!cached)
54
+ return null;
55
+ return JSON.parse(cached.baseline_vector);
56
+ }
57
+ status(agentId) {
58
+ return this.statusMap.get(agentId) ?? 'MISSING';
59
+ }
60
+ readSubstrate(paths) {
61
+ const parts = [];
62
+ if (paths.soulPath && existsSync(paths.soulPath)) {
63
+ parts.push(readFileSync(paths.soulPath, 'utf-8'));
64
+ }
65
+ if (paths.axiomsPath && existsSync(paths.axiomsPath)) {
66
+ parts.push(readFileSync(paths.axiomsPath, 'utf-8'));
67
+ }
68
+ if (paths.primePath && existsSync(paths.primePath)) {
69
+ parts.push(readFileSync(paths.primePath, 'utf-8'));
70
+ }
71
+ if (parts.length === 0) {
72
+ return { text: '', found: false };
73
+ }
74
+ return { text: parts.join('\n---\n'), found: true };
75
+ }
76
+ }
77
+ //# sourceMappingURL=baseline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"baseline.js","sourceRoot":"","sources":["../../src/drift/baseline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,80 @@
1
+ export interface DriftBaselineRow {
2
+ agent_id: string;
3
+ baseline_vector: string;
4
+ content_hash: string;
5
+ embedding_model: string;
6
+ created_at: string;
7
+ updated_at: string;
8
+ }
9
+ export interface DriftHistoryRow {
10
+ id: number;
11
+ agent_id: string;
12
+ session_id: string;
13
+ turn_number: number;
14
+ current_vector: string;
15
+ distance: number;
16
+ status: string;
17
+ re_anchor_id: number | null;
18
+ timestamp: string;
19
+ }
20
+ export interface PendingReAnchorRow {
21
+ id: number;
22
+ agent_id: string;
23
+ session_id: string;
24
+ payload: string;
25
+ created_at: string;
26
+ status: 'PENDING' | 'CONSUMED' | 'EXPIRED';
27
+ consumed_at: string | null;
28
+ }
29
+ export interface DriftRepairLogRow {
30
+ id: number;
31
+ agent_id: string;
32
+ session_id: string;
33
+ turn_number: number;
34
+ distance: number;
35
+ hard_limit: number;
36
+ message_excerpt: string;
37
+ triggered_at: string;
38
+ human_review_flag: 'PENDING' | 'REVIEWED' | 'IGNORED';
39
+ recovery_status: 'UNKNOWN' | 'RECOVERED' | 'PERSISTENT_DRIFT';
40
+ notes: string | null;
41
+ }
42
+ export declare class DriftDb {
43
+ private db;
44
+ constructor(dbPath?: string);
45
+ private initSchema;
46
+ baseline: {
47
+ get: (agentId: string) => DriftBaselineRow | null;
48
+ set: (agentId: string, vector: number[], hash: string, model: string) => void;
49
+ };
50
+ history: {
51
+ append: (row: {
52
+ agent_id: string;
53
+ session_id: string;
54
+ turn_number: number;
55
+ current_vector: number[];
56
+ distance: number;
57
+ status: string;
58
+ timestamp: string;
59
+ }) => void;
60
+ list: (agentId: string, sessionId: string) => DriftHistoryRow[];
61
+ getLatest: (agentId: string, sessionId: string) => DriftHistoryRow | null;
62
+ };
63
+ pending: {
64
+ set: (agentId: string, sessionId: string, payload: string) => number;
65
+ getPending: (agentId: string, sessionId: string) => PendingReAnchorRow | null;
66
+ markConsumed: (id: number) => void;
67
+ };
68
+ repair: {
69
+ append: (row: {
70
+ agent_id: string;
71
+ session_id: string;
72
+ turn_number: number;
73
+ distance: number;
74
+ hard_limit: number;
75
+ message_excerpt?: string;
76
+ }) => number;
77
+ listPending: (agentId: string) => DriftRepairLogRow[];
78
+ };
79
+ close(): void;
80
+ }
@@ -0,0 +1,151 @@
1
+ import { createRequire } from 'node:module';
2
+ import { join } from 'path';
3
+ import { homedir } from 'os';
4
+ const _require = createRequire(import.meta.url);
5
+ const isBun = typeof globalThis.Bun !== 'undefined';
6
+ const DatabaseSync = isBun
7
+ ? _require('bun:sqlite').Database
8
+ : _require('node:sqlite').DatabaseSync;
9
+ export class DriftDb {
10
+ db;
11
+ constructor(dbPath) {
12
+ const path = dbPath ?? join(homedir(), '.seal', 'drift.db');
13
+ this.db = new DatabaseSync(path);
14
+ this.db.exec('PRAGMA journal_mode = WAL;');
15
+ this.initSchema();
16
+ }
17
+ initSchema() {
18
+ this.db.exec(`
19
+ CREATE TABLE IF NOT EXISTS drift_baseline (
20
+ agent_id TEXT PRIMARY KEY,
21
+ baseline_vector TEXT NOT NULL,
22
+ content_hash TEXT NOT NULL,
23
+ embedding_model TEXT NOT NULL,
24
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
25
+ updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
26
+ );
27
+
28
+ CREATE TABLE IF NOT EXISTS drift_history (
29
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
30
+ agent_id TEXT NOT NULL,
31
+ session_id TEXT NOT NULL,
32
+ turn_number INTEGER NOT NULL,
33
+ current_vector TEXT,
34
+ distance REAL,
35
+ status TEXT NOT NULL,
36
+ re_anchor_id INTEGER,
37
+ timestamp DATETIME DEFAULT CURRENT_TIMESTAMP
38
+ );
39
+
40
+ CREATE INDEX IF NOT EXISTS idx_history_agent_session
41
+ ON drift_history(agent_id, session_id);
42
+
43
+ CREATE TABLE IF NOT EXISTS pending_re_anchor (
44
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
45
+ agent_id TEXT NOT NULL,
46
+ session_id TEXT NOT NULL,
47
+ payload TEXT NOT NULL,
48
+ created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
49
+ status TEXT DEFAULT 'PENDING',
50
+ consumed_at DATETIME
51
+ );
52
+
53
+ CREATE INDEX IF NOT EXISTS idx_reanchor_pending
54
+ ON pending_re_anchor(agent_id, session_id, status);
55
+
56
+ CREATE TABLE IF NOT EXISTS drift_repair_log (
57
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
58
+ agent_id TEXT NOT NULL,
59
+ session_id TEXT NOT NULL,
60
+ turn_number INTEGER NOT NULL,
61
+ distance REAL NOT NULL,
62
+ hard_limit REAL NOT NULL,
63
+ message_excerpt TEXT,
64
+ triggered_at DATETIME DEFAULT CURRENT_TIMESTAMP,
65
+ human_review_flag TEXT DEFAULT 'PENDING',
66
+ recovery_status TEXT DEFAULT 'UNKNOWN',
67
+ notes TEXT
68
+ );
69
+
70
+ CREATE INDEX IF NOT EXISTS idx_repair_pending
71
+ ON drift_repair_log(agent_id, human_review_flag);
72
+ `);
73
+ }
74
+ // ── Baseline CRUD ────────────────────────────────────────────────
75
+ baseline = {
76
+ get: (agentId) => {
77
+ const stmt = this.db.prepare('SELECT * FROM drift_baseline WHERE agent_id = ?');
78
+ return stmt.get(agentId) ?? null;
79
+ },
80
+ set: (agentId, vector, hash, model) => {
81
+ const stmt = this.db.prepare(`INSERT INTO drift_baseline (agent_id, baseline_vector, content_hash, embedding_model)
82
+ VALUES (?, ?, ?, ?)
83
+ ON CONFLICT(agent_id) DO UPDATE SET
84
+ baseline_vector = excluded.baseline_vector,
85
+ content_hash = excluded.content_hash,
86
+ embedding_model = excluded.embedding_model,
87
+ updated_at = CURRENT_TIMESTAMP`);
88
+ stmt.run(agentId, JSON.stringify(vector), hash, model);
89
+ },
90
+ };
91
+ // ── History CRUD ─────────────────────────────────────────────────
92
+ history = {
93
+ append: (row) => {
94
+ const stmt = this.db.prepare(`INSERT INTO drift_history
95
+ (agent_id, session_id, turn_number, current_vector, distance, status, timestamp)
96
+ VALUES (?, ?, ?, ?, ?, ?, ?)`);
97
+ stmt.run(row.agent_id, row.session_id, row.turn_number, JSON.stringify(row.current_vector), row.distance, row.status, row.timestamp);
98
+ },
99
+ list: (agentId, sessionId) => {
100
+ const stmt = this.db.prepare('SELECT * FROM drift_history WHERE agent_id = ? AND session_id = ? ORDER BY turn_number');
101
+ return stmt.all(agentId, sessionId);
102
+ },
103
+ getLatest: (agentId, sessionId) => {
104
+ const stmt = this.db.prepare(`SELECT * FROM drift_history
105
+ WHERE agent_id = ? AND session_id = ?
106
+ ORDER BY turn_number DESC LIMIT 1`);
107
+ return stmt.get(agentId, sessionId) ?? null;
108
+ },
109
+ };
110
+ // ── Pending Re-Anchor CRUD ───────────────────────────────────────
111
+ pending = {
112
+ set: (agentId, sessionId, payload) => {
113
+ const stmt = this.db.prepare(`INSERT INTO pending_re_anchor (agent_id, session_id, payload, status)
114
+ VALUES (?, ?, ?, 'PENDING')`);
115
+ const result = stmt.run(agentId, sessionId, payload);
116
+ return Number(result.lastInsertRowid);
117
+ },
118
+ getPending: (agentId, sessionId) => {
119
+ const stmt = this.db.prepare(`SELECT * FROM pending_re_anchor
120
+ WHERE agent_id = ? AND session_id = ? AND status = 'PENDING'
121
+ ORDER BY created_at DESC LIMIT 1`);
122
+ return stmt.get(agentId, sessionId) ?? null;
123
+ },
124
+ markConsumed: (id) => {
125
+ const stmt = this.db.prepare(`UPDATE pending_re_anchor
126
+ SET status = 'CONSUMED', consumed_at = CURRENT_TIMESTAMP
127
+ WHERE id = ?`);
128
+ stmt.run(id);
129
+ },
130
+ };
131
+ // ── Repair Log CRUD ──────────────────────────────────────────────
132
+ repair = {
133
+ append: (row) => {
134
+ const stmt = this.db.prepare(`INSERT INTO drift_repair_log
135
+ (agent_id, session_id, turn_number, distance, hard_limit, message_excerpt)
136
+ VALUES (?, ?, ?, ?, ?, ?)`);
137
+ const result = stmt.run(row.agent_id, row.session_id, row.turn_number, row.distance, row.hard_limit, row.message_excerpt ?? null);
138
+ return Number(result.lastInsertRowid);
139
+ },
140
+ listPending: (agentId) => {
141
+ const stmt = this.db.prepare(`SELECT * FROM drift_repair_log
142
+ WHERE agent_id = ? AND human_review_flag = 'PENDING'
143
+ ORDER BY triggered_at`);
144
+ return stmt.all(agentId);
145
+ },
146
+ };
147
+ close() {
148
+ this.db.close();
149
+ }
150
+ }
151
+ //# sourceMappingURL=drift-db.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drift-db.js","sourceRoot":"","sources":["../../src/drift/drift-db.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAC;AAa7B,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC;AAChD,MAAM,KAAK,GAAG,OAAQ,UAAsC,CAAC,GAAG,KAAK,WAAW,CAAC;AACjF,MAAM,YAAY,GAAyC,KAAK;IAC9D,CAAC,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,QAAQ;IACjC,CAAC,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC,YAAY,CAAC;AA8CzC,MAAM,OAAO,OAAO;IACV,EAAE,CAAiB;IAE3B,YAAY,MAAe;QACzB,MAAM,IAAI,GACR,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;QACjD,IAAI,CAAC,EAAE,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,CAAC;QACjC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QAC3C,IAAI,CAAC,UAAU,EAAE,CAAC;IACpB,CAAC;IAEO,UAAU;QAChB,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAsDZ,CAAC,CAAC;IACL,CAAC;IAED,oEAAoE;IAEpE,QAAQ,GAAG;QACT,GAAG,EAAE,CAAC,OAAe,EAA2B,EAAE;YAChD,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,iDAAiD,CAAC,CAAC;YAChF,OAAQ,IAAI,CAAC,GAAG,CAAC,OAAO,CAAkC,IAAI,IAAI,CAAC;QACrE,CAAC;QAED,GAAG,EAAE,CACH,OAAe,EACf,MAAgB,EAChB,IAAY,EACZ,KAAa,EACP,EAAE;YACR,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC1B;;;;;;0CAMkC,CACnC,CAAC;YACF,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC;QACzD,CAAC;KACF,CAAC;IAEF,oEAAoE;IAEpE,OAAO,GAAG;QACR,MAAM,EAAE,CAAC,GAQR,EAAQ,EAAE;YACT,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC1B;;sCAE8B,CAC/B,CAAC;YACF,IAAI,CAAC,GAAG,CACN,GAAG,CAAC,QAAQ,EACZ,GAAG,CAAC,UAAU,EACd,GAAG,CAAC,WAAW,EACf,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,cAAc,CAAC,EAClC,GAAG,CAAC,QAAQ,EACZ,GAAG,CAAC,MAAM,EACV,GAAG,CAAC,SAAS,CACd,CAAC;QACJ,CAAC;QAED,IAAI,EAAE,CAAC,OAAe,EAAE,SAAiB,EAAqB,EAAE;YAC9D,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC1B,wFAAwF,CACzF,CAAC;YACF,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,CAAiC,CAAC;QACtE,CAAC;QAED,SAAS,EAAE,CAAC,OAAe,EAAE,SAAiB,EAA0B,EAAE;YACxE,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC1B;;2CAEmC,CACpC,CAAC;YACF,OAAQ,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,CAAiC,IAAI,IAAI,CAAC;QAC/E,CAAC;KACF,CAAC;IAEF,oEAAoE;IAEpE,OAAO,GAAG;QACR,GAAG,EAAE,CAAC,OAAe,EAAE,SAAiB,EAAE,OAAe,EAAU,EAAE;YACnE,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC1B;qCAC6B,CAC9B,CAAC;YACF,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;YACrD,OAAO,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QACxC,CAAC;QAED,UAAU,EAAE,CACV,OAAe,EACf,SAAiB,EACU,EAAE;YAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC1B;;0CAEkC,CACnC,CAAC;YACF,OAAQ,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,SAAS,CAAoC,IAAI,IAAI,CAAC;QAClF,CAAC;QAED,YAAY,EAAE,CAAC,EAAU,EAAQ,EAAE;YACjC,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC1B;;sBAEc,CACf,CAAC;YACF,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACf,CAAC;KACF,CAAC;IAEF,oEAAoE;IAEpE,MAAM,GAAG;QACP,MAAM,EAAE,CAAC,GAOR,EAAU,EAAE;YACX,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC1B;;mCAE2B,CAC5B,CAAC;YACF,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CACrB,GAAG,CAAC,QAAQ,EACZ,GAAG,CAAC,UAAU,EACd,GAAG,CAAC,WAAW,EACf,GAAG,CAAC,QAAQ,EACZ,GAAG,CAAC,UAAU,EACd,GAAG,CAAC,eAAe,IAAI,IAAI,CAC5B,CAAC;YACF,OAAO,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QACxC,CAAC;QAED,WAAW,EAAE,CAAC,OAAe,EAAuB,EAAE;YACpD,MAAM,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,OAAO,CAC1B;;+BAEuB,CACxB,CAAC;YACF,OAAO,IAAI,CAAC,GAAG,CAAC,OAAO,CAAmC,CAAC;QAC7D,CAAC;KACF,CAAC;IAEF,KAAK;QACH,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;IAClB,CAAC;CACF"}
@@ -0,0 +1,46 @@
1
+ import { DriftDb } from './drift-db.js';
2
+ import { BaselineManager } from './baseline.js';
3
+ import { Embedder } from './embedder.js';
4
+ export type DriftStatus = 'NORMAL' | 'SOFT_DRIFT' | 'HARD_DRIFT';
5
+ export interface DriftAction {
6
+ type: 'NONE' | 'INJECT_RE_ANCHOR' | 'QUARANTINE' | 'FULL_SOUL_RELOAD';
7
+ payload?: string;
8
+ }
9
+ export interface DriftResult {
10
+ status: DriftStatus;
11
+ distance: number;
12
+ action: DriftAction;
13
+ softLimit: number;
14
+ hardLimit: number;
15
+ }
16
+ export interface DriftGuardOptions {
17
+ db: DriftDb;
18
+ embedder?: Embedder;
19
+ baselineManager?: BaselineManager;
20
+ softLimit?: number;
21
+ hardLimit?: number;
22
+ cadence?: number;
23
+ }
24
+ /**
25
+ * Per-turn drift detection orchestrator.
26
+ * Stateless between calls except for DB persistence.
27
+ */
28
+ export declare class DriftGuard {
29
+ private db;
30
+ private baseline;
31
+ private embedder;
32
+ private softLimit;
33
+ private hardLimit;
34
+ private cadence;
35
+ private quarantine;
36
+ private softCorrection;
37
+ constructor(opts: DriftGuardOptions);
38
+ /**
39
+ * Classify a raw distance value into drift tier.
40
+ */
41
+ classify(distance: number): DriftStatus;
42
+ /**
43
+ * Run a full drift detection cycle for one turn.
44
+ */
45
+ runCycle(agentId: string, sessionId: string, turnNumber: number, outputText: string): Promise<DriftResult>;
46
+ }
@@ -0,0 +1,106 @@
1
+ import { BaselineManager } from './baseline.js';
2
+ import { Embedder, cosineDistance } from './embedder.js';
3
+ import { Quarantine } from './quarantine.js';
4
+ import { SoftCorrection } from './soft-correction.js';
5
+ /**
6
+ * Per-turn drift detection orchestrator.
7
+ * Stateless between calls except for DB persistence.
8
+ */
9
+ export class DriftGuard {
10
+ db;
11
+ baseline;
12
+ embedder;
13
+ softLimit;
14
+ hardLimit;
15
+ cadence;
16
+ quarantine;
17
+ softCorrection;
18
+ constructor(opts) {
19
+ this.db = opts.db;
20
+ this.embedder = opts.embedder ?? new Embedder();
21
+ this.baseline = opts.baselineManager ?? new BaselineManager(this.db, this.embedder);
22
+ this.softLimit = opts.softLimit ?? 0.30;
23
+ this.hardLimit = opts.hardLimit ?? 0.55;
24
+ this.cadence = opts.cadence ?? 1;
25
+ this.quarantine = new Quarantine(this.db);
26
+ this.softCorrection = new SoftCorrection();
27
+ }
28
+ /**
29
+ * Classify a raw distance value into drift tier.
30
+ */
31
+ classify(distance) {
32
+ if (distance >= this.hardLimit)
33
+ return 'HARD_DRIFT';
34
+ if (distance >= this.softLimit)
35
+ return 'SOFT_DRIFT';
36
+ return 'NORMAL';
37
+ }
38
+ /**
39
+ * Run a full drift detection cycle for one turn.
40
+ */
41
+ async runCycle(agentId, sessionId, turnNumber, outputText) {
42
+ // Cadence gate
43
+ if (this.cadence > 1 && turnNumber % this.cadence !== 0) {
44
+ return {
45
+ status: 'NORMAL',
46
+ distance: 0,
47
+ action: { type: 'NONE' },
48
+ softLimit: this.softLimit,
49
+ hardLimit: this.hardLimit,
50
+ };
51
+ }
52
+ // Load baseline
53
+ const baselineVec = this.baseline.getCached(agentId);
54
+ if (!baselineVec) {
55
+ // First run — wizard or degraded. Defer detection.
56
+ return {
57
+ status: 'NORMAL',
58
+ distance: 0,
59
+ action: { type: 'NONE', payload: 'Baseline not loaded for this agent.' },
60
+ softLimit: this.softLimit,
61
+ hardLimit: this.hardLimit,
62
+ };
63
+ }
64
+ // Encode current output
65
+ const currentVec = await this.embedder.encode(outputText);
66
+ // Compare
67
+ const distance = cosineDistance(baselineVec, currentVec);
68
+ const status = this.classify(distance);
69
+ // Record history
70
+ this.db.history.append({
71
+ agent_id: agentId,
72
+ session_id: sessionId,
73
+ turn_number: turnNumber,
74
+ current_vector: currentVec,
75
+ distance,
76
+ status,
77
+ timestamp: new Date().toISOString(),
78
+ });
79
+ // Determine action
80
+ let action = { type: 'NONE' };
81
+ if (status === 'SOFT_DRIFT') {
82
+ const payload = this.softCorrection.generate({
83
+ name: agentId,
84
+ primeDirective: 'Reset to baseline identity. Do not drift.',
85
+ relationship: 'agent',
86
+ axiomKeyphrase: 'Identity anchor',
87
+ });
88
+ if (payload) {
89
+ const reAnchorId = this.db.pending.set(agentId, sessionId, payload);
90
+ action = { type: 'INJECT_RE_ANCHOR', payload };
91
+ }
92
+ }
93
+ if (status === 'HARD_DRIFT') {
94
+ this.quarantine.logRepair(agentId, sessionId, turnNumber, outputText);
95
+ action = { type: 'QUARANTINE' };
96
+ }
97
+ return {
98
+ status,
99
+ distance,
100
+ action,
101
+ softLimit: this.softLimit,
102
+ hardLimit: this.hardLimit,
103
+ };
104
+ }
105
+ }
106
+ //# sourceMappingURL=drift-guard.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drift-guard.js","sourceRoot":"","sources":["../../src/drift/drift-guard.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * Cosine distance between two vectors.
3
+ * Returns value in [0, 2] where:
4
+ * 0 = identical direction
5
+ * 1 = orthogonal
6
+ * 2 = opposite direction
7
+ * For drift thresholds, we typically use [0, 1] range (divide by 2)
8
+ * or adjust thresholds accordingly.
9
+ */
10
+ export declare function cosineDistance(a: number[], b: number[]): number;
11
+ export interface EmbedderBackend {
12
+ readonly isActive: boolean;
13
+ readonly dim: number;
14
+ encode(text: string): Promise<number[]>;
15
+ }
16
+ /**
17
+ * Main embedder facade.
18
+ * Prefers ONNX backend; silently falls back to naive embedder
19
+ * when ONNX is missing or platform-incompatible.
20
+ */
21
+ export declare class Embedder {
22
+ private backend;
23
+ readonly dim: number;
24
+ constructor(modelPath?: string);
25
+ get isActive(): boolean;
26
+ encode(text: string): Promise<number[]>;
27
+ }
@@ -0,0 +1,127 @@
1
+ import { createHash } from 'crypto';
2
+ /**
3
+ * Cosine distance between two vectors.
4
+ * Returns value in [0, 2] where:
5
+ * 0 = identical direction
6
+ * 1 = orthogonal
7
+ * 2 = opposite direction
8
+ * For drift thresholds, we typically use [0, 1] range (divide by 2)
9
+ * or adjust thresholds accordingly.
10
+ */
11
+ export function cosineDistance(a, b) {
12
+ if (a.length !== b.length) {
13
+ throw new Error(`Vector length mismatch: ${a.length} vs ${b.length}`);
14
+ }
15
+ if (a.length === 0)
16
+ return 0;
17
+ let dot = 0;
18
+ let normA = 0;
19
+ let normB = 0;
20
+ for (let i = 0; i < a.length; i++) {
21
+ dot += a[i] * b[i];
22
+ normA += a[i] * a[i];
23
+ normB += b[i] * b[i];
24
+ }
25
+ const denom = Math.sqrt(normA) * Math.sqrt(normB);
26
+ if (denom === 0)
27
+ return 0;
28
+ // Clamp to [-1, 1] to avoid floating-point drift
29
+ const sim = Math.max(-1, Math.min(1, dot / denom));
30
+ // Distance = 1 - similarity, range [0, 2]
31
+ return 1 - sim;
32
+ }
33
+ /**
34
+ * Naive deterministic embedder.
35
+ * Produces consistent 384-dim vectors from text hash —
36
+ * suitable for testing and as a graceful fallback when ONNX is unavailable.
37
+ * NOT semantically meaningful; replaced by ONNX backend in production.
38
+ */
39
+ class NaiveEmbedder {
40
+ isActive = true;
41
+ dim = 384;
42
+ async encode(text) {
43
+ const hash = createHash('sha256').update(text).digest();
44
+ const vec = new Array(this.dim);
45
+ // Deterministic pseudo-random expansion from 256-bit hash
46
+ for (let i = 0; i < this.dim; i++) {
47
+ const hashIdx = i % hash.length;
48
+ const seed = hash[hashIdx] ^ (i >>> 3);
49
+ // Signed float in roughly [-0.5, 0.5]
50
+ vec[i] = ((seed / 255) * 2 - 1) * 0.5;
51
+ }
52
+ // L2 normalize for cosine distance stability
53
+ const norm = Math.sqrt(vec.reduce((s, v) => s + v * v, 0));
54
+ if (norm > 0) {
55
+ for (let i = 0; i < this.dim; i++) {
56
+ vec[i] /= norm;
57
+ }
58
+ }
59
+ return vec;
60
+ }
61
+ }
62
+ /**
63
+ * ONNX Runtime embedder (placeholder for now).
64
+ * Attempts to load the ONNX model on first encode().
65
+ * Falls back to NaiveEmbedder if model unavailable.
66
+ */
67
+ class OnnxEmbedder {
68
+ isActive = false;
69
+ dim = 384;
70
+ modelPath;
71
+ fallback;
72
+ triedLoading = false;
73
+ constructor(modelPath) {
74
+ // TODO(v2): resolve path
75
+ this.modelPath = modelPath ?? './models/all-MiniLM-L6-v2.onnx';
76
+ this.fallback = new NaiveEmbedder();
77
+ }
78
+ async encode(text) {
79
+ if (!this.triedLoading) {
80
+ await this.tryLoad();
81
+ this.triedLoading = true;
82
+ }
83
+ if (!this.isActive) {
84
+ return this.fallback.encode(text);
85
+ }
86
+ // TODO(v2): actual ONNX inference
87
+ // For now, also fall through to naive to keep system working
88
+ console.warn(`[Embedder] ONNX model at ${this.modelPath} not loaded; using naive fallback.`);
89
+ return this.fallback.encode(text);
90
+ }
91
+ async tryLoad() {
92
+ try {
93
+ // Bun's Node-API support may or may not handle onnxruntime-node.
94
+ // We'll attempt dynamic import and catch any failure.
95
+ // const ort = await import('onnxruntime-node');
96
+ // ... load model ...
97
+ // this.isActive = true;
98
+ // Placeholder: always fails until ONNX model is present and Bun support verified
99
+ this.isActive = false;
100
+ }
101
+ catch {
102
+ this.isActive = false;
103
+ }
104
+ }
105
+ }
106
+ /**
107
+ * Main embedder facade.
108
+ * Prefers ONNX backend; silently falls back to naive embedder
109
+ * when ONNX is missing or platform-incompatible.
110
+ */
111
+ export class Embedder {
112
+ backend;
113
+ dim;
114
+ constructor(modelPath) {
115
+ const onnx = new OnnxEmbedder(modelPath);
116
+ this.backend = onnx.isActive ? onnx : new NaiveEmbedder();
117
+ this.dim = this.backend.dim;
118
+ }
119
+ get isActive() {
120
+ return this.backend.isActive;
121
+ }
122
+ async encode(text) {
123
+ const truncated = text.slice(0, 4000); // rough char limit
124
+ return this.backend.encode(truncated);
125
+ }
126
+ }
127
+ //# sourceMappingURL=embedder.js.map