contextos-mcp 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (223) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +260 -0
  3. package/bin/mcp.mjs +61 -0
  4. package/bin/swarm.mjs +45 -0
  5. package/dist/agents/aider.d.ts +12 -0
  6. package/dist/agents/aider.js +192 -0
  7. package/dist/agents/aider.js.map +1 -0
  8. package/dist/agents/claude-code.d.ts +9 -0
  9. package/dist/agents/claude-code.js +236 -0
  10. package/dist/agents/claude-code.js.map +1 -0
  11. package/dist/agents/codex.d.ts +14 -0
  12. package/dist/agents/codex.js +203 -0
  13. package/dist/agents/codex.js.map +1 -0
  14. package/dist/agents/direct-llm.d.ts +22 -0
  15. package/dist/agents/direct-llm.js +254 -0
  16. package/dist/agents/direct-llm.js.map +1 -0
  17. package/dist/agents/mock.d.ts +10 -0
  18. package/dist/agents/mock.js +170 -0
  19. package/dist/agents/mock.js.map +1 -0
  20. package/dist/agents/opencode.d.ts +23 -0
  21. package/dist/agents/opencode.js +631 -0
  22. package/dist/agents/opencode.js.map +1 -0
  23. package/dist/agents/provider.d.ts +11 -0
  24. package/dist/agents/provider.js +31 -0
  25. package/dist/agents/provider.js.map +1 -0
  26. package/dist/compression/compressor.d.ts +28 -0
  27. package/dist/compression/compressor.js +268 -0
  28. package/dist/compression/compressor.js.map +1 -0
  29. package/dist/config.d.ts +43 -0
  30. package/dist/config.js +172 -0
  31. package/dist/config.js.map +1 -0
  32. package/dist/contextos/loader.d.ts +46 -0
  33. package/dist/contextos/loader.js +120 -0
  34. package/dist/contextos/loader.js.map +1 -0
  35. package/dist/contextos/selector.d.ts +46 -0
  36. package/dist/contextos/selector.js +80 -0
  37. package/dist/contextos/selector.js.map +1 -0
  38. package/dist/core/action-dispatcher.d.ts +15 -0
  39. package/dist/core/action-dispatcher.js +28 -0
  40. package/dist/core/action-dispatcher.js.map +1 -0
  41. package/dist/core/action-schema.d.ts +72 -0
  42. package/dist/core/action-schema.js +86 -0
  43. package/dist/core/action-schema.js.map +1 -0
  44. package/dist/core/repl-interface.d.ts +48 -0
  45. package/dist/core/repl-interface.js +5 -0
  46. package/dist/core/repl-interface.js.map +1 -0
  47. package/dist/core/repl.d.ts +59 -0
  48. package/dist/core/repl.js +353 -0
  49. package/dist/core/repl.js.map +1 -0
  50. package/dist/core/rlm.d.ts +65 -0
  51. package/dist/core/rlm.js +564 -0
  52. package/dist/core/rlm.js.map +1 -0
  53. package/dist/core/runtime.py +470 -0
  54. package/dist/core/types.d.ts +265 -0
  55. package/dist/core/types.js +19 -0
  56. package/dist/core/types.js.map +1 -0
  57. package/dist/env.d.ts +10 -0
  58. package/dist/env.js +75 -0
  59. package/dist/env.js.map +1 -0
  60. package/dist/hooks/runner.d.ts +43 -0
  61. package/dist/hooks/runner.js +173 -0
  62. package/dist/hooks/runner.js.map +1 -0
  63. package/dist/labs/cli.d.ts +15 -0
  64. package/dist/labs/cli.js +295 -0
  65. package/dist/labs/cli.js.map +1 -0
  66. package/dist/labs/episodic-memory.d.ts +132 -0
  67. package/dist/labs/episodic-memory.js +391 -0
  68. package/dist/labs/episodic-memory.js.map +1 -0
  69. package/dist/labs/interactive-swarm.d.ts +20 -0
  70. package/dist/labs/interactive-swarm.js +1173 -0
  71. package/dist/labs/interactive-swarm.js.map +1 -0
  72. package/dist/labs/interactive.d.ts +10 -0
  73. package/dist/labs/interactive.js +2099 -0
  74. package/dist/labs/interactive.js.map +1 -0
  75. package/dist/labs/ts-analyzer.d.ts +74 -0
  76. package/dist/labs/ts-analyzer.js +379 -0
  77. package/dist/labs/ts-analyzer.js.map +1 -0
  78. package/dist/labs/viewer.d.ts +12 -0
  79. package/dist/labs/viewer.js +1284 -0
  80. package/dist/labs/viewer.js.map +1 -0
  81. package/dist/main.d.ts +15 -0
  82. package/dist/main.js +247 -0
  83. package/dist/main.js.map +1 -0
  84. package/dist/mcp/server.d.ts +16 -0
  85. package/dist/mcp/server.js +192775 -0
  86. package/dist/mcp/server.js.map +1 -0
  87. package/dist/mcp/session.d.ts +117 -0
  88. package/dist/mcp/session.js +450 -0
  89. package/dist/mcp/session.js.map +1 -0
  90. package/dist/mcp/state.d.ts +42 -0
  91. package/dist/mcp/state.js +537 -0
  92. package/dist/mcp/state.js.map +1 -0
  93. package/dist/mcp/tools/contextos.d.ts +17 -0
  94. package/dist/mcp/tools/contextos.js +583 -0
  95. package/dist/mcp/tools/contextos.js.map +1 -0
  96. package/dist/mcp/tools.d.ts +15 -0
  97. package/dist/mcp/tools.js +393 -0
  98. package/dist/mcp/tools.js.map +1 -0
  99. package/dist/orchestration/reviewer-gate.d.ts +43 -0
  100. package/dist/orchestration/reviewer-gate.js +280 -0
  101. package/dist/orchestration/reviewer-gate.js.map +1 -0
  102. package/dist/orchestration/reviewer-prompt.d.ts +18 -0
  103. package/dist/orchestration/reviewer-prompt.js +67 -0
  104. package/dist/orchestration/reviewer-prompt.js.map +1 -0
  105. package/dist/orchestration/verification-runner.d.ts +53 -0
  106. package/dist/orchestration/verification-runner.js +352 -0
  107. package/dist/orchestration/verification-runner.js.map +1 -0
  108. package/dist/plugins/adapter.d.ts +11 -0
  109. package/dist/plugins/adapter.js +11 -0
  110. package/dist/plugins/adapter.js.map +1 -0
  111. package/dist/plugins/core/archive.d.ts +9 -0
  112. package/dist/plugins/core/archive.js +128 -0
  113. package/dist/plugins/core/archive.js.map +1 -0
  114. package/dist/plugins/core/digest.d.ts +11 -0
  115. package/dist/plugins/core/digest.js +70 -0
  116. package/dist/plugins/core/digest.js.map +1 -0
  117. package/dist/plugins/core/grants.d.ts +22 -0
  118. package/dist/plugins/core/grants.js +90 -0
  119. package/dist/plugins/core/grants.js.map +1 -0
  120. package/dist/plugins/core/index.d.ts +10 -0
  121. package/dist/plugins/core/index.js +11 -0
  122. package/dist/plugins/core/index.js.map +1 -0
  123. package/dist/plugins/core/pinning.d.ts +15 -0
  124. package/dist/plugins/core/pinning.js +86 -0
  125. package/dist/plugins/core/pinning.js.map +1 -0
  126. package/dist/plugins/core/types.d.ts +105 -0
  127. package/dist/plugins/core/types.js +22 -0
  128. package/dist/plugins/core/types.js.map +1 -0
  129. package/dist/plugins/core/updater.d.ts +16 -0
  130. package/dist/plugins/core/updater.js +64 -0
  131. package/dist/plugins/core/updater.js.map +1 -0
  132. package/dist/plugins/loader.d.ts +65 -0
  133. package/dist/plugins/loader.js +110 -0
  134. package/dist/plugins/loader.js.map +1 -0
  135. package/dist/prompts/orchestrator.d.ts +6 -0
  136. package/dist/prompts/orchestrator.js +114 -0
  137. package/dist/prompts/orchestrator.js.map +1 -0
  138. package/dist/routing/model-resolver.d.ts +27 -0
  139. package/dist/routing/model-resolver.js +265 -0
  140. package/dist/routing/model-resolver.js.map +1 -0
  141. package/dist/routing/model-router.d.ts +130 -0
  142. package/dist/routing/model-router.js +515 -0
  143. package/dist/routing/model-router.js.map +1 -0
  144. package/dist/runtime/attestations.cjs +260 -0
  145. package/dist/runtime/reviewer-pipeline.cjs +319 -0
  146. package/dist/runtime/sandbox.cjs +468 -0
  147. package/dist/runtime/state-machine.cjs +885 -0
  148. package/dist/runtime/thread-store.cjs +175 -0
  149. package/dist/runtime/transactional-git.cjs +315 -0
  150. package/dist/runtime/verification-pipeline.cjs +435 -0
  151. package/dist/sandbox/execution.d.ts +165 -0
  152. package/dist/sandbox/execution.js +497 -0
  153. package/dist/sandbox/execution.js.map +1 -0
  154. package/dist/security/file-policy.d.ts +22 -0
  155. package/dist/security/file-policy.js +53 -0
  156. package/dist/security/file-policy.js.map +1 -0
  157. package/dist/security/repository-boundary.d.ts +21 -0
  158. package/dist/security/repository-boundary.js +119 -0
  159. package/dist/security/repository-boundary.js.map +1 -0
  160. package/dist/security/secret-filter.d.ts +36 -0
  161. package/dist/security/secret-filter.js +149 -0
  162. package/dist/security/secret-filter.js.map +1 -0
  163. package/dist/swarm.d.ts +14 -0
  164. package/dist/swarm.js +624 -0
  165. package/dist/swarm.js.map +1 -0
  166. package/dist/threads/cache.d.ts +64 -0
  167. package/dist/threads/cache.js +241 -0
  168. package/dist/threads/cache.js.map +1 -0
  169. package/dist/threads/manager.d.ts +94 -0
  170. package/dist/threads/manager.js +914 -0
  171. package/dist/threads/manager.js.map +1 -0
  172. package/dist/ui/banner.d.ts +14 -0
  173. package/dist/ui/banner.js +42 -0
  174. package/dist/ui/banner.js.map +1 -0
  175. package/dist/ui/dashboard.d.ts +33 -0
  176. package/dist/ui/dashboard.js +135 -0
  177. package/dist/ui/dashboard.js.map +1 -0
  178. package/dist/ui/index.d.ts +11 -0
  179. package/dist/ui/index.js +12 -0
  180. package/dist/ui/index.js.map +1 -0
  181. package/dist/ui/log.d.ts +39 -0
  182. package/dist/ui/log.js +126 -0
  183. package/dist/ui/log.js.map +1 -0
  184. package/dist/ui/onboarding.d.ts +14 -0
  185. package/dist/ui/onboarding.js +755 -0
  186. package/dist/ui/onboarding.js.map +1 -0
  187. package/dist/ui/run-log.d.ts +50 -0
  188. package/dist/ui/run-log.js +60 -0
  189. package/dist/ui/run-log.js.map +1 -0
  190. package/dist/ui/spinner.d.ts +41 -0
  191. package/dist/ui/spinner.js +172 -0
  192. package/dist/ui/spinner.js.map +1 -0
  193. package/dist/ui/streaming-feed.d.ts +72 -0
  194. package/dist/ui/streaming-feed.js +386 -0
  195. package/dist/ui/streaming-feed.js.map +1 -0
  196. package/dist/ui/summary.d.ts +18 -0
  197. package/dist/ui/summary.js +113 -0
  198. package/dist/ui/summary.js.map +1 -0
  199. package/dist/ui/text-input.d.ts +19 -0
  200. package/dist/ui/text-input.js +266 -0
  201. package/dist/ui/text-input.js.map +1 -0
  202. package/dist/ui/theme.d.ts +63 -0
  203. package/dist/ui/theme.js +97 -0
  204. package/dist/ui/theme.js.map +1 -0
  205. package/dist/utils/command-exists.d.ts +11 -0
  206. package/dist/utils/command-exists.js +41 -0
  207. package/dist/utils/command-exists.js.map +1 -0
  208. package/dist/utils/process-security.d.ts +19 -0
  209. package/dist/utils/process-security.js +90 -0
  210. package/dist/utils/process-security.js.map +1 -0
  211. package/dist/utils/rolling-buffer.d.ts +16 -0
  212. package/dist/utils/rolling-buffer.js +30 -0
  213. package/dist/utils/rolling-buffer.js.map +1 -0
  214. package/dist/utils/safe-spawn.d.ts +13 -0
  215. package/dist/utils/safe-spawn.js +49 -0
  216. package/dist/utils/safe-spawn.js.map +1 -0
  217. package/dist/worktree/manager.d.ts +69 -0
  218. package/dist/worktree/manager.js +593 -0
  219. package/dist/worktree/manager.js.map +1 -0
  220. package/dist/worktree/merge.d.ts +58 -0
  221. package/dist/worktree/merge.js +389 -0
  222. package/dist/worktree/merge.js.map +1 -0
  223. package/package.json +63 -0
@@ -0,0 +1,119 @@
1
+ /**
2
+ * Repository boundary enforcement with nearest-parent realpath resolution.
3
+ *
4
+ * Prevents arbitrary file reads/writes, path traversals (../),
5
+ * sibling-prefix escapes (e.g. /repo-sibling attempting to match /repo),
6
+ * UNC paths, null bytes, and symlink/junction escapes.
7
+ */
8
+ import * as fs from "node:fs";
9
+ import * as path from "node:path";
10
+ export class SecurityBoundaryException extends Error {
11
+ constructor(message) {
12
+ super(message);
13
+ this.name = "SecurityBoundaryException";
14
+ }
15
+ }
16
+ function normalizeForComparison(p) {
17
+ const normalized = path.normalize(p);
18
+ return process.platform === "win32" ? normalized.toLowerCase() : normalized;
19
+ }
20
+ function isUncPath(p) {
21
+ return p.startsWith("\\\\") || p.startsWith("//");
22
+ }
23
+ /**
24
+ * Checks whether targetPath is contained within repoRoot.
25
+ */
26
+ export function isWithinRepository(targetPath, repoRoot) {
27
+ try {
28
+ assertWithinRepository(targetPath, repoRoot);
29
+ return true;
30
+ }
31
+ catch {
32
+ return false;
33
+ }
34
+ }
35
+ /**
36
+ * Asserts that targetPath is strictly within repoRoot.
37
+ *
38
+ * If valid, returns the canonical resolved path.
39
+ * If targetPath or repoRoot escapes boundaries, throws SecurityBoundaryException.
40
+ */
41
+ export function assertWithinRepository(targetPath, repoRoot) {
42
+ if (!targetPath || typeof targetPath !== "string") {
43
+ throw new SecurityBoundaryException("Target path must be a non-empty string");
44
+ }
45
+ if (!repoRoot || typeof repoRoot !== "string") {
46
+ throw new SecurityBoundaryException("Repository root must be a non-empty string");
47
+ }
48
+ if (targetPath.includes("\0") || repoRoot.includes("\0")) {
49
+ throw new SecurityBoundaryException("Path contains null bytes");
50
+ }
51
+ if (isUncPath(targetPath) || isUncPath(repoRoot)) {
52
+ throw new SecurityBoundaryException("UNC network paths are not permitted");
53
+ }
54
+ let canonicalRepoRoot;
55
+ try {
56
+ const absRepoRoot = path.resolve(repoRoot);
57
+ if (!fs.existsSync(absRepoRoot)) {
58
+ throw new SecurityBoundaryException(`Repository root does not exist: ${repoRoot}`);
59
+ }
60
+ canonicalRepoRoot = fs.realpathSync(absRepoRoot);
61
+ }
62
+ catch (err) {
63
+ if (err instanceof SecurityBoundaryException)
64
+ throw err;
65
+ const msg = err instanceof Error ? err.message : String(err);
66
+ throw new SecurityBoundaryException(`Failed to resolve repository root: ${msg}`);
67
+ }
68
+ // Resolve target relative to canonicalRepoRoot if relative
69
+ const absoluteTarget = path.isAbsolute(targetPath)
70
+ ? path.resolve(targetPath)
71
+ : path.resolve(canonicalRepoRoot, targetPath);
72
+ let canonicalTarget;
73
+ if (fs.existsSync(absoluteTarget)) {
74
+ try {
75
+ canonicalTarget = fs.realpathSync(absoluteTarget);
76
+ }
77
+ catch (err) {
78
+ const msg = err instanceof Error ? err.message : String(err);
79
+ throw new SecurityBoundaryException(`Failed to resolve path: ${msg}`);
80
+ }
81
+ }
82
+ else {
83
+ // Target does not exist yet: find nearest existing parent directory
84
+ let current = path.dirname(absoluteTarget);
85
+ const uncreatedSegments = [path.basename(absoluteTarget)];
86
+ while (!fs.existsSync(current)) {
87
+ const parent = path.dirname(current);
88
+ if (parent === current) {
89
+ throw new SecurityBoundaryException(`Cannot resolve parent directory for: ${targetPath}`);
90
+ }
91
+ uncreatedSegments.unshift(path.basename(current));
92
+ current = parent;
93
+ }
94
+ try {
95
+ const resolvedParent = fs.realpathSync(current);
96
+ const normParent = normalizeForComparison(resolvedParent);
97
+ const normRoot = normalizeForComparison(canonicalRepoRoot);
98
+ const rootPrefix = normRoot.endsWith(path.sep) ? normRoot : normRoot + path.sep;
99
+ if (normParent !== normRoot && !normParent.startsWith(rootPrefix)) {
100
+ throw new SecurityBoundaryException(`Parent directory ${resolvedParent} escapes repository boundary: ${canonicalRepoRoot}`);
101
+ }
102
+ canonicalTarget = path.join(resolvedParent, ...uncreatedSegments);
103
+ }
104
+ catch (err) {
105
+ if (err instanceof SecurityBoundaryException)
106
+ throw err;
107
+ const msg = err instanceof Error ? err.message : String(err);
108
+ throw new SecurityBoundaryException(`Failed to resolve parent directory: ${msg}`);
109
+ }
110
+ }
111
+ const normTarget = normalizeForComparison(canonicalTarget);
112
+ const normRoot = normalizeForComparison(canonicalRepoRoot);
113
+ const rootPrefix = normRoot.endsWith(path.sep) ? normRoot : normRoot + path.sep;
114
+ if (normTarget !== normRoot && !normTarget.startsWith(rootPrefix)) {
115
+ throw new SecurityBoundaryException(`Path "${targetPath}" resolves to "${canonicalTarget}" which is outside repository "${canonicalRepoRoot}"`);
116
+ }
117
+ return canonicalTarget;
118
+ }
119
+ //# sourceMappingURL=repository-boundary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"repository-boundary.js","sourceRoot":"","sources":["../../src/security/repository-boundary.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Secret Filter — prevents sensitive data from leaking to external LLM agents.
3
+ *
4
+ * Scans file contents and paths before they are included in agent prompts.
5
+ * Blocks files that likely contain secrets (API keys, credentials, SSH keys).
6
+ */
7
+ export interface SecretPatternDef {
8
+ name: string;
9
+ pattern: RegExp;
10
+ }
11
+ /** Structured secret pattern definitions with deterministic category names. */
12
+ export declare const SECRET_PATTERN_DEFS: SecretPatternDef[];
13
+ /** Backward-compatible array of RegExps */
14
+ export declare const SECRET_CONTENT_PATTERNS: RegExp[];
15
+ /**
16
+ * Check if a file path should be blocked from agent access.
17
+ *
18
+ * @param filePath - Relative or absolute path to check
19
+ * @returns true if the file should be BLOCKED (not sent to agents)
20
+ */
21
+ export declare function isBlockedPath(filePath: string): boolean;
22
+ /**
23
+ * Check if file content contains obvious secrets.
24
+ *
25
+ * @param content - The file content to scan
26
+ * @returns true if secrets were detected (file should NOT be sent to agents)
27
+ */
28
+ export declare function containsSecrets(content: string): boolean;
29
+ /**
30
+ * Sanitize a string by redacting any detected secret patterns.
31
+ * Replaces matched patterns with category-tagged [REDACTED:<NAME>].
32
+ *
33
+ * @param text - Text to sanitize
34
+ * @returns Text with secrets replaced by [REDACTED:<NAME>]
35
+ */
36
+ export declare function redactSecrets(text: string): string;
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Secret Filter — prevents sensitive data from leaking to external LLM agents.
3
+ *
4
+ * Scans file contents and paths before they are included in agent prompts.
5
+ * Blocks files that likely contain secrets (API keys, credentials, SSH keys).
6
+ */
7
+ import * as path from "node:path";
8
+ /** Exact filenames that MUST NEVER be sent to external agents. */
9
+ const BLOCKED_EXACT_FILENAMES = new Set([
10
+ "credentials",
11
+ "credentials.json",
12
+ "service-account.json",
13
+ "serviceaccountkey.json",
14
+ ".netrc",
15
+ ".git-credentials",
16
+ ".npmrc",
17
+ ".pypirc",
18
+ ]);
19
+ /** File extensions that should never be sent. */
20
+ const BLOCKED_EXTENSIONS = new Set([".pem", ".key", ".p12", ".pfx", ".jks", ".keystore", ".pkcs12", ".crt", ".der"]);
21
+ /** Directory names that should be blocked entirely. */
22
+ const BLOCKED_DIRS = new Set([".ssh", ".gnupg", ".aws", ".azure", ".gcp", ".kube", ".credentials"]);
23
+ /** Structured secret pattern definitions with deterministic category names. */
24
+ export const SECRET_PATTERN_DEFS = [
25
+ {
26
+ name: "AWS_KEY",
27
+ pattern: /\b(?:AKIA|AGPA|AIDA|AROA|AIPA|ANPA|ANVA|ASIA)[0-9A-Z]{16}\b/,
28
+ },
29
+ {
30
+ name: "GITHUB_FINE_GRAINED_PAT",
31
+ pattern: /\bgithub_pat_[0-9a-zA-Z_]{60,}\b/,
32
+ },
33
+ {
34
+ name: "GITHUB_PAT",
35
+ pattern: /\bghp_[0-9a-zA-Z]{36}\b/,
36
+ },
37
+ {
38
+ name: "GITHUB_OAUTH",
39
+ pattern: /\bgho_[0-9a-zA-Z]{36}\b/,
40
+ },
41
+ {
42
+ name: "SLACK_TOKEN",
43
+ pattern: /\bxox[baprs]-[0-9a-zA-Z-]{10,48}\b/,
44
+ },
45
+ {
46
+ name: "OPENAI_KEY",
47
+ pattern: /\bsk-(?:proj-)?[A-Za-z0-9_-]{32,}\b/,
48
+ },
49
+ {
50
+ name: "ANTHROPIC_KEY",
51
+ pattern: /\bsk-ant-[A-Za-z0-9-]{90,}\b/,
52
+ },
53
+ {
54
+ name: "GOOGLE_KEY",
55
+ pattern: /\bAIza[A-Za-z0-9_-]{35}\b/,
56
+ },
57
+ {
58
+ name: "NPM_TOKEN",
59
+ pattern: /\bnpm_[A-Za-z0-9]{32,36}\b/,
60
+ },
61
+ {
62
+ name: "PRIVATE_KEY",
63
+ pattern: /-----BEGIN\s+(?:[A-Z0-9_-]+\s+)?PRIVATE\s+KEY-----[\s\S]*?-----END\s+(?:[A-Z0-9_-]+\s+)?PRIVATE\s+KEY-----|-----BEGIN\s+(?:[A-Z0-9_-]+\s+)?PRIVATE\s+KEY-----/,
64
+ },
65
+ {
66
+ name: "CERTIFICATE",
67
+ pattern: /-----BEGIN\s+CERTIFICATE-----[\s\S]*?-----END\s+CERTIFICATE-----|-----BEGIN\s+CERTIFICATE-----/,
68
+ },
69
+ {
70
+ name: "JWT_TOKEN",
71
+ pattern: /\beyJ[A-Za-z0-9-_=]+\.[A-Za-z0-9-_=]+\.?[A-Za-z0-9-_.+/=]*\b/,
72
+ },
73
+ {
74
+ name: "GENERIC_SECRET",
75
+ pattern: /(?:API[_-]?KEY|SECRET[_-]?KEY|ACCESS[_-]?KEY|PRIVATE[_-]?KEY|AUTH[_-]?TOKEN|PASSWORD)\s*[=:]\s*['"]?[A-Za-z0-9+/=_-]{16,}['"]?/i,
76
+ },
77
+ ];
78
+ /** Backward-compatible array of RegExps */
79
+ export const SECRET_CONTENT_PATTERNS = SECRET_PATTERN_DEFS.map((d) => d.pattern);
80
+ /**
81
+ * Check if a file path should be blocked from agent access.
82
+ *
83
+ * @param filePath - Relative or absolute path to check
84
+ * @returns true if the file should be BLOCKED (not sent to agents)
85
+ */
86
+ export function isBlockedPath(filePath) {
87
+ if (!filePath)
88
+ return false;
89
+ const normalized = path.normalize(filePath).replace(/\\/g, "/");
90
+ const basename = path.basename(normalized).toLowerCase();
91
+ const ext = path.extname(normalized).toLowerCase();
92
+ const parts = normalized
93
+ .split("/")
94
+ .map((p) => p.toLowerCase())
95
+ .filter(Boolean);
96
+ // Block all .env variants (.env, .env.local, .env.staging, foo.env)
97
+ if (basename === ".env" || basename.startsWith(".env.") || basename.endsWith(".env")) {
98
+ return true;
99
+ }
100
+ // Check blocked filenames
101
+ if (BLOCKED_EXACT_FILENAMES.has(basename)) {
102
+ return true;
103
+ }
104
+ // Check blocked extensions
105
+ if (BLOCKED_EXTENSIONS.has(ext)) {
106
+ return true;
107
+ }
108
+ // Check blocked directory segments
109
+ if (parts.some((p) => BLOCKED_DIRS.has(p))) {
110
+ return true;
111
+ }
112
+ // Check private SSH keys (id_rsa, id_ed25519, etc., except public keys ending in .pub)
113
+ if (basename.startsWith("id_") && !basename.endsWith(".pub")) {
114
+ return true;
115
+ }
116
+ return false;
117
+ }
118
+ /**
119
+ * Check if file content contains obvious secrets.
120
+ *
121
+ * @param content - The file content to scan
122
+ * @returns true if secrets were detected (file should NOT be sent to agents)
123
+ */
124
+ export function containsSecrets(content) {
125
+ if (!content)
126
+ return false;
127
+ // Scan up to 1MB of content for comprehensive coverage without memory spikes
128
+ const sample = content.length > 1_000_000 ? content.slice(0, 1_000_000) : content;
129
+ return SECRET_PATTERN_DEFS.some(({ pattern }) => pattern.test(sample));
130
+ }
131
+ /**
132
+ * Sanitize a string by redacting any detected secret patterns.
133
+ * Replaces matched patterns with category-tagged [REDACTED:<NAME>].
134
+ *
135
+ * @param text - Text to sanitize
136
+ * @returns Text with secrets replaced by [REDACTED:<NAME>]
137
+ */
138
+ export function redactSecrets(text) {
139
+ if (!text)
140
+ return text;
141
+ let result = text;
142
+ for (const { name, pattern } of SECRET_PATTERN_DEFS) {
143
+ const flags = pattern.flags.includes("g") ? pattern.flags : `${pattern.flags}g`;
144
+ const regex = new RegExp(pattern.source, flags);
145
+ result = result.replace(regex, `[REDACTED:${name}]`);
146
+ }
147
+ return result;
148
+ }
149
+ //# sourceMappingURL=secret-filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secret-filter.js","sourceRoot":"","sources":["../../src/security/secret-filter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Swarm mode — orchestrates coding agents in parallel via the RLM loop.
3
+ *
4
+ * Usage: swarm --dir ./my-project "add error handling to all API routes"
5
+ *
6
+ * This module:
7
+ * 1. Parses swarm-specific CLI args
8
+ * 2. Scans the target directory to build a codebase context
9
+ * 3. Sets up ThreadManager + WorktreeManager
10
+ * 4. Runs the RLM loop with the swarm orchestrator prompt
11
+ * 5. Cleans up worktrees on exit
12
+ */
13
+ import "./env.js";
14
+ export declare function runSwarmMode(rawArgs: string[]): Promise<void>;