@sochdb/sochdb 0.4.0 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/README.md +220 -33
  2. package/_bin/aarch64-apple-darwin/libsochdb_storage.dylib +0 -0
  3. package/_bin/aarch64-apple-darwin/sochdb-bulk +0 -0
  4. package/_bin/aarch64-apple-darwin/sochdb-grpc-server +0 -0
  5. package/_bin/aarch64-apple-darwin/sochdb-server +0 -0
  6. package/_bin/x86_64-pc-windows-msvc/sochdb-bulk.exe +0 -0
  7. package/_bin/x86_64-pc-windows-msvc/sochdb-grpc-server.exe +0 -0
  8. package/_bin/x86_64-pc-windows-msvc/sochdb_storage.dll +0 -0
  9. package/_bin/x86_64-unknown-linux-gnu/libsochdb_storage.so +0 -0
  10. package/_bin/x86_64-unknown-linux-gnu/sochdb-bulk +0 -0
  11. package/_bin/x86_64-unknown-linux-gnu/sochdb-grpc-server +0 -0
  12. package/_bin/x86_64-unknown-linux-gnu/sochdb-server +0 -0
  13. package/bin/sochdb-bulk.js +1 -1
  14. package/bin/sochdb-grpc-server.js +1 -1
  15. package/bin/sochdb-server.js +1 -1
  16. package/dist/cjs/context-builder.js +280 -0
  17. package/dist/cjs/database.js +2 -2
  18. package/dist/cjs/embedded/database.js +2 -2
  19. package/dist/cjs/errors.js +99 -7
  20. package/dist/cjs/index.js +40 -3
  21. package/dist/cjs/ipc-client.js +2 -2
  22. package/dist/cjs/memory/consolidation.js +202 -0
  23. package/dist/cjs/memory/extraction.js +181 -0
  24. package/dist/cjs/memory/index.js +26 -0
  25. package/dist/cjs/memory/retrieval.js +232 -0
  26. package/dist/cjs/memory/types.js +69 -0
  27. package/dist/cjs/namespace.js +255 -0
  28. package/dist/cjs/queue.js +289 -0
  29. package/dist/cjs/semantic-cache.js +220 -0
  30. package/dist/esm/context-builder.js +280 -0
  31. package/dist/esm/database.js +2 -2
  32. package/dist/esm/embedded/database.js +2 -2
  33. package/dist/esm/errors.js +107 -7
  34. package/dist/esm/index.js +40 -3
  35. package/dist/esm/ipc-client.js +2 -2
  36. package/dist/esm/memory/consolidation.js +206 -0
  37. package/dist/esm/memory/extraction.js +185 -0
  38. package/dist/esm/memory/index.js +26 -0
  39. package/dist/esm/memory/retrieval.js +243 -0
  40. package/dist/esm/memory/types.js +72 -0
  41. package/dist/esm/namespace.js +262 -0
  42. package/dist/esm/queue.js +291 -0
  43. package/dist/esm/semantic-cache.js +223 -0
  44. package/dist/types/context-builder.d.ts +97 -0
  45. package/dist/types/context-builder.d.ts.map +1 -0
  46. package/dist/types/database.d.ts +1 -1
  47. package/dist/types/embedded/database.d.ts +1 -1
  48. package/dist/types/errors.d.ts +57 -1
  49. package/dist/types/errors.d.ts.map +1 -1
  50. package/dist/types/index.d.ts +12 -2
  51. package/dist/types/index.d.ts.map +1 -1
  52. package/dist/types/ipc-client.d.ts +1 -1
  53. package/dist/types/memory/consolidation.d.ts +66 -0
  54. package/dist/types/memory/consolidation.d.ts.map +1 -0
  55. package/dist/types/memory/extraction.d.ts +82 -0
  56. package/dist/types/memory/extraction.d.ts.map +1 -0
  57. package/dist/types/memory/index.d.ts +10 -0
  58. package/dist/types/memory/index.d.ts.map +1 -0
  59. package/dist/types/memory/retrieval.d.ts +46 -0
  60. package/dist/types/memory/retrieval.d.ts.map +1 -0
  61. package/dist/types/memory/types.d.ts +147 -0
  62. package/dist/types/memory/types.d.ts.map +1 -0
  63. package/dist/types/namespace.d.ts +129 -0
  64. package/dist/types/namespace.d.ts.map +1 -0
  65. package/dist/types/queue.d.ts +120 -0
  66. package/dist/types/queue.d.ts.map +1 -0
  67. package/dist/types/semantic-cache.d.ts +84 -0
  68. package/dist/types/semantic-cache.d.ts.map +1 -0
  69. package/package.json +1 -1
package/README.md CHANGED
@@ -1,8 +1,202 @@
1
- # SochDB Node.js SDK v0.4.0
1
+ # SochDB Node.js SDK
2
2
 
3
3
  **Dual-mode architecture: Embedded (FFI) + Server (gRPC/IPC)**
4
4
  Choose the deployment mode that fits your needs.
5
5
 
6
+ ## Features
7
+
8
+ ### Memory System - LLM-Native Memory for AI Agents
9
+ Complete memory system with extraction, consolidation, and hybrid retrieval:
10
+
11
+ ```typescript
12
+ import {
13
+ EmbeddedDatabase,
14
+ ExtractionPipeline,
15
+ Consolidator,
16
+ HybridRetriever,
17
+ AllowedSet,
18
+ } from '@sochdb/sochdb';
19
+
20
+ const db = await EmbeddedDatabase.open('./memory_db');
21
+
22
+ // Extract entities and relations from text
23
+ const pipeline = ExtractionPipeline.fromDatabase(db, 'user_123', {
24
+ entityTypes: ['person', 'organization', 'location'],
25
+ minConfidence: 0.7,
26
+ });
27
+
28
+ const result = await pipeline.extractAndCommit(
29
+ 'Alice works at Acme Corp',
30
+ myLLMExtractor // Your LLM integration
31
+ );
32
+ console.log(`Extracted ${result.entities.length} entities`);
33
+
34
+ // Consolidate facts with event sourcing
35
+ const consolidator = Consolidator.fromDatabase(db, 'user_123');
36
+ await consolidator.add({
37
+ fact: { subject: 'Alice', predicate: 'lives_in', object: 'SF' },
38
+ source: 'conversation_1',
39
+ confidence: 0.9,
40
+ });
41
+
42
+ const updated = await consolidator.consolidate();
43
+ const facts = await consolidator.getCanonicalFacts();
44
+
45
+ // Hybrid retrieval with RRF fusion
46
+ const retriever = HybridRetriever.fromDatabase(db, 'user_123', 'documents');
47
+ await retriever.indexDocuments(docs);
48
+
49
+ const results = await retriever.retrieve(
50
+ 'machine learning papers',
51
+ queryEmbedding,
52
+ AllowedSet.fromNamespace('user_123')
53
+ );
54
+ ```
55
+
56
+ **[→ See Full Example](./examples/memory-system-example.ts)**
57
+
58
+ **Key Features:**
59
+ - ✅ Extraction Pipeline: Compile LLM outputs into typed facts
60
+ - ✅ Event-Sourced Consolidation: Append-only with temporal updates
61
+ - ✅ Hybrid Retrieval: RRF fusion of vector + keyword search
62
+ - ✅ Namespace Isolation: Multi-tenant security with pre-filtering
63
+ - ✅ Schema Validation: Type checking and confidence thresholds
64
+
65
+ ### Semantic Cache - LLM Response Caching
66
+ Vector similarity-based caching for LLM responses to reduce costs and latency:
67
+
68
+ ```typescript
69
+ import { EmbeddedDatabase, SemanticCache } from '@sochdb/sochdb';
70
+
71
+ const db = await EmbeddedDatabase.open('./mydb');
72
+ const cache = new SemanticCache(db, 'llm_responses');
73
+
74
+ // Store LLM response with embedding
75
+ await cache.put(
76
+ 'What is machine learning?',
77
+ 'Machine learning is a subset of AI...',
78
+ embedding, // 384-dim vector
79
+ 3600, // TTL in seconds
80
+ { model: 'gpt-4', tokens: 150 }
81
+ );
82
+
83
+ // Check cache before calling LLM
84
+ const hit = await cache.get(queryEmbedding, 0.85);
85
+ if (hit) {
86
+ console.log(`Cache HIT! Similarity: ${hit.score.toFixed(4)}`);
87
+ console.log(`Response: ${hit.value}`);
88
+ }
89
+
90
+ // Get statistics
91
+ const stats = await cache.stats();
92
+ console.log(`Hit rate: ${(stats.hitRate * 100).toFixed(1)}%`);
93
+ ```
94
+
95
+ **[→ See Full Example](./examples/semantic-cache-example.ts)**
96
+
97
+ **Key Benefits:**
98
+ - ✅ Cosine similarity matching (0-1 threshold)
99
+ - ✅ TTL-based expiration
100
+ - ✅ Hit/miss statistics tracking
101
+ - ✅ Memory usage monitoring
102
+ - ✅ Automatic expired entry purging
103
+
104
+ ### Context Query Builder - Token-Aware LLM Context
105
+ Assemble LLM context with priority-based truncation and token budgeting:
106
+
107
+ ```typescript
108
+ import { ContextQueryBuilder, ContextOutputFormat, TruncationStrategy } from '@sochdb/sochdb';
109
+
110
+ const builder = new ContextQueryBuilder()
111
+ .withBudget(4096) // Token limit
112
+ .setFormat(ContextOutputFormat.TOON)
113
+ .setTruncation(TruncationStrategy.TAIL_DROP);
114
+
115
+ builder
116
+ .literal('SYSTEM', 0, 'You are a helpful AI assistant.')
117
+ .literal('USER_PROFILE', 1, 'User: Alice, Role: Engineer')
118
+ .literal('HISTORY', 2, 'Recent conversation context...')
119
+ .literal('KNOWLEDGE', 3, 'Retrieved documents...');
120
+
121
+ const result = builder.execute();
122
+ console.log(`Tokens: ${result.tokenCount}/${4096}`);
123
+ console.log(`Context:\n${result.text}`);
124
+ ```
125
+
126
+ **[→ See Full Example](./examples/context-builder-example.ts)**
127
+
128
+ **Key Benefits:**
129
+ - ✅ Priority-based section ordering (lower = higher priority)
130
+ - ✅ Token budget enforcement
131
+ - ✅ Multiple truncation strategies (tail drop, head drop, proportional)
132
+ - ✅ Multiple output formats (TOON, JSON, Markdown)
133
+ - ✅ Token count estimation
134
+
135
+ ### Namespace API - Multi-Tenant Isolation
136
+ First-class namespace handles for secure multi-tenancy and data isolation:
137
+
138
+ ```typescript
139
+ import { Database, Namespace, Collection, DistanceMetric } from '@sochdb/sochdb';
140
+
141
+ const db = await Database.open('./mydb');
142
+
143
+ // Create isolated namespace for each tenant
144
+ const namespace = new Namespace(db, 'tenant_acme', {
145
+ name: 'tenant_acme',
146
+ displayName: 'ACME Corporation',
147
+ labels: { plan: 'enterprise', region: 'us-west' }
148
+ });
149
+
150
+ // Create vector collection
151
+ const collection = await namespace.createCollection({
152
+ name: 'documents',
153
+ dimension: 384,
154
+ metric: DistanceMetric.Cosine,
155
+ indexed: true
156
+ });
157
+
158
+ // Insert and search vectors
159
+ await collection.insert([1.0, 2.0, ...], { title: 'Doc 1' });
160
+ const results = await collection.search({ queryVector: [...], k: 10 });
161
+ ```
162
+
163
+ **[→ See Full Example](./examples/namespace-example.ts)**
164
+
165
+ ### Priority Queue API - Task Processing
166
+ Efficient priority queue with ordered-key storage (no O(N) blob rewrites):
167
+
168
+ ```typescript
169
+ import { Database, PriorityQueue } from '@sochdb/sochdb';
170
+
171
+ const db = await Database.open('./queue_db');
172
+ const queue = PriorityQueue.fromDatabase(db, 'tasks');
173
+
174
+ // Enqueue with priority (lower = higher urgency)
175
+ await queue.enqueue(1, Buffer.from('urgent task'), { type: 'payment' });
176
+
177
+ // Worker processes tasks
178
+ const task = await queue.dequeue('worker-1');
179
+ if (task) {
180
+ // Process task...
181
+ await queue.ack(task.taskId);
182
+ }
183
+
184
+ // Get statistics
185
+ const stats = await queue.stats();
186
+ console.log(`Pending: ${stats.pending}, Completed: ${stats.completed}`);
187
+ ```
188
+
189
+ **[→ See Full Example](./examples/queue-example.ts)**
190
+
191
+ **Key Benefits:**
192
+ - ✅ O(log N) enqueue/dequeue with ordered scans
193
+ - ✅ Atomic claim protocol for concurrent workers
194
+ - ✅ Visibility timeout for crash recovery
195
+ - ✅ Dead letter queue for failed tasks
196
+ - ✅ Multiple queues per database
197
+
198
+ ---
199
+
6
200
  ## Architecture: Flexible Deployment
7
201
 
8
202
  ```
@@ -67,40 +261,33 @@ npm install
67
261
 
68
262
  1. [Quick Start](#1-quick-start)
69
263
  2. [Installation](#2-installation)
70
- 3. [Architecture Overview](#3-architecture-overview)
71
- 4. [Core Key-Value Operations](#4-core-key-value-operations)
72
- 5. [Transactions (ACID with SSI)](#5-transactions-acid-with-ssi)
73
- 6. [Query Builder](#6-query-builder)
74
- 7. [Prefix Scanning](#7-prefix-scanning)
75
- 8. [SQL Operations](#8-sql-operations)
76
- 9. [Table Management & Index Policies](#9-table-management--index-policies)
77
- 10. [Namespaces & Multi-Tenancy](#10-namespaces--multi-tenancy)
78
- 11. [Collections & Vector Search](#11-collections--vector-search)
79
- 12. [Hybrid Search (Vector + BM25)](#12-hybrid-search-vector--bm25)
80
- 13. [Graph Operations](#13-graph-operations)
81
- 14. [Temporal Graph (Time-Travel)](#14-temporal-graph-time-travel)
82
- 15. [Semantic Cache](#15-semantic-cache)
83
- 16. [Context Query Builder (LLM Optimization) and Session](#16-context-query-builder-llm-optimization)
84
- 17. [Atomic Multi-Index Writes](#17-atomic-multi-index-writes)
85
- 18. [Recovery & WAL Management](#18-recovery--wal-management)
86
- 19. [Checkpoints & Snapshots](#19-checkpoints--snapshots)
87
- 20. [Compression & Storage](#20-compression--storage)
88
- 21. [Statistics & Monitoring](#21-statistics--monitoring)
89
- 22. [Distributed Tracing](#22-distributed-tracing)
90
- 23. [Workflow & Run Tracking](#23-workflow--run-tracking)
264
+ 3. [Features](#3-features)
265
+ - [Namespace API](#namespace-api---multi-tenant-isolation)
266
+ - [Priority Queue API](#priority-queue-api---task-processing)
267
+ 4. [Architecture Overview](#4-architecture-overview)
268
+ 5. [Core Key-Value Operations](#5-core-key-value-operations)
269
+ 6. [Transactions (ACID with SSI)](#6-transactions-acid-with-ssi)
270
+ 7. [Query Builder](#7-query-builder)
271
+ 8. [Prefix Scanning](#8-prefix-scanning)
272
+ 9. [SQL Operations](#9-sql-operations)
273
+ 10. [Table Management & Index Policies](#10-table-management--index-policies)
274
+ 11. [Namespaces & Collections](#11-namespaces--collections)
275
+ 12. [Priority Queues](#12-priority-queues)
276
+ 13. [Vector Search](#13-vector-search)
277
+ 14. [Hybrid Search (Vector + BM25)](#14-hybrid-search-vector--bm25)
278
+ 15. [Graph Operations](#15-graph-operations)
279
+ 16. [Temporal Graph (Time-Travel)](#16-temporal-graph-time-travel)
280
+ 17. [Semantic Cache](#17-semantic-cache)
281
+ 18. [Context Query Builder (LLM Optimization)](#18-context-query-builder-llm-optimization)
282
+ 19. [Atomic Multi-Index Writes](#19-atomic-multi-index-writes)
283
+ 20. [Recovery & WAL Management](#20-recovery--wal-management)
284
+ 21. [Checkpoints & Snapshots](#21-checkpoints--snapshots)
285
+ 22. [Compression & Storage](#22-compression--storage)
286
+ 23. [Statistics & Monitoring](#23-statistics--monitoring)
91
287
  24. [Server Mode (gRPC Client)](#24-server-mode-grpc-client)
92
288
  25. [IPC Client (Unix Sockets)](#25-ipc-client-unix-sockets)
93
- 26. [Standalone VectorIndex](#26-standalone-vectorindex)
94
- 27. [Vector Utilities](#27-vector-utilities)
95
- 28. [Data Formats (TOON/JSON/Columnar)](#28-data-formats-toonjsoncolumnar)
96
- 29. [Policy Service](#29-policy-service)
97
- 30. [MCP (Model Context Protocol)](#30-mcp-model-context-protocol)
98
- 31. [Configuration Reference](#31-configuration-reference)
99
- 32. [Error Handling](#32-error-handling)
100
- 33. [Async Support](#33-async-support)
101
- 34. [Building & Development](#34-building--development)
102
- 35. [Complete Examples](#35-complete-examples)
103
- 36. [Migration Guide](#36-migration-guide)
289
+ 26. [Error Handling](#26-error-handling)
290
+ 27. [Complete Examples](#27-complete-examples)
104
291
 
105
292
  ---
106
293
 
@@ -46,7 +46,7 @@ sochdb-bulk binary not found!
46
46
  Searched at: ${bundledPath}
47
47
 
48
48
  To fix:
49
- 1. Reinstall the package: npm install --force @sushanth/sochdb
49
+ 1. Reinstall the package: npm install --force @sochdb/sochdb
50
50
  2. Or set SOCHDB_BULK_PATH environment variable
51
51
  `);
52
52
  }
@@ -46,7 +46,7 @@ sochdb-grpc-server binary not found!
46
46
  Searched at: ${bundledPath}
47
47
 
48
48
  To fix:
49
- 1. Reinstall the package: npm install --force @sushanth/sochdb
49
+ 1. Reinstall the package: npm install --force @sochdb/sochdb
50
50
  2. Or set SOCHDB_GRPC_SERVER_PATH environment variable
51
51
  `);
52
52
  }
@@ -46,7 +46,7 @@ sochdb-server binary not found!
46
46
  Searched at: ${bundledPath}
47
47
 
48
48
  To fix:
49
- 1. Reinstall the package: npm install --force @sushanth/sochdb
49
+ 1. Reinstall the package: npm install --force @sochdb/sochdb
50
50
  2. Or set SOCHDB_SERVER_PATH environment variable
51
51
  `);
52
52
  }
@@ -0,0 +1,280 @@
1
+ "use strict";
2
+ /**
3
+ * Context Query Builder for LLM Context Assembly
4
+ *
5
+ * Token-aware context assembly with priority-based truncation.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.ContextQueryBuilder = exports.TruncationStrategy = exports.ContextOutputFormat = void 0;
9
+ exports.createContextBuilder = createContextBuilder;
10
+ var ContextOutputFormat;
11
+ (function (ContextOutputFormat) {
12
+ ContextOutputFormat["TOON"] = "toon";
13
+ ContextOutputFormat["JSON"] = "json";
14
+ ContextOutputFormat["MARKDOWN"] = "markdown";
15
+ })(ContextOutputFormat || (exports.ContextOutputFormat = ContextOutputFormat = {}));
16
+ var TruncationStrategy;
17
+ (function (TruncationStrategy) {
18
+ TruncationStrategy["TAIL_DROP"] = "tail_drop";
19
+ TruncationStrategy["HEAD_DROP"] = "head_drop";
20
+ TruncationStrategy["PROPORTIONAL"] = "proportional";
21
+ })(TruncationStrategy || (exports.TruncationStrategy = TruncationStrategy = {}));
22
+ /**
23
+ * Context Query Builder for assembling LLM context
24
+ */
25
+ class ContextQueryBuilder {
26
+ constructor() {
27
+ this.tokenBudget = 4096;
28
+ this.format = ContextOutputFormat.TOON;
29
+ this.truncation = TruncationStrategy.TAIL_DROP;
30
+ this.sections = [];
31
+ }
32
+ /**
33
+ * Set session ID for context
34
+ */
35
+ forSession(sessionId) {
36
+ this.sessionId = sessionId;
37
+ return this;
38
+ }
39
+ /**
40
+ * Set token budget
41
+ */
42
+ withBudget(tokens) {
43
+ this.tokenBudget = tokens;
44
+ return this;
45
+ }
46
+ /**
47
+ * Set output format
48
+ */
49
+ setFormat(format) {
50
+ this.format = format;
51
+ return this;
52
+ }
53
+ /**
54
+ * Set truncation strategy
55
+ */
56
+ setTruncation(strategy) {
57
+ this.truncation = strategy;
58
+ return this;
59
+ }
60
+ /**
61
+ * Add literal text section
62
+ */
63
+ literal(name, priority, text) {
64
+ const tokenCount = this.estimateTokens(text);
65
+ this.sections.push({
66
+ name,
67
+ priority,
68
+ content: text,
69
+ tokenCount,
70
+ });
71
+ return this;
72
+ }
73
+ /**
74
+ * Start a new section
75
+ */
76
+ section(name, priority) {
77
+ this.currentSection = {
78
+ name,
79
+ priority,
80
+ content: '',
81
+ tokenCount: 0,
82
+ };
83
+ return this;
84
+ }
85
+ /**
86
+ * Add content to current section
87
+ */
88
+ get(path) {
89
+ if (!this.currentSection) {
90
+ throw new Error('No active section. Call section() first.');
91
+ }
92
+ this.currentSection.content += `GET ${path}\n`;
93
+ return this;
94
+ }
95
+ /**
96
+ * Add last N records query
97
+ */
98
+ last(n, table) {
99
+ if (!this.currentSection) {
100
+ throw new Error('No active section. Call section() first.');
101
+ }
102
+ this.currentSection.content += `LAST ${n} FROM ${table}\n`;
103
+ return this;
104
+ }
105
+ /**
106
+ * Add where equals condition
107
+ */
108
+ whereEq(field, value) {
109
+ if (!this.currentSection) {
110
+ throw new Error('No active section. Call section() first.');
111
+ }
112
+ this.currentSection.content += `WHERE ${field} = ${JSON.stringify(value)}\n`;
113
+ return this;
114
+ }
115
+ /**
116
+ * Add vector search
117
+ */
118
+ search(collection, embedding, k) {
119
+ if (!this.currentSection) {
120
+ throw new Error('No active section. Call section() first.');
121
+ }
122
+ this.currentSection.content += `SEARCH ${collection} WITH ${embedding} LIMIT ${k}\n`;
123
+ return this;
124
+ }
125
+ /**
126
+ * Add SQL query
127
+ */
128
+ sql(query) {
129
+ if (!this.currentSection) {
130
+ throw new Error('No active section. Call section() first.');
131
+ }
132
+ this.currentSection.content += `SQL: ${query}\n`;
133
+ return this;
134
+ }
135
+ /**
136
+ * Finish current section
137
+ */
138
+ done() {
139
+ if (this.currentSection) {
140
+ this.currentSection.tokenCount = this.estimateTokens(this.currentSection.content);
141
+ this.sections.push(this.currentSection);
142
+ this.currentSection = undefined;
143
+ }
144
+ return this;
145
+ }
146
+ /**
147
+ * Execute and build context
148
+ */
149
+ execute() {
150
+ // Finish any pending section
151
+ if (this.currentSection) {
152
+ this.done();
153
+ }
154
+ // Sort sections by priority (lower = higher priority)
155
+ const sortedSections = [...this.sections].sort((a, b) => a.priority - b.priority);
156
+ // Calculate total tokens
157
+ let totalTokens = sortedSections.reduce((sum, s) => sum + s.tokenCount, 0);
158
+ // Truncate if needed
159
+ const truncatedSections = [];
160
+ const includedSections = [];
161
+ if (totalTokens <= this.tokenBudget) {
162
+ // No truncation needed
163
+ for (const section of sortedSections) {
164
+ includedSections.push(section);
165
+ truncatedSections.push({
166
+ name: section.name,
167
+ tokenCount: section.tokenCount,
168
+ truncated: false,
169
+ });
170
+ }
171
+ }
172
+ else {
173
+ // Apply truncation strategy
174
+ let remainingBudget = this.tokenBudget;
175
+ if (this.truncation === TruncationStrategy.TAIL_DROP) {
176
+ // Include sections in priority order until budget exhausted
177
+ for (const section of sortedSections) {
178
+ if (section.tokenCount <= remainingBudget) {
179
+ includedSections.push(section);
180
+ remainingBudget -= section.tokenCount;
181
+ truncatedSections.push({
182
+ name: section.name,
183
+ tokenCount: section.tokenCount,
184
+ truncated: false,
185
+ });
186
+ }
187
+ else {
188
+ truncatedSections.push({
189
+ name: section.name,
190
+ tokenCount: 0,
191
+ truncated: true,
192
+ });
193
+ }
194
+ }
195
+ }
196
+ else if (this.truncation === TruncationStrategy.PROPORTIONAL) {
197
+ // Proportionally reduce all sections
198
+ const ratio = this.tokenBudget / totalTokens;
199
+ for (const section of sortedSections) {
200
+ const allocatedTokens = Math.floor(section.tokenCount * ratio);
201
+ const truncatedContent = this.truncateText(section.content, allocatedTokens);
202
+ includedSections.push({
203
+ ...section,
204
+ content: truncatedContent,
205
+ tokenCount: allocatedTokens,
206
+ });
207
+ truncatedSections.push({
208
+ name: section.name,
209
+ tokenCount: allocatedTokens,
210
+ truncated: allocatedTokens < section.tokenCount,
211
+ });
212
+ }
213
+ }
214
+ }
215
+ // Build final context based on format
216
+ let text = '';
217
+ let actualTokens = 0;
218
+ if (this.format === ContextOutputFormat.TOON) {
219
+ text = this.buildToonFormat(includedSections);
220
+ }
221
+ else if (this.format === ContextOutputFormat.JSON) {
222
+ text = this.buildJsonFormat(includedSections);
223
+ }
224
+ else {
225
+ text = this.buildMarkdownFormat(includedSections);
226
+ }
227
+ actualTokens = this.estimateTokens(text);
228
+ return {
229
+ text,
230
+ tokenCount: actualTokens,
231
+ sections: truncatedSections,
232
+ };
233
+ }
234
+ // Helper methods
235
+ estimateTokens(text) {
236
+ // Rough estimate: ~4 characters per token for English
237
+ return Math.ceil(text.length / 4);
238
+ }
239
+ truncateText(text, maxTokens) {
240
+ const maxChars = maxTokens * 4;
241
+ if (text.length <= maxChars) {
242
+ return text;
243
+ }
244
+ return text.substring(0, maxChars) + '...';
245
+ }
246
+ buildToonFormat(sections) {
247
+ const lines = [];
248
+ for (const section of sections) {
249
+ lines.push(`[${section.name}]`);
250
+ lines.push(section.content);
251
+ lines.push('');
252
+ }
253
+ return lines.join('\n');
254
+ }
255
+ buildJsonFormat(sections) {
256
+ const obj = {};
257
+ for (const section of sections) {
258
+ obj[section.name] = section.content;
259
+ }
260
+ return JSON.stringify(obj, null, 2);
261
+ }
262
+ buildMarkdownFormat(sections) {
263
+ const lines = [];
264
+ for (const section of sections) {
265
+ lines.push(`## ${section.name}`);
266
+ lines.push('');
267
+ lines.push(section.content);
268
+ lines.push('');
269
+ }
270
+ return lines.join('\n');
271
+ }
272
+ }
273
+ exports.ContextQueryBuilder = ContextQueryBuilder;
274
+ /**
275
+ * Create a context query builder
276
+ */
277
+ function createContextBuilder() {
278
+ return new ContextQueryBuilder();
279
+ }
280
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGV4dC1idWlsZGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbnRleHQtYnVpbGRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7R0FJRzs7O0FBc1RILG9EQUVDO0FBdFRELElBQVksbUJBSVg7QUFKRCxXQUFZLG1CQUFtQjtJQUM3QixvQ0FBYSxDQUFBO0lBQ2Isb0NBQWEsQ0FBQTtJQUNiLDRDQUFxQixDQUFBO0FBQ3ZCLENBQUMsRUFKVyxtQkFBbUIsbUNBQW5CLG1CQUFtQixRQUk5QjtBQUVELElBQVksa0JBSVg7QUFKRCxXQUFZLGtCQUFrQjtJQUM1Qiw2Q0FBdUIsQ0FBQTtJQUN2Qiw2Q0FBdUIsQ0FBQTtJQUN2QixtREFBNkIsQ0FBQTtBQUMvQixDQUFDLEVBSlcsa0JBQWtCLGtDQUFsQixrQkFBa0IsUUFJN0I7QUFlRDs7R0FFRztBQUNILE1BQWEsbUJBQW1CO0lBQWhDO1FBRVUsZ0JBQVcsR0FBVyxJQUFJLENBQUM7UUFDM0IsV0FBTSxHQUF3QixtQkFBbUIsQ0FBQyxJQUFJLENBQUM7UUFDdkQsZUFBVSxHQUF1QixrQkFBa0IsQ0FBQyxTQUFTLENBQUM7UUFDOUQsYUFBUSxHQUFjLEVBQUUsQ0FBQztJQThRbkMsQ0FBQztJQTNRQzs7T0FFRztJQUNILFVBQVUsQ0FBQyxTQUFpQjtRQUMxQixJQUFJLENBQUMsU0FBUyxHQUFHLFNBQVMsQ0FBQztRQUMzQixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7T0FFRztJQUNILFVBQVUsQ0FBQyxNQUFjO1FBQ3ZCLElBQUksQ0FBQyxXQUFXLEdBQUcsTUFBTSxDQUFDO1FBQzFCLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOztPQUVHO0lBQ0gsU0FBUyxDQUFDLE1BQTJCO1FBQ25DLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDO1FBQ3JCLE9BQU8sSUFBSSxDQUFDO0lBQ2QsQ0FBQztJQUVEOztPQUVHO0lBQ0gsYUFB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YSxFQUFFLENBQUM7UUFFM0IsS0FBSyxNQUFNLE9BQU8sSUFBSSxRQUFRLEVBQUUsQ0FBQztZQUMvQixLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sT0FBTyxDQUFDLElBQUksRUFBRSxDQUFDLENBQUM7WUFDakMsS0FBSyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUNmLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFDO1lBQzVCLEtBQUssQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7UUFDakIsQ0FBQztRQUVELE9BQU8sS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUMxQixDQUFDO0NBQ0Y7QUFuUkQsa0RBbVJDO0FBRUQ7O0dBRUc7QUFDSCxTQUFnQixvQkFBb0I7SUFDbEMsT0FBTyxJQUFJLG1CQUFtQixFQUFFLENBQUM7QUFDbkMsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQ29udGV4dCBRdWVyeSBCdWlsZGVyIGZvciBMTE0gQ29udGV4dCBBc3NlbWJseVxuICogXG4gKiBUb2tlbi1hd2FyZSBjb250ZXh0IGFzc2VtYmx5IHdpdGggcHJpb3JpdHktYmFzZWQgdHJ1bmNhdGlvbi5cbiAqL1xuXG5leHBvcnQgZW51bSBDb250ZXh0T3V0cHV0Rm9ybWF0IHtcbiAgVE9PTiA9ICd0b29uJyxcbiAgSlNPTiA9ICdqc29uJyxcbiAgTUFSS0RPV04gPSAnbWFya2Rvd24nLFxufVxuXG5leHBvcnQgZW51bSBUcnVuY2F0aW9uU3RyYXRlZ3kge1xuICBUQUlMX0RST1AgPSAndGFpbF9kcm9wJywgICAgICAgLy8gRHJvcCBmcm9tIGVuZFxuICBIRUFEX0RST1AgPSAnaGVhZF9kcm9wJywgICAgICAgLy8gRHJvcCBmcm9tIGJlZ2lubmluZ1xuICBQUk9QT1JUSU9OQUwgPSAncHJvcG9ydGlvbmFsJywgLy8gUHJvcG9ydGlvbmFsIGFjcm9zcyBzZWN0aW9uc1xufVxuXG5pbnRlcmZhY2UgU2VjdGlvbiB7XG4gIG5hbWU6IHN0cmluZztcbiAgcHJpb3JpdHk6IG51bWJlcjtcbiAgY29udGVudDogc3RyaW5nO1xuICB0b2tlbkNvdW50OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29udGV4dFJlc3VsdCB7XG4gIHRleHQ6IHN0cmluZztcbiAgdG9rZW5Db3VudDogbnVtYmVyO1xuICBzZWN0aW9uczogQXJyYXk8eyBuYW1lOiBzdHJpbmc7IHRva2VuQ291bnQ6IG51bWJlcjsgdHJ1bmNhdGVkOiBib29sZWFuIH0+O1xufVxuXG4vKipcbiAqIENvbnRleHQgUXVlcnkgQnVpbGRlciBmb3IgYXNzZW1ibGluZyBMTE0gY29udGV4dFxuICovXG5leHBvcnQgY2xhc3MgQ29udGV4dFF1ZXJ5QnVpbGRlciB7XG4gIHByaXZhdGUgc2Vzc2lvbklkPzogc3RyaW5nO1xuICBwcml2YXRlIHRva2VuQnVkZ2V0OiBudW1iZXIgPSA0MDk2O1xuICBwcml2YXRlIGZvcm1hdDogQ29udGV4dE91dHB1dEZvcm1hdCA9IENvbnRleHRPdXRwdXRGb3JtYXQuVE9PTjtcbiAgcHJpdmF0ZSB0cnVuY2F0aW9uOiBUcnVuY2F0aW9uU3RyYXRlZ3kgPSBUcnVuY2F0aW9uU3RyYXRlZ3kuVEFJTF9EUk9QO1xuICBwcml2YXRlIHNlY3Rpb25zOiBTZWN0aW9uW10gPSBbXTtcbiAgcHJpdmF0ZSBjdXJyZW50U2VjdGlvbj86IFNlY3Rpb247XG5cbiAgLyoqXG4gICAqIFNldCBzZXNzaW9uIElEIGZvciBjb250ZXh0XG4gICAqL1xuICBmb3JTZXNzaW9uKHNlc3Npb25JZDogc3RyaW5nKTogdGhpcyB7XG4gICAgdGhpcy5zZXNzaW9uSWQgPSBzZXNzaW9uSWQ7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogU2V0IHRva2VuIGJ1ZGdldFxuICAgKi9cbiAgd2l0aEJ1ZGdldCh0b2tlbnM6IG51bWJlcik6IHRoaXMge1xuICAgIHRoaXMudG9rZW5CdWRnZXQgPSB0b2tlbnM7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogU2V0IG91dHB1dCBmb3JtYXRcbiAgICovXG4gIHNldEZvcm1hdChmb3JtYXQ6IENvbnRleHRPdXRwdXRGb3JtYXQpOiB0aGlzIHtcbiAgICB0aGlzLmZvcm1hdCA9IGZvcm1hdDtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBTZXQgdHJ1bmNhdGlvbiBzdHJhdGVneVxuICAgKi9cbiAgc2V0VHJ1bmNhdGlvbihzdHJhdGVneTogVHJ1bmNhdGlvblN0cmF0ZWd5KTogdGhpcyB7XG4gICAgdGhpcy50cnVuY2F0aW9uID0gc3RyYXRlZ3k7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQWRkIGxpdGVyYWwgdGV4dCBzZWN0aW9uXG4gICAqL1xuICBsaXRlcmFsKG5hbWU6IHN0cmluZywgcHJpb3JpdHk6IG51bWJlciwgdGV4dDogc3RyaW5nKTogdGhpcyB7XG4gICAgY29uc3QgdG9rZW5Db3VudCA9IHRoaXMuZXN0aW1hdGVUb2tlbnModGV4dCk7XG4gICAgdGhpcy5zZWN0aW9ucy5wdXNoKHtcbiAgICAgIG5hbWUsXG4gICAgICBwcmlvcml0eSxcbiAgICAgIGNvbnRlbnQ6IHRleHQsXG4gICAgICB0b2tlbkNvdW50LFxuICAgIH0pO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIFN0YXJ0IGEgbmV3IHNlY3Rpb25cbiAgICovXG4gIHNlY3Rpb24obmFtZTogc3RyaW5nLCBwcmlvcml0eTogbnVtYmVyKTogdGhpcyB7XG4gICAgdGhpcy5jdXJyZW50U2VjdGlvbiA9IHtcbiAgICAgIG5hbWUsXG4gICAgICBwcmlvcml0eSxcbiAgICAgIGNvbnRlbnQ6ICcnLFxuICAgICAgdG9rZW5Db3VudDogMCxcbiAgICB9O1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBjb250ZW50IHRvIGN1cnJlbnQgc2VjdGlvblxuICAgKi9cbiAgZ2V0KHBhdGg6IHN0cmluZyk6IHRoaXMge1xuICAgIGlmICghdGhpcy5jdXJyZW50U2VjdGlvbikge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKCdObyBhY3RpdmUgc2VjdGlvbi4gQ2FsbCBzZWN0aW9uKCkgZmlyc3QuJyk7XG4gICAgfVxuICAgIHRoaXMuY3VycmVudFNlY3Rpb24uY29udGVudCArPSBgR0VUICR7cGF0aH1cXG5gO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBsYXN0IE4gcmVjb3JkcyBxdWVyeVxuICAgKi9cbiAgbGFzdChuOiBudW1iZXIsIHRhYmxlOiBzdHJpbmcpOiB0aGlzIHtcbiAgICBpZiAoIXRoaXMuY3VycmVudFNlY3Rpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTm8gYWN0aXZlIHNlY3Rpb24uIENhbGwgc2VjdGlvbigpIGZpcnN0LicpO1xuICAgIH1cbiAgICB0aGlzLmN1cnJlbnRTZWN0aW9uLmNvbnRlbnQgKz0gYExBU1QgJHtufSBGUk9NICR7dGFibGV9XFxuYDtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBBZGQgd2hlcmUgZXF1YWxzIGNvbmRpdGlvblxuICAgKi9cbiAgd2hlcmVFcShmaWVsZDogc3RyaW5nLCB2YWx1ZTogYW55KTogdGhpcyB7XG4gICAgaWYgKCF0aGlzLmN1cnJlbnRTZWN0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIGFjdGl2ZSBzZWN0aW9uLiBDYWxsIHNlY3Rpb24oKSBmaXJzdC4nKTtcbiAgICB9XG4gICAgdGhpcy5jdXJyZW50U2VjdGlvbi5jb250ZW50ICs9IGBXSEVSRSAke2ZpZWxkfSA9ICR7SlNPTi5zdHJpbmdpZnkodmFsdWUpfVxcbmA7XG4gICAgcmV0dXJuIHRoaXM7XG4gIH1cblxuICAvKipcbiAgICogQWRkIHZlY3RvciBzZWFyY2hcbiAgICovXG4gIHNlYXJjaChjb2xsZWN0aW9uOiBzdHJpbmcsIGVtYmVkZGluZzogc3RyaW5nLCBrOiBudW1iZXIpOiB0aGlzIHtcbiAgICBpZiAoIXRoaXMuY3VycmVudFNlY3Rpb24pIHtcbiAgICAgIHRocm93IG5ldyBFcnJvcignTm8gYWN0aXZlIHNlY3Rpb24uIENhbGwgc2VjdGlvbigpIGZpcnN0LicpO1xuICAgIH1cbiAgICB0aGlzLmN1cnJlbnRTZWN0aW9uLmNvbnRlbnQgKz0gYFNFQVJDSCAke2NvbGxlY3Rpb259IFdJVEggJHtlbWJlZGRpbmd9IExJTUlUICR7a31cXG5gO1xuICAgIHJldHVybiB0aGlzO1xuICB9XG5cbiAgLyoqXG4gICAqIEFkZCBTUUwgcXVlcnlcbiAgICovXG4gIHNxbChxdWVyeTogc3RyaW5nKTogdGhpcyB7XG4gICAgaWYgKCF0aGlzLmN1cnJlbnRTZWN0aW9uKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ05vIGFjdGl2ZSBzZWN0aW9uLiBDYWxsIHNlY3Rpb24oKSBmaXJzdC4nKTtcbiAgICB9XG4gICAgdGhpcy5jdXJyZW50U2VjdGlvbi5jb250ZW50ICs9IGBTUUw6ICR7cXVlcnl9XFxuYDtcbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBGaW5pc2ggY3VycmVudCBzZWN0aW9uXG4gICAqL1xuICBkb25lKCk6IHRoaXMge1xuICAgIGlmICh0aGlzLmN1cnJlbnRTZWN0aW9uKSB7XG4gICAgICB0aGlzLmN1cnJlbnRTZWN0aW9uLnRva2VuQ291bnQgPSB0aGlzLmVzdGltYXRlVG9rZW5zKHRoaXMuY3VycmVudFNlY3Rpb24uY29udGVudCk7XG4gICAgICB0aGlzLnNlY3Rpb25zLnB1c2godGhpcy5jdXJyZW50U2VjdGlvbik7XG4gICAgICB0aGlzLmN1cnJlbnRTZWN0aW9uID0gdW5kZWZpbmVkO1xuICAgIH1cbiAgICByZXR1cm4gdGhpcztcbiAgfVxuXG4gIC8qKlxuICAgKiBFeGVjdXRlIGFuZCBidWlsZCBjb250ZXh0XG4gICAqL1xuICBleGVjdXRlKCk6IENvbnRleHRSZXN1bHQge1xuICAgIC8vIEZpbmlzaCBhbnkgcGVuZGluZyBzZWN0aW9uXG4gICAgaWYgKHRoaXMuY3VycmVudFNlY3Rpb24pIHtcbiAgICAgIHRoaXMuZG9uZSgpO1xuICAgIH1cblxuICAgIC8vIFNvcnQgc2VjdGlvbnMgYnkgcHJpb3JpdHkgKGxvd2VyID0gaGlnaGVyIHByaW9yaXR5KVxuICAgIGNvbnN0IHNvcnRlZFNlY3Rpb25zID0gWy4uLnRoaXMuc2VjdGlvbnNdLnNvcnQoKGEsIGIpID0+IGEucHJpb3JpdHkgLSBiLnByaW9yaXR5KTtcblxuICAgIC8vIENhbGN1bGF0ZSB0b3RhbCB0b2tlbnNcbiAgICBsZXQgdG90YWxUb2tlbnMgPSBzb3J0ZWRTZWN0aW9ucy5yZWR1Y2UoKHN1bSwgcykgPT4gc3VtICsgcy50b2tlbkNvdW50LCAwKTtcblxuICAgIC8vIFRydW5jYXRlIGlmIG5lZWRlZFxuICAgIGNvbnN0IHRydW5jYXRlZFNlY3Rpb25zOiBBcnJheTx7IG5hbWU6IHN0cmluZzsgdG9rZW5Db3VudDogbnVtYmVyOyB0cnVuY2F0ZWQ6IGJvb2xlYW4gfT4gPSBbXTtcbiAgICBjb25zdCBpbmNsdWRlZFNlY3Rpb25zOiBTZWN0aW9uW10gPSBbXTtcblxuICAgIGlmICh0b3RhbFRva2VucyA8PSB0aGlzLnRva2VuQnVkZ2V0KSB7XG4gICAgICAvLyBObyB0cnVuY2F0aW9uIG5lZWRlZFxuICAgICAgZm9yIChjb25zdCBzZWN0aW9uIG9mIHNvcnRlZFNlY3Rpb25zKSB7XG4gICAgICAgIGluY2x1ZGVkU2VjdGlvbnMucHVzaChzZWN0aW9uKTtcbiAgICAgICAgdHJ1bmNhdGVkU2VjdGlvbnMucHVzaCh7XG4gICAgICAgICAgbmFtZTogc2VjdGlvbi5uYW1lLFxuICAgICAgICAgIHRva2VuQ291bnQ6IHNlY3Rpb24udG9rZW5Db3VudCxcbiAgICAgICAgICB0cnVuY2F0ZWQ6IGZhbHNlLFxuICAgICAgICB9KTtcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgLy8gQXBwbHkgdHJ1bmNhdGlvbiBzdHJhdGVneVxuICAgICAgbGV0IHJlbWFpbmluZ0J1ZGdldCA9IHRoaXMudG9rZW5CdWRnZXQ7XG5cbiAgICAgIGlmICh0aGlzLnRydW5jYXRpb24gPT09IFRydW5jYXRpb25TdHJhdGVneS5UQUlMX0RST1ApIHtcbiAgICAgICAgLy8gSW5jbHVkZSBzZWN0aW9ucyBpbiBwcmlvcml0eSBvcmRlciB1bnRpbCBidWRnZXQgZXhoYXVzdGVkXG4gICAgICAgIGZvciAoY29uc3Qgc2VjdGlvbiBvZiBzb3J0ZWRTZWN0aW9ucykge1xuICAgICAgICAgIGlmIChzZWN0aW9uLnRva2VuQ291bnQgPD0gcmVtYWluaW5nQnVkZ2V0KSB7XG4gICAgICAgICAgICBpbmNsdWRlZFNlY3Rpb25zLnB1c2goc2VjdGlvbik7XG4gICAgICAgICAgICByZW1haW5pbmdCdWRnZXQgLT0gc2VjdGlvbi50b2tlbkNvdW50O1xuICAgICAgICAgICAgdHJ1bmNhdGVkU2VjdGlvbnMucHVzaCh7XG4gICAgICAgICAgICAgIG5hbWU6IHNlY3Rpb24ubmFtZSxcbiAgICAgICAgICAgICAgdG9rZW5Db3VudDogc2VjdGlvbi50b2tlbkNvdW50LFxuICAgICAgICAgICAgICB0cnVuY2F0ZWQ6IGZhbHNlLFxuICAgICAgICAgICAgfSk7XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHRydW5jYXRlZFNlY3Rpb25zLnB1c2goe1xuICAgICAgICAgICAgICBuYW1lOiBzZWN0aW9uLm5hbWUsXG4gICAgICAgICAgICAgIHRva2VuQ291bnQ6IDAsXG4gICAgICAgICAgICAgIHRydW5jYXRlZDogdHJ1ZSxcbiAgICAgICAgICAgIH0pO1xuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfSBlbHNlIGlmICh0aGlzLnRydW5jYXRpb24gPT09IFRydW5jYXRpb25TdHJhdGVneS5QUk9QT1JUSU9OQUwpIHtcbiAgICAgICAgLy8gUHJvcG9ydGlvbmFsbHkgcmVkdWNlIGFsbCBzZWN0aW9uc1xuICAgICAgICBjb25zdCByYXRpbyA9IHRoaXMudG9rZW5CdWRnZXQgLyB0b3RhbFRva2VucztcbiAgICAgICAgZm9yIChjb25zdCBzZWN0aW9uIG9mIHNvcnRlZFNlY3Rpb25zKSB7XG4gICAgICAgICAgY29uc3QgYWxsb2NhdGVkVG9rZW5zID0gTWF0aC5mbG9vcihzZWN0aW9uLnRva2VuQ291bnQgKiByYXRpbyk7XG4gICAgICAgICAgY29uc3QgdHJ1bmNhdGVkQ29udGVudCA9IHRoaXMudHJ1bmNhdGVUZXh0KHNlY3Rpb24uY29udGVudCwgYWxsb2NhdGVkVG9rZW5zKTtcbiAgICAgICAgICBpbmNsdWRlZFNlY3Rpb25zLnB1c2goe1xuICAgICAgICAgICAgLi4uc2VjdGlvbixcbiAgICAgICAgICAgIGNvbnRlbnQ6IHRydW5jYXRlZENvbnRlbnQsXG4gICAgICAgICAgICB0b2tlbkNvdW50OiBhbGxvY2F0ZWRUb2tlbnMsXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgdHJ1bmNhdGVkU2VjdGlvbnMucHVzaCh7XG4gICAgICAgICAgICBuYW1lOiBzZWN0aW9uLm5hbWUsXG4gICAgICAgICAgICB0b2tlbkNvdW50OiBhbGxvY2F0ZWRUb2tlbnMsXG4gICAgICAgICAgICB0cnVuY2F0ZWQ6IGFsbG9jYXRlZFRva2VucyA8IHNlY3Rpb24udG9rZW5Db3VudCxcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cblxuICAgIC8vIEJ1aWxkIGZpbmFsIGNvbnRleHQgYmFzZWQgb24gZm9ybWF0XG4gICAgbGV0IHRleHQgPSAnJztcbiAgICBsZXQgYWN0dWFsVG9rZW5zID0gMDtcblxuICAgIGlmICh0aGlzLmZvcm1hdCA9PT0gQ29udGV4dE91dHB1dEZvcm1hdC5UT09OKSB7XG4gICAgICB0ZXh0ID0gdGhpcy5idWlsZFRvb25Gb3JtYXQoaW5jbHVkZWRTZWN0aW9ucyk7XG4gICAgfSBlbHNlIGlmICh0aGlzLmZvcm1hdCA9PT0gQ29udGV4dE91dHB1dEZvcm1hdC5KU09OKSB7XG4gICAgICB0ZXh0ID0gdGhpcy5idWlsZEpzb25Gb3JtYXQoaW5jbHVkZWRTZWN0aW9ucyk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRleHQgPSB0aGlzLmJ1aWxkTWFya2Rvd25Gb3JtYXQoaW5jbHVkZWRTZWN0aW9ucyk7XG4gICAgfVxuXG4gICAgYWN0dWFsVG9rZW5zID0gdGhpcy5lc3RpbWF0ZVRva2Vucyh0ZXh0KTtcblxuICAgIHJldHVybiB7XG4gICAgICB0ZXh0LFxuICAgICAgdG9rZW5Db3VudDogYWN0dWFsVG9rZW5zLFxuICAgICAgc2VjdGlvbnM6IHRydW5jYXRlZFNlY3Rpb25zLFxuICAgIH07XG4gIH1cblxuICAvLyBIZWxwZXIgbWV0aG9kc1xuICBwcml2YXRlIGVzdGltYXRlVG9rZW5zKHRleHQ6IHN0cmluZyk6IG51bWJlciB7XG4gICAgLy8gUm91Z2ggZXN0aW1hdGU6IH40IGNoYXJhY3RlcnMgcGVyIHRva2VuIGZvciBFbmdsaXNoXG4gICAgcmV0dXJuIE1hdGguY2VpbCh0ZXh0Lmxlbmd0aCAvIDQpO1xuICB9XG5cbiAgcHJpdmF0ZSB0cnVuY2F0ZVRleHQodGV4dDogc3RyaW5nLCBtYXhUb2tlbnM6IG51bWJlcik6IHN0cmluZyB7XG4gICAgY29uc3QgbWF4Q2hhcnMgPSBtYXhUb2tlbnMgKiA0O1xuICAgIGlmICh0ZXh0Lmxlbmd0aCA8PSBtYXhDaGFycykge1xuICAgICAgcmV0dXJuIHRleHQ7XG4gICAgfVxuICAgIHJldHVybiB0ZXh0LnN1YnN0cmluZygwLCBtYXhDaGFycykgKyAnLi4uJztcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRUb29uRm9ybWF0KHNlY3Rpb25zOiBTZWN0aW9uW10pOiBzdHJpbmcge1xuICAgIGNvbnN0IGxpbmVzOiBzdHJpbmdbXSA9IFtdO1xuICAgIFxuICAgIGZvciAoY29uc3Qgc2VjdGlvbiBvZiBzZWN0aW9ucykge1xuICAgICAgbGluZXMucHVzaChgWyR7c2VjdGlvbi5uYW1lfV1gKTtcbiAgICAgIGxpbmVzLnB1c2goc2VjdGlvbi5jb250ZW50KTtcbiAgICAgIGxpbmVzLnB1c2goJycpO1xuICAgIH1cbiAgICBcbiAgICByZXR1cm4gbGluZXMuam9pbignXFxuJyk7XG4gIH1cblxuICBwcml2YXRlIGJ1aWxkSnNvbkZvcm1hdChzZWN0aW9uczogU2VjdGlvbltdKTogc3RyaW5nIHtcbiAgICBjb25zdCBvYmo6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7fTtcbiAgICBcbiAgICBmb3IgKGNvbnN0IHNlY3Rpb24gb2Ygc2VjdGlvbnMpIHtcbiAgICAgIG9ialtzZWN0aW9uLm5hbWVdID0gc2VjdGlvbi5jb250ZW50O1xuICAgIH1cbiAgICBcbiAgICByZXR1cm4gSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCAyKTtcbiAgfVxuXG4gIHByaXZhdGUgYnVpbGRNYXJrZG93bkZvcm1hdChzZWN0aW9uczogU2VjdGlvbltdKTogc3RyaW5nIHtcbiAgICBjb25zdCBsaW5lczogc3RyaW5nW10gPSBbXTtcbiAgICBcbiAgICBmb3IgKGNvbnN0IHNlY3Rpb24gb2Ygc2VjdGlvbnMpIHtcbiAgICAgIGxpbmVzLnB1c2goYCMjICR7c2VjdGlvbi5uYW1lfWApO1xuICAgICAgbGluZXMucHVzaCgnJyk7XG4gICAgICBsaW5lcy5wdXNoKHNlY3Rpb24uY29udGVudCk7XG4gICAgICBsaW5lcy5wdXNoKCcnKTtcbiAgICB9XG4gICAgXG4gICAgcmV0dXJuIGxpbmVzLmpvaW4oJ1xcbicpO1xuICB9XG59XG5cbi8qKlxuICogQ3JlYXRlIGEgY29udGV4dCBxdWVyeSBidWlsZGVyXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVDb250ZXh0QnVpbGRlcigpOiBDb250ZXh0UXVlcnlCdWlsZGVyIHtcbiAgcmV0dXJuIG5ldyBDb250ZXh0UXVlcnlCdWlsZGVyKCk7XG59XG4iXX0=