@ai-agent-context/core 0.1.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 (236) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +285 -0
  3. package/dist/.tsbuildinfo +1 -0
  4. package/dist/adapters/filesystem/fs-adapter.d.ts +50 -0
  5. package/dist/adapters/filesystem/fs-adapter.d.ts.map +1 -0
  6. package/dist/adapters/filesystem/fs-adapter.js +168 -0
  7. package/dist/adapters/filesystem/fs-adapter.js.map +1 -0
  8. package/dist/adapters/filesystem/sensitive.d.ts +26 -0
  9. package/dist/adapters/filesystem/sensitive.d.ts.map +1 -0
  10. package/dist/adapters/filesystem/sensitive.js +67 -0
  11. package/dist/adapters/filesystem/sensitive.js.map +1 -0
  12. package/dist/adapters/git/git-adapter.d.ts +47 -0
  13. package/dist/adapters/git/git-adapter.d.ts.map +1 -0
  14. package/dist/adapters/git/git-adapter.js +109 -0
  15. package/dist/adapters/git/git-adapter.js.map +1 -0
  16. package/dist/adapters/language/json/adapter.d.ts +24 -0
  17. package/dist/adapters/language/json/adapter.d.ts.map +1 -0
  18. package/dist/adapters/language/json/adapter.js +54 -0
  19. package/dist/adapters/language/json/adapter.js.map +1 -0
  20. package/dist/adapters/language/markdown/adapter.d.ts +41 -0
  21. package/dist/adapters/language/markdown/adapter.d.ts.map +1 -0
  22. package/dist/adapters/language/markdown/adapter.js +124 -0
  23. package/dist/adapters/language/markdown/adapter.js.map +1 -0
  24. package/dist/adapters/language/package-json/adapter.d.ts +47 -0
  25. package/dist/adapters/language/package-json/adapter.d.ts.map +1 -0
  26. package/dist/adapters/language/package-json/adapter.js +153 -0
  27. package/dist/adapters/language/package-json/adapter.js.map +1 -0
  28. package/dist/adapters/language/registry.d.ts +35 -0
  29. package/dist/adapters/language/registry.d.ts.map +1 -0
  30. package/dist/adapters/language/registry.js +79 -0
  31. package/dist/adapters/language/registry.js.map +1 -0
  32. package/dist/adapters/language/ts-js/adapter.d.ts +14 -0
  33. package/dist/adapters/language/ts-js/adapter.d.ts.map +1 -0
  34. package/dist/adapters/language/ts-js/adapter.js +59 -0
  35. package/dist/adapters/language/ts-js/adapter.js.map +1 -0
  36. package/dist/adapters/language/ts-js/extractor.d.ts +21 -0
  37. package/dist/adapters/language/ts-js/extractor.d.ts.map +1 -0
  38. package/dist/adapters/language/ts-js/extractor.js +779 -0
  39. package/dist/adapters/language/ts-js/extractor.js.map +1 -0
  40. package/dist/adapters/language/ts-js/lexer.d.ts +30 -0
  41. package/dist/adapters/language/ts-js/lexer.d.ts.map +1 -0
  42. package/dist/adapters/language/ts-js/lexer.js +446 -0
  43. package/dist/adapters/language/ts-js/lexer.js.map +1 -0
  44. package/dist/adapters/language/ts-js/package-signals.d.ts +5 -0
  45. package/dist/adapters/language/ts-js/package-signals.d.ts.map +1 -0
  46. package/dist/adapters/language/ts-js/package-signals.js +113 -0
  47. package/dist/adapters/language/ts-js/package-signals.js.map +1 -0
  48. package/dist/adapters/language/tsconfig/adapter.d.ts +38 -0
  49. package/dist/adapters/language/tsconfig/adapter.d.ts.map +1 -0
  50. package/dist/adapters/language/tsconfig/adapter.js +130 -0
  51. package/dist/adapters/language/tsconfig/adapter.js.map +1 -0
  52. package/dist/adapters/language/types.d.ts +152 -0
  53. package/dist/adapters/language/types.d.ts.map +1 -0
  54. package/dist/adapters/language/types.js +51 -0
  55. package/dist/adapters/language/types.js.map +1 -0
  56. package/dist/agent-context.d.ts +122 -0
  57. package/dist/agent-context.d.ts.map +1 -0
  58. package/dist/agent-context.js +243 -0
  59. package/dist/agent-context.js.map +1 -0
  60. package/dist/config/defaults.d.ts +13 -0
  61. package/dist/config/defaults.d.ts.map +1 -0
  62. package/dist/config/defaults.js +98 -0
  63. package/dist/config/defaults.js.map +1 -0
  64. package/dist/config/load.d.ts +25 -0
  65. package/dist/config/load.d.ts.map +1 -0
  66. package/dist/config/load.js +106 -0
  67. package/dist/config/load.js.map +1 -0
  68. package/dist/config/types.d.ts +95 -0
  69. package/dist/config/types.d.ts.map +1 -0
  70. package/dist/config/types.js +8 -0
  71. package/dist/config/types.js.map +1 -0
  72. package/dist/config/validate.d.ts +15 -0
  73. package/dist/config/validate.d.ts.map +1 -0
  74. package/dist/config/validate.js +202 -0
  75. package/dist/config/validate.js.map +1 -0
  76. package/dist/core/architecture/detector.d.ts +10 -0
  77. package/dist/core/architecture/detector.d.ts.map +1 -0
  78. package/dist/core/architecture/detector.js +37 -0
  79. package/dist/core/architecture/detector.js.map +1 -0
  80. package/dist/core/architecture/entry-points.d.ts +20 -0
  81. package/dist/core/architecture/entry-points.d.ts.map +1 -0
  82. package/dist/core/architecture/entry-points.js +190 -0
  83. package/dist/core/architecture/entry-points.js.map +1 -0
  84. package/dist/core/architecture/role-detector.d.ts +32 -0
  85. package/dist/core/architecture/role-detector.d.ts.map +1 -0
  86. package/dist/core/architecture/role-detector.js +240 -0
  87. package/dist/core/architecture/role-detector.js.map +1 -0
  88. package/dist/core/context/explain.d.ts +36 -0
  89. package/dist/core/context/explain.d.ts.map +1 -0
  90. package/dist/core/context/explain.js +199 -0
  91. package/dist/core/context/explain.js.map +1 -0
  92. package/dist/core/context/repository-context.d.ts +16 -0
  93. package/dist/core/context/repository-context.d.ts.map +1 -0
  94. package/dist/core/context/repository-context.js +134 -0
  95. package/dist/core/context/repository-context.js.map +1 -0
  96. package/dist/core/context/types.d.ts +94 -0
  97. package/dist/core/context/types.d.ts.map +1 -0
  98. package/dist/core/context/types.js +2 -0
  99. package/dist/core/context/types.js.map +1 -0
  100. package/dist/core/conventions/detector.d.ts +55 -0
  101. package/dist/core/conventions/detector.d.ts.map +1 -0
  102. package/dist/core/conventions/detector.js +438 -0
  103. package/dist/core/conventions/detector.js.map +1 -0
  104. package/dist/core/conventions/renderer.d.ts +16 -0
  105. package/dist/core/conventions/renderer.d.ts.map +1 -0
  106. package/dist/core/conventions/renderer.js +42 -0
  107. package/dist/core/conventions/renderer.js.map +1 -0
  108. package/dist/core/decisions/detector.d.ts +45 -0
  109. package/dist/core/decisions/detector.d.ts.map +1 -0
  110. package/dist/core/decisions/detector.js +256 -0
  111. package/dist/core/decisions/detector.js.map +1 -0
  112. package/dist/core/diff/differ.d.ts +26 -0
  113. package/dist/core/diff/differ.d.ts.map +1 -0
  114. package/dist/core/diff/differ.js +159 -0
  115. package/dist/core/diff/differ.js.map +1 -0
  116. package/dist/core/git-analysis/activity.d.ts +35 -0
  117. package/dist/core/git-analysis/activity.d.ts.map +1 -0
  118. package/dist/core/git-analysis/activity.js +123 -0
  119. package/dist/core/git-analysis/activity.js.map +1 -0
  120. package/dist/core/graph/aliases.d.ts +20 -0
  121. package/dist/core/graph/aliases.d.ts.map +1 -0
  122. package/dist/core/graph/aliases.js +99 -0
  123. package/dist/core/graph/aliases.js.map +1 -0
  124. package/dist/core/graph/knowledge-graph.d.ts +91 -0
  125. package/dist/core/graph/knowledge-graph.d.ts.map +1 -0
  126. package/dist/core/graph/knowledge-graph.js +572 -0
  127. package/dist/core/graph/knowledge-graph.js.map +1 -0
  128. package/dist/core/graph/modules.d.ts +28 -0
  129. package/dist/core/graph/modules.d.ts.map +1 -0
  130. package/dist/core/graph/modules.js +139 -0
  131. package/dist/core/graph/modules.js.map +1 -0
  132. package/dist/core/graph/resolver.d.ts +50 -0
  133. package/dist/core/graph/resolver.d.ts.map +1 -0
  134. package/dist/core/graph/resolver.js +180 -0
  135. package/dist/core/graph/resolver.js.map +1 -0
  136. package/dist/core/scanner/cache.d.ts +49 -0
  137. package/dist/core/scanner/cache.d.ts.map +1 -0
  138. package/dist/core/scanner/cache.js +101 -0
  139. package/dist/core/scanner/cache.js.map +1 -0
  140. package/dist/core/scanner/scanner.d.ts +60 -0
  141. package/dist/core/scanner/scanner.d.ts.map +1 -0
  142. package/dist/core/scanner/scanner.js +304 -0
  143. package/dist/core/scanner/scanner.js.map +1 -0
  144. package/dist/core/scanner/types.d.ts +47 -0
  145. package/dist/core/scanner/types.d.ts.map +1 -0
  146. package/dist/core/scanner/types.js +18 -0
  147. package/dist/core/scanner/types.js.map +1 -0
  148. package/dist/core/search/analyzer.d.ts +16 -0
  149. package/dist/core/search/analyzer.d.ts.map +1 -0
  150. package/dist/core/search/analyzer.js +165 -0
  151. package/dist/core/search/analyzer.js.map +1 -0
  152. package/dist/core/search/bm25.d.ts +21 -0
  153. package/dist/core/search/bm25.d.ts.map +1 -0
  154. package/dist/core/search/bm25.js +108 -0
  155. package/dist/core/search/bm25.js.map +1 -0
  156. package/dist/core/search/documents.d.ts +20 -0
  157. package/dist/core/search/documents.d.ts.map +1 -0
  158. package/dist/core/search/documents.js +106 -0
  159. package/dist/core/search/documents.js.map +1 -0
  160. package/dist/core/search/service.d.ts +30 -0
  161. package/dist/core/search/service.d.ts.map +1 -0
  162. package/dist/core/search/service.js +54 -0
  163. package/dist/core/search/service.js.map +1 -0
  164. package/dist/core/search/types.d.ts +44 -0
  165. package/dist/core/search/types.d.ts.map +1 -0
  166. package/dist/core/search/types.js +2 -0
  167. package/dist/core/search/types.js.map +1 -0
  168. package/dist/core/serialization/documents.d.ts +26 -0
  169. package/dist/core/serialization/documents.d.ts.map +1 -0
  170. package/dist/core/serialization/documents.js +224 -0
  171. package/dist/core/serialization/documents.js.map +1 -0
  172. package/dist/core/serialization/reader.d.ts +22 -0
  173. package/dist/core/serialization/reader.d.ts.map +1 -0
  174. package/dist/core/serialization/reader.js +65 -0
  175. package/dist/core/serialization/reader.js.map +1 -0
  176. package/dist/core/serialization/types.d.ts +184 -0
  177. package/dist/core/serialization/types.d.ts.map +1 -0
  178. package/dist/core/serialization/types.js +2 -0
  179. package/dist/core/serialization/types.js.map +1 -0
  180. package/dist/core/serialization/writer.d.ts +17 -0
  181. package/dist/core/serialization/writer.d.ts.map +1 -0
  182. package/dist/core/serialization/writer.js +64 -0
  183. package/dist/core/serialization/writer.js.map +1 -0
  184. package/dist/core/workspace/package-facts.d.ts +12 -0
  185. package/dist/core/workspace/package-facts.d.ts.map +1 -0
  186. package/dist/core/workspace/package-facts.js +50 -0
  187. package/dist/core/workspace/package-facts.js.map +1 -0
  188. package/dist/core/workspace/workspace.d.ts +32 -0
  189. package/dist/core/workspace/workspace.d.ts.map +1 -0
  190. package/dist/core/workspace/workspace.js +167 -0
  191. package/dist/core/workspace/workspace.js.map +1 -0
  192. package/dist/errors.d.ts +50 -0
  193. package/dist/errors.d.ts.map +1 -0
  194. package/dist/errors.js +64 -0
  195. package/dist/errors.js.map +1 -0
  196. package/dist/index.d.ts +80 -0
  197. package/dist/index.d.ts.map +1 -0
  198. package/dist/index.js +66 -0
  199. package/dist/index.js.map +1 -0
  200. package/dist/logging/diagnostics.d.ts +64 -0
  201. package/dist/logging/diagnostics.d.ts.map +1 -0
  202. package/dist/logging/diagnostics.js +92 -0
  203. package/dist/logging/diagnostics.js.map +1 -0
  204. package/dist/model/canonical.d.ts +24 -0
  205. package/dist/model/canonical.d.ts.map +1 -0
  206. package/dist/model/canonical.js +69 -0
  207. package/dist/model/canonical.js.map +1 -0
  208. package/dist/model/schema.d.ts +37 -0
  209. package/dist/model/schema.d.ts.map +1 -0
  210. package/dist/model/schema.js +42 -0
  211. package/dist/model/schema.js.map +1 -0
  212. package/dist/model/types.d.ts +402 -0
  213. package/dist/model/types.d.ts.map +1 -0
  214. package/dist/model/types.js +10 -0
  215. package/dist/model/types.js.map +1 -0
  216. package/dist/pipeline/scan-pipeline.d.ts +69 -0
  217. package/dist/pipeline/scan-pipeline.d.ts.map +1 -0
  218. package/dist/pipeline/scan-pipeline.js +270 -0
  219. package/dist/pipeline/scan-pipeline.js.map +1 -0
  220. package/dist/util/concurrency.d.ts +17 -0
  221. package/dist/util/concurrency.d.ts.map +1 -0
  222. package/dist/util/concurrency.js +46 -0
  223. package/dist/util/concurrency.js.map +1 -0
  224. package/dist/util/glob.d.ts +26 -0
  225. package/dist/util/glob.d.ts.map +1 -0
  226. package/dist/util/glob.js +198 -0
  227. package/dist/util/glob.js.map +1 -0
  228. package/dist/util/paths.d.ts +23 -0
  229. package/dist/util/paths.d.ts.map +1 -0
  230. package/dist/util/paths.js +115 -0
  231. package/dist/util/paths.js.map +1 -0
  232. package/dist/util/text.d.ts +22 -0
  233. package/dist/util/text.d.ts.map +1 -0
  234. package/dist/util/text.js +66 -0
  235. package/dist/util/text.js.map +1 -0
  236. package/package.json +52 -0
@@ -0,0 +1,168 @@
1
+ /**
2
+ * File system adapter.
3
+ *
4
+ * Responsibilities:
5
+ * - deterministic, streaming directory traversal (never loads file contents here);
6
+ * - include/exclude/ignore glob evaluation with safe directory pruning;
7
+ * - bounded concurrency for stat/hash/read work is owned by the callers.
8
+ *
9
+ * The rest of the pipeline only talks to this adapter, so swapping in a virtual
10
+ * file system (or a remote checkout) later does not touch the analysis core.
11
+ */
12
+ import { readdir, readFile, stat } from 'node:fs/promises';
13
+ import { existsSync } from 'node:fs';
14
+ import path from 'node:path';
15
+ import { toPosix, normalizeRelative } from "../../util/paths.js";
16
+ import { compareStrings } from "../../model/canonical.js";
17
+ import { PatternSet } from "../../util/glob.js";
18
+ const DEFAULT_MAX_FILES = 500_000;
19
+ /** Leading literal directory of a glob pattern, used for directory pruning. */
20
+ function literalPrefix(pattern) {
21
+ const segments = pattern.replace(/\\/g, '/').split('/');
22
+ const literal = [];
23
+ for (const segment of segments) {
24
+ if (/[*?[{]/.test(segment))
25
+ break;
26
+ literal.push(segment);
27
+ }
28
+ return literal.join('/');
29
+ }
30
+ export class FileSystemAdapter {
31
+ root;
32
+ prefixes = [];
33
+ constructor(root) {
34
+ this.root = path.resolve(root);
35
+ }
36
+ /**
37
+ * Traverses the repository, returning files sorted by path.
38
+ *
39
+ * Traversal is breadth-first with an explicit queue, so deep trees cannot blow
40
+ * the call stack, and directory entries are read in sorted order so that the
41
+ * resulting context does not depend on file system ordering.
42
+ */
43
+ async walk(options = {}) {
44
+ const files = [];
45
+ const maxFiles = options.maxFiles ?? DEFAULT_MAX_FILES;
46
+ const canPrune = this.canPrune(options.include);
47
+ const queue = [''];
48
+ while (queue.length > 0) {
49
+ const relativeDir = queue.shift();
50
+ const absoluteDir = relativeDir.length === 0 ? this.root : path.join(this.root, relativeDir);
51
+ let entries;
52
+ try {
53
+ entries = await readdir(absoluteDir, { withFileTypes: true });
54
+ }
55
+ catch {
56
+ // Unreadable directory: analysis continues and the caller reports a warning.
57
+ continue;
58
+ }
59
+ entries.sort((a, b) => compareStrings(a.name, b.name));
60
+ for (const entry of entries) {
61
+ const relativePath = relativeDir.length === 0 ? entry.name : `${relativeDir}/${entry.name}`;
62
+ const absolutePath = path.join(absoluteDir, entry.name);
63
+ const isSymbolicLink = entry.isSymbolicLink();
64
+ if (entry.isDirectory() || isSymbolicLink) {
65
+ if (isSymbolicLink && options.followSymlinks !== true)
66
+ continue;
67
+ if (this.isExcludedDirectory(relativePath, options))
68
+ continue;
69
+ if (canPrune && !this.canContainIncluded(relativePath, options.include))
70
+ continue;
71
+ options.onDirectory?.(relativePath);
72
+ queue.push(relativePath);
73
+ continue;
74
+ }
75
+ if (!entry.isFile())
76
+ continue;
77
+ if (this.isExcludedFile(relativePath, options))
78
+ continue;
79
+ if (!this.matchesInclude(relativePath, options.include))
80
+ continue;
81
+ let stats;
82
+ try {
83
+ stats = await stat(absolutePath);
84
+ }
85
+ catch {
86
+ continue;
87
+ }
88
+ const walked = {
89
+ path: relativePath,
90
+ absolutePath,
91
+ size: stats.size,
92
+ mtimeMs: Math.round(stats.mtimeMs),
93
+ isSymbolicLink,
94
+ };
95
+ files.push(walked);
96
+ options.onFile?.(walked);
97
+ if (files.length >= maxFiles)
98
+ return files;
99
+ }
100
+ }
101
+ files.sort((a, b) => compareStrings(a.path, b.path));
102
+ return files;
103
+ }
104
+ isExcludedDirectory(relativePath, options) {
105
+ if (options.exclude?.test(relativePath, true))
106
+ return true;
107
+ if (options.ignore?.test(relativePath, true))
108
+ return true;
109
+ return false;
110
+ }
111
+ isExcludedFile(relativePath, options) {
112
+ if (options.exclude?.test(relativePath, false))
113
+ return true;
114
+ if (options.ignore?.test(relativePath, false))
115
+ return true;
116
+ return false;
117
+ }
118
+ matchesInclude(relativePath, include) {
119
+ if (!include || include.isEmpty)
120
+ return true;
121
+ return include.matchesAny(relativePath);
122
+ }
123
+ /** `true` when directory pruning is safe for the configured include patterns. */
124
+ canPrune(include) {
125
+ if (!include || include.isEmpty)
126
+ return false;
127
+ const prefixes = include.rules.filter((rule) => !rule.negated).map((rule) => literalPrefix(rule.raw));
128
+ if (prefixes.length === 0 || prefixes.some((prefix) => prefix.length === 0))
129
+ return false;
130
+ this.prefixes.length = 0;
131
+ this.prefixes.push(...new Set(prefixes));
132
+ return true;
133
+ }
134
+ canContainIncluded(relativeDir, include) {
135
+ if (!include || this.prefixes.length === 0)
136
+ return true;
137
+ const normalized = normalizeRelative(relativeDir);
138
+ return this.prefixes.some((prefix) => prefix === normalized || prefix.startsWith(`${normalized}/`) || normalized.startsWith(`${prefix}/`));
139
+ }
140
+ exists(relativePath) {
141
+ return existsSync(path.join(this.root, relativePath));
142
+ }
143
+ async readText(relativePath) {
144
+ return readFile(path.join(this.root, relativePath), 'utf8');
145
+ }
146
+ async readJson(relativePath) {
147
+ const contents = await this.readText(relativePath);
148
+ return JSON.parse(contents);
149
+ }
150
+ async tryReadText(relativePath) {
151
+ try {
152
+ return await this.readText(relativePath);
153
+ }
154
+ catch {
155
+ return null;
156
+ }
157
+ }
158
+ toRelative(absolutePath) {
159
+ return toPosix(path.relative(this.root, absolutePath));
160
+ }
161
+ toAbsolute(relativePath) {
162
+ return path.join(this.root, relativePath);
163
+ }
164
+ get basename() {
165
+ return path.basename(this.root);
166
+ }
167
+ }
168
+ //# sourceMappingURL=fs-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fs-adapter.js","sourceRoot":"","sources":["../../../src/adapters/filesystem/fs-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ export declare const REDACTED = "[REDACTED]";
2
+ interface SecretPattern {
3
+ name: string;
4
+ regex: RegExp;
5
+ }
6
+ /** Value-level patterns used to detect and redact secret material. */
7
+ export declare const SECRET_VALUE_PATTERNS: SecretPattern[];
8
+ /** `true` when the text appears to contain secret material. */
9
+ export declare function containsSecret(text: string): boolean;
10
+ /** Replaces secret-looking values with `[REDACTED]`, keeping the surrounding text. */
11
+ export declare function redactSecrets(text: string): string;
12
+ export interface SensitiveFilterOptions {
13
+ allowSensitiveFiles: boolean;
14
+ extraSensitivePatterns?: string[];
15
+ }
16
+ /** Path-level filter; checked before any file content is read. */
17
+ export declare class SensitivePathFilter {
18
+ private readonly patterns;
19
+ private readonly allow;
20
+ constructor(options: SensitiveFilterOptions);
21
+ /** `true` when the file must not be read. */
22
+ isBlocked(relativePath: string): boolean;
23
+ toArray(): string[];
24
+ }
25
+ export {};
26
+ //# sourceMappingURL=sensitive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sensitive.d.ts","sourceRoot":"","sources":["../../../src/adapters/filesystem/sensitive.ts"],"names":[],"mappings":"AAcA,eAAO,MAAM,QAAQ,eAAe,CAAC;AAErC,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,sEAAsE;AACtE,eAAO,MAAM,qBAAqB,EAAE,aAAa,EAchD,CAAC;AAEF,+DAA+D;AAC/D,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAKpD;AAED,sFAAsF;AACtF,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CASlD;AAED,MAAM,WAAW,sBAAsB;IACrC,mBAAmB,EAAE,OAAO,CAAC;IAC7B,sBAAsB,CAAC,EAAE,MAAM,EAAE,CAAC;CACnC;AAED,kEAAkE;AAClE,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAa;IACtC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAU;gBAEpB,OAAO,EAAE,sBAAsB;IAK3C,6CAA6C;IAC7C,SAAS,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO;IAKxC,OAAO,IAAI,MAAM,EAAE;CAGpB"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Secret handling.
3
+ *
4
+ * Two guarantees:
5
+ * 1. Sensitive *files* are never read (`.env`, keys, certificates, credentials).
6
+ * 2. Any text copied into the generated context (ADR excerpts, commit subjects)
7
+ * is passed through {@link redactSecrets} first, so a secret accidentally
8
+ * committed to the repository cannot leak into `.agent/`.
9
+ *
10
+ * The package performs no network calls and sends nothing anywhere.
11
+ */
12
+ import { PatternSet } from "../../util/glob.js";
13
+ import { DEFAULT_SENSITIVE_PATTERNS } from "../../config/defaults.js";
14
+ export const REDACTED = '[REDACTED]';
15
+ /** Value-level patterns used to detect and redact secret material. */
16
+ export const SECRET_VALUE_PATTERNS = [
17
+ { name: 'private-key-block', regex: /-----BEGIN [A-Z ]*PRIVATE KEY-----[\s\S]*?-----END [A-Z ]*PRIVATE KEY-----/g },
18
+ {
19
+ name: 'assigned-secret',
20
+ regex: /\b(api[_-]?key|secret|token|password|passwd|pwd|private[_-]?key|access[_-]?key|client[_-]?secret|auth[_-]?token)\b\s*[:=]\s*["']?([A-Za-z0-9_\-./+]{8,})["']?/gi,
21
+ },
22
+ { name: 'openai-key', regex: /\bsk-[A-Za-z0-9_-]{16,}\b/g },
23
+ { name: 'anthropic-key', regex: /\bsk-ant-[A-Za-z0-9_-]{16,}\b/g },
24
+ { name: 'github-token', regex: /\b(gh[pousr]_[A-Za-z0-9]{20,})\b/g },
25
+ { name: 'aws-access-key', regex: /\b(AKIA|ASIA)[0-9A-Z]{16}\b/g },
26
+ { name: 'slack-token', regex: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g },
27
+ { name: 'google-api-key', regex: /\bAIza[0-9A-Za-z_-]{35}\b/g },
28
+ { name: 'jwt', regex: /\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g },
29
+ { name: 'credentials-in-url', regex: /\/\/[A-Za-z0-9._%-]+:[^\s@/]+@/g },
30
+ ];
31
+ /** `true` when the text appears to contain secret material. */
32
+ export function containsSecret(text) {
33
+ return SECRET_VALUE_PATTERNS.some((pattern) => {
34
+ pattern.regex.lastIndex = 0;
35
+ return pattern.regex.test(text);
36
+ });
37
+ }
38
+ /** Replaces secret-looking values with `[REDACTED]`, keeping the surrounding text. */
39
+ export function redactSecrets(text) {
40
+ let output = text;
41
+ output = output.replace(SECRET_VALUE_PATTERNS[0].regex, `${REDACTED} private key`);
42
+ output = output.replace(SECRET_VALUE_PATTERNS[1].regex, (_match, key) => `${key}: "${REDACTED}"`);
43
+ for (const pattern of SECRET_VALUE_PATTERNS.slice(2, 8)) {
44
+ output = output.replace(pattern.regex, REDACTED);
45
+ }
46
+ output = output.replace(SECRET_VALUE_PATTERNS[8].regex, `//${REDACTED}@`);
47
+ return output;
48
+ }
49
+ /** Path-level filter; checked before any file content is read. */
50
+ export class SensitivePathFilter {
51
+ patterns;
52
+ allow;
53
+ constructor(options) {
54
+ this.allow = options.allowSensitiveFiles;
55
+ this.patterns = new PatternSet([...DEFAULT_SENSITIVE_PATTERNS, ...(options.extraSensitivePatterns ?? [])]);
56
+ }
57
+ /** `true` when the file must not be read. */
58
+ isBlocked(relativePath) {
59
+ if (this.allow)
60
+ return false;
61
+ return this.patterns.test(relativePath, false);
62
+ }
63
+ toArray() {
64
+ return this.patterns.toArray();
65
+ }
66
+ }
67
+ //# sourceMappingURL=sensitive.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sensitive.js","sourceRoot":"","sources":["../../../src/adapters/filesystem/sensitive.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ export interface GitCommit {
2
+ sha: string;
3
+ /** Author name as recorded by git (neutral ownership signal). */
4
+ author: string;
5
+ /** ISO 8601 author date. */
6
+ date: string;
7
+ /** Author date in milliseconds since epoch. */
8
+ dateMs: number;
9
+ subject: string;
10
+ /** Repository-relative POSIX paths touched by the commit. */
11
+ files: string[];
12
+ }
13
+ export interface GitLogOptions {
14
+ windowDays: number;
15
+ maxCommits: number;
16
+ }
17
+ export interface GitAvailability {
18
+ available: boolean;
19
+ /** Reason why git signals are unavailable, when `available === false`. */
20
+ reason?: string;
21
+ /** Absolute path of the repository top level. */
22
+ toplevel?: string;
23
+ /** Current branch name, when resolvable. */
24
+ branch?: string | null;
25
+ head?: string | null;
26
+ }
27
+ export interface GitAdapterOptions {
28
+ /** Path or name of the git binary. */
29
+ gitBinary?: string;
30
+ /** Hard timeout for every git invocation, in milliseconds. */
31
+ timeoutMs?: number;
32
+ }
33
+ export declare class GitAdapter {
34
+ private readonly root;
35
+ private readonly binary;
36
+ private readonly timeoutMs;
37
+ private availability;
38
+ constructor(root: string, options?: GitAdapterOptions);
39
+ private run;
40
+ /** Detects whether git signals can be produced for this repository. */
41
+ probe(): Promise<GitAvailability>;
42
+ /** Reads the commit history inside the configured window. */
43
+ log(options: GitLogOptions): Promise<GitCommit[]>;
44
+ }
45
+ /** Parses the output produced by {@link LOG_FORMAT} combined with `--name-only`. */
46
+ export declare function parseGitLog(output: string): GitCommit[];
47
+ //# sourceMappingURL=git-adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-adapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/git/git-adapter.ts"],"names":[],"mappings":"AAYA,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,iEAAiE;IACjE,MAAM,EAAE,MAAM,CAAC;IACf,4BAA4B;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,+CAA+C;IAC/C,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,6DAA6D;IAC7D,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,aAAa;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,0EAA0E;IAC1E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,4CAA4C;IAC5C,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,sCAAsC;IACtC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAYD,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAS;IAC9B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IACnC,OAAO,CAAC,YAAY,CAAgC;gBAExC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB;YAM3C,GAAG;IAajB,uEAAuE;IACjE,KAAK,IAAI,OAAO,CAAC,eAAe,CAAC;IAwBvC,6DAA6D;IACvD,GAAG,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;CAcxD;AAED,oFAAoF;AACpF,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,CA0BvD"}
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Git adapter.
3
+ *
4
+ * Git is part of the core functionality (recently changed files, commit counts,
5
+ * ownership signals, architectural change history), but it is strictly optional
6
+ * at runtime: when `git` is missing or the directory is not a repository, the
7
+ * adapter reports that and analysis continues without git signals.
8
+ *
9
+ * Nothing leaves the machine: `git` is invoked locally through `child_process`.
10
+ */
11
+ import { execFile } from 'node:child_process';
12
+ const RECORD_SEPARATOR = '\u001e';
13
+ const FIELD_SEPARATOR = '\u001f';
14
+ const LOG_FORMAT = `%x1e%H%x1f%an%x1f%aI%x1f%s%x1e`;
15
+ export class GitAdapter {
16
+ root;
17
+ binary;
18
+ timeoutMs;
19
+ availability = null;
20
+ constructor(root, options = {}) {
21
+ this.root = root;
22
+ this.binary = options.gitBinary ?? 'git';
23
+ this.timeoutMs = options.timeoutMs ?? 20_000;
24
+ }
25
+ async run(args) {
26
+ return new Promise((resolve) => {
27
+ execFile(this.binary, ['--no-pager', '-c', 'core.quotepath=false', ...args], { cwd: this.root, timeout: this.timeoutMs, windowsHide: true, maxBuffer: 64 * 1024 * 1024 }, (error, stdout, stderr) => {
28
+ resolve({ ok: error === null, stdout: stdout?.toString() ?? '', stderr: stderr?.toString() ?? '' });
29
+ });
30
+ });
31
+ }
32
+ /** Detects whether git signals can be produced for this repository. */
33
+ async probe() {
34
+ if (this.availability !== null)
35
+ return this.availability;
36
+ const inside = await this.run(['rev-parse', '--is-inside-work-tree']);
37
+ if (!inside.ok) {
38
+ this.availability = {
39
+ available: false,
40
+ reason: inside.stderr.trim().length > 0 ? inside.stderr.trim() : 'not a git repository',
41
+ };
42
+ return this.availability;
43
+ }
44
+ const toplevel = await this.run(['rev-parse', '--show-toplevel']);
45
+ const branch = await this.run(['rev-parse', '--abbrev-ref', 'HEAD']);
46
+ const head = await this.run(['rev-parse', 'HEAD']);
47
+ const hasCommits = head.ok;
48
+ this.availability = {
49
+ available: hasCommits,
50
+ reason: hasCommits ? undefined : 'repository has no commits yet',
51
+ toplevel: toplevel.ok ? toplevel.stdout.trim() : undefined,
52
+ branch: branch.ok ? branch.stdout.trim() : null,
53
+ head: hasCommits ? head.stdout.trim() : null,
54
+ };
55
+ return this.availability;
56
+ }
57
+ /** Reads the commit history inside the configured window. */
58
+ async log(options) {
59
+ const availability = await this.probe();
60
+ if (!availability?.available)
61
+ return [];
62
+ const result = await this.run([
63
+ 'log',
64
+ `--since=${options.windowDays}.days.ago`,
65
+ `--max-count=${options.maxCommits}`,
66
+ '--name-only',
67
+ `--format=${LOG_FORMAT}`,
68
+ '--date-order',
69
+ ]);
70
+ if (!result.ok)
71
+ return [];
72
+ return parseGitLog(result.stdout);
73
+ }
74
+ }
75
+ /** Parses the output produced by {@link LOG_FORMAT} combined with `--name-only`. */
76
+ export function parseGitLog(output) {
77
+ const commits = [];
78
+ const chunks = output.split(RECORD_SEPARATOR);
79
+ for (const chunk of chunks) {
80
+ const trimmed = chunk.replace(/^\s+/, '');
81
+ if (trimmed.length === 0)
82
+ continue;
83
+ const lines = trimmed.split('\n');
84
+ const header = lines.shift();
85
+ if (header === undefined)
86
+ continue;
87
+ const [sha, author, date, ...subjectParts] = header.split(FIELD_SEPARATOR);
88
+ if (sha === undefined || author === undefined || date === undefined)
89
+ continue;
90
+ const dateMs = Date.parse(date);
91
+ const files = lines
92
+ .map((line) => line.trim())
93
+ .filter((line) => line.length > 0 && !line.startsWith(FIELD_SEPARATOR))
94
+ .map((line) => line.replace(/\\/g, '/'));
95
+ commits.push({
96
+ sha: sha.trim(),
97
+ author: author.trim(),
98
+ date,
99
+ dateMs: Number.isNaN(dateMs) ? 0 : dateMs,
100
+ subject: subjectPartIsEmpty(subjectParts) ? '' : subjectParts.join(FIELD_SEPARATOR).trim(),
101
+ files,
102
+ });
103
+ }
104
+ return commits;
105
+ }
106
+ function subjectPartIsEmpty(parts) {
107
+ return parts.length === 0 || parts.join('').trim().length === 0;
108
+ }
109
+ //# sourceMappingURL=git-adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git-adapter.js","sourceRoot":"","sources":["../../../src/adapters/git/git-adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * JSON adapter — structural facts only (top-level keys, validity).
3
+ *
4
+ * Invalid JSON is a warning, never a fatal error: the scan continues and the
5
+ * remaining files are still analyzed.
6
+ */
7
+ import { type FileDescriptor, type LanguageAdapter, type ParsedFile } from '../types.ts';
8
+ export declare class JsonAdapter implements LanguageAdapter {
9
+ readonly id = "json";
10
+ readonly displayName = "JSON";
11
+ readonly languageIds: readonly string[];
12
+ /** Structural files are analyzed regardless of the `languages` setting. */
13
+ readonly alwaysEnabled = true;
14
+ handles(file: FileDescriptor): boolean;
15
+ parse(input: {
16
+ path: string;
17
+ language: string;
18
+ contents: string;
19
+ }): ParsedFile;
20
+ }
21
+ export declare function isPlainObject(value: unknown): value is Record<string, unknown>;
22
+ /** Removes a UTF-8 BOM so that JSON.parse does not fail on Windows checkouts. */
23
+ export declare function stripJsonPreamble(contents: string): string;
24
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../src/adapters/language/json/adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAoB,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAE3G,qBAAa,WAAY,YAAW,eAAe;IACjD,QAAQ,CAAC,EAAE,UAAU;IACrB,QAAQ,CAAC,WAAW,UAAU;IAC9B,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAY;IACnD,2EAA2E;IAC3E,QAAQ,CAAC,aAAa,QAAQ;IAE9B,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO;IAItC,KAAK,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,UAAU;CA4B/E;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE9E;AAED,iFAAiF;AACjF,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE1D"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * JSON adapter — structural facts only (top-level keys, validity).
3
+ *
4
+ * Invalid JSON is a warning, never a fatal error: the scan continues and the
5
+ * remaining files are still analyzed.
6
+ */
7
+ import { createParsedFile } from "../types.js";
8
+ export class JsonAdapter {
9
+ id = 'json';
10
+ displayName = 'JSON';
11
+ languageIds = ['json'];
12
+ /** Structural files are analyzed regardless of the `languages` setting. */
13
+ alwaysEnabled = true;
14
+ handles(file) {
15
+ return file.extension === '.json';
16
+ }
17
+ parse(input) {
18
+ try {
19
+ const value = JSON.parse(stripJsonPreamble(input.contents));
20
+ const keys = isPlainObject(value) ? Object.keys(value).sort() : [];
21
+ return createParsedFile(input.path, 'json', {
22
+ metadata: {
23
+ 'json.valid': true,
24
+ 'json.topLevelKeys': keys,
25
+ 'json.rootType': Array.isArray(value) ? 'array' : value === null ? 'null' : typeof value,
26
+ },
27
+ });
28
+ }
29
+ catch (error) {
30
+ const message = error instanceof Error ? error.message : String(error);
31
+ return createParsedFile(input.path, 'json', {
32
+ parseStatus: 'partial',
33
+ metadata: { 'json.valid': false },
34
+ diagnostics: [
35
+ {
36
+ code: 'WARN_JSON_INVALID',
37
+ severity: 'warning',
38
+ message: `failed to parse ${input.path}`,
39
+ source: input.path,
40
+ hint: message,
41
+ },
42
+ ],
43
+ });
44
+ }
45
+ }
46
+ }
47
+ export function isPlainObject(value) {
48
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
49
+ }
50
+ /** Removes a UTF-8 BOM so that JSON.parse does not fail on Windows checkouts. */
51
+ export function stripJsonPreamble(contents) {
52
+ return contents.charCodeAt(0) === 0xfeff ? contents.slice(1) : contents;
53
+ }
54
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../../../../src/adapters/language/json/adapter.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,gBAAgB,EAA8D,MAAM,aAAa,CAAC;AAE3G,MAAM,OAAO,WAAW;IACb,EAAE,GAAG,MAAM,CAAC;IACZ,WAAW,GAAG,MAAM,CAAC;IACrB,WAAW,GAAsB,CAAC,MAAM,CAAC,CAAC;IACnD,2EAA2E;IAClE,aAAa,GAAG,IAAI,CAAC;IAE9B,OAAO,CAAC,IAAoB;QAC1B,OAAO,IAAI,CAAC,SAAS,KAAK,OAAO,CAAC;IACpC,CAAC;IAED,KAAK,CAAC,KAA2D;QAC/D,IAAI,CAAC;YACH,MAAM,KAAK,GAAY,IAAI,CAAC,KAAK,CAAC,iBAAiB,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC;YACrE,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YACnE,OAAO,gBAAgB,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE;gBAC1C,QAAQ,EAAE;oBACR,YAAY,EAAE,IAAI;oBAClB,mBAAmB,EAAE,IAAI;oBACzB,eAAe,EAAE,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,KAAK;iBACzF;aACF,CAAC,CAAC;QACL,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YACvE,OAAO,gBAAgB,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE;gBAC1C,WAAW,EAAE,SAAS;gBACtB,QAAQ,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE;gBACjC,WAAW,EAAE;oBACX;wBACE,IAAI,EAAE,mBAAmB;wBACzB,QAAQ,EAAE,SAAS;wBACnB,OAAO,EAAE,mBAAmB,KAAK,CAAC,IAAI,EAAE;wBACxC,MAAM,EAAE,KAAK,CAAC,IAAI;wBAClB,IAAI,EAAE,OAAO;qBACd;iBACF;aACF,CAAC,CAAC;QACL,CAAC;IACH,CAAC;CACF;AAED,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,OAAO,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC;AAC1E,CAAC"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Markdown adapter.
3
+ *
4
+ * Markdown is where repositories already document their conventions, decisions
5
+ * and architecture. The adapter extracts structure (headings, links, section
6
+ * positions) so that the decision and convention detectors can attach evidence
7
+ * to real documents instead of guessing.
8
+ */
9
+ import { type FileDescriptor, type LanguageAdapter, type ParsedFile } from '../types.ts';
10
+ export interface MarkdownHeading {
11
+ level: number;
12
+ title: string;
13
+ line: number;
14
+ /** Heading text in lowercase, for cheap section matching. */
15
+ normalized: string;
16
+ }
17
+ export interface MarkdownLink {
18
+ text: string;
19
+ target: string;
20
+ line: number;
21
+ }
22
+ export declare function extractHeadings(contents: string): MarkdownHeading[];
23
+ export declare function extractMarkdownLinks(contents: string): MarkdownLink[];
24
+ /** First non-empty paragraph after the front matter, used as a short excerpt. */
25
+ export declare function firstParagraph(contents: string): string;
26
+ /** Removes a YAML front matter block, when present. */
27
+ export declare function stripFrontMatter(contents: string): string;
28
+ export declare function extractFrontMatter(contents: string): Record<string, string>;
29
+ export declare class MarkdownAdapter implements LanguageAdapter {
30
+ readonly id = "markdown";
31
+ readonly displayName = "Markdown";
32
+ readonly languageIds: readonly string[];
33
+ readonly alwaysEnabled = true;
34
+ handles(file: FileDescriptor): boolean;
35
+ parse(input: {
36
+ path: string;
37
+ language: string;
38
+ contents: string;
39
+ }): ParsedFile;
40
+ }
41
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../../../../src/adapters/language/markdown/adapter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,EAAoB,KAAK,cAAc,EAAE,KAAK,eAAe,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAE3G,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,6DAA6D;IAC7D,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,eAAe,EAAE,CAsBnE;AAED,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE,CAarE;AAED,iFAAiF;AACjF,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAiBvD;AAED,uDAAuD;AACvD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAKzD;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAY3E;AAED,qBAAa,eAAgB,YAAW,eAAe;IACrD,QAAQ,CAAC,EAAE,cAAc;IACzB,QAAQ,CAAC,WAAW,cAAc;IAClC,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAsB;IAC7D,QAAQ,CAAC,aAAa,QAAQ;IAE9B,OAAO,CAAC,IAAI,EAAE,cAAc,GAAG,OAAO;IAItC,KAAK,CAAC,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,UAAU;CAoB/E"}