@stackmemoryai/stackmemory 0.5.61 → 0.5.62
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/scripts/initialize.js +68 -1
- package/dist/scripts/initialize.js.map +2 -2
- package/dist/src/core/retrieval/index.js +2 -0
- package/dist/src/core/retrieval/index.js.map +2 -2
- package/dist/src/core/retrieval/privacy-filter.js +129 -0
- package/dist/src/core/retrieval/privacy-filter.js.map +7 -0
- package/dist/src/core/retrieval/unified-context-assembler.js +273 -0
- package/dist/src/core/retrieval/unified-context-assembler.js.map +7 -0
- package/dist/src/hooks/diffmem-hooks.js +377 -0
- package/dist/src/hooks/diffmem-hooks.js.map +7 -0
- package/dist/src/integrations/diffmem/client.js +209 -0
- package/dist/src/integrations/diffmem/client.js.map +7 -0
- package/dist/src/integrations/diffmem/config.js +15 -0
- package/dist/src/integrations/diffmem/config.js.map +7 -0
- package/dist/src/integrations/diffmem/index.js +12 -0
- package/dist/src/integrations/diffmem/index.js.map +7 -0
- package/dist/src/integrations/diffmem/types.js +5 -0
- package/dist/src/integrations/diffmem/types.js.map +7 -0
- package/dist/src/integrations/mcp/handlers/diffmem-handlers.js +456 -0
- package/dist/src/integrations/mcp/handlers/diffmem-handlers.js.map +7 -0
- package/dist/src/integrations/mcp/server.js +121 -0
- package/dist/src/integrations/mcp/server.js.map +2 -2
- package/package.json +3 -1
- package/scripts/initialize.ts +83 -1
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
import { join } from "path";
|
|
14
14
|
import { execSync } from "child_process";
|
|
15
15
|
import chalk from "chalk";
|
|
16
|
+
const enableDiffMem = process.argv.includes("--with-diffmem");
|
|
16
17
|
function getEnv(key, defaultValue) {
|
|
17
18
|
const value = process.env[key];
|
|
18
19
|
if (value === void 0) {
|
|
@@ -102,15 +103,81 @@ try {
|
|
|
102
103
|
} catch {
|
|
103
104
|
console.log(chalk.yellow("\u26A0") + " Build failed - run npm run build manually");
|
|
104
105
|
}
|
|
106
|
+
if (enableDiffMem) {
|
|
107
|
+
console.log(chalk.blue("\n\u{1F9E0} Setting up DiffMem integration...\n"));
|
|
108
|
+
const diffmemDir = join(stackDir, "diffmem");
|
|
109
|
+
const diffmemStorageDir = join(diffmemDir, "storage");
|
|
110
|
+
const diffmemWorktreesDir = join(diffmemDir, "worktrees");
|
|
111
|
+
mkdirSync(diffmemStorageDir, { recursive: true });
|
|
112
|
+
mkdirSync(diffmemWorktreesDir, { recursive: true });
|
|
113
|
+
if (!existsSync(join(diffmemStorageDir, ".git"))) {
|
|
114
|
+
try {
|
|
115
|
+
execSync("git init", { cwd: diffmemStorageDir, stdio: "pipe" });
|
|
116
|
+
execSync('git commit --allow-empty -m "Initialize DiffMem storage"', {
|
|
117
|
+
cwd: diffmemStorageDir,
|
|
118
|
+
stdio: "pipe"
|
|
119
|
+
});
|
|
120
|
+
console.log(chalk.green("\u2713") + " Initialized DiffMem storage repository");
|
|
121
|
+
} catch {
|
|
122
|
+
console.log(
|
|
123
|
+
chalk.yellow("\u26A0") + " Failed to initialize git repo for DiffMem"
|
|
124
|
+
);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
const diffmemConfigPath = join(diffmemDir, "config.json");
|
|
128
|
+
const diffmemConfig = {
|
|
129
|
+
enabled: true,
|
|
130
|
+
endpoint: "http://localhost:8000",
|
|
131
|
+
userId: process.env["USER"] || "default",
|
|
132
|
+
storagePath: diffmemStorageDir,
|
|
133
|
+
worktreePath: diffmemWorktreesDir
|
|
134
|
+
};
|
|
135
|
+
writeFileSync(diffmemConfigPath, JSON.stringify(diffmemConfig, null, 2));
|
|
136
|
+
console.log(chalk.green("\u2713") + " Created DiffMem configuration");
|
|
137
|
+
const envPath = join(projectRoot, ".env");
|
|
138
|
+
const diffmemEnvVars = `
|
|
139
|
+
# DiffMem Configuration (Long-term User Memory)
|
|
140
|
+
DIFFMEM_ENABLED=true
|
|
141
|
+
DIFFMEM_ENDPOINT=http://localhost:8000
|
|
142
|
+
DIFFMEM_USER_ID=${process.env["USER"] || "default"}
|
|
143
|
+
DIFFMEM_STORAGE_PATH=${diffmemStorageDir}
|
|
144
|
+
DIFFMEM_WORKTREE_PATH=${diffmemWorktreesDir}
|
|
145
|
+
`;
|
|
146
|
+
if (existsSync(envPath)) {
|
|
147
|
+
const envContent = readFileSync(envPath, "utf-8");
|
|
148
|
+
if (!envContent.includes("DIFFMEM_")) {
|
|
149
|
+
appendFileSync(envPath, diffmemEnvVars);
|
|
150
|
+
console.log(chalk.green("\u2713") + " Added DiffMem configuration to .env");
|
|
151
|
+
}
|
|
152
|
+
} else {
|
|
153
|
+
writeFileSync(envPath, diffmemEnvVars.trim() + "\n");
|
|
154
|
+
console.log(chalk.green("\u2713") + " Created .env with DiffMem configuration");
|
|
155
|
+
}
|
|
156
|
+
console.log(chalk.green("\u2713") + " DiffMem integration configured");
|
|
157
|
+
console.log(
|
|
158
|
+
chalk.gray(
|
|
159
|
+
" Note: DiffMem server must be running for user memory features"
|
|
160
|
+
)
|
|
161
|
+
);
|
|
162
|
+
}
|
|
105
163
|
console.log(chalk.green.bold("\n\u2705 StackMemory initialized successfully!\n"));
|
|
106
164
|
console.log(chalk.gray("Next steps:"));
|
|
107
165
|
console.log(chalk.gray("1. Add the MCP configuration above to Claude Code"));
|
|
108
166
|
console.log(chalk.gray("2. Restart Claude Code"));
|
|
109
167
|
console.log(chalk.gray("3. Start using context tracking!"));
|
|
168
|
+
if (enableDiffMem) {
|
|
169
|
+
console.log(chalk.gray("4. Start DiffMem server: npm run diffmem:start"));
|
|
170
|
+
}
|
|
110
171
|
console.log(chalk.gray("\nUseful commands:"));
|
|
111
172
|
console.log(
|
|
112
173
|
chalk.cyan(" npm run mcp:dev") + " - Start MCP server in dev mode"
|
|
113
174
|
);
|
|
114
175
|
console.log(chalk.cyan(" npm run status") + " - Check StackMemory status");
|
|
115
|
-
console.log(chalk.cyan(" npm run analyze") + " - Analyze context usage
|
|
176
|
+
console.log(chalk.cyan(" npm run analyze") + " - Analyze context usage");
|
|
177
|
+
if (enableDiffMem) {
|
|
178
|
+
console.log(
|
|
179
|
+
chalk.cyan(" npm run diffmem:start") + " - Start DiffMem server"
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
console.log();
|
|
116
183
|
//# sourceMappingURL=initialize.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../scripts/initialize.ts"],
|
|
4
|
-
"sourcesContent": ["#!/usr/bin/env tsx\n/**\n * Initialize StackMemory in the current project\n */\n\nimport {\n existsSync,\n mkdirSync,\n writeFileSync,\n readFileSync,\n appendFileSync,\n} from 'fs';\nimport { join } from 'path';\nimport { execSync } from 'child_process';\nimport chalk from 'chalk';\n// Type-safe environment variable access\nfunction getEnv(key: string, defaultValue?: string): string {\n const value = process.env[key];\n if (value === undefined) {\n if (defaultValue !== undefined) return defaultValue;\n throw new Error(`Environment variable ${key} is required`);\n }\n return value;\n}\n\nfunction getOptionalEnv(key: string): string | undefined {\n return process.env[key];\n}\n\nconst projectRoot = process.cwd();\n\nconsole.log(chalk.blue.bold('\\n\uD83D\uDE80 Initializing StackMemory...\\n'));\n\n// 1. Create .stackmemory directory\nconst stackDir = join(projectRoot, '.stackmemory');\nif (!existsSync(stackDir)) {\n mkdirSync(stackDir, { recursive: true });\n console.log(chalk.green('\u2713') + ' Created .stackmemory directory');\n} else {\n console.log(chalk.yellow('\u26A0') + ' .stackmemory directory already exists');\n}\n\n// 2. Add to .gitignore\nconst gitignorePath = join(projectRoot, '.gitignore');\nconst gitignoreEntry =\n '\\n# StackMemory\\n.stackmemory/*.db\\n.stackmemory/*.db-*\\n';\n\nif (existsSync(gitignorePath)) {\n const gitignore = readFileSync(gitignorePath, 'utf-8');\n if (!gitignore.includes('.stackmemory')) {\n appendFileSync(gitignorePath, gitignoreEntry);\n console.log(chalk.green('\u2713') + ' Added .stackmemory to .gitignore');\n }\n} else {\n writeFileSync(gitignorePath, gitignoreEntry);\n console.log(chalk.green('\u2713') + ' Created .gitignore with .stackmemory');\n}\n\n// 3. Create config file\nconst configPath = join(stackDir, 'config.json');\nif (!existsSync(configPath)) {\n const config = {\n projectId: projectRoot.split('/').pop(),\n userId: process.env['USER'] || 'default',\n teamId: 'local',\n initialized: new Date().toISOString(),\n };\n writeFileSync(configPath, JSON.stringify(config, null, 2));\n console.log(chalk.green('\u2713') + ' Created config file');\n}\n\n// 4. Create initial JSONL file\nconst jsonlPath = join(stackDir, 'frames.jsonl');\nif (!existsSync(jsonlPath)) {\n const initialFrame = {\n id: 'init_' + Date.now(),\n type: 'system',\n content: 'StackMemory initialized',\n timestamp: Date.now(),\n };\n writeFileSync(jsonlPath, JSON.stringify(initialFrame) + '\\n');\n console.log(chalk.green('\u2713') + ' Created frames.jsonl');\n}\n\n// 5. Create MCP config for Claude Code\nconst isMacOS = process.platform === 'darwin';\nconst mcpConfigPath = isMacOS\n ? join(\n process.env['HOME'] || '~',\n 'Library',\n 'Application Support',\n 'Claude',\n 'claude_desktop_config.json'\n )\n : join(\n process.env['HOME'] || '~',\n '.config',\n 'claude',\n 'claude_desktop_config.json'\n );\nconsole.log(chalk.blue('\\n\uD83D\uDCDD MCP Configuration for Claude Code:\\n'));\n\nconst mcpConfig = {\n mcpServers: {\n stackmemory: {\n command: 'node',\n args: [join(projectRoot, 'dist', 'integrations', 'mcp', 'server.js')],\n env: {\n PROJECT_ROOT: projectRoot,\n },\n },\n },\n};\n\nconsole.log(chalk.gray('Add this to your Claude Code MCP configuration:'));\nconsole.log(chalk.gray('(' + mcpConfigPath + ')\\n'));\nconsole.log(chalk.cyan(JSON.stringify(mcpConfig, null, 2)));\n\n// 6. Build the project\nconsole.log(chalk.blue('\\n\uD83D\uDCE6 Building TypeScript files...\\n'));\ntry {\n execSync('npm run build', { stdio: 'inherit', cwd: projectRoot });\n console.log(chalk.green('\u2713') + ' Build completed');\n} catch {\n console.log(chalk.yellow('\u26A0') + ' Build failed - run npm run build manually');\n}\n\nconsole.log(chalk.green.bold('\\n\u2705 StackMemory initialized successfully!\\n'));\nconsole.log(chalk.gray('Next steps:'));\nconsole.log(chalk.gray('1. Add the MCP configuration above to Claude Code'));\nconsole.log(chalk.gray('2. Restart Claude Code'));\nconsole.log(chalk.gray('3. Start using context tracking!'));\nconsole.log(chalk.gray('\\nUseful commands:'));\nconsole.log(\n chalk.cyan(' npm run mcp:dev') + ' - Start MCP server in dev mode'\n);\nconsole.log(chalk.cyan(' npm run status') + ' - Check StackMemory status');\nconsole.log(chalk.cyan(' npm run analyze') + ' - Analyze context usage
|
|
5
|
-
"mappings": ";;;;;AAKA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,YAAY;AACrB,SAAS,gBAAgB;AACzB,OAAO,WAAW;
|
|
4
|
+
"sourcesContent": ["#!/usr/bin/env tsx\n/**\n * Initialize StackMemory in the current project\n */\n\nimport {\n existsSync,\n mkdirSync,\n writeFileSync,\n readFileSync,\n appendFileSync,\n} from 'fs';\nimport { join } from 'path';\nimport { execSync } from 'child_process';\nimport chalk from 'chalk';\n\n// Parse CLI args for --with-diffmem flag\nconst enableDiffMem = process.argv.includes('--with-diffmem');\n// Type-safe environment variable access\nfunction getEnv(key: string, defaultValue?: string): string {\n const value = process.env[key];\n if (value === undefined) {\n if (defaultValue !== undefined) return defaultValue;\n throw new Error(`Environment variable ${key} is required`);\n }\n return value;\n}\n\nfunction getOptionalEnv(key: string): string | undefined {\n return process.env[key];\n}\n\nconst projectRoot = process.cwd();\n\nconsole.log(chalk.blue.bold('\\n\uD83D\uDE80 Initializing StackMemory...\\n'));\n\n// 1. Create .stackmemory directory\nconst stackDir = join(projectRoot, '.stackmemory');\nif (!existsSync(stackDir)) {\n mkdirSync(stackDir, { recursive: true });\n console.log(chalk.green('\u2713') + ' Created .stackmemory directory');\n} else {\n console.log(chalk.yellow('\u26A0') + ' .stackmemory directory already exists');\n}\n\n// 2. Add to .gitignore\nconst gitignorePath = join(projectRoot, '.gitignore');\nconst gitignoreEntry =\n '\\n# StackMemory\\n.stackmemory/*.db\\n.stackmemory/*.db-*\\n';\n\nif (existsSync(gitignorePath)) {\n const gitignore = readFileSync(gitignorePath, 'utf-8');\n if (!gitignore.includes('.stackmemory')) {\n appendFileSync(gitignorePath, gitignoreEntry);\n console.log(chalk.green('\u2713') + ' Added .stackmemory to .gitignore');\n }\n} else {\n writeFileSync(gitignorePath, gitignoreEntry);\n console.log(chalk.green('\u2713') + ' Created .gitignore with .stackmemory');\n}\n\n// 3. Create config file\nconst configPath = join(stackDir, 'config.json');\nif (!existsSync(configPath)) {\n const config = {\n projectId: projectRoot.split('/').pop(),\n userId: process.env['USER'] || 'default',\n teamId: 'local',\n initialized: new Date().toISOString(),\n };\n writeFileSync(configPath, JSON.stringify(config, null, 2));\n console.log(chalk.green('\u2713') + ' Created config file');\n}\n\n// 4. Create initial JSONL file\nconst jsonlPath = join(stackDir, 'frames.jsonl');\nif (!existsSync(jsonlPath)) {\n const initialFrame = {\n id: 'init_' + Date.now(),\n type: 'system',\n content: 'StackMemory initialized',\n timestamp: Date.now(),\n };\n writeFileSync(jsonlPath, JSON.stringify(initialFrame) + '\\n');\n console.log(chalk.green('\u2713') + ' Created frames.jsonl');\n}\n\n// 5. Create MCP config for Claude Code\nconst isMacOS = process.platform === 'darwin';\nconst mcpConfigPath = isMacOS\n ? join(\n process.env['HOME'] || '~',\n 'Library',\n 'Application Support',\n 'Claude',\n 'claude_desktop_config.json'\n )\n : join(\n process.env['HOME'] || '~',\n '.config',\n 'claude',\n 'claude_desktop_config.json'\n );\nconsole.log(chalk.blue('\\n\uD83D\uDCDD MCP Configuration for Claude Code:\\n'));\n\nconst mcpConfig = {\n mcpServers: {\n stackmemory: {\n command: 'node',\n args: [join(projectRoot, 'dist', 'integrations', 'mcp', 'server.js')],\n env: {\n PROJECT_ROOT: projectRoot,\n },\n },\n },\n};\n\nconsole.log(chalk.gray('Add this to your Claude Code MCP configuration:'));\nconsole.log(chalk.gray('(' + mcpConfigPath + ')\\n'));\nconsole.log(chalk.cyan(JSON.stringify(mcpConfig, null, 2)));\n\n// 6. Build the project\nconsole.log(chalk.blue('\\n\uD83D\uDCE6 Building TypeScript files...\\n'));\ntry {\n execSync('npm run build', { stdio: 'inherit', cwd: projectRoot });\n console.log(chalk.green('\u2713') + ' Build completed');\n} catch {\n console.log(chalk.yellow('\u26A0') + ' Build failed - run npm run build manually');\n}\n\n// 7. Optional: Initialize DiffMem for long-term user memory\nif (enableDiffMem) {\n console.log(chalk.blue('\\n\uD83E\uDDE0 Setting up DiffMem integration...\\n'));\n\n const diffmemDir = join(stackDir, 'diffmem');\n const diffmemStorageDir = join(diffmemDir, 'storage');\n const diffmemWorktreesDir = join(diffmemDir, 'worktrees');\n\n // Create DiffMem directories\n mkdirSync(diffmemStorageDir, { recursive: true });\n mkdirSync(diffmemWorktreesDir, { recursive: true });\n\n // Initialize git repo for storage\n if (!existsSync(join(diffmemStorageDir, '.git'))) {\n try {\n execSync('git init', { cwd: diffmemStorageDir, stdio: 'pipe' });\n execSync('git commit --allow-empty -m \"Initialize DiffMem storage\"', {\n cwd: diffmemStorageDir,\n stdio: 'pipe',\n });\n console.log(chalk.green('\u2713') + ' Initialized DiffMem storage repository');\n } catch {\n console.log(\n chalk.yellow('\u26A0') + ' Failed to initialize git repo for DiffMem'\n );\n }\n }\n\n // Create DiffMem config\n const diffmemConfigPath = join(diffmemDir, 'config.json');\n const diffmemConfig = {\n enabled: true,\n endpoint: 'http://localhost:8000',\n userId: process.env['USER'] || 'default',\n storagePath: diffmemStorageDir,\n worktreePath: diffmemWorktreesDir,\n };\n writeFileSync(diffmemConfigPath, JSON.stringify(diffmemConfig, null, 2));\n console.log(chalk.green('\u2713') + ' Created DiffMem configuration');\n\n // Add DiffMem env vars to .env file\n const envPath = join(projectRoot, '.env');\n const diffmemEnvVars = `\n# DiffMem Configuration (Long-term User Memory)\nDIFFMEM_ENABLED=true\nDIFFMEM_ENDPOINT=http://localhost:8000\nDIFFMEM_USER_ID=${process.env['USER'] || 'default'}\nDIFFMEM_STORAGE_PATH=${diffmemStorageDir}\nDIFFMEM_WORKTREE_PATH=${diffmemWorktreesDir}\n`;\n\n if (existsSync(envPath)) {\n const envContent = readFileSync(envPath, 'utf-8');\n if (!envContent.includes('DIFFMEM_')) {\n appendFileSync(envPath, diffmemEnvVars);\n console.log(chalk.green('\u2713') + ' Added DiffMem configuration to .env');\n }\n } else {\n writeFileSync(envPath, diffmemEnvVars.trim() + '\\n');\n console.log(chalk.green('\u2713') + ' Created .env with DiffMem configuration');\n }\n\n console.log(chalk.green('\u2713') + ' DiffMem integration configured');\n console.log(\n chalk.gray(\n ' Note: DiffMem server must be running for user memory features'\n )\n );\n}\n\nconsole.log(chalk.green.bold('\\n\u2705 StackMemory initialized successfully!\\n'));\nconsole.log(chalk.gray('Next steps:'));\nconsole.log(chalk.gray('1. Add the MCP configuration above to Claude Code'));\nconsole.log(chalk.gray('2. Restart Claude Code'));\nconsole.log(chalk.gray('3. Start using context tracking!'));\nif (enableDiffMem) {\n console.log(chalk.gray('4. Start DiffMem server: npm run diffmem:start'));\n}\nconsole.log(chalk.gray('\\nUseful commands:'));\nconsole.log(\n chalk.cyan(' npm run mcp:dev') + ' - Start MCP server in dev mode'\n);\nconsole.log(chalk.cyan(' npm run status') + ' - Check StackMemory status');\nconsole.log(chalk.cyan(' npm run analyze') + ' - Analyze context usage');\nif (enableDiffMem) {\n console.log(\n chalk.cyan(' npm run diffmem:start') + ' - Start DiffMem server'\n );\n}\nconsole.log();\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -5,4 +5,6 @@ const __dirname = __pathDirname(__filename);
|
|
|
5
5
|
export * from "./types.js";
|
|
6
6
|
export * from "./summary-generator.js";
|
|
7
7
|
export * from "./llm-context-retrieval.js";
|
|
8
|
+
export * from "./privacy-filter.js";
|
|
9
|
+
export * from "./unified-context-assembler.js";
|
|
8
10
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/core/retrieval/index.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * LLM-Driven Context Retrieval Module\n * Exports all retrieval functionality\n */\n\nexport * from './types.js';\nexport * from './summary-generator.js';\nexport * from './llm-context-retrieval.js';\n"],
|
|
5
|
-
"mappings": ";;;;AAKA,cAAc;AACd,cAAc;AACd,cAAc;",
|
|
4
|
+
"sourcesContent": ["/**\n * LLM-Driven Context Retrieval Module\n * Exports all retrieval functionality\n */\n\nexport * from './types.js';\nexport * from './summary-generator.js';\nexport * from './llm-context-retrieval.js';\nexport * from './privacy-filter.js';\nexport * from './unified-context-assembler.js';\n"],
|
|
5
|
+
"mappings": ";;;;AAKA,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;AACd,cAAc;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { fileURLToPath as __fileURLToPath } from 'url';
|
|
2
|
+
import { dirname as __pathDirname } from 'path';
|
|
3
|
+
const __filename = __fileURLToPath(import.meta.url);
|
|
4
|
+
const __dirname = __pathDirname(__filename);
|
|
5
|
+
import { SENSITIVE_PATTERNS } from "../security/input-sanitizer.js";
|
|
6
|
+
const PRIVACY_PATTERNS = {
|
|
7
|
+
// Permissive: Only critical secrets
|
|
8
|
+
permissive: [],
|
|
9
|
+
// Standard: Secrets + PII basics
|
|
10
|
+
standard: [
|
|
11
|
+
// Email addresses
|
|
12
|
+
/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b/g,
|
|
13
|
+
// Phone numbers (various formats)
|
|
14
|
+
/\b(?:\+?1[-.\s]?)?(?:\(?\d{3}\)?[-.\s]?)?\d{3}[-.\s]?\d{4}\b/g,
|
|
15
|
+
// SSN-like patterns
|
|
16
|
+
/\b\d{3}[-.\s]?\d{2}[-.\s]?\d{4}\b/g,
|
|
17
|
+
// IP addresses (v4)
|
|
18
|
+
/\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/g
|
|
19
|
+
],
|
|
20
|
+
// Strict: All standard + additional PII
|
|
21
|
+
strict: [
|
|
22
|
+
// Credit card-like numbers (13-19 digits, optionally separated)
|
|
23
|
+
/\b(?:\d{4}[-.\s]?){3,4}\d{1,4}\b/g,
|
|
24
|
+
// Date of birth patterns (various formats)
|
|
25
|
+
/\b(?:0?[1-9]|1[0-2])[-/](?:0?[1-9]|[12][0-9]|3[01])[-/](?:19|20)\d{2}\b/g,
|
|
26
|
+
// AWS-style keys
|
|
27
|
+
/\b(?:AKIA|ABIA|ACCA|ASIA)[A-Z0-9]{16}\b/g,
|
|
28
|
+
// Private key markers
|
|
29
|
+
/-----BEGIN (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----/g,
|
|
30
|
+
// JWT tokens
|
|
31
|
+
/\beyJ[A-Za-z0-9_-]*\.eyJ[A-Za-z0-9_-]*\.[A-Za-z0-9_-]*/g,
|
|
32
|
+
// URLs with credentials
|
|
33
|
+
/(?:https?|ftp):\/\/[^\s:@]+:[^\s:@]+@[^\s]+/gi,
|
|
34
|
+
// MAC addresses
|
|
35
|
+
/\b(?:[0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2}\b/g,
|
|
36
|
+
// UUID-like patterns that might be sensitive
|
|
37
|
+
/\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/gi
|
|
38
|
+
]
|
|
39
|
+
};
|
|
40
|
+
class PrivacyFilter {
|
|
41
|
+
config;
|
|
42
|
+
patterns;
|
|
43
|
+
constructor(config) {
|
|
44
|
+
this.config = config;
|
|
45
|
+
this.patterns = this.buildPatternList();
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Build the complete list of patterns based on privacy mode
|
|
49
|
+
*/
|
|
50
|
+
buildPatternList() {
|
|
51
|
+
const patterns = [];
|
|
52
|
+
patterns.push(...SENSITIVE_PATTERNS);
|
|
53
|
+
switch (this.config.mode) {
|
|
54
|
+
case "strict":
|
|
55
|
+
patterns.push(...PRIVACY_PATTERNS.strict);
|
|
56
|
+
patterns.push(...PRIVACY_PATTERNS.standard);
|
|
57
|
+
break;
|
|
58
|
+
case "standard":
|
|
59
|
+
patterns.push(...PRIVACY_PATTERNS.standard);
|
|
60
|
+
break;
|
|
61
|
+
case "permissive":
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
return patterns;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Filter sensitive patterns from content
|
|
68
|
+
* @param content The content to filter
|
|
69
|
+
* @returns Filtered content and count of redactions
|
|
70
|
+
*/
|
|
71
|
+
filter(content) {
|
|
72
|
+
if (!content) {
|
|
73
|
+
return { filtered: "", redactedCount: 0 };
|
|
74
|
+
}
|
|
75
|
+
let filtered = content;
|
|
76
|
+
let redactedCount = 0;
|
|
77
|
+
for (const pattern of this.patterns) {
|
|
78
|
+
pattern.lastIndex = 0;
|
|
79
|
+
const matches = content.match(pattern);
|
|
80
|
+
if (matches) {
|
|
81
|
+
redactedCount += matches.length;
|
|
82
|
+
}
|
|
83
|
+
filtered = filtered.replace(pattern, "[REDACTED]");
|
|
84
|
+
}
|
|
85
|
+
return { filtered, redactedCount };
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Check if content contains sensitive data without modifying it
|
|
89
|
+
* @param content The content to check
|
|
90
|
+
* @returns True if sensitive data is detected
|
|
91
|
+
*/
|
|
92
|
+
containsSensitive(content) {
|
|
93
|
+
if (!content) return false;
|
|
94
|
+
for (const pattern of this.patterns) {
|
|
95
|
+
pattern.lastIndex = 0;
|
|
96
|
+
if (pattern.test(content)) {
|
|
97
|
+
return true;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Get the current privacy mode
|
|
104
|
+
*/
|
|
105
|
+
getMode() {
|
|
106
|
+
return this.config.mode;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Update the privacy mode and rebuild patterns
|
|
110
|
+
*/
|
|
111
|
+
setMode(mode) {
|
|
112
|
+
this.config.mode = mode;
|
|
113
|
+
this.patterns = this.buildPatternList();
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Get the count of active patterns
|
|
117
|
+
*/
|
|
118
|
+
getPatternCount() {
|
|
119
|
+
return this.patterns.length;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
function createPrivacyFilter(mode = "standard") {
|
|
123
|
+
return new PrivacyFilter({ mode });
|
|
124
|
+
}
|
|
125
|
+
export {
|
|
126
|
+
PrivacyFilter,
|
|
127
|
+
createPrivacyFilter
|
|
128
|
+
};
|
|
129
|
+
//# sourceMappingURL=privacy-filter.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/core/retrieval/privacy-filter.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Privacy Filter for Unified Context Assembly\n * Filters sensitive patterns from content before including in context\n */\n\nimport { SENSITIVE_PATTERNS } from '../security/input-sanitizer.js';\n\nexport type PrivacyMode = 'strict' | 'standard' | 'permissive';\n\nexport interface PrivacyFilterConfig {\n mode: PrivacyMode;\n}\n\nexport interface FilterResult {\n filtered: string;\n redactedCount: number;\n}\n\n/**\n * Additional patterns for privacy filtering beyond security patterns\n * Organized by strictness level\n */\nconst PRIVACY_PATTERNS: Record<PrivacyMode, RegExp[]> = {\n // Permissive: Only critical secrets\n permissive: [],\n\n // Standard: Secrets + PII basics\n standard: [\n // Email addresses\n /\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b/g,\n // Phone numbers (various formats)\n /\\b(?:\\+?1[-.\\s]?)?(?:\\(?\\d{3}\\)?[-.\\s]?)?\\d{3}[-.\\s]?\\d{4}\\b/g,\n // SSN-like patterns\n /\\b\\d{3}[-.\\s]?\\d{2}[-.\\s]?\\d{4}\\b/g,\n // IP addresses (v4)\n /\\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\b/g,\n ],\n\n // Strict: All standard + additional PII\n strict: [\n // Credit card-like numbers (13-19 digits, optionally separated)\n /\\b(?:\\d{4}[-.\\s]?){3,4}\\d{1,4}\\b/g,\n // Date of birth patterns (various formats)\n /\\b(?:0?[1-9]|1[0-2])[-/](?:0?[1-9]|[12][0-9]|3[01])[-/](?:19|20)\\d{2}\\b/g,\n // AWS-style keys\n /\\b(?:AKIA|ABIA|ACCA|ASIA)[A-Z0-9]{16}\\b/g,\n // Private key markers\n /-----BEGIN (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----[\\s\\S]*?-----END (?:RSA |EC |DSA |OPENSSH )?PRIVATE KEY-----/g,\n // JWT tokens\n /\\beyJ[A-Za-z0-9_-]*\\.eyJ[A-Za-z0-9_-]*\\.[A-Za-z0-9_-]*/g,\n // URLs with credentials\n /(?:https?|ftp):\\/\\/[^\\s:@]+:[^\\s:@]+@[^\\s]+/gi,\n // MAC addresses\n /\\b(?:[0-9A-Fa-f]{2}[:-]){5}[0-9A-Fa-f]{2}\\b/g,\n // UUID-like patterns that might be sensitive\n /\\b[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\\b/gi,\n ],\n};\n\n/**\n * Privacy Filter class for filtering sensitive content\n */\nexport class PrivacyFilter {\n private config: PrivacyFilterConfig;\n private patterns: RegExp[];\n\n constructor(config: PrivacyFilterConfig) {\n this.config = config;\n this.patterns = this.buildPatternList();\n }\n\n /**\n * Build the complete list of patterns based on privacy mode\n */\n private buildPatternList(): RegExp[] {\n const patterns: RegExp[] = [];\n\n // Always include security patterns (API keys, tokens, etc.)\n patterns.push(...SENSITIVE_PATTERNS);\n\n // Add mode-specific patterns\n switch (this.config.mode) {\n case 'strict':\n patterns.push(...PRIVACY_PATTERNS.strict);\n patterns.push(...PRIVACY_PATTERNS.standard);\n break;\n case 'standard':\n patterns.push(...PRIVACY_PATTERNS.standard);\n break;\n case 'permissive':\n // Only security patterns (already added above)\n break;\n }\n\n return patterns;\n }\n\n /**\n * Filter sensitive patterns from content\n * @param content The content to filter\n * @returns Filtered content and count of redactions\n */\n filter(content: string): FilterResult {\n if (!content) {\n return { filtered: '', redactedCount: 0 };\n }\n\n let filtered = content;\n let redactedCount = 0;\n\n for (const pattern of this.patterns) {\n // Reset regex state for global patterns\n pattern.lastIndex = 0;\n\n // Count matches before replacing\n const matches = content.match(pattern);\n if (matches) {\n redactedCount += matches.length;\n }\n\n // Replace sensitive content\n filtered = filtered.replace(pattern, '[REDACTED]');\n }\n\n return { filtered, redactedCount };\n }\n\n /**\n * Check if content contains sensitive data without modifying it\n * @param content The content to check\n * @returns True if sensitive data is detected\n */\n containsSensitive(content: string): boolean {\n if (!content) return false;\n\n for (const pattern of this.patterns) {\n pattern.lastIndex = 0;\n if (pattern.test(content)) {\n return true;\n }\n }\n\n return false;\n }\n\n /**\n * Get the current privacy mode\n */\n getMode(): PrivacyMode {\n return this.config.mode;\n }\n\n /**\n * Update the privacy mode and rebuild patterns\n */\n setMode(mode: PrivacyMode): void {\n this.config.mode = mode;\n this.patterns = this.buildPatternList();\n }\n\n /**\n * Get the count of active patterns\n */\n getPatternCount(): number {\n return this.patterns.length;\n }\n}\n\n/**\n * Create a privacy filter with default config\n */\nexport function createPrivacyFilter(\n mode: PrivacyMode = 'standard'\n): PrivacyFilter {\n return new PrivacyFilter({ mode });\n}\n"],
|
|
5
|
+
"mappings": ";;;;AAKA,SAAS,0BAA0B;AAiBnC,MAAM,mBAAkD;AAAA;AAAA,EAEtD,YAAY,CAAC;AAAA;AAAA,EAGb,UAAU;AAAA;AAAA,IAER;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA,EACF;AAAA;AAAA,EAGA,QAAQ;AAAA;AAAA,IAEN;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA,EACF;AACF;AAKO,MAAM,cAAc;AAAA,EACjB;AAAA,EACA;AAAA,EAER,YAAY,QAA6B;AACvC,SAAK,SAAS;AACd,SAAK,WAAW,KAAK,iBAAiB;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAA6B;AACnC,UAAM,WAAqB,CAAC;AAG5B,aAAS,KAAK,GAAG,kBAAkB;AAGnC,YAAQ,KAAK,OAAO,MAAM;AAAA,MACxB,KAAK;AACH,iBAAS,KAAK,GAAG,iBAAiB,MAAM;AACxC,iBAAS,KAAK,GAAG,iBAAiB,QAAQ;AAC1C;AAAA,MACF,KAAK;AACH,iBAAS,KAAK,GAAG,iBAAiB,QAAQ;AAC1C;AAAA,MACF,KAAK;AAEH;AAAA,IACJ;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,OAAO,SAA+B;AACpC,QAAI,CAAC,SAAS;AACZ,aAAO,EAAE,UAAU,IAAI,eAAe,EAAE;AAAA,IAC1C;AAEA,QAAI,WAAW;AACf,QAAI,gBAAgB;AAEpB,eAAW,WAAW,KAAK,UAAU;AAEnC,cAAQ,YAAY;AAGpB,YAAM,UAAU,QAAQ,MAAM,OAAO;AACrC,UAAI,SAAS;AACX,yBAAiB,QAAQ;AAAA,MAC3B;AAGA,iBAAW,SAAS,QAAQ,SAAS,YAAY;AAAA,IACnD;AAEA,WAAO,EAAE,UAAU,cAAc;AAAA,EACnC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,kBAAkB,SAA0B;AAC1C,QAAI,CAAC,QAAS,QAAO;AAErB,eAAW,WAAW,KAAK,UAAU;AACnC,cAAQ,YAAY;AACpB,UAAI,QAAQ,KAAK,OAAO,GAAG;AACzB,eAAO;AAAA,MACT;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA,EAKA,UAAuB;AACrB,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA;AAAA;AAAA;AAAA,EAKA,QAAQ,MAAyB;AAC/B,SAAK,OAAO,OAAO;AACnB,SAAK,WAAW,KAAK,iBAAiB;AAAA,EACxC;AAAA;AAAA;AAAA;AAAA,EAKA,kBAA0B;AACxB,WAAO,KAAK,SAAS;AAAA,EACvB;AACF;AAKO,SAAS,oBACd,OAAoB,YACL;AACf,SAAO,IAAI,cAAc,EAAE,KAAK,CAAC;AACnC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,273 @@
|
|
|
1
|
+
import { fileURLToPath as __fileURLToPath } from 'url';
|
|
2
|
+
import { dirname as __pathDirname } from 'path';
|
|
3
|
+
const __filename = __fileURLToPath(import.meta.url);
|
|
4
|
+
const __dirname = __pathDirname(__filename);
|
|
5
|
+
import {
|
|
6
|
+
createPrivacyFilter
|
|
7
|
+
} from "./privacy-filter.js";
|
|
8
|
+
import { logger } from "../monitoring/logger.js";
|
|
9
|
+
const DEFAULT_UNIFIED_CONTEXT_CONFIG = {
|
|
10
|
+
totalTokenBudget: 8e3,
|
|
11
|
+
userKnowledgeBudget: 0.2,
|
|
12
|
+
// 20%
|
|
13
|
+
taskContextBudget: 0.7,
|
|
14
|
+
// 70%
|
|
15
|
+
systemContextBudget: 0.1,
|
|
16
|
+
// 10%
|
|
17
|
+
privacyMode: "standard"
|
|
18
|
+
};
|
|
19
|
+
function estimateTokens(content) {
|
|
20
|
+
if (!content) return 0;
|
|
21
|
+
return Math.ceil(content.length / 4);
|
|
22
|
+
}
|
|
23
|
+
function truncateToTokenBudget(content, tokenBudget) {
|
|
24
|
+
if (!content) return "";
|
|
25
|
+
const estimatedTokens = estimateTokens(content);
|
|
26
|
+
if (estimatedTokens <= tokenBudget) {
|
|
27
|
+
return content;
|
|
28
|
+
}
|
|
29
|
+
const charLimit = tokenBudget * 4;
|
|
30
|
+
const truncated = content.substring(0, charLimit);
|
|
31
|
+
const lastSpace = truncated.lastIndexOf(" ");
|
|
32
|
+
if (lastSpace > charLimit * 0.8) {
|
|
33
|
+
return truncated.substring(0, lastSpace) + "...";
|
|
34
|
+
}
|
|
35
|
+
return truncated + "...";
|
|
36
|
+
}
|
|
37
|
+
class UnifiedContextAssembler {
|
|
38
|
+
stackMemoryRetrieval;
|
|
39
|
+
diffMemHooks;
|
|
40
|
+
config;
|
|
41
|
+
privacyFilter;
|
|
42
|
+
constructor(stackMemoryRetrieval, diffMemHooks, config = {}) {
|
|
43
|
+
this.stackMemoryRetrieval = stackMemoryRetrieval;
|
|
44
|
+
this.diffMemHooks = diffMemHooks;
|
|
45
|
+
this.config = { ...DEFAULT_UNIFIED_CONTEXT_CONFIG, ...config };
|
|
46
|
+
this.privacyFilter = createPrivacyFilter(this.config.privacyMode);
|
|
47
|
+
const totalAllocation = this.config.userKnowledgeBudget + this.config.taskContextBudget + this.config.systemContextBudget;
|
|
48
|
+
if (Math.abs(totalAllocation - 1) > 1e-3) {
|
|
49
|
+
logger.warn("Budget allocations do not sum to 1.0", {
|
|
50
|
+
userKnowledge: this.config.userKnowledgeBudget,
|
|
51
|
+
taskContext: this.config.taskContextBudget,
|
|
52
|
+
systemContext: this.config.systemContextBudget,
|
|
53
|
+
total: totalAllocation
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Assemble unified context from all sources
|
|
59
|
+
*/
|
|
60
|
+
async assemble(query) {
|
|
61
|
+
const startTime = Date.now();
|
|
62
|
+
let totalPrivacyFiltered = 0;
|
|
63
|
+
const userKnowledgeBudget = Math.floor(
|
|
64
|
+
this.config.totalTokenBudget * this.config.userKnowledgeBudget
|
|
65
|
+
);
|
|
66
|
+
const taskContextBudget = Math.floor(
|
|
67
|
+
this.config.totalTokenBudget * this.config.taskContextBudget
|
|
68
|
+
);
|
|
69
|
+
const systemContextBudget = Math.floor(
|
|
70
|
+
this.config.totalTokenBudget * this.config.systemContextBudget
|
|
71
|
+
);
|
|
72
|
+
const {
|
|
73
|
+
content: userKnowledge,
|
|
74
|
+
memories: diffMemMemories,
|
|
75
|
+
available: diffMemAvailable
|
|
76
|
+
} = await this.gatherUserKnowledge(query, userKnowledgeBudget);
|
|
77
|
+
const userKnowledgeFiltered = this.privacyFilter.filter(userKnowledge);
|
|
78
|
+
totalPrivacyFiltered += userKnowledgeFiltered.redactedCount;
|
|
79
|
+
const filteredUserKnowledge = truncateToTokenBudget(
|
|
80
|
+
userKnowledgeFiltered.filtered,
|
|
81
|
+
userKnowledgeBudget
|
|
82
|
+
);
|
|
83
|
+
const { content: taskContext, frameCount } = await this.gatherTaskContext(
|
|
84
|
+
query,
|
|
85
|
+
taskContextBudget
|
|
86
|
+
);
|
|
87
|
+
const taskContextFiltered = this.privacyFilter.filter(taskContext);
|
|
88
|
+
totalPrivacyFiltered += taskContextFiltered.redactedCount;
|
|
89
|
+
const filteredTaskContext = truncateToTokenBudget(
|
|
90
|
+
taskContextFiltered.filtered,
|
|
91
|
+
taskContextBudget
|
|
92
|
+
);
|
|
93
|
+
const systemContext = this.gatherSystemContext(systemContextBudget);
|
|
94
|
+
const systemContextFiltered = this.privacyFilter.filter(systemContext);
|
|
95
|
+
totalPrivacyFiltered += systemContextFiltered.redactedCount;
|
|
96
|
+
const filteredSystemContext = truncateToTokenBudget(
|
|
97
|
+
systemContextFiltered.filtered,
|
|
98
|
+
systemContextBudget
|
|
99
|
+
);
|
|
100
|
+
const combined = this.combineContextSections(
|
|
101
|
+
filteredUserKnowledge,
|
|
102
|
+
filteredTaskContext,
|
|
103
|
+
filteredSystemContext
|
|
104
|
+
);
|
|
105
|
+
const tokenUsage = {
|
|
106
|
+
userKnowledge: estimateTokens(filteredUserKnowledge),
|
|
107
|
+
taskContext: estimateTokens(filteredTaskContext),
|
|
108
|
+
systemContext: estimateTokens(filteredSystemContext),
|
|
109
|
+
total: estimateTokens(combined),
|
|
110
|
+
budget: this.config.totalTokenBudget
|
|
111
|
+
};
|
|
112
|
+
const metadata = {
|
|
113
|
+
diffMemAvailable,
|
|
114
|
+
diffMemMemories,
|
|
115
|
+
stackMemoryFrames: frameCount,
|
|
116
|
+
privacyFiltered: totalPrivacyFiltered
|
|
117
|
+
};
|
|
118
|
+
logger.info("Unified context assembled", {
|
|
119
|
+
query: query.substring(0, 50),
|
|
120
|
+
tokenUsage,
|
|
121
|
+
metadata,
|
|
122
|
+
assemblyTimeMs: Date.now() - startTime
|
|
123
|
+
});
|
|
124
|
+
return {
|
|
125
|
+
userKnowledge: filteredUserKnowledge,
|
|
126
|
+
taskContext: filteredTaskContext,
|
|
127
|
+
systemContext: filteredSystemContext,
|
|
128
|
+
combined,
|
|
129
|
+
tokenUsage,
|
|
130
|
+
metadata
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Gather user knowledge from DiffMem
|
|
135
|
+
*/
|
|
136
|
+
async gatherUserKnowledge(query, tokenBudget) {
|
|
137
|
+
if (!this.diffMemHooks) {
|
|
138
|
+
return { content: "", memories: 0, available: false };
|
|
139
|
+
}
|
|
140
|
+
try {
|
|
141
|
+
const status = await this.diffMemHooks.getStatus();
|
|
142
|
+
if (!status.connected) {
|
|
143
|
+
logger.debug("DiffMem not connected");
|
|
144
|
+
return { content: "", memories: 0, available: false };
|
|
145
|
+
}
|
|
146
|
+
const memories = await this.diffMemHooks.getRelevantMemories(query, 10);
|
|
147
|
+
if (memories.length === 0) {
|
|
148
|
+
return { content: "", memories: 0, available: true };
|
|
149
|
+
}
|
|
150
|
+
const sections = ["## User Knowledge"];
|
|
151
|
+
const byCategory = /* @__PURE__ */ new Map();
|
|
152
|
+
for (const memory of memories) {
|
|
153
|
+
const existing = byCategory.get(memory.category) || [];
|
|
154
|
+
existing.push(memory);
|
|
155
|
+
byCategory.set(memory.category, existing);
|
|
156
|
+
}
|
|
157
|
+
for (const [category, categoryMemories] of byCategory) {
|
|
158
|
+
sections.push(`
|
|
159
|
+
### ${this.formatCategory(category)}`);
|
|
160
|
+
for (const memory of categoryMemories) {
|
|
161
|
+
const confidence = memory.confidence >= 0.8 ? "(high confidence)" : memory.confidence >= 0.5 ? "" : "(tentative)";
|
|
162
|
+
sections.push(`- ${memory.content} ${confidence}`);
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
const content = sections.join("\n");
|
|
166
|
+
return {
|
|
167
|
+
content: truncateToTokenBudget(content, tokenBudget),
|
|
168
|
+
memories: memories.length,
|
|
169
|
+
available: true
|
|
170
|
+
};
|
|
171
|
+
} catch (error) {
|
|
172
|
+
logger.warn("Failed to gather user knowledge from DiffMem", { error });
|
|
173
|
+
return { content: "", memories: 0, available: false };
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
/**
|
|
177
|
+
* Format category name for display
|
|
178
|
+
*/
|
|
179
|
+
formatCategory(category) {
|
|
180
|
+
return category.split("_").map((word) => word.charAt(0).toUpperCase() + word.slice(1)).join(" ");
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Gather task context from StackMemory
|
|
184
|
+
*/
|
|
185
|
+
async gatherTaskContext(query, tokenBudget) {
|
|
186
|
+
try {
|
|
187
|
+
const retrievedContext = await this.stackMemoryRetrieval.retrieveContext(
|
|
188
|
+
query,
|
|
189
|
+
{
|
|
190
|
+
tokenBudget
|
|
191
|
+
}
|
|
192
|
+
);
|
|
193
|
+
return {
|
|
194
|
+
content: retrievedContext.context,
|
|
195
|
+
frameCount: retrievedContext.frames.length
|
|
196
|
+
};
|
|
197
|
+
} catch (error) {
|
|
198
|
+
logger.warn("Failed to gather task context from StackMemory", { error });
|
|
199
|
+
return { content: "", frameCount: 0 };
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Gather system context (environment, timestamps, etc.)
|
|
204
|
+
*/
|
|
205
|
+
gatherSystemContext(tokenBudget) {
|
|
206
|
+
const sections = ["## System Context"];
|
|
207
|
+
sections.push(`
|
|
208
|
+
**Current Time**: ${(/* @__PURE__ */ new Date()).toISOString()}`);
|
|
209
|
+
const nodeEnv = process.env.NODE_ENV || "development";
|
|
210
|
+
sections.push(`**Environment**: ${nodeEnv}`);
|
|
211
|
+
const projectId = process.env.STACKMEMORY_PROJECT_ID;
|
|
212
|
+
if (projectId) {
|
|
213
|
+
sections.push(`**Project**: ${projectId}`);
|
|
214
|
+
}
|
|
215
|
+
const sessionId = process.env.STACKMEMORY_SESSION_ID;
|
|
216
|
+
if (sessionId) {
|
|
217
|
+
sections.push(`**Session**: ${sessionId.substring(0, 8)}...`);
|
|
218
|
+
}
|
|
219
|
+
const content = sections.join("\n");
|
|
220
|
+
return truncateToTokenBudget(content, tokenBudget);
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Combine all context sections into a single string
|
|
224
|
+
*/
|
|
225
|
+
combineContextSections(userKnowledge, taskContext, systemContext) {
|
|
226
|
+
const sections = [];
|
|
227
|
+
if (taskContext) {
|
|
228
|
+
sections.push(taskContext);
|
|
229
|
+
}
|
|
230
|
+
if (userKnowledge) {
|
|
231
|
+
sections.push(userKnowledge);
|
|
232
|
+
}
|
|
233
|
+
if (systemContext) {
|
|
234
|
+
sections.push(systemContext);
|
|
235
|
+
}
|
|
236
|
+
return sections.join("\n\n---\n\n");
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Update privacy mode
|
|
240
|
+
*/
|
|
241
|
+
setPrivacyMode(mode) {
|
|
242
|
+
this.config.privacyMode = mode;
|
|
243
|
+
this.privacyFilter.setMode(mode);
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Get current configuration
|
|
247
|
+
*/
|
|
248
|
+
getConfig() {
|
|
249
|
+
return { ...this.config };
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Update configuration
|
|
253
|
+
*/
|
|
254
|
+
updateConfig(config) {
|
|
255
|
+
this.config = { ...this.config, ...config };
|
|
256
|
+
if (config.privacyMode) {
|
|
257
|
+
this.privacyFilter.setMode(config.privacyMode);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
function createUnifiedContextAssembler(stackMemoryRetrieval, diffMemHooks = null, config = {}) {
|
|
262
|
+
return new UnifiedContextAssembler(
|
|
263
|
+
stackMemoryRetrieval,
|
|
264
|
+
diffMemHooks,
|
|
265
|
+
config
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
export {
|
|
269
|
+
DEFAULT_UNIFIED_CONTEXT_CONFIG,
|
|
270
|
+
UnifiedContextAssembler,
|
|
271
|
+
createUnifiedContextAssembler
|
|
272
|
+
};
|
|
273
|
+
//# sourceMappingURL=unified-context-assembler.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/core/retrieval/unified-context-assembler.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Unified Context Assembler\n * Combines StackMemory task context with DiffMem user knowledge\n * Applies privacy filtering and respects token budgets\n */\n\nimport {\n PrivacyFilter,\n PrivacyMode,\n createPrivacyFilter,\n} from './privacy-filter.js';\nimport { LLMContextRetrieval } from './llm-context-retrieval.js';\nimport {\n UserMemory,\n MemoryQuery,\n DiffMemStatus,\n} from '../../integrations/diffmem/types.js';\nimport { logger } from '../monitoring/logger.js';\n\n/**\n * Configuration for unified context assembly\n */\nexport interface UnifiedContextConfig {\n /** Total token budget for all context */\n totalTokenBudget: number;\n /** Fraction of budget for user knowledge (0.0-1.0) */\n userKnowledgeBudget: number;\n /** Fraction of budget for task context (0.0-1.0) */\n taskContextBudget: number;\n /** Fraction of budget for system context (0.0-1.0) */\n systemContextBudget: number;\n /** Privacy filtering mode */\n privacyMode: PrivacyMode;\n}\n\n/**\n * Token usage breakdown\n */\nexport interface TokenUsage {\n userKnowledge: number;\n taskContext: number;\n systemContext: number;\n total: number;\n budget: number;\n}\n\n/**\n * Metadata about the assembled context\n */\nexport interface ContextMetadata {\n diffMemAvailable: boolean;\n diffMemMemories: number;\n stackMemoryFrames: number;\n privacyFiltered: number;\n}\n\n/**\n * Result of unified context assembly\n */\nexport interface UnifiedContext {\n /** User knowledge from DiffMem */\n userKnowledge: string;\n /** Task context from StackMemory */\n taskContext: string;\n /** System context (environment, configuration) */\n systemContext: string;\n /** Combined context string */\n combined: string;\n /** Token usage breakdown */\n tokenUsage: TokenUsage;\n /** Assembly metadata */\n metadata: ContextMetadata;\n}\n\n/**\n * Interface for DiffMem hooks (to be implemented by DiffMem integration)\n */\nexport interface DiffMemHooks {\n /** Check if DiffMem is available and connected */\n getStatus(): Promise<DiffMemStatus>;\n /** Query user memories */\n queryMemories(query: MemoryQuery): Promise<UserMemory[]>;\n /** Get memories relevant to a query string */\n getRelevantMemories(query: string, limit?: number): Promise<UserMemory[]>;\n}\n\n/**\n * Default configuration\n */\nexport const DEFAULT_UNIFIED_CONTEXT_CONFIG: UnifiedContextConfig = {\n totalTokenBudget: 8000,\n userKnowledgeBudget: 0.2, // 20%\n taskContextBudget: 0.7, // 70%\n systemContextBudget: 0.1, // 10%\n privacyMode: 'standard',\n};\n\n/**\n * Estimate token count from content\n * Uses rough approximation: 1 token \u2248 4 characters\n */\nfunction estimateTokens(content: string): number {\n if (!content) return 0;\n return Math.ceil(content.length / 4);\n}\n\n/**\n * Truncate content to fit within token budget\n */\nfunction truncateToTokenBudget(content: string, tokenBudget: number): string {\n if (!content) return '';\n\n const estimatedTokens = estimateTokens(content);\n if (estimatedTokens <= tokenBudget) {\n return content;\n }\n\n // Truncate to approximate character limit\n const charLimit = tokenBudget * 4;\n const truncated = content.substring(0, charLimit);\n\n // Try to truncate at a word boundary\n const lastSpace = truncated.lastIndexOf(' ');\n if (lastSpace > charLimit * 0.8) {\n return truncated.substring(0, lastSpace) + '...';\n }\n\n return truncated + '...';\n}\n\n/**\n * Unified Context Assembler\n * Orchestrates context retrieval from multiple sources\n */\nexport class UnifiedContextAssembler {\n private stackMemoryRetrieval: LLMContextRetrieval;\n private diffMemHooks: DiffMemHooks | null;\n private config: UnifiedContextConfig;\n private privacyFilter: PrivacyFilter;\n\n constructor(\n stackMemoryRetrieval: LLMContextRetrieval,\n diffMemHooks: DiffMemHooks | null,\n config: Partial<UnifiedContextConfig> = {}\n ) {\n this.stackMemoryRetrieval = stackMemoryRetrieval;\n this.diffMemHooks = diffMemHooks;\n this.config = { ...DEFAULT_UNIFIED_CONTEXT_CONFIG, ...config };\n this.privacyFilter = createPrivacyFilter(this.config.privacyMode);\n\n // Validate budget allocations\n const totalAllocation =\n this.config.userKnowledgeBudget +\n this.config.taskContextBudget +\n this.config.systemContextBudget;\n\n if (Math.abs(totalAllocation - 1.0) > 0.001) {\n logger.warn('Budget allocations do not sum to 1.0', {\n userKnowledge: this.config.userKnowledgeBudget,\n taskContext: this.config.taskContextBudget,\n systemContext: this.config.systemContextBudget,\n total: totalAllocation,\n });\n }\n }\n\n /**\n * Assemble unified context from all sources\n */\n async assemble(query: string): Promise<UnifiedContext> {\n const startTime = Date.now();\n let totalPrivacyFiltered = 0;\n\n // Calculate token budgets for each section\n const userKnowledgeBudget = Math.floor(\n this.config.totalTokenBudget * this.config.userKnowledgeBudget\n );\n const taskContextBudget = Math.floor(\n this.config.totalTokenBudget * this.config.taskContextBudget\n );\n const systemContextBudget = Math.floor(\n this.config.totalTokenBudget * this.config.systemContextBudget\n );\n\n // 1. Gather user knowledge from DiffMem\n const {\n content: userKnowledge,\n memories: diffMemMemories,\n available: diffMemAvailable,\n } = await this.gatherUserKnowledge(query, userKnowledgeBudget);\n\n // Apply privacy filter to user knowledge\n const userKnowledgeFiltered = this.privacyFilter.filter(userKnowledge);\n totalPrivacyFiltered += userKnowledgeFiltered.redactedCount;\n const filteredUserKnowledge = truncateToTokenBudget(\n userKnowledgeFiltered.filtered,\n userKnowledgeBudget\n );\n\n // 2. Gather task context from StackMemory\n const { content: taskContext, frameCount } = await this.gatherTaskContext(\n query,\n taskContextBudget\n );\n\n // Apply privacy filter to task context\n const taskContextFiltered = this.privacyFilter.filter(taskContext);\n totalPrivacyFiltered += taskContextFiltered.redactedCount;\n const filteredTaskContext = truncateToTokenBudget(\n taskContextFiltered.filtered,\n taskContextBudget\n );\n\n // 3. Gather system context\n const systemContext = this.gatherSystemContext(systemContextBudget);\n\n // Apply privacy filter to system context\n const systemContextFiltered = this.privacyFilter.filter(systemContext);\n totalPrivacyFiltered += systemContextFiltered.redactedCount;\n const filteredSystemContext = truncateToTokenBudget(\n systemContextFiltered.filtered,\n systemContextBudget\n );\n\n // 4. Combine all context sections\n const combined = this.combineContextSections(\n filteredUserKnowledge,\n filteredTaskContext,\n filteredSystemContext\n );\n\n // Calculate token usage\n const tokenUsage: TokenUsage = {\n userKnowledge: estimateTokens(filteredUserKnowledge),\n taskContext: estimateTokens(filteredTaskContext),\n systemContext: estimateTokens(filteredSystemContext),\n total: estimateTokens(combined),\n budget: this.config.totalTokenBudget,\n };\n\n const metadata: ContextMetadata = {\n diffMemAvailable,\n diffMemMemories,\n stackMemoryFrames: frameCount,\n privacyFiltered: totalPrivacyFiltered,\n };\n\n logger.info('Unified context assembled', {\n query: query.substring(0, 50),\n tokenUsage,\n metadata,\n assemblyTimeMs: Date.now() - startTime,\n });\n\n return {\n userKnowledge: filteredUserKnowledge,\n taskContext: filteredTaskContext,\n systemContext: filteredSystemContext,\n combined,\n tokenUsage,\n metadata,\n };\n }\n\n /**\n * Gather user knowledge from DiffMem\n */\n private async gatherUserKnowledge(\n query: string,\n tokenBudget: number\n ): Promise<{ content: string; memories: number; available: boolean }> {\n if (!this.diffMemHooks) {\n return { content: '', memories: 0, available: false };\n }\n\n try {\n // Check DiffMem status\n const status = await this.diffMemHooks.getStatus();\n if (!status.connected) {\n logger.debug('DiffMem not connected');\n return { content: '', memories: 0, available: false };\n }\n\n // Query relevant memories\n const memories = await this.diffMemHooks.getRelevantMemories(query, 10);\n\n if (memories.length === 0) {\n return { content: '', memories: 0, available: true };\n }\n\n // Format memories into context string\n const sections: string[] = ['## User Knowledge'];\n\n // Group memories by category\n const byCategory = new Map<string, UserMemory[]>();\n for (const memory of memories) {\n const existing = byCategory.get(memory.category) || [];\n existing.push(memory);\n byCategory.set(memory.category, existing);\n }\n\n // Format each category\n for (const [category, categoryMemories] of byCategory) {\n sections.push(`\\n### ${this.formatCategory(category)}`);\n for (const memory of categoryMemories) {\n const confidence =\n memory.confidence >= 0.8\n ? '(high confidence)'\n : memory.confidence >= 0.5\n ? ''\n : '(tentative)';\n sections.push(`- ${memory.content} ${confidence}`);\n }\n }\n\n const content = sections.join('\\n');\n return {\n content: truncateToTokenBudget(content, tokenBudget),\n memories: memories.length,\n available: true,\n };\n } catch (error) {\n logger.warn('Failed to gather user knowledge from DiffMem', { error });\n return { content: '', memories: 0, available: false };\n }\n }\n\n /**\n * Format category name for display\n */\n private formatCategory(category: string): string {\n return category\n .split('_')\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\n .join(' ');\n }\n\n /**\n * Gather task context from StackMemory\n */\n private async gatherTaskContext(\n query: string,\n tokenBudget: number\n ): Promise<{ content: string; frameCount: number }> {\n try {\n const retrievedContext = await this.stackMemoryRetrieval.retrieveContext(\n query,\n {\n tokenBudget,\n }\n );\n\n return {\n content: retrievedContext.context,\n frameCount: retrievedContext.frames.length,\n };\n } catch (error) {\n logger.warn('Failed to gather task context from StackMemory', { error });\n return { content: '', frameCount: 0 };\n }\n }\n\n /**\n * Gather system context (environment, timestamps, etc.)\n */\n private gatherSystemContext(tokenBudget: number): string {\n const sections: string[] = ['## System Context'];\n\n // Add timestamp\n sections.push(`\\n**Current Time**: ${new Date().toISOString()}`);\n\n // Add environment info (sanitized)\n const nodeEnv = process.env.NODE_ENV || 'development';\n sections.push(`**Environment**: ${nodeEnv}`);\n\n // Add project info if available\n const projectId = process.env.STACKMEMORY_PROJECT_ID;\n if (projectId) {\n sections.push(`**Project**: ${projectId}`);\n }\n\n // Add session info\n const sessionId = process.env.STACKMEMORY_SESSION_ID;\n if (sessionId) {\n sections.push(`**Session**: ${sessionId.substring(0, 8)}...`);\n }\n\n const content = sections.join('\\n');\n return truncateToTokenBudget(content, tokenBudget);\n }\n\n /**\n * Combine all context sections into a single string\n */\n private combineContextSections(\n userKnowledge: string,\n taskContext: string,\n systemContext: string\n ): string {\n const sections: string[] = [];\n\n // Add sections in priority order\n if (taskContext) {\n sections.push(taskContext);\n }\n\n if (userKnowledge) {\n sections.push(userKnowledge);\n }\n\n if (systemContext) {\n sections.push(systemContext);\n }\n\n return sections.join('\\n\\n---\\n\\n');\n }\n\n /**\n * Update privacy mode\n */\n setPrivacyMode(mode: PrivacyMode): void {\n this.config.privacyMode = mode;\n this.privacyFilter.setMode(mode);\n }\n\n /**\n * Get current configuration\n */\n getConfig(): UnifiedContextConfig {\n return { ...this.config };\n }\n\n /**\n * Update configuration\n */\n updateConfig(config: Partial<UnifiedContextConfig>): void {\n this.config = { ...this.config, ...config };\n if (config.privacyMode) {\n this.privacyFilter.setMode(config.privacyMode);\n }\n }\n}\n\n/**\n * Factory function to create a unified context assembler\n */\nexport function createUnifiedContextAssembler(\n stackMemoryRetrieval: LLMContextRetrieval,\n diffMemHooks: DiffMemHooks | null = null,\n config: Partial<UnifiedContextConfig> = {}\n): UnifiedContextAssembler {\n return new UnifiedContextAssembler(\n stackMemoryRetrieval,\n diffMemHooks,\n config\n );\n}\n"],
|
|
5
|
+
"mappings": ";;;;AAMA;AAAA,EAGE;AAAA,OACK;AAOP,SAAS,cAAc;AAwEhB,MAAM,iCAAuD;AAAA,EAClE,kBAAkB;AAAA,EAClB,qBAAqB;AAAA;AAAA,EACrB,mBAAmB;AAAA;AAAA,EACnB,qBAAqB;AAAA;AAAA,EACrB,aAAa;AACf;AAMA,SAAS,eAAe,SAAyB;AAC/C,MAAI,CAAC,QAAS,QAAO;AACrB,SAAO,KAAK,KAAK,QAAQ,SAAS,CAAC;AACrC;AAKA,SAAS,sBAAsB,SAAiB,aAA6B;AAC3E,MAAI,CAAC,QAAS,QAAO;AAErB,QAAM,kBAAkB,eAAe,OAAO;AAC9C,MAAI,mBAAmB,aAAa;AAClC,WAAO;AAAA,EACT;AAGA,QAAM,YAAY,cAAc;AAChC,QAAM,YAAY,QAAQ,UAAU,GAAG,SAAS;AAGhD,QAAM,YAAY,UAAU,YAAY,GAAG;AAC3C,MAAI,YAAY,YAAY,KAAK;AAC/B,WAAO,UAAU,UAAU,GAAG,SAAS,IAAI;AAAA,EAC7C;AAEA,SAAO,YAAY;AACrB;AAMO,MAAM,wBAAwB;AAAA,EAC3B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YACE,sBACA,cACA,SAAwC,CAAC,GACzC;AACA,SAAK,uBAAuB;AAC5B,SAAK,eAAe;AACpB,SAAK,SAAS,EAAE,GAAG,gCAAgC,GAAG,OAAO;AAC7D,SAAK,gBAAgB,oBAAoB,KAAK,OAAO,WAAW;AAGhE,UAAM,kBACJ,KAAK,OAAO,sBACZ,KAAK,OAAO,oBACZ,KAAK,OAAO;AAEd,QAAI,KAAK,IAAI,kBAAkB,CAAG,IAAI,MAAO;AAC3C,aAAO,KAAK,wCAAwC;AAAA,QAClD,eAAe,KAAK,OAAO;AAAA,QAC3B,aAAa,KAAK,OAAO;AAAA,QACzB,eAAe,KAAK,OAAO;AAAA,QAC3B,OAAO;AAAA,MACT,CAAC;AAAA,IACH;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,OAAwC;AACrD,UAAM,YAAY,KAAK,IAAI;AAC3B,QAAI,uBAAuB;AAG3B,UAAM,sBAAsB,KAAK;AAAA,MAC/B,KAAK,OAAO,mBAAmB,KAAK,OAAO;AAAA,IAC7C;AACA,UAAM,oBAAoB,KAAK;AAAA,MAC7B,KAAK,OAAO,mBAAmB,KAAK,OAAO;AAAA,IAC7C;AACA,UAAM,sBAAsB,KAAK;AAAA,MAC/B,KAAK,OAAO,mBAAmB,KAAK,OAAO;AAAA,IAC7C;AAGA,UAAM;AAAA,MACJ,SAAS;AAAA,MACT,UAAU;AAAA,MACV,WAAW;AAAA,IACb,IAAI,MAAM,KAAK,oBAAoB,OAAO,mBAAmB;AAG7D,UAAM,wBAAwB,KAAK,cAAc,OAAO,aAAa;AACrE,4BAAwB,sBAAsB;AAC9C,UAAM,wBAAwB;AAAA,MAC5B,sBAAsB;AAAA,MACtB;AAAA,IACF;AAGA,UAAM,EAAE,SAAS,aAAa,WAAW,IAAI,MAAM,KAAK;AAAA,MACtD;AAAA,MACA;AAAA,IACF;AAGA,UAAM,sBAAsB,KAAK,cAAc,OAAO,WAAW;AACjE,4BAAwB,oBAAoB;AAC5C,UAAM,sBAAsB;AAAA,MAC1B,oBAAoB;AAAA,MACpB;AAAA,IACF;AAGA,UAAM,gBAAgB,KAAK,oBAAoB,mBAAmB;AAGlE,UAAM,wBAAwB,KAAK,cAAc,OAAO,aAAa;AACrE,4BAAwB,sBAAsB;AAC9C,UAAM,wBAAwB;AAAA,MAC5B,sBAAsB;AAAA,MACtB;AAAA,IACF;AAGA,UAAM,WAAW,KAAK;AAAA,MACpB;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAGA,UAAM,aAAyB;AAAA,MAC7B,eAAe,eAAe,qBAAqB;AAAA,MACnD,aAAa,eAAe,mBAAmB;AAAA,MAC/C,eAAe,eAAe,qBAAqB;AAAA,MACnD,OAAO,eAAe,QAAQ;AAAA,MAC9B,QAAQ,KAAK,OAAO;AAAA,IACtB;AAEA,UAAM,WAA4B;AAAA,MAChC;AAAA,MACA;AAAA,MACA,mBAAmB;AAAA,MACnB,iBAAiB;AAAA,IACnB;AAEA,WAAO,KAAK,6BAA6B;AAAA,MACvC,OAAO,MAAM,UAAU,GAAG,EAAE;AAAA,MAC5B;AAAA,MACA;AAAA,MACA,gBAAgB,KAAK,IAAI,IAAI;AAAA,IAC/B,CAAC;AAED,WAAO;AAAA,MACL,eAAe;AAAA,MACf,aAAa;AAAA,MACb,eAAe;AAAA,MACf;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,oBACZ,OACA,aACoE;AACpE,QAAI,CAAC,KAAK,cAAc;AACtB,aAAO,EAAE,SAAS,IAAI,UAAU,GAAG,WAAW,MAAM;AAAA,IACtD;AAEA,QAAI;AAEF,YAAM,SAAS,MAAM,KAAK,aAAa,UAAU;AACjD,UAAI,CAAC,OAAO,WAAW;AACrB,eAAO,MAAM,uBAAuB;AACpC,eAAO,EAAE,SAAS,IAAI,UAAU,GAAG,WAAW,MAAM;AAAA,MACtD;AAGA,YAAM,WAAW,MAAM,KAAK,aAAa,oBAAoB,OAAO,EAAE;AAEtE,UAAI,SAAS,WAAW,GAAG;AACzB,eAAO,EAAE,SAAS,IAAI,UAAU,GAAG,WAAW,KAAK;AAAA,MACrD;AAGA,YAAM,WAAqB,CAAC,mBAAmB;AAG/C,YAAM,aAAa,oBAAI,IAA0B;AACjD,iBAAW,UAAU,UAAU;AAC7B,cAAM,WAAW,WAAW,IAAI,OAAO,QAAQ,KAAK,CAAC;AACrD,iBAAS,KAAK,MAAM;AACpB,mBAAW,IAAI,OAAO,UAAU,QAAQ;AAAA,MAC1C;AAGA,iBAAW,CAAC,UAAU,gBAAgB,KAAK,YAAY;AACrD,iBAAS,KAAK;AAAA,MAAS,KAAK,eAAe,QAAQ,CAAC,EAAE;AACtD,mBAAW,UAAU,kBAAkB;AACrC,gBAAM,aACJ,OAAO,cAAc,MACjB,sBACA,OAAO,cAAc,MACnB,KACA;AACR,mBAAS,KAAK,KAAK,OAAO,OAAO,IAAI,UAAU,EAAE;AAAA,QACnD;AAAA,MACF;AAEA,YAAM,UAAU,SAAS,KAAK,IAAI;AAClC,aAAO;AAAA,QACL,SAAS,sBAAsB,SAAS,WAAW;AAAA,QACnD,UAAU,SAAS;AAAA,QACnB,WAAW;AAAA,MACb;AAAA,IACF,SAAS,OAAO;AACd,aAAO,KAAK,gDAAgD,EAAE,MAAM,CAAC;AACrE,aAAO,EAAE,SAAS,IAAI,UAAU,GAAG,WAAW,MAAM;AAAA,IACtD;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,eAAe,UAA0B;AAC/C,WAAO,SACJ,MAAM,GAAG,EACT,IAAI,CAAC,SAAS,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,CAAC,EAC1D,KAAK,GAAG;AAAA,EACb;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,kBACZ,OACA,aACkD;AAClD,QAAI;AACF,YAAM,mBAAmB,MAAM,KAAK,qBAAqB;AAAA,QACvD;AAAA,QACA;AAAA,UACE;AAAA,QACF;AAAA,MACF;AAEA,aAAO;AAAA,QACL,SAAS,iBAAiB;AAAA,QAC1B,YAAY,iBAAiB,OAAO;AAAA,MACtC;AAAA,IACF,SAAS,OAAO;AACd,aAAO,KAAK,kDAAkD,EAAE,MAAM,CAAC;AACvE,aAAO,EAAE,SAAS,IAAI,YAAY,EAAE;AAAA,IACtC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,oBAAoB,aAA6B;AACvD,UAAM,WAAqB,CAAC,mBAAmB;AAG/C,aAAS,KAAK;AAAA,qBAAuB,oBAAI,KAAK,GAAE,YAAY,CAAC,EAAE;AAG/D,UAAM,UAAU,QAAQ,IAAI,YAAY;AACxC,aAAS,KAAK,oBAAoB,OAAO,EAAE;AAG3C,UAAM,YAAY,QAAQ,IAAI;AAC9B,QAAI,WAAW;AACb,eAAS,KAAK,gBAAgB,SAAS,EAAE;AAAA,IAC3C;AAGA,UAAM,YAAY,QAAQ,IAAI;AAC9B,QAAI,WAAW;AACb,eAAS,KAAK,gBAAgB,UAAU,UAAU,GAAG,CAAC,CAAC,KAAK;AAAA,IAC9D;AAEA,UAAM,UAAU,SAAS,KAAK,IAAI;AAClC,WAAO,sBAAsB,SAAS,WAAW;AAAA,EACnD;AAAA;AAAA;AAAA;AAAA,EAKQ,uBACN,eACA,aACA,eACQ;AACR,UAAM,WAAqB,CAAC;AAG5B,QAAI,aAAa;AACf,eAAS,KAAK,WAAW;AAAA,IAC3B;AAEA,QAAI,eAAe;AACjB,eAAS,KAAK,aAAa;AAAA,IAC7B;AAEA,QAAI,eAAe;AACjB,eAAS,KAAK,aAAa;AAAA,IAC7B;AAEA,WAAO,SAAS,KAAK,aAAa;AAAA,EACpC;AAAA;AAAA;AAAA;AAAA,EAKA,eAAe,MAAyB;AACtC,SAAK,OAAO,cAAc;AAC1B,SAAK,cAAc,QAAQ,IAAI;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,EAKA,YAAkC;AAChC,WAAO,EAAE,GAAG,KAAK,OAAO;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA,EAKA,aAAa,QAA6C;AACxD,SAAK,SAAS,EAAE,GAAG,KAAK,QAAQ,GAAG,OAAO;AAC1C,QAAI,OAAO,aAAa;AACtB,WAAK,cAAc,QAAQ,OAAO,WAAW;AAAA,IAC/C;AAAA,EACF;AACF;AAKO,SAAS,8BACd,sBACA,eAAoC,MACpC,SAAwC,CAAC,GAChB;AACzB,SAAO,IAAI;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|