ai-contextify 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.
- package/LICENSE +21 -0
- package/README.md +237 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +93 -0
- package/dist/cli.js.map +1 -0
- package/dist/exporters/chunks.d.ts +7 -0
- package/dist/exporters/chunks.d.ts.map +1 -0
- package/dist/exporters/chunks.js +18 -0
- package/dist/exporters/chunks.js.map +1 -0
- package/dist/exporters/markdown.d.ts +9 -0
- package/dist/exporters/markdown.d.ts.map +1 -0
- package/dist/exporters/markdown.js +62 -0
- package/dist/exporters/markdown.js.map +1 -0
- package/dist/exporters/metadata.d.ts +3 -0
- package/dist/exporters/metadata.d.ts.map +1 -0
- package/dist/exporters/metadata.js +7 -0
- package/dist/exporters/metadata.js.map +1 -0
- package/dist/exporters/xml.d.ts +12 -0
- package/dist/exporters/xml.d.ts.map +1 -0
- package/dist/exporters/xml.js +35 -0
- package/dist/exporters/xml.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +128 -0
- package/dist/index.js.map +1 -0
- package/dist/parsers/code.d.ts +2 -0
- package/dist/parsers/code.d.ts.map +1 -0
- package/dist/parsers/code.js +6 -0
- package/dist/parsers/code.js.map +1 -0
- package/dist/parsers/docx.d.ts +2 -0
- package/dist/parsers/docx.d.ts.map +1 -0
- package/dist/parsers/docx.js +16 -0
- package/dist/parsers/docx.js.map +1 -0
- package/dist/parsers/index.d.ts +8 -0
- package/dist/parsers/index.d.ts.map +1 -0
- package/dist/parsers/index.js +56 -0
- package/dist/parsers/index.js.map +1 -0
- package/dist/parsers/json.d.ts +2 -0
- package/dist/parsers/json.d.ts.map +1 -0
- package/dist/parsers/json.js +12 -0
- package/dist/parsers/json.js.map +1 -0
- package/dist/parsers/markdown.d.ts +2 -0
- package/dist/parsers/markdown.d.ts.map +1 -0
- package/dist/parsers/markdown.js +11 -0
- package/dist/parsers/markdown.js.map +1 -0
- package/dist/parsers/pdf.d.ts +2 -0
- package/dist/parsers/pdf.d.ts.map +1 -0
- package/dist/parsers/pdf.js +17 -0
- package/dist/parsers/pdf.js.map +1 -0
- package/dist/parsers/text.d.ts +2 -0
- package/dist/parsers/text.d.ts.map +1 -0
- package/dist/parsers/text.js +6 -0
- package/dist/parsers/text.js.map +1 -0
- package/dist/scanner/index.d.ts +15 -0
- package/dist/scanner/index.d.ts.map +1 -0
- package/dist/scanner/index.js +66 -0
- package/dist/scanner/index.js.map +1 -0
- package/dist/types.d.ts +50 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/chunking.d.ts +11 -0
- package/dist/utils/chunking.d.ts.map +1 -0
- package/dist/utils/chunking.js +62 -0
- package/dist/utils/chunking.js.map +1 -0
- package/dist/utils/language.d.ts +3 -0
- package/dist/utils/language.d.ts.map +1 -0
- package/dist/utils/language.js +72 -0
- package/dist/utils/language.js.map +1 -0
- package/dist/utils/logger.d.ts +9 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +10 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/tokens.d.ts +9 -0
- package/dist/utils/tokens.d.ts.map +1 -0
- package/dist/utils/tokens.js +22 -0
- package/dist/utils/tokens.js.map +1 -0
- package/package.json +62 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 ai-contextify contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# ai-contextify
|
|
2
|
+
|
|
3
|
+
> Convierte archivos y proyectos completos en contexto optimizado para LLMs como **Claude**, **ChatGPT** y **Gemini**.
|
|
4
|
+
|
|
5
|
+
`ai-contextify` es una CLI moderna de Node.js que escanea una carpeta, parsea cada archivo soportado (PDF, DOCX, Markdown, TXT, JSON, código fuente…), normaliza todo a Markdown limpio y emite un único bundle listo para pegar en cualquier prompt de modelo de lenguaje — junto con un `metadata.json` que describe cada archivo, su tamaño y una estimación de tokens.
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx ai-contextify ./docs
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
context-output/
|
|
13
|
+
├── combined.md # un gran documento markdown listo para prompts
|
|
14
|
+
└── metadata.json # tipos, tamaños, tokens estimados y errores por archivo
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Características
|
|
20
|
+
|
|
21
|
+
- **Escaneo recursivo** con exclusiones sensatas por defecto (omite `node_modules`, `dist`, `build`, `.git`, lockfiles).
|
|
22
|
+
- **Parsers multi-formato**
|
|
23
|
+
- PDF (`pdf-parse`)
|
|
24
|
+
- DOCX (`mammoth` → Markdown)
|
|
25
|
+
- Markdown / MDX (normalizado con `remark` + GFM)
|
|
26
|
+
- Texto plano, logs, RST
|
|
27
|
+
- JSON / JSONC (formateado)
|
|
28
|
+
- Código fuente en 40+ lenguajes (con fenced code blocks correctos)
|
|
29
|
+
- **Estimación de tokens** integrada — conoce el presupuesto antes de pegar.
|
|
30
|
+
- **Chunking opcional** (`--chunk 6000`) para ventanas de contexto pequeñas.
|
|
31
|
+
- **Export XML estilo Claude opcional** (`--xml`) usando tags `<documents>` / `<document_content>`.
|
|
32
|
+
- **UX bonita en terminal** con spinners de `ora` y colores de `chalk`.
|
|
33
|
+
- **TypeScript estricto**, ESM, multiplataforma (macOS, Linux, Windows), Node ≥ 18.
|
|
34
|
+
- Diseñado para ser **extensible** — agrega un parser nuevo soltando un archivo en `src/parsers/` y registrándolo en `src/parsers/index.ts`.
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## Instalación
|
|
39
|
+
|
|
40
|
+
Úsalo directamente sin instalar:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
npx ai-contextify ./docs
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
O instálalo globalmente:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
npm install -g ai-contextify
|
|
50
|
+
ai-contextify ./docs
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## Uso
|
|
56
|
+
|
|
57
|
+
```
|
|
58
|
+
ai-contextify <input> [opciones]
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
| Opción | Descripción | Por defecto |
|
|
62
|
+
| ----------------------- | ------------------------------------------------------------------------------------ | ------------------ |
|
|
63
|
+
| `-o, --output <dir>` | Directorio de salida | `context-output` |
|
|
64
|
+
| `-i, --include <globs…>`| Patrones glob a incluir | todo |
|
|
65
|
+
| `-e, --exclude <globs…>`| Patrones glob adicionales a excluir (los defaults siempre se aplican) | — |
|
|
66
|
+
| `--max-size <bytes>` | Omite archivos más grandes que esta cantidad de bytes | `10485760` (10 MB) |
|
|
67
|
+
| `--chunk <tokens>` | Emite también `chunks/chunk-N.md` de aproximadamente esta cantidad de tokens | desactivado |
|
|
68
|
+
| `--xml` | Emite también `context.xml` en el formato `<documents>` de Claude | desactivado |
|
|
69
|
+
| `--title <título>` | Título usado en `combined.md` | derivado del input |
|
|
70
|
+
| `--follow-symlinks` | Sigue enlaces simbólicos al escanear | `false` |
|
|
71
|
+
| `-V, --version` | Muestra la versión | |
|
|
72
|
+
| `-h, --help` | Muestra la ayuda | |
|
|
73
|
+
|
|
74
|
+
### Ejemplos
|
|
75
|
+
|
|
76
|
+
Empaqueta una carpeta de docs:
|
|
77
|
+
|
|
78
|
+
```bash
|
|
79
|
+
ai-contextify ./docs
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Salida personalizada, descartando tests y la carpeta de build:
|
|
83
|
+
|
|
84
|
+
```bash
|
|
85
|
+
ai-contextify ./src -o ./context -e "**/*.test.ts" "**/__snapshots__/**"
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Divide en chunks de ~6k tokens para modelos pequeños y además emite XML de Claude:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
ai-contextify ./project --chunk 6000 --xml
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Un solo archivo:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
ai-contextify ./paper.pdf
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## API programática
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
import { build } from "ai-contextify";
|
|
106
|
+
|
|
107
|
+
const summary = await build({
|
|
108
|
+
input: "./docs",
|
|
109
|
+
output: "./context-output",
|
|
110
|
+
chunkSize: 6000,
|
|
111
|
+
emitXml: true,
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
console.log(`Se escribieron ${summary.fileCount} archivos, ~${summary.totalTokens} tokens`);
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
El tipo exportado `BuildSummary` te dice qué se escribió, dónde, y cuántos tokens estás a punto de gastar.
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## Salida
|
|
122
|
+
|
|
123
|
+
### `combined.md`
|
|
124
|
+
|
|
125
|
+
Un único documento Markdown que:
|
|
126
|
+
|
|
127
|
+
1. Comienza con un encabezado (título, origen, número de archivos, tokens totales).
|
|
128
|
+
2. Lista una tabla de contenidos clickeable.
|
|
129
|
+
3. Renderiza cada archivo como su propia sección, con bloques de código usando el tag de lenguaje correcto y PDFs/DOCX renderizados como texto plano.
|
|
130
|
+
|
|
131
|
+
### `metadata.json`
|
|
132
|
+
|
|
133
|
+
```json
|
|
134
|
+
{
|
|
135
|
+
"inputDir": "/ruta/abs/a/docs",
|
|
136
|
+
"outputDir": "/ruta/abs/a/context-output",
|
|
137
|
+
"generatedAt": "2026-05-24T12:00:00.000Z",
|
|
138
|
+
"fileCount": 12,
|
|
139
|
+
"totalBytes": 84211,
|
|
140
|
+
"totalTokens": 21034,
|
|
141
|
+
"durationMs": 482,
|
|
142
|
+
"files": [
|
|
143
|
+
{ "path": "README.md", "kind": "markdown", "bytes": 4321, "tokens": 1080 }
|
|
144
|
+
],
|
|
145
|
+
"artifacts": {
|
|
146
|
+
"combined": "/ruta/abs/a/context-output/combined.md",
|
|
147
|
+
"metadata": "/ruta/abs/a/context-output/metadata.json"
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### `context.xml` (con `--xml`)
|
|
153
|
+
|
|
154
|
+
```xml
|
|
155
|
+
<documents>
|
|
156
|
+
<document index="1">
|
|
157
|
+
<source>README.md</source>
|
|
158
|
+
<kind>markdown</kind>
|
|
159
|
+
<tokens>1080</tokens>
|
|
160
|
+
<document_content>
|
|
161
|
+
…
|
|
162
|
+
</document_content>
|
|
163
|
+
</document>
|
|
164
|
+
</documents>
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### `chunks/` (con `--chunk N`)
|
|
168
|
+
|
|
169
|
+
`chunk-01.md`, `chunk-02.md`, … cada uno ≲ N tokens. Los cortes ocurren en límites de párrafo cuando es posible.
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
## Desarrollo
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
pnpm install
|
|
177
|
+
pnpm build
|
|
178
|
+
npm link
|
|
179
|
+
ai-contextify ./example
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Scripts:
|
|
183
|
+
|
|
184
|
+
| Script | Qué hace |
|
|
185
|
+
| -------------- | ----------------------------------------- |
|
|
186
|
+
| `pnpm dev` | Ejecuta la CLI desde el código con `tsx` |
|
|
187
|
+
| `pnpm build` | Compila TypeScript a `dist/` |
|
|
188
|
+
| `pnpm start` | Ejecuta la CLI compilada |
|
|
189
|
+
| `pnpm clean` | Elimina `dist/` |
|
|
190
|
+
|
|
191
|
+
Estructura del proyecto:
|
|
192
|
+
|
|
193
|
+
```
|
|
194
|
+
src/
|
|
195
|
+
├── cli.ts # Punto de entrada de Commander
|
|
196
|
+
├── index.ts # API programática build()
|
|
197
|
+
├── types.ts
|
|
198
|
+
├── scanner/ # Escaneo con fast-glob y exclusiones sensatas
|
|
199
|
+
├── parsers/
|
|
200
|
+
│ ├── pdf.ts
|
|
201
|
+
│ ├── docx.ts
|
|
202
|
+
│ ├── markdown.ts
|
|
203
|
+
│ ├── text.ts
|
|
204
|
+
│ ├── json.ts
|
|
205
|
+
│ ├── code.ts
|
|
206
|
+
│ └── index.ts # Detección de tipo + dispatch
|
|
207
|
+
├── exporters/
|
|
208
|
+
│ ├── markdown.ts # combined.md
|
|
209
|
+
│ ├── metadata.ts # metadata.json
|
|
210
|
+
│ ├── xml.ts # Formato <documents> de Claude
|
|
211
|
+
│ └── chunks.ts # chunks/chunk-N.md
|
|
212
|
+
└── utils/
|
|
213
|
+
├── logger.ts
|
|
214
|
+
├── tokens.ts # Estimador de tokens barato y sin dependencias
|
|
215
|
+
├── chunking.ts
|
|
216
|
+
└── language.ts # extensión → tag de lenguaje
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
### Agregar un parser
|
|
220
|
+
|
|
221
|
+
1. Crea `src/parsers/miformato.ts` exportando `async function parseMiformato(path: string): Promise<string>`.
|
|
222
|
+
2. Agrega un nuevo `FileKind` en `src/types.ts`.
|
|
223
|
+
3. Registra la extensión en `detectKind()` y el dispatch en `parseFile()` dentro de `src/parsers/index.ts`.
|
|
224
|
+
|
|
225
|
+
Eso es todo — el scanner, los exporters y el pipeline de metadata lo recogen automáticamente.
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## Contribuir
|
|
230
|
+
|
|
231
|
+
¡Los PRs son bienvenidos! Si quieres agregar un parser nuevo, soportar otro formato de export, o mejorar el estimador de tokens, abre un issue para discutirlo primero.
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
235
|
+
## Licencia
|
|
236
|
+
|
|
237
|
+
[MIT](./LICENSE)
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import process from "node:process";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
import { build } from "./index.js";
|
|
7
|
+
import { logger } from "./utils/logger.js";
|
|
8
|
+
import { formatTokenCount } from "./utils/tokens.js";
|
|
9
|
+
const program = new Command();
|
|
10
|
+
program
|
|
11
|
+
.name("ai-contextify")
|
|
12
|
+
.description("Convert files and entire projects into optimized context for LLMs (Claude, ChatGPT, Gemini).")
|
|
13
|
+
.version("0.1.0")
|
|
14
|
+
.argument("<input>", "File or directory to convert into LLM context")
|
|
15
|
+
.option("-o, --output <dir>", "Output directory", "context-output")
|
|
16
|
+
.option("-i, --include <patterns...>", "Glob patterns to include (default: everything)")
|
|
17
|
+
.option("-e, --exclude <patterns...>", "Extra glob patterns to exclude (node_modules/dist/build/.git are always excluded)")
|
|
18
|
+
.option("--max-size <bytes>", "Skip files larger than this many bytes", String(10 * 1024 * 1024))
|
|
19
|
+
.option("--chunk <tokens>", "Also emit chunk-*.md files of approximately this many tokens")
|
|
20
|
+
.option("--xml", "Also emit context.xml in Claude's <documents> format")
|
|
21
|
+
.option("--title <title>", "Title for the combined.md document")
|
|
22
|
+
.option("--follow-symlinks", "Follow symbolic links while scanning", false)
|
|
23
|
+
.action(async (input, opts) => {
|
|
24
|
+
const absoluteInput = path.resolve(input);
|
|
25
|
+
const absoluteOutput = path.resolve(opts.output);
|
|
26
|
+
logger.step(`Input: ${chalk.bold(absoluteInput)}`);
|
|
27
|
+
logger.step(`Output: ${chalk.bold(absoluteOutput)}`);
|
|
28
|
+
const maxSizeBytes = Number.parseInt(opts.maxSize, 10);
|
|
29
|
+
if (!Number.isFinite(maxSizeBytes) || maxSizeBytes <= 0) {
|
|
30
|
+
logger.error(`Invalid --max-size: ${opts.maxSize}`);
|
|
31
|
+
process.exit(1);
|
|
32
|
+
}
|
|
33
|
+
const chunkSize = opts.chunk ? Number.parseInt(opts.chunk, 10) : undefined;
|
|
34
|
+
if (opts.chunk && (!Number.isFinite(chunkSize) || (chunkSize ?? 0) <= 0)) {
|
|
35
|
+
logger.error(`Invalid --chunk: ${opts.chunk}`);
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const summary = await build({
|
|
40
|
+
input: absoluteInput,
|
|
41
|
+
output: absoluteOutput,
|
|
42
|
+
include: opts.include,
|
|
43
|
+
exclude: opts.exclude,
|
|
44
|
+
maxFileSizeBytes: maxSizeBytes,
|
|
45
|
+
followSymlinks: opts.followSymlinks,
|
|
46
|
+
chunkSize,
|
|
47
|
+
emitXml: opts.xml === true,
|
|
48
|
+
title: opts.title,
|
|
49
|
+
});
|
|
50
|
+
console.log("");
|
|
51
|
+
logger.success(chalk.bold("Done!"));
|
|
52
|
+
logger.dim(` Files: ${summary.fileCount}`);
|
|
53
|
+
logger.dim(` Bytes: ${summary.totalBytes.toLocaleString()}`);
|
|
54
|
+
logger.dim(` Tokens: ~${formatTokenCount(summary.totalTokens)}`);
|
|
55
|
+
logger.dim(` Duration: ${(summary.durationMs / 1000).toFixed(2)}s`);
|
|
56
|
+
if (summary.artifacts.combined) {
|
|
57
|
+
logger.dim(` ${chalk.cyan("combined.md")} → ${summary.artifacts.combined}`);
|
|
58
|
+
}
|
|
59
|
+
if (summary.artifacts.metadata) {
|
|
60
|
+
logger.dim(` ${chalk.cyan("metadata.json")} → ${summary.artifacts.metadata}`);
|
|
61
|
+
}
|
|
62
|
+
if (summary.artifacts.xml) {
|
|
63
|
+
logger.dim(` ${chalk.cyan("context.xml")} → ${summary.artifacts.xml}`);
|
|
64
|
+
}
|
|
65
|
+
if (summary.artifacts.chunks?.length) {
|
|
66
|
+
logger.dim(` ${chalk.cyan("chunks/")} → ${summary.artifacts.chunks.length} files`);
|
|
67
|
+
}
|
|
68
|
+
const errored = summary.files.filter((f) => f.parseError);
|
|
69
|
+
if (errored.length > 0) {
|
|
70
|
+
console.log("");
|
|
71
|
+
logger.warn(`${errored.length} file(s) failed to parse:`);
|
|
72
|
+
for (const f of errored.slice(0, 10)) {
|
|
73
|
+
logger.dim(` - ${f.path}: ${f.parseError}`);
|
|
74
|
+
}
|
|
75
|
+
if (errored.length > 10) {
|
|
76
|
+
logger.dim(` …and ${errored.length - 10} more (see metadata.json)`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
82
|
+
logger.error(message);
|
|
83
|
+
if (process.env.DEBUG)
|
|
84
|
+
console.error(err);
|
|
85
|
+
process.exit(1);
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
program.parseAsync(process.argv).catch((err) => {
|
|
89
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
90
|
+
logger.error(message);
|
|
91
|
+
process.exit(1);
|
|
92
|
+
});
|
|
93
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/cli.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAarD,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,eAAe,CAAC;KACrB,WAAW,CACV,8FAA8F,CAC/F;KACA,OAAO,CAAC,OAAO,CAAC;KAChB,QAAQ,CAAC,SAAS,EAAE,+CAA+C,CAAC;KACpE,MAAM,CAAC,oBAAoB,EAAE,kBAAkB,EAAE,gBAAgB,CAAC;KAClE,MAAM,CACL,6BAA6B,EAC7B,gDAAgD,CACjD;KACA,MAAM,CACL,6BAA6B,EAC7B,mFAAmF,CACpF;KACA,MAAM,CACL,oBAAoB,EACpB,wCAAwC,EACxC,MAAM,CAAC,EAAE,GAAG,IAAI,GAAG,IAAI,CAAC,CACzB;KACA,MAAM,CACL,kBAAkB,EAClB,8DAA8D,CAC/D;KACA,MAAM,CAAC,OAAO,EAAE,sDAAsD,CAAC;KACvE,MAAM,CAAC,iBAAiB,EAAE,oCAAoC,CAAC;KAC/D,MAAM,CAAC,mBAAmB,EAAE,sCAAsC,EAAE,KAAK,CAAC;KAC1E,MAAM,CAAC,KAAK,EAAE,KAAa,EAAE,IAAgB,EAAE,EAAE;IAChD,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1C,MAAM,cAAc,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAEjD,MAAM,CAAC,IAAI,CAAC,WAAW,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,CAAC,CAAC;IACpD,MAAM,CAAC,IAAI,CAAC,WAAW,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC;IAErD,MAAM,YAAY,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACvD,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,IAAI,YAAY,IAAI,CAAC,EAAE,CAAC;QACxD,MAAM,CAAC,KAAK,CAAC,uBAAuB,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QACpD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;IAC3E,IAAI,IAAI,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QACzE,MAAM,CAAC,KAAK,CAAC,oBAAoB,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;QAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,KAAK,CAAC;YAC1B,KAAK,EAAE,aAAa;YACpB,MAAM,EAAE,cAAc;YACtB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,gBAAgB,EAAE,YAAY;YAC9B,cAAc,EAAE,IAAI,CAAC,cAAc;YACnC,SAAS;YACT,OAAO,EAAE,IAAI,CAAC,GAAG,KAAK,IAAI;YAC1B,KAAK,EAAE,IAAI,CAAC,KAAK;SAClB,CAAC,CAAC;QAEH,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QACpC,MAAM,CAAC,GAAG,CAAC,gBAAgB,OAAO,CAAC,SAAS,EAAE,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,CAAC,gBAAgB,OAAO,CAAC,UAAU,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC;QAClE,MAAM,CAAC,GAAG,CAAC,iBAAiB,gBAAgB,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;QACrE,MAAM,CAAC,GAAG,CAAC,gBAAgB,CAAC,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACtE,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;YAC/B,MAAM,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,OAAO,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;QAChF,CAAC;QACD,IAAI,OAAO,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC;YAC/B,MAAM,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,MAAM,OAAO,CAAC,SAAS,CAAC,QAAQ,EAAE,CAAC,CAAC;QACjF,CAAC;QACD,IAAI,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC;YAC1B,MAAM,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,OAAO,OAAO,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,CAAC;QAC3E,CAAC;QACD,IAAI,OAAO,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC;YACrC,MAAM,CAAC,GAAG,CACR,KAAK,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,YAAY,OAAO,CAAC,SAAS,CAAC,MAAM,CAAC,MAAM,QAAQ,CAC9E,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;QAC1D,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAChB,MAAM,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,2BAA2B,CAAC,CAAC;YAC1D,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;gBACrC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC;YAC/C,CAAC;YACD,IAAI,OAAO,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;gBACxB,MAAM,CAAC,GAAG,CAAC,UAAU,OAAO,CAAC,MAAM,GAAG,EAAE,2BAA2B,CAAC,CAAC;YACvE,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACtB,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK;YAAE,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC1C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,UAAU,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;IACtD,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACjE,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IACtB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunks.d.ts","sourceRoot":"","sources":["../../src/exporters/chunks.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,kBAAkB;IACjC,SAAS,EAAE,MAAM,CAAC;IAClB,gBAAgB,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,YAAY,CAChC,OAAO,EAAE,kBAAkB,GAC1B,OAAO,CAAC,MAAM,EAAE,CAAC,CAgBnB"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
import { chunkText } from "../utils/chunking.js";
|
|
4
|
+
export async function exportChunks(options) {
|
|
5
|
+
const chunks = chunkText(options.combinedMarkdown, options.chunkTokens);
|
|
6
|
+
await fs.ensureDir(options.outputDir);
|
|
7
|
+
const written = [];
|
|
8
|
+
const pad = String(chunks.length).length;
|
|
9
|
+
for (const chunk of chunks) {
|
|
10
|
+
const filename = `chunk-${String(chunk.index + 1).padStart(pad, "0")}.md`;
|
|
11
|
+
const fullPath = path.join(options.outputDir, filename);
|
|
12
|
+
const header = `<!-- chunk ${chunk.index + 1}/${chunks.length} · ~${chunk.tokens} tokens -->\n\n`;
|
|
13
|
+
await fs.writeFile(fullPath, header + chunk.content + "\n", "utf8");
|
|
14
|
+
written.push(fullPath);
|
|
15
|
+
}
|
|
16
|
+
return written;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=chunks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chunks.js","sourceRoot":"","sources":["../../src/exporters/chunks.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAQjD,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAA2B;IAE3B,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,gBAAgB,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;IACxE,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAEtC,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC;IAEzC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,SAAS,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,KAAK,CAAC;QAC1E,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QACxD,MAAM,MAAM,GAAG,cAAc,KAAK,CAAC,KAAK,GAAG,CAAC,IAAI,MAAM,CAAC,MAAM,OAAO,KAAK,CAAC,MAAM,iBAAiB,CAAC;QAClG,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,KAAK,CAAC,OAAO,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;QACpE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IACzB,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { ParsedFile } from "../types.js";
|
|
2
|
+
export interface MarkdownExportOptions {
|
|
3
|
+
outputPath: string;
|
|
4
|
+
title: string;
|
|
5
|
+
inputDir: string;
|
|
6
|
+
generatedAt: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function exportCombinedMarkdown(files: ParsedFile[], options: MarkdownExportOptions): Promise<void>;
|
|
9
|
+
//# sourceMappingURL=markdown.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.d.ts","sourceRoot":"","sources":["../../src/exporters/markdown.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAI9C,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,wBAAsB,sBAAsB,CAC1C,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,IAAI,CAAC,CA8Cf"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
import { detectLanguage } from "../utils/language.js";
|
|
4
|
+
import { formatTokenCount } from "../utils/tokens.js";
|
|
5
|
+
export async function exportCombinedMarkdown(files, options) {
|
|
6
|
+
const lines = [];
|
|
7
|
+
lines.push(`# ${options.title}`);
|
|
8
|
+
lines.push("");
|
|
9
|
+
lines.push(`> Generated by **ai-contextify** on ${options.generatedAt}.`, `> Source: \`${options.inputDir}\``, `> Files: ${files.length} · Total tokens (est.): ${formatTokenCount(files.reduce((acc, f) => acc + f.estimatedTokens, 0))}`);
|
|
10
|
+
lines.push("");
|
|
11
|
+
lines.push("## Table of contents");
|
|
12
|
+
lines.push("");
|
|
13
|
+
for (const file of files) {
|
|
14
|
+
const anchor = anchorFor(file.relativePath);
|
|
15
|
+
lines.push(`- [\`${file.relativePath}\`](#${anchor}) — ${file.kind} · ${formatTokenCount(file.estimatedTokens)} tok`);
|
|
16
|
+
}
|
|
17
|
+
lines.push("");
|
|
18
|
+
lines.push("---");
|
|
19
|
+
lines.push("");
|
|
20
|
+
for (const file of files) {
|
|
21
|
+
lines.push(`## \`${file.relativePath}\``);
|
|
22
|
+
lines.push("");
|
|
23
|
+
lines.push(`- **Kind:** ${file.kind}`, `- **Size:** ${file.bytes} bytes`, `- **Estimated tokens:** ${file.estimatedTokens}`);
|
|
24
|
+
if (file.parseError) {
|
|
25
|
+
lines.push(`- **Parse error:** ${file.parseError}`);
|
|
26
|
+
}
|
|
27
|
+
lines.push("");
|
|
28
|
+
lines.push(renderBody(file));
|
|
29
|
+
lines.push("");
|
|
30
|
+
lines.push("---");
|
|
31
|
+
lines.push("");
|
|
32
|
+
}
|
|
33
|
+
await fs.ensureDir(path.dirname(options.outputPath));
|
|
34
|
+
await fs.writeFile(options.outputPath, lines.join("\n"), "utf8");
|
|
35
|
+
}
|
|
36
|
+
function renderBody(file) {
|
|
37
|
+
if (!file.content.trim())
|
|
38
|
+
return "_(empty)_";
|
|
39
|
+
if (file.kind === "markdown")
|
|
40
|
+
return file.content.trim();
|
|
41
|
+
if (file.kind === "code" || file.kind === "json") {
|
|
42
|
+
const lang = file.language ?? detectLanguage(file.extension, file.relativePath);
|
|
43
|
+
return wrapFence(file.content, lang);
|
|
44
|
+
}
|
|
45
|
+
// pdf / docx / text / unknown → render as plain text block.
|
|
46
|
+
return file.content.trim();
|
|
47
|
+
}
|
|
48
|
+
function wrapFence(content, language) {
|
|
49
|
+
// Pick a fence longer than any run of backticks in the content.
|
|
50
|
+
const longestBacktickRun = (content.match(/`+/g) ?? [])
|
|
51
|
+
.reduce((max, run) => Math.max(max, run.length), 0);
|
|
52
|
+
const fenceLength = Math.max(3, longestBacktickRun + 1);
|
|
53
|
+
const fence = "`".repeat(fenceLength);
|
|
54
|
+
return `${fence}${language}\n${content.replace(/\s+$/, "")}\n${fence}`;
|
|
55
|
+
}
|
|
56
|
+
function anchorFor(relPath) {
|
|
57
|
+
return relPath
|
|
58
|
+
.toLowerCase()
|
|
59
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
60
|
+
.replace(/(^-|-$)/g, "");
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=markdown.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown.js","sourceRoot":"","sources":["../../src/exporters/markdown.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.d.ts","sourceRoot":"","sources":["../../src/exporters/metadata.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAEhD,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,YAAY,GACpB,OAAO,CAAC,IAAI,CAAC,CAOf"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
export async function exportMetadata(outputPath, summary) {
|
|
4
|
+
await fs.ensureDir(path.dirname(outputPath));
|
|
5
|
+
await fs.writeFile(outputPath, `${JSON.stringify(summary, null, 2)}\n`, "utf8");
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=metadata.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metadata.js","sourceRoot":"","sources":["../../src/exporters/metadata.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,UAAU,CAAC;AAG1B,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,UAAkB,EAClB,OAAqB;IAErB,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IAC7C,MAAM,EAAE,CAAC,SAAS,CAChB,UAAU,EACV,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EACvC,MAAM,CACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { ParsedFile } from "../types.js";
|
|
2
|
+
export interface XmlExportOptions {
|
|
3
|
+
outputPath: string;
|
|
4
|
+
inputDir: string;
|
|
5
|
+
generatedAt: string;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Emit a Claude-style `<documents>` XML bundle. This format is the one
|
|
9
|
+
* Anthropic recommends for stuffing multiple documents into a single prompt.
|
|
10
|
+
*/
|
|
11
|
+
export declare function exportClaudeXml(files: ParsedFile[], options: XmlExportOptions): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=xml.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xml.d.ts","sourceRoot":"","sources":["../../src/exporters/xml.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE9C,MAAM,WAAW,gBAAgB;IAC/B,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,UAAU,EAAE,EACnB,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,IAAI,CAAC,CAqBf"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import fs from "fs-extra";
|
|
3
|
+
/**
|
|
4
|
+
* Emit a Claude-style `<documents>` XML bundle. This format is the one
|
|
5
|
+
* Anthropic recommends for stuffing multiple documents into a single prompt.
|
|
6
|
+
*/
|
|
7
|
+
export async function exportClaudeXml(files, options) {
|
|
8
|
+
const lines = [];
|
|
9
|
+
lines.push(`<!-- ai-contextify · ${options.generatedAt} -->`);
|
|
10
|
+
lines.push(`<!-- source: ${escapeAttr(options.inputDir)} -->`);
|
|
11
|
+
lines.push("<documents>");
|
|
12
|
+
files.forEach((file, index) => {
|
|
13
|
+
lines.push(` <document index="${index + 1}">`);
|
|
14
|
+
lines.push(` <source>${escapeText(file.relativePath)}</source>`);
|
|
15
|
+
lines.push(` <kind>${file.kind}</kind>`);
|
|
16
|
+
lines.push(` <tokens>${file.estimatedTokens}</tokens>`);
|
|
17
|
+
lines.push(" <document_content>");
|
|
18
|
+
lines.push(escapeText(file.content));
|
|
19
|
+
lines.push(" </document_content>");
|
|
20
|
+
lines.push(" </document>");
|
|
21
|
+
});
|
|
22
|
+
lines.push("</documents>");
|
|
23
|
+
await fs.ensureDir(path.dirname(options.outputPath));
|
|
24
|
+
await fs.writeFile(options.outputPath, `${lines.join("\n")}\n`, "utf8");
|
|
25
|
+
}
|
|
26
|
+
function escapeText(value) {
|
|
27
|
+
return value
|
|
28
|
+
.replace(/&/g, "&")
|
|
29
|
+
.replace(/</g, "<")
|
|
30
|
+
.replace(/>/g, ">");
|
|
31
|
+
}
|
|
32
|
+
function escapeAttr(value) {
|
|
33
|
+
return escapeText(value).replace(/"/g, """);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=xml.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"xml.js","sourceRoot":"","sources":["../../src/exporters/xml.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,UAAU,CAAC;AAS1B;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAmB,EACnB,OAAyB;IAEzB,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,wBAAwB,OAAO,CAAC,WAAW,MAAM,CAAC,CAAC;IAC9D,KAAK,CAAC,IAAI,CAAC,gBAAgB,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/D,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;IAE1B,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC5B,KAAK,CAAC,IAAI,CAAC,sBAAsB,KAAK,GAAG,CAAC,IAAI,CAAC,CAAC;QAChD,KAAK,CAAC,IAAI,CAAC,eAAe,UAAU,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,CAAC;QACpE,KAAK,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,IAAI,SAAS,CAAC,CAAC;QAC5C,KAAK,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,eAAe,WAAW,CAAC,CAAC;QAC3D,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC;QACrC,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,CAAC;QACtC,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC;IAE3B,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC;IACrD,MAAM,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC1E,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,KAAK;SACT,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC;SACrB,OAAO,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AAC3B,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,UAAU,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;AACnD,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,YAAY,EAAc,MAAM,YAAY,CAAC;AAWzE,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAkIxE;AAED,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC"}
|