claude-flow 2.5.0-alpha.141 → 2.7.0-alpha.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 (154) hide show
  1. package/.claude/agents/reasoning/README.md +171 -0
  2. package/.claude/agents/reasoning/agent.md +816 -0
  3. package/.claude/agents/reasoning/example-reasoning-agent-template.md +362 -0
  4. package/.claude/agents/reasoning/goal-planner.md +73 -0
  5. package/.claude/commands/coordination/README.md +9 -0
  6. package/.claude/commands/memory/README.md +9 -0
  7. package/.claude/settings.json +3 -3
  8. package/.claude/sparc-modes.json +108 -0
  9. package/README.md +1 -6
  10. package/bin/claude-flow +1 -1
  11. package/dist/src/cli/command-registry.js +70 -6
  12. package/dist/src/cli/command-registry.js.map +1 -1
  13. package/dist/src/cli/help-formatter.js +5 -3
  14. package/dist/src/cli/help-formatter.js.map +1 -1
  15. package/dist/src/cli/help-text.js +53 -5
  16. package/dist/src/cli/help-text.js.map +1 -1
  17. package/dist/src/cli/simple-cli.js +182 -172
  18. package/dist/src/cli/simple-cli.js.map +1 -1
  19. package/dist/src/cli/simple-commands/agent-booster.js +415 -0
  20. package/dist/src/cli/simple-commands/agent-booster.js.map +1 -0
  21. package/dist/src/cli/simple-commands/agent.js +856 -13
  22. package/dist/src/cli/simple-commands/agent.js.map +1 -1
  23. package/dist/src/cli/simple-commands/config.js +115 -257
  24. package/dist/src/cli/simple-commands/config.js.map +1 -1
  25. package/dist/src/cli/simple-commands/env-template.js +180 -0
  26. package/dist/src/cli/simple-commands/env-template.js.map +1 -0
  27. package/dist/src/cli/simple-commands/init/help.js +23 -0
  28. package/dist/src/cli/simple-commands/init/help.js.map +1 -1
  29. package/dist/src/cli/simple-commands/init/index.js +63 -0
  30. package/dist/src/cli/simple-commands/init/index.js.map +1 -1
  31. package/dist/src/cli/simple-commands/memory.js +414 -16
  32. package/dist/src/cli/simple-commands/memory.js.map +1 -1
  33. package/dist/src/cli/simple-commands/proxy.js +304 -0
  34. package/dist/src/cli/simple-commands/proxy.js.map +1 -0
  35. package/dist/src/cli/simple-commands/sparc.js +16 -19
  36. package/dist/src/cli/simple-commands/sparc.js.map +1 -1
  37. package/dist/src/cli/validation-helper.js.map +1 -1
  38. package/dist/src/core/version.js +1 -1
  39. package/dist/src/execution/agent-executor.js +181 -0
  40. package/dist/src/execution/agent-executor.js.map +1 -0
  41. package/dist/src/execution/index.js +12 -0
  42. package/dist/src/execution/index.js.map +1 -0
  43. package/dist/src/execution/provider-manager.js +110 -0
  44. package/dist/src/execution/provider-manager.js.map +1 -0
  45. package/dist/src/hooks/redaction-hook.js +89 -0
  46. package/dist/src/hooks/redaction-hook.js.map +1 -0
  47. package/dist/src/memory/swarm-memory.js +340 -421
  48. package/dist/src/memory/swarm-memory.js.map +1 -1
  49. package/dist/src/reasoningbank/reasoningbank-adapter.js +144 -0
  50. package/dist/src/reasoningbank/reasoningbank-adapter.js.map +1 -0
  51. package/dist/src/utils/key-redactor.js +108 -0
  52. package/dist/src/utils/key-redactor.js.map +1 -0
  53. package/dist/src/utils/metrics-reader.js.map +1 -1
  54. package/docs/AGENT-BOOSTER-INTEGRATION.md +407 -0
  55. package/docs/AGENTIC-FLOW-INTEGRATION-GUIDE.md +753 -0
  56. package/docs/AGENTIC_FLOW_EXECUTION_FIX_REPORT.md +474 -0
  57. package/docs/AGENTIC_FLOW_INTEGRATION_STATUS.md +143 -0
  58. package/docs/AGENTIC_FLOW_MVP_COMPLETE.md +367 -0
  59. package/docs/AGENTIC_FLOW_SECURITY_TEST_REPORT.md +369 -0
  60. package/docs/COMMAND-VERIFICATION-REPORT.md +441 -0
  61. package/docs/COMMIT_SUMMARY.md +247 -0
  62. package/docs/DEEP_REVIEW_COMPREHENSIVE_REPORT.md +922 -0
  63. package/docs/DOCKER-VALIDATION-REPORT.md +281 -0
  64. package/docs/ENV-SETUP-GUIDE.md +270 -0
  65. package/docs/FINAL_PRE_PUBLISH_VALIDATION.md +823 -0
  66. package/docs/FINAL_VALIDATION_REPORT.md +165 -0
  67. package/docs/HOOKS-V2-MODIFICATION.md +146 -0
  68. package/docs/INDEX.md +568 -0
  69. package/docs/INTEGRATION_COMPLETE.md +414 -0
  70. package/docs/MEMORY_REDACTION_TEST_REPORT.md +300 -0
  71. package/docs/PERFORMANCE-SYSTEMS-STATUS.md +340 -0
  72. package/docs/PRE_RELEASE_FIXES_REPORT.md +435 -0
  73. package/docs/README.md +35 -0
  74. package/docs/REASONING-AGENTS.md +482 -0
  75. package/docs/REASONINGBANK-AGENT-CREATION-GUIDE.md +813 -0
  76. package/docs/REASONINGBANK-ANALYSIS-COMPLETE.md +479 -0
  77. package/docs/REASONINGBANK-BENCHMARK-RESULTS.md +166 -0
  78. package/docs/REASONINGBANK-BENCHMARK.md +396 -0
  79. package/docs/REASONINGBANK-CLI-INTEGRATION.md +455 -0
  80. package/docs/REASONINGBANK-CORE-INTEGRATION.md +658 -0
  81. package/docs/REASONINGBANK-COST-OPTIMIZATION.md +329 -0
  82. package/docs/REASONINGBANK-DEMO.md +419 -0
  83. package/docs/REASONINGBANK-INTEGRATION-COMPLETE.md +249 -0
  84. package/docs/REASONINGBANK-INTEGRATION-STATUS.md +179 -0
  85. package/docs/REASONINGBANK-VALIDATION.md +532 -0
  86. package/docs/REASONINGBANK_ARCHITECTURE.md +475 -0
  87. package/docs/REASONINGBANK_INTEGRATION_COMPLETE.md +558 -0
  88. package/docs/REASONINGBANK_INTEGRATION_PLAN.md +1188 -0
  89. package/docs/REGRESSION-ANALYSIS-REPORT.md +500 -0
  90. package/docs/RELEASE_v2.6.0-alpha.2.md +658 -0
  91. package/docs/api/API_DOCUMENTATION.md +721 -0
  92. package/docs/architecture/ARCHITECTURE.md +1690 -0
  93. package/docs/ci-cd/README.md +368 -0
  94. package/docs/development/DEPLOYMENT.md +2348 -0
  95. package/docs/development/DEVELOPMENT_WORKFLOW.md +1333 -0
  96. package/docs/development/build-analysis-report.md +252 -0
  97. package/docs/development/pair-optimization.md +156 -0
  98. package/docs/development/token-tracking-status.md +103 -0
  99. package/docs/development/training-pipeline-demo.md +163 -0
  100. package/docs/development/training-pipeline-real-only.md +196 -0
  101. package/docs/epic-sdk-integration.md +1269 -0
  102. package/docs/experimental/RIEMANN_HYPOTHESIS_PROOF.md +124 -0
  103. package/docs/experimental/computational_verification.py +436 -0
  104. package/docs/experimental/novel_approaches.md +560 -0
  105. package/docs/experimental/riemann_hypothesis_analysis.md +263 -0
  106. package/docs/experimental/riemann_proof_attempt.md +124 -0
  107. package/docs/experimental/riemann_synthesis.md +277 -0
  108. package/docs/experimental/verification_results.json +12 -0
  109. package/docs/experimental/visualization_insights.md +720 -0
  110. package/docs/guides/USER_GUIDE.md +1138 -0
  111. package/docs/guides/token-tracking-guide.md +291 -0
  112. package/docs/reference/AGENTS.md +1011 -0
  113. package/docs/reference/MCP_TOOLS.md +2188 -0
  114. package/docs/reference/SPARC.md +717 -0
  115. package/docs/reference/SWARM.md +2000 -0
  116. package/docs/sdk/CLAUDE-CODE-SDK-DEEP-ANALYSIS.md +649 -0
  117. package/docs/sdk/CLAUDE-FLOW-SDK-INTEGRATION-ANALYSIS.md +242 -0
  118. package/docs/sdk/INTEGRATION-ROADMAP.md +420 -0
  119. package/docs/sdk/MCP-TOOLS-UPDATE.md +270 -0
  120. package/docs/sdk/SDK-ADVANCED-FEATURES-INTEGRATION.md +723 -0
  121. package/docs/sdk/SDK-ALL-FEATURES-INTEGRATION-MATRIX.md +612 -0
  122. package/docs/sdk/SDK-INTEGRATION-COMPLETE.md +358 -0
  123. package/docs/sdk/SDK-INTEGRATION-PHASES-V2.5.md +750 -0
  124. package/docs/sdk/SDK-LEVERAGE-REAL-FEATURES.md +676 -0
  125. package/docs/sdk/SDK-VALIDATION-RESULTS.md +400 -0
  126. package/docs/sdk/epic-sdk-integration.md +1269 -0
  127. package/docs/setup/remote-setup.md +93 -0
  128. package/docs/validation/final-validation-summary.md +220 -0
  129. package/docs/validation/verification-integration.md +190 -0
  130. package/docs/validation/verification-validation.md +349 -0
  131. package/docs/wiki/background-commands.md +1213 -0
  132. package/docs/wiki/session-persistence.md +342 -0
  133. package/docs/wiki/stream-chain-command.md +537 -0
  134. package/package.json +4 -2
  135. package/src/cli/command-registry.js +70 -5
  136. package/src/cli/help-text.js +26 -5
  137. package/src/cli/simple-cli.ts +18 -7
  138. package/src/cli/simple-commands/agent-booster.js +515 -0
  139. package/src/cli/simple-commands/agent.js +1001 -12
  140. package/src/cli/simple-commands/agent.ts +137 -0
  141. package/src/cli/simple-commands/config.ts +127 -0
  142. package/src/cli/simple-commands/env-template.js +190 -0
  143. package/src/cli/simple-commands/init/help.js +23 -0
  144. package/src/cli/simple-commands/init/index.js +84 -6
  145. package/src/cli/simple-commands/memory.js +497 -16
  146. package/src/cli/simple-commands/proxy.js +384 -0
  147. package/src/cli/simple-commands/sparc.js +16 -19
  148. package/src/execution/agent-executor.ts +306 -0
  149. package/src/execution/index.ts +19 -0
  150. package/src/execution/provider-manager.ts +187 -0
  151. package/src/hooks/redaction-hook.ts +115 -0
  152. package/src/reasoningbank/reasoningbank-adapter.js +191 -0
  153. package/src/utils/key-redactor.js +178 -0
  154. package/src/utils/key-redactor.ts +184 -0
@@ -0,0 +1,191 @@
1
+ /**
2
+ * ReasoningBank Adapter for Claude-Flow
3
+ *
4
+ * Wraps agentic-flow's ReasoningBank SDK for use in claude-flow memory commands
5
+ */
6
+
7
+ import { db, initialize, retrieveMemories, computeEmbedding, loadConfig } from 'agentic-flow/dist/reasoningbank/index.js';
8
+ import { v4 as uuidv4 } from 'uuid';
9
+
10
+ /**
11
+ * Initialize ReasoningBank database
12
+ */
13
+ export async function initializeReasoningBank() {
14
+ // Set database path
15
+ process.env.CLAUDE_FLOW_DB_PATH = '.swarm/memory.db';
16
+
17
+ await initialize();
18
+ return true;
19
+ }
20
+
21
+ /**
22
+ * Store a memory in ReasoningBank
23
+ */
24
+ export async function storeMemory(key, value, options = {}) {
25
+ const memoryId = `mem_${uuidv4()}`;
26
+
27
+ const memory = {
28
+ id: memoryId,
29
+ type: options.type || 'fact',
30
+ pattern_data: JSON.stringify({
31
+ key,
32
+ value,
33
+ namespace: options.namespace || 'default',
34
+ agent: options.agent || 'memory-agent',
35
+ domain: options.domain || 'general',
36
+ }),
37
+ confidence: options.confidence || 0.8,
38
+ usage_count: 0,
39
+ created_at: new Date().toISOString(),
40
+ };
41
+
42
+ // Store memory
43
+ db.upsertMemory(memory);
44
+
45
+ // Compute and store embedding for semantic search
46
+ try {
47
+ const config = loadConfig();
48
+ const embeddingModel = config.embeddings.provider || 'claude';
49
+
50
+ const embedding = await computeEmbedding(`${key}: ${value}`);
51
+ const vectorArray = new Float32Array(embedding);
52
+
53
+ db.upsertEmbedding({
54
+ memory_id: memoryId,
55
+ vector: vectorArray,
56
+ model: embeddingModel, // Dynamic model from config
57
+ dims: vectorArray.length, // Required: embedding dimensions
58
+ created_at: new Date().toISOString(),
59
+ });
60
+ } catch (error) {
61
+ console.warn('[ReasoningBank] Warning: Could not compute embedding:', error.message);
62
+ // Continue without embedding - memory is still stored
63
+ }
64
+
65
+ return memoryId;
66
+ }
67
+
68
+ /**
69
+ * Query memories from ReasoningBank
70
+ */
71
+ export async function queryMemories(searchQuery, options = {}) {
72
+ try {
73
+ // Use ReasoningBank's semantic retrieval
74
+ const memories = await retrieveMemories(searchQuery, {
75
+ domain: options.domain || 'general',
76
+ agent: options.agent || 'memory-agent',
77
+ k: options.limit || 10,
78
+ });
79
+
80
+ return memories.map(mem => {
81
+ try {
82
+ const data = JSON.parse(mem.pattern_data);
83
+ return {
84
+ id: mem.id,
85
+ key: data.key,
86
+ value: data.value,
87
+ namespace: data.namespace,
88
+ confidence: mem.confidence,
89
+ usage_count: mem.usage_count,
90
+ created_at: mem.created_at,
91
+ score: mem.score || 0,
92
+ };
93
+ } catch {
94
+ return null;
95
+ }
96
+ }).filter(Boolean);
97
+ } catch (error) {
98
+ // Fallback to simple query if semantic search fails
99
+ console.warn('[ReasoningBank] Semantic search failed, using simple query:', error.message);
100
+
101
+ const dbInstance = db.getDb();
102
+ const rows = dbInstance.prepare(`
103
+ SELECT * FROM patterns
104
+ WHERE pattern_data LIKE ?
105
+ ORDER BY confidence DESC, usage_count DESC
106
+ LIMIT ?
107
+ `).all(`%${searchQuery}%`, options.limit || 10);
108
+
109
+ return rows.map(row => {
110
+ try {
111
+ const data = JSON.parse(row.pattern_data);
112
+ return {
113
+ id: row.id,
114
+ key: data.key,
115
+ value: data.value,
116
+ namespace: data.namespace,
117
+ confidence: row.confidence,
118
+ usage_count: row.usage_count,
119
+ created_at: row.created_at,
120
+ };
121
+ } catch {
122
+ return null;
123
+ }
124
+ }).filter(Boolean);
125
+ }
126
+ }
127
+
128
+ /**
129
+ * List all memories
130
+ */
131
+ export async function listMemories(options = {}) {
132
+ const dbInstance = db.getDb();
133
+
134
+ const limit = options.limit || 10;
135
+ const sortBy = options.sort || 'created_at';
136
+ const sortOrder = options.order || 'DESC';
137
+
138
+ const rows = dbInstance.prepare(`
139
+ SELECT * FROM patterns
140
+ ORDER BY ${sortBy} ${sortOrder}
141
+ LIMIT ?
142
+ `).all(limit);
143
+
144
+ return rows.map(row => {
145
+ try {
146
+ const data = JSON.parse(row.pattern_data);
147
+ return {
148
+ id: row.id,
149
+ key: data.key,
150
+ value: data.value,
151
+ namespace: data.namespace,
152
+ confidence: row.confidence,
153
+ usage_count: row.usage_count,
154
+ created_at: row.created_at,
155
+ };
156
+ } catch {
157
+ return null;
158
+ }
159
+ }).filter(Boolean);
160
+ }
161
+
162
+ /**
163
+ * Get ReasoningBank statistics
164
+ */
165
+ export async function getStatus() {
166
+ const dbInstance = db.getDb();
167
+
168
+ const stats = dbInstance.prepare(`
169
+ SELECT
170
+ COUNT(*) as total_memories,
171
+ AVG(confidence) as avg_confidence,
172
+ SUM(usage_count) as total_usage
173
+ FROM patterns
174
+ `).get();
175
+
176
+ const embeddingCount = dbInstance.prepare(`
177
+ SELECT COUNT(*) as count FROM pattern_embeddings
178
+ `).get();
179
+
180
+ const trajectoryCount = dbInstance.prepare(`
181
+ SELECT COUNT(*) as count FROM task_trajectories
182
+ `).get();
183
+
184
+ return {
185
+ total_memories: stats.total_memories || 0,
186
+ avg_confidence: stats.avg_confidence || 0,
187
+ total_usage: stats.total_usage || 0,
188
+ total_embeddings: embeddingCount.count || 0,
189
+ total_trajectories: trajectoryCount.count || 0,
190
+ };
191
+ }
@@ -0,0 +1,178 @@
1
+ /**
2
+ * API Key Redaction Utility
3
+ * Prevents sensitive data from leaking into logs, memory, or git commits
4
+ */
5
+
6
+ export class KeyRedactor {
7
+ static API_KEY_PATTERNS = [
8
+ // Anthropic API keys
9
+ /sk-ant-[a-zA-Z0-9_-]{95,}/gi,
10
+
11
+ // OpenRouter API keys
12
+ /sk-or-[a-zA-Z0-9_-]{32,}/gi,
13
+
14
+ // Google/Gemini API keys
15
+ /AIza[a-zA-Z0-9_-]{35}/gi,
16
+
17
+ // Generic API keys
18
+ /[a-zA-Z0-9_-]{20,}API[a-zA-Z0-9_-]{20,}/gi,
19
+
20
+ // Bearer tokens
21
+ /Bearer\s+[a-zA-Z0-9_\-\.]{20,}/gi,
22
+
23
+ // Environment variable format
24
+ /([A-Z_]+_API_KEY|[A-Z_]+_TOKEN|[A-Z_]+_SECRET)=["']?([^"'\s]+)["']?/gi,
25
+
26
+ // Supabase keys
27
+ /eyJ[a-zA-Z0-9_-]*\.eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*/gi,
28
+ ];
29
+
30
+ static SENSITIVE_FIELDS = [
31
+ 'apiKey',
32
+ 'api_key',
33
+ 'token',
34
+ 'secret',
35
+ 'password',
36
+ 'private_key',
37
+ 'privateKey',
38
+ 'accessToken',
39
+ 'access_token',
40
+ 'refreshToken',
41
+ 'refresh_token',
42
+ ];
43
+
44
+ /**
45
+ * Redact API keys and sensitive data from text
46
+ */
47
+ static redact(text, showPrefix = true) {
48
+ if (!text) return text;
49
+
50
+ let redacted = text;
51
+
52
+ // Redact using patterns
53
+ this.API_KEY_PATTERNS.forEach(pattern => {
54
+ redacted = redacted.replace(pattern, (match) => {
55
+ if (showPrefix && match.length > 8) {
56
+ const prefix = match.substring(0, 8);
57
+ return `${prefix}...[REDACTED]`;
58
+ }
59
+ return '[REDACTED_API_KEY]';
60
+ });
61
+ });
62
+
63
+ return redacted;
64
+ }
65
+
66
+ /**
67
+ * Redact sensitive fields in objects
68
+ */
69
+ static redactObject(obj, deep = true) {
70
+ if (!obj || typeof obj !== 'object') return obj;
71
+
72
+ const redacted = { ...obj };
73
+
74
+ Object.keys(redacted).forEach(key => {
75
+ const lowerKey = key.toLowerCase();
76
+
77
+ // Check if field name is sensitive
78
+ const isSensitive = this.SENSITIVE_FIELDS.some(field =>
79
+ lowerKey.includes(field)
80
+ );
81
+
82
+ if (isSensitive && typeof redacted[key] === 'string') {
83
+ const value = redacted[key];
84
+ if (value && value.length > 8) {
85
+ redacted[key] = `${value.substring(0, 4)}...[REDACTED]`;
86
+ } else {
87
+ redacted[key] = '[REDACTED]';
88
+ }
89
+ } else if (deep && typeof redacted[key] === 'object' && redacted[key] !== null) {
90
+ redacted[key] = this.redactObject(redacted[key], deep);
91
+ } else if (typeof redacted[key] === 'string') {
92
+ // Redact any API keys in string values
93
+ redacted[key] = this.redact(redacted[key]);
94
+ }
95
+ });
96
+
97
+ return redacted;
98
+ }
99
+
100
+ /**
101
+ * Sanitize text for safe logging
102
+ */
103
+ static sanitize(text) {
104
+ return this.redact(text, true);
105
+ }
106
+
107
+ /**
108
+ * Sanitize command arguments
109
+ */
110
+ static sanitizeArgs(args) {
111
+ return args.map(arg => {
112
+ // Check if arg is a flag value pair
113
+ if (arg.includes('key') || arg.includes('token') || arg.includes('secret')) {
114
+ return this.redact(arg);
115
+ }
116
+ return arg;
117
+ });
118
+ }
119
+
120
+ /**
121
+ * Check if text contains unredacted sensitive data
122
+ */
123
+ static containsSensitiveData(text) {
124
+ return this.API_KEY_PATTERNS.some(pattern => pattern.test(text));
125
+ }
126
+
127
+ /**
128
+ * Validate that text is safe for logging/storage
129
+ */
130
+ static validate(text) {
131
+ const warnings = [];
132
+
133
+ this.API_KEY_PATTERNS.forEach((pattern, index) => {
134
+ if (pattern.test(text)) {
135
+ warnings.push(`Potential API key detected (pattern ${index + 1})`);
136
+ }
137
+ });
138
+
139
+ return {
140
+ safe: warnings.length === 0,
141
+ warnings,
142
+ };
143
+ }
144
+
145
+ /**
146
+ * Redact environment variables
147
+ */
148
+ static redactEnv(env) {
149
+ const redacted = {};
150
+
151
+ Object.keys(env).forEach(key => {
152
+ const value = env[key];
153
+ if (!value) {
154
+ redacted[key] = '';
155
+ return;
156
+ }
157
+
158
+ const lowerKey = key.toLowerCase();
159
+ const isSensitive = lowerKey.includes('key') ||
160
+ lowerKey.includes('token') ||
161
+ lowerKey.includes('secret') ||
162
+ lowerKey.includes('password');
163
+
164
+ if (isSensitive) {
165
+ redacted[key] = value.length > 8
166
+ ? `${value.substring(0, 4)}...[REDACTED]`
167
+ : '[REDACTED]';
168
+ } else {
169
+ redacted[key] = value;
170
+ }
171
+ });
172
+
173
+ return redacted;
174
+ }
175
+ }
176
+
177
+ // Export singleton instance
178
+ export const redactor = KeyRedactor;
@@ -0,0 +1,184 @@
1
+ /**
2
+ * API Key Redaction Utility
3
+ * Prevents sensitive data from leaking into logs, memory, or git commits
4
+ */
5
+
6
+ export interface RedactionConfig {
7
+ patterns: RegExp[];
8
+ replacement: string;
9
+ maskLength: number;
10
+ }
11
+
12
+ export class KeyRedactor {
13
+ private static readonly API_KEY_PATTERNS = [
14
+ // Anthropic API keys
15
+ /sk-ant-[a-zA-Z0-9_-]{95,}/gi,
16
+
17
+ // OpenRouter API keys
18
+ /sk-or-[a-zA-Z0-9_-]{32,}/gi,
19
+
20
+ // Google/Gemini API keys
21
+ /AIza[a-zA-Z0-9_-]{35}/gi,
22
+
23
+ // Generic API keys
24
+ /[a-zA-Z0-9_-]{20,}API[a-zA-Z0-9_-]{20,}/gi,
25
+
26
+ // Bearer tokens
27
+ /Bearer\s+[a-zA-Z0-9_\-\.]{20,}/gi,
28
+
29
+ // Environment variable format
30
+ /([A-Z_]+_API_KEY|[A-Z_]+_TOKEN|[A-Z_]+_SECRET)=["']?([^"'\s]+)["']?/gi,
31
+
32
+ // Supabase keys
33
+ /eyJ[a-zA-Z0-9_-]*\.eyJ[a-zA-Z0-9_-]*\.[a-zA-Z0-9_-]*/gi,
34
+ ];
35
+
36
+ private static readonly SENSITIVE_FIELDS = [
37
+ 'apiKey',
38
+ 'api_key',
39
+ 'token',
40
+ 'secret',
41
+ 'password',
42
+ 'private_key',
43
+ 'privateKey',
44
+ 'accessToken',
45
+ 'access_token',
46
+ 'refreshToken',
47
+ 'refresh_token',
48
+ ];
49
+
50
+ /**
51
+ * Redact API keys and sensitive data from text
52
+ */
53
+ static redact(text: string, showPrefix = true): string {
54
+ if (!text) return text;
55
+
56
+ let redacted = text;
57
+
58
+ // Redact using patterns
59
+ this.API_KEY_PATTERNS.forEach(pattern => {
60
+ redacted = redacted.replace(pattern, (match) => {
61
+ if (showPrefix && match.length > 8) {
62
+ const prefix = match.substring(0, 8);
63
+ return `${prefix}...[REDACTED]`;
64
+ }
65
+ return '[REDACTED_API_KEY]';
66
+ });
67
+ });
68
+
69
+ return redacted;
70
+ }
71
+
72
+ /**
73
+ * Redact sensitive fields in objects
74
+ */
75
+ static redactObject<T extends Record<string, any>>(obj: T, deep = true): T {
76
+ if (!obj || typeof obj !== 'object') return obj;
77
+
78
+ const redacted = { ...obj };
79
+
80
+ Object.keys(redacted).forEach(key => {
81
+ const lowerKey = key.toLowerCase();
82
+
83
+ // Check if field name is sensitive
84
+ const isSensitive = this.SENSITIVE_FIELDS.some(field =>
85
+ lowerKey.includes(field)
86
+ );
87
+
88
+ if (isSensitive && typeof redacted[key] === 'string') {
89
+ const value = redacted[key] as string;
90
+ if (value && value.length > 8) {
91
+ redacted[key] = `${value.substring(0, 4)}...[REDACTED]` as any;
92
+ } else {
93
+ redacted[key] = '[REDACTED]' as any;
94
+ }
95
+ } else if (deep && typeof redacted[key] === 'object' && redacted[key] !== null) {
96
+ redacted[key] = this.redactObject(redacted[key], deep);
97
+ } else if (typeof redacted[key] === 'string') {
98
+ // Redact any API keys in string values
99
+ redacted[key] = this.redact(redacted[key]) as any;
100
+ }
101
+ });
102
+
103
+ return redacted;
104
+ }
105
+
106
+ /**
107
+ * Sanitize text for safe logging
108
+ */
109
+ static sanitize(text: string): string {
110
+ return this.redact(text, true);
111
+ }
112
+
113
+ /**
114
+ * Sanitize command arguments
115
+ */
116
+ static sanitizeArgs(args: string[]): string[] {
117
+ return args.map(arg => {
118
+ // Check if arg is a flag value pair
119
+ if (arg.includes('key') || arg.includes('token') || arg.includes('secret')) {
120
+ return this.redact(arg);
121
+ }
122
+ return arg;
123
+ });
124
+ }
125
+
126
+ /**
127
+ * Check if text contains unredacted sensitive data
128
+ */
129
+ static containsSensitiveData(text: string): boolean {
130
+ return this.API_KEY_PATTERNS.some(pattern => pattern.test(text));
131
+ }
132
+
133
+ /**
134
+ * Validate that text is safe for logging/storage
135
+ */
136
+ static validate(text: string): { safe: boolean; warnings: string[] } {
137
+ const warnings: string[] = [];
138
+
139
+ this.API_KEY_PATTERNS.forEach((pattern, index) => {
140
+ if (pattern.test(text)) {
141
+ warnings.push(`Potential API key detected (pattern ${index + 1})`);
142
+ }
143
+ });
144
+
145
+ return {
146
+ safe: warnings.length === 0,
147
+ warnings,
148
+ };
149
+ }
150
+
151
+ /**
152
+ * Redact environment variables
153
+ */
154
+ static redactEnv(env: Record<string, string | undefined>): Record<string, string> {
155
+ const redacted: Record<string, string> = {};
156
+
157
+ Object.keys(env).forEach(key => {
158
+ const value = env[key];
159
+ if (!value) {
160
+ redacted[key] = '';
161
+ return;
162
+ }
163
+
164
+ const lowerKey = key.toLowerCase();
165
+ const isSensitive = lowerKey.includes('key') ||
166
+ lowerKey.includes('token') ||
167
+ lowerKey.includes('secret') ||
168
+ lowerKey.includes('password');
169
+
170
+ if (isSensitive) {
171
+ redacted[key] = value.length > 8
172
+ ? `${value.substring(0, 4)}...[REDACTED]`
173
+ : '[REDACTED]';
174
+ } else {
175
+ redacted[key] = value;
176
+ }
177
+ });
178
+
179
+ return redacted;
180
+ }
181
+ }
182
+
183
+ // Export singleton instance
184
+ export const redactor = KeyRedactor;