docworks 0.11.0-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. package/README.md +200 -0
  2. package/dist/commands/check.d.ts +7 -0
  3. package/dist/commands/check.d.ts.map +1 -0
  4. package/dist/commands/check.js +61 -0
  5. package/dist/commands/check.js.map +1 -0
  6. package/dist/commands/init.d.ts +5 -0
  7. package/dist/commands/init.d.ts.map +1 -0
  8. package/dist/commands/init.js +165 -0
  9. package/dist/commands/init.js.map +1 -0
  10. package/dist/commands/test.d.ts +5 -0
  11. package/dist/commands/test.d.ts.map +1 -0
  12. package/dist/commands/test.js +45 -0
  13. package/dist/commands/test.js.map +1 -0
  14. package/dist/core/ai.d.ts +2 -0
  15. package/dist/core/ai.d.ts.map +1 -0
  16. package/dist/core/ai.js +29 -0
  17. package/dist/core/ai.js.map +1 -0
  18. package/dist/core/cache.d.ts +3 -0
  19. package/dist/core/cache.d.ts.map +1 -0
  20. package/dist/core/cache.js +31 -0
  21. package/dist/core/cache.js.map +1 -0
  22. package/dist/core/validator.d.ts +4 -0
  23. package/dist/core/validator.d.ts.map +1 -0
  24. package/dist/core/validator.js +47 -0
  25. package/dist/core/validator.js.map +1 -0
  26. package/dist/index.d.ts +3 -0
  27. package/dist/index.d.ts.map +1 -0
  28. package/dist/index.js +32 -0
  29. package/dist/index.js.map +1 -0
  30. package/dist/providers/anthropic.d.ts +10 -0
  31. package/dist/providers/anthropic.d.ts.map +1 -0
  32. package/dist/providers/anthropic.js +51 -0
  33. package/dist/providers/anthropic.js.map +1 -0
  34. package/dist/providers/base.d.ts +12 -0
  35. package/dist/providers/base.d.ts.map +1 -0
  36. package/dist/providers/base.js +14 -0
  37. package/dist/providers/base.js.map +1 -0
  38. package/dist/providers/openai.d.ts +10 -0
  39. package/dist/providers/openai.d.ts.map +1 -0
  40. package/dist/providers/openai.js +42 -0
  41. package/dist/providers/openai.js.map +1 -0
  42. package/dist/sources/base.d.ts +3 -0
  43. package/dist/sources/base.d.ts.map +1 -0
  44. package/dist/sources/base.js +17 -0
  45. package/dist/sources/base.js.map +1 -0
  46. package/dist/sources/llms-txt.d.ts +7 -0
  47. package/dist/sources/llms-txt.d.ts.map +1 -0
  48. package/dist/sources/llms-txt.js +43 -0
  49. package/dist/sources/llms-txt.js.map +1 -0
  50. package/dist/sources/mcp.d.ts +9 -0
  51. package/dist/sources/mcp.d.ts.map +1 -0
  52. package/dist/sources/mcp.js +33 -0
  53. package/dist/sources/mcp.js.map +1 -0
  54. package/dist/types/config.d.ts +26 -0
  55. package/dist/types/config.d.ts.map +1 -0
  56. package/dist/types/config.js +2 -0
  57. package/dist/types/config.js.map +1 -0
  58. package/dist/utils/config.d.ts +3 -0
  59. package/dist/utils/config.d.ts.map +1 -0
  60. package/dist/utils/config.js +18 -0
  61. package/dist/utils/config.js.map +1 -0
  62. package/dist/utils/reporter.d.ts +4 -0
  63. package/dist/utils/reporter.d.ts.map +1 -0
  64. package/dist/utils/reporter.js +111 -0
  65. package/dist/utils/reporter.js.map +1 -0
  66. package/package.json +84 -0
  67. package/templates/api.yml +21 -0
  68. package/templates/default.yml +19 -0
  69. package/templates/gitbook.yml +13 -0
  70. package/templates/library.yml +21 -0
  71. package/templates/mintlify.yml +18 -0
  72. package/templates/readme.yml +13 -0
package/README.md ADDED
@@ -0,0 +1,200 @@
1
+ <img width="250" height="70" alt="logo-light" src="https://github.com/user-attachments/assets/ab45ecc7-adad-42e2-84bd-a87145fbc01b" />
2
+ <br/><br/>
3
+
4
+ Ensure your docs answer critical questions. AI-powered validation that checks if developers can actually find what they need.
5
+
6
+ ## The Problem
7
+
8
+ Your docs mention "authentication" 50 times, but developers still can't figure out HOW to authenticate. Keywords exist, but answers are fragmented across pages. Support tickets spike.
9
+
10
+ ## How It Works
11
+
12
+ Define what questions your docs must answer. DocWorks uses AI to verify they remain answerable after every change.
13
+
14
+ ```yaml
15
+ # docworks.yml
16
+ questions:
17
+ critical:
18
+ - How do I authenticate?
19
+ - What are the rate limits?
20
+ - How do I handle errors?
21
+ ```
22
+
23
+ ## Install
24
+
25
+ ```bash
26
+ npm install -g docworks
27
+ ```
28
+
29
+ ## Quick Start
30
+
31
+ ```bash
32
+ # 1. Initialize with smart defaults
33
+ docworks init
34
+
35
+ # 2. Check your docs (with your OpenAI key)
36
+ OPENAI_API_KEY=sk-... docworks check
37
+ ```
38
+
39
+ Output:
40
+
41
+ ```
42
+ ✅ How do I authenticate?
43
+ ✅ What are the rate limits?
44
+ ❌ How do I handle errors?
45
+
46
+ Documentation check failed:
47
+ Critical questions cannot be answered from current docs
48
+ ```
49
+
50
+ ## CI/CD Integration
51
+
52
+ ```yaml
53
+ # .github/workflows/docs.yml
54
+ name: Documentation Check
55
+ on: [pull_request]
56
+
57
+ jobs:
58
+ check:
59
+ runs-on: ubuntu-latest
60
+ steps:
61
+ - uses: actions/checkout@v3
62
+ - run: npx docworks check
63
+ env:
64
+ OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
65
+ ```
66
+
67
+ ## Configuration
68
+
69
+ ```yaml
70
+ # docworks.yml
71
+ questions:
72
+ critical: # These block PRs if unanswerable
73
+ - How do I install this?
74
+ - How do I authenticate?
75
+
76
+ important: # These warn but don't block
77
+ - How do I debug issues?
78
+ - What are the rate limits?
79
+
80
+ nice_to_have: # Informational only
81
+ - Are there TypeScript types?
82
+
83
+ # Optional: Use your preferred AI provider
84
+ provider: openai # or anthropic, azure
85
+ model: gpt-4o-mini
86
+ ```
87
+
88
+ ## Templates
89
+
90
+ Start quickly with pre-built templates:
91
+
92
+ ```bash
93
+ # API documentation
94
+ docworks init --template api
95
+
96
+ # NPM package
97
+ docworks init --template library
98
+
99
+ # Internal platform
100
+ docworks init --template internal
101
+ ```
102
+
103
+ ## Why DocWorks?
104
+
105
+ - **Explicit control** - You define what matters, not magic patterns
106
+ - **AI-powered** - Understands context, not just keywords
107
+ - **Progressive adoption** - Start advisory, enable blocking when ready
108
+ - **Provider flexible** - OpenAI, Anthropic, Azure (BYO keys)
109
+ - **Fast** - Cached responses, parallel validation
110
+
111
+ ## Examples
112
+
113
+ ### API Documentation
114
+
115
+ ```yaml
116
+ questions:
117
+ critical:
118
+ - How do I authenticate with the API?
119
+ - What are the API endpoints?
120
+ - How do I handle errors?
121
+ ```
122
+
123
+ ### Library/Package
124
+
125
+ ```yaml
126
+ questions:
127
+ critical:
128
+ - How do I install this package?
129
+ - How do I import and use it?
130
+ - What's a basic example?
131
+ ```
132
+
133
+ ### Internal Docs
134
+
135
+ ```yaml
136
+ questions:
137
+ critical:
138
+ - How do I get access?
139
+ - Who do I contact for help?
140
+ - Where are the runbooks?
141
+ ```
142
+
143
+ ## How It Really Works
144
+
145
+ 1. **You define questions** your docs must answer
146
+ 2. **DocWorks reads** all your documentation
147
+ 3. **AI validates** each question is answerable
148
+ 4. **CI/CD enforces** on every PR
149
+
150
+ No keyword matching. No regex patterns. Just: "Can a developer find this answer?"
151
+
152
+ ## Requirements
153
+
154
+ - Node.js 16+
155
+ - OpenAI API key (or Anthropic, Azure)
156
+ - Documentation in Markdown
157
+
158
+ ## Pricing
159
+
160
+ - **DocWorks**: Free, open source, MIT licensed
161
+ - **AI costs**: ~$0.01 per check with caching (you pay provider directly)
162
+
163
+ ## Development
164
+
165
+ ```bash
166
+ # Clone and install
167
+ git clone https://github.com/caiopizzol/docworks
168
+ cd docworks
169
+ npm install
170
+
171
+ # Run locally
172
+ npm run dev
173
+
174
+ # Run tests
175
+ npm test
176
+ ```
177
+
178
+ ## FAQ
179
+
180
+ **Q: Will this block my PRs?**
181
+ A: Not by default. Starts in advisory mode. Enable blocking when ready.
182
+
183
+ **Q: What if the AI is wrong?**
184
+ A: Adjust confidence thresholds, use advisory mode, or override specific questions.
185
+
186
+ **Q: Can I use this with private docs?**
187
+ A: Yes. Runs in your CI with your API keys. Docs never leave your infrastructure.
188
+
189
+ **Q: Does it support other languages?**
190
+ A: Currently Markdown/MDX. More formats coming soon.
191
+
192
+ ## License
193
+
194
+ MIT
195
+
196
+ ## Links
197
+
198
+ - [Documentation](https://docworks.dev)
199
+ - [GitHub](https://github.com/caiopizzol/docworks)
200
+ - [NPM](https://npmjs.com/package/docworks)
@@ -0,0 +1,7 @@
1
+ export declare function check(options: {
2
+ config: string;
3
+ journey?: string;
4
+ cache?: boolean;
5
+ format?: 'terminal' | 'json' | 'github';
6
+ }): Promise<void>;
7
+ //# sourceMappingURL=check.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.d.ts","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"AAMA,wBAAsB,KAAK,CAAC,OAAO,EAAE;IACnC,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,QAAQ,CAAA;CACxC,GAAG,OAAO,CAAC,IAAI,CAAC,CA2EhB"}
@@ -0,0 +1,61 @@
1
+ import { loadConfig } from '../utils/config.js';
2
+ import { createSource } from '../sources/base.js';
3
+ import { validateJourneys, validateQuestions } from '../core/validator.js';
4
+ import { formatReport, formatJSON } from '../utils/reporter.js';
5
+ export async function check(options) {
6
+ try {
7
+ // Load config
8
+ const config = await loadConfig(options.config || 'docworks.yml');
9
+ // Validate API key
10
+ const apiKey = process.env.OPENAI_API_KEY ||
11
+ process.env.ANTHROPIC_API_KEY ||
12
+ config.api_key;
13
+ if (!apiKey) {
14
+ console.error('❌ No API key found\n');
15
+ console.error('Set one of:');
16
+ console.error(' export OPENAI_API_KEY=sk-...');
17
+ console.error(' export ANTHROPIC_API_KEY=sk-ant-...');
18
+ process.exit(1);
19
+ }
20
+ // Load documentation
21
+ console.log('📚 Loading documentation...');
22
+ const source = await createSource(config);
23
+ console.log(`Source: ${source.name}\n`);
24
+ const docs = await source.fetch();
25
+ // Validate journeys
26
+ console.log('🔍 Validating journeys...\n');
27
+ let results;
28
+ if (options.journey) {
29
+ // Validate single journey
30
+ const questions = config.journeys[options.journey];
31
+ if (!questions) {
32
+ console.error(`Journey "${options.journey}" not found`);
33
+ process.exit(1);
34
+ }
35
+ console.log(`Journey: ${options.journey}`);
36
+ console.log('─'.repeat(40));
37
+ results = {
38
+ [options.journey]: await validateQuestions(questions, docs, apiKey, options.cache !== false),
39
+ };
40
+ }
41
+ else {
42
+ // Validate all journeys
43
+ results = await validateJourneys(config.journeys, docs, apiKey, options.cache !== false);
44
+ }
45
+ // Format output
46
+ if (options.format === 'json') {
47
+ console.log(formatJSON(results, source.name));
48
+ const hasFailures = Object.values(results).some((questions) => questions.some((q) => q.answerable === 'NO'));
49
+ process.exit(hasFailures ? 1 : 0);
50
+ }
51
+ else {
52
+ const exitCode = formatReport(results, options.format === 'github');
53
+ process.exit(exitCode);
54
+ }
55
+ }
56
+ catch (error) {
57
+ console.error('❌ Error:', error.message);
58
+ process.exit(1);
59
+ }
60
+ }
61
+ //# sourceMappingURL=check.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"check.js","sourceRoot":"","sources":["../../src/commands/check.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function init(options: {
2
+ template?: string;
3
+ platform?: string;
4
+ }): Promise<void>;
5
+ //# sourceMappingURL=init.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAkHA,wBAAsB,IAAI,CAAC,OAAO,EAAE;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqChB"}
@@ -0,0 +1,165 @@
1
+ import fs from 'fs';
2
+ import { glob } from 'glob';
3
+ const TEMPLATES = {
4
+ default: `# DocWorks Configuration
5
+ source: ./llms.txt
6
+
7
+ journeys:
8
+ getting_started:
9
+ - How do I install this?
10
+ - How do I get started?
11
+ - Where are examples?
12
+
13
+ development:
14
+ - How do I run tests?
15
+ - How do I debug issues?
16
+ - Where can I get help?
17
+
18
+ provider: openai
19
+ model: gpt-4o-mini`,
20
+ api: `# DocWorks Configuration - API Documentation
21
+ source: ./llms.txt
22
+
23
+ journeys:
24
+ authentication:
25
+ - How do I authenticate?
26
+ - Where do I get API keys?
27
+ - What auth methods are supported?
28
+
29
+ integration:
30
+ - What are the endpoints?
31
+ - How do I handle errors?
32
+ - What are the rate limits?
33
+
34
+ production:
35
+ - How do I monitor usage?
36
+ - Where are status pages?
37
+ - How do I get support?
38
+
39
+ provider: openai
40
+ model: gpt-4o-mini`,
41
+ library: `# DocWorks Configuration - Library/Package
42
+ source: ./llms.txt
43
+
44
+ journeys:
45
+ setup:
46
+ - How do I install this package?
47
+ - How do I import it?
48
+ - What are the requirements?
49
+
50
+ basic_usage:
51
+ - What's a hello world example?
52
+ - What are the main functions?
53
+ - How do I configure options?
54
+
55
+ typescript:
56
+ - Does it have TypeScript support?
57
+ - Where are the type definitions?
58
+ - How do I use with TypeScript?
59
+
60
+ provider: openai
61
+ model: gpt-4o-mini`,
62
+ mintlify: `# DocWorks Configuration - Mintlify
63
+ source:
64
+ type: mcp
65
+ server: "@mintlify/mcp-server"
66
+
67
+ journeys:
68
+ api_reference:
69
+ - Where is the API reference?
70
+ - Are all endpoints documented?
71
+ - Do examples work?
72
+
73
+ getting_started:
74
+ - Is there a quickstart guide?
75
+ - How do I authenticate?
76
+ - What SDKs are available?
77
+
78
+ provider: openai
79
+ model: gpt-4o-mini`,
80
+ readme: `# DocWorks Configuration - ReadMe
81
+ source:
82
+ type: mcp
83
+ server: "@readme/mcp-server"
84
+
85
+ journeys:
86
+ developer_experience:
87
+ - Can I try the API interactively?
88
+ - Are there code examples?
89
+ - Is versioning documented?
90
+
91
+ provider: openai
92
+ model: gpt-4o-mini`,
93
+ gitbook: `# DocWorks Configuration - GitBook
94
+ source:
95
+ type: mcp
96
+ server: "@gitbook/mcp-server"
97
+
98
+ journeys:
99
+ knowledge_base:
100
+ - Is content organized logically?
101
+ - Can I search effectively?
102
+ - Are guides comprehensive?
103
+
104
+ provider: openai
105
+ model: gpt-4o-mini`,
106
+ };
107
+ export async function init(options) {
108
+ console.log('🚀 Initializing DocWorks...\n');
109
+ // Check existing config
110
+ if (fs.existsSync('docworks.yml')) {
111
+ console.log('⚠️ docworks.yml already exists');
112
+ process.exit(1);
113
+ }
114
+ // Select template
115
+ const templateName = options.platform || options.template || 'default';
116
+ const template = TEMPLATES[templateName];
117
+ if (!template) {
118
+ console.error(`Unknown template: ${templateName}`);
119
+ console.log('Available: default, api, library, mintlify, readme, gitbook');
120
+ process.exit(1);
121
+ }
122
+ // Create llms.txt if needed (not for MCP platforms)
123
+ if (!options.platform && !fs.existsSync('llms.txt')) {
124
+ await createLLMSTxt();
125
+ }
126
+ // Write config
127
+ fs.writeFileSync('docworks.yml', template);
128
+ console.log('✅ Created docworks.yml\n');
129
+ // Next steps
130
+ console.log('Next steps:');
131
+ if (!options.platform) {
132
+ console.log('1. Review llms.txt - ensure all docs are listed');
133
+ }
134
+ console.log('2. Set your API key:');
135
+ console.log(' export OPENAI_API_KEY=sk-...');
136
+ console.log('3. Run validation:');
137
+ console.log(' docworks check');
138
+ }
139
+ async function createLLMSTxt() {
140
+ console.log('📝 Creating llms.txt...');
141
+ // Find common documentation files
142
+ const patterns = ['README.md', 'readme.md', 'docs/**/*.md', '*.md'];
143
+ const files = new Set();
144
+ for (const pattern of patterns) {
145
+ const matches = await glob(pattern, {
146
+ ignore: ['node_modules/**', '.git/**', 'CHANGELOG.md'],
147
+ });
148
+ matches.forEach((file) => files.add(file));
149
+ }
150
+ const content = [
151
+ '# Documentation sources for DocWorks',
152
+ '# Add your documentation files below, one per line',
153
+ '# Lines starting with # are comments',
154
+ '',
155
+ ...Array.from(files).slice(0, 20), // Limit initial list
156
+ '',
157
+ '# Add more files as needed:',
158
+ '# docs/api/authentication.md',
159
+ '# examples/quickstart.js',
160
+ '# https://api.example.com/openapi.json',
161
+ ].join('\n');
162
+ fs.writeFileSync('llms.txt', content);
163
+ console.log(`✅ Created llms.txt with ${files.size} documentation files\n`);
164
+ }
165
+ //# sourceMappingURL=init.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function test(options: {
2
+ config: string;
3
+ ai?: string;
4
+ }): Promise<void>;
5
+ //# sourceMappingURL=test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.d.ts","sourceRoot":"","sources":["../../src/commands/test.ts"],"names":[],"mappings":"AAIA,wBAAsB,IAAI,CAAC,OAAO,EAAE;IAClC,MAAM,EAAE,MAAM,CAAA;IACd,EAAE,CAAC,EAAE,MAAM,CAAA;CACZ,GAAG,OAAO,CAAC,IAAI,CAAC,CA+ChB"}
@@ -0,0 +1,45 @@
1
+ import { loadConfig } from '../utils/config.js';
2
+ import { createSource } from '../sources/base.js';
3
+ import { createProvider } from '../providers/base.js';
4
+ export async function test(options) {
5
+ if (!options.ai) {
6
+ console.error('Specify a task: docworks test --ai "build hello world"');
7
+ process.exit(1);
8
+ }
9
+ try {
10
+ const config = await loadConfig(options.config || 'docworks.yml');
11
+ const apiKey = process.env.OPENAI_API_KEY || config.api_key;
12
+ if (!apiKey) {
13
+ console.error('❌ No API key found');
14
+ process.exit(1);
15
+ }
16
+ // Load docs
17
+ console.log('📚 Loading documentation...');
18
+ const source = await createSource(config);
19
+ const docs = await source.fetch();
20
+ // Ask AI to complete task
21
+ console.log(`\n🤖 Testing: "${options.ai}"\n`);
22
+ const provider = createProvider(config.provider || 'openai', apiKey);
23
+ const prompt = `
24
+ Using ONLY this documentation, ${options.ai}.
25
+ Provide working code.
26
+
27
+ Documentation:
28
+ ${docs.substring(0, 30000)}
29
+
30
+ Provide ONLY the code, no explanation.`;
31
+ const response = await provider.complete(prompt);
32
+ console.log('Generated code:');
33
+ console.log('─'.repeat(40));
34
+ console.log(response);
35
+ console.log('─'.repeat(40));
36
+ // Future: Actually execute and validate the code
37
+ console.log('\n✅ AI successfully generated code from documentation');
38
+ console.log('⚠️ Code execution validation coming soon');
39
+ }
40
+ catch (error) {
41
+ console.error('❌ Error:', error.message);
42
+ process.exit(1);
43
+ }
44
+ }
45
+ //# sourceMappingURL=test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test.js","sourceRoot":"","sources":["../../src/commands/test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAA;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAErD,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,OAG1B;IACC,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,CAAC,wDAAwD,CAAC,CAAA;QACvE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;IAED,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC,MAAM,IAAI,cAAc,CAAC,CAAA;QACjE,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,MAAM,CAAC,OAAO,CAAA;QAE3D,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAA;YACnC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;QACjB,CAAC;QAED,YAAY;QACZ,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAA;QAC1C,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC,MAAM,CAAC,CAAA;QACzC,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,KAAK,EAAE,CAAA;QAEjC,0BAA0B;QAC1B,OAAO,CAAC,GAAG,CAAC,kBAAkB,OAAO,CAAC,EAAE,KAAK,CAAC,CAAA;QAE9C,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,QAAQ,IAAI,QAAQ,EAAE,MAAM,CAAC,CAAA;QACpE,MAAM,MAAM,GAAG;iCACc,OAAO,CAAC,EAAE;;;;EAIzC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC;;uCAEa,CAAA;QAEnC,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;QAEhD,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;QAC9B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAA;QAC3B,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;QACrB,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAA;QAE3B,iDAAiD;QACjD,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAA;QACpE,OAAO,CAAC,GAAG,CAAC,2CAA2C,CAAC,CAAA;IAC1D,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,UAAU,EAAG,KAAe,CAAC,OAAO,CAAC,CAAA;QACnD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function checkAnswerability(question: string, docs: string, apiKey: string, provider?: string, model?: string): Promise<import("../providers/base.js").ValidationResult>;
2
+ //# sourceMappingURL=ai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../src/core/ai.ts"],"names":[],"mappings":"AAEA,wBAAsB,kBAAkB,CACtC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,QAAQ,SAAW,EACnB,KAAK,CAAC,EAAE,MAAM,4DA8Bf"}
@@ -0,0 +1,29 @@
1
+ import { createProvider } from '../providers/base.js';
2
+ export async function checkAnswerability(question, docs, apiKey, provider = 'openai', model) {
3
+ const maxRetries = 3;
4
+ let lastError = null;
5
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
6
+ try {
7
+ const aiProvider = createProvider(provider, apiKey, model);
8
+ return await aiProvider.checkAnswerability(question, docs);
9
+ }
10
+ catch (error) {
11
+ lastError = error;
12
+ // Retry on rate limits with exponential backoff
13
+ if (error.status === 429 && attempt < maxRetries) {
14
+ const delay = Math.pow(2, attempt) * 1000;
15
+ await new Promise((resolve) => setTimeout(resolve, delay));
16
+ continue;
17
+ }
18
+ // Don't retry on other errors
19
+ break;
20
+ }
21
+ }
22
+ // Return error state instead of throwing
23
+ return {
24
+ answerable: 'NO',
25
+ reason: lastError?.message || 'Unknown error',
26
+ location: 'N/A',
27
+ };
28
+ }
29
+ //# sourceMappingURL=ai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai.js","sourceRoot":"","sources":["../../src/core/ai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAErD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,QAAgB,EAChB,IAAY,EACZ,MAAc,EACd,QAAQ,GAAG,QAAQ,EACnB,KAAc;IAEd,MAAM,UAAU,GAAG,CAAC,CAAA;IACpB,IAAI,SAAS,GAAiB,IAAI,CAAA;IAElC,KAAK,IAAI,OAAO,GAAG,CAAC,EAAE,OAAO,IAAI,UAAU,EAAE,OAAO,EAAE,EAAE,CAAC;QACvD,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,CAAA;YAC1D,OAAO,MAAM,UAAU,CAAC,kBAAkB,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;QAC5D,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,SAAS,GAAG,KAAK,CAAA;YAEjB,gDAAgD;YAChD,IAAI,KAAK,CAAC,MAAM,KAAK,GAAG,IAAI,OAAO,GAAG,UAAU,EAAE,CAAC;gBACjD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,GAAG,IAAI,CAAA;gBACzC,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAA;gBAC1D,SAAQ;YACV,CAAC;YAED,8BAA8B;YAC9B,MAAK;QACP,CAAC;IACH,CAAC;IAED,yCAAyC;IACzC,OAAO;QACL,UAAU,EAAE,IAAa;QACzB,MAAM,EAAE,SAAS,EAAE,OAAO,IAAI,eAAe;QAC7C,QAAQ,EAAE,KAAK;KAChB,CAAA;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function getCached(key: string): any;
2
+ export declare function setCached(key: string, data: any): void;
3
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/core/cache.ts"],"names":[],"mappings":"AAYA,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAgB1C;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,GAAG,IAAI,CAUtD"}
@@ -0,0 +1,31 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import os from 'os';
4
+ const CACHE_DIR = path.join(os.homedir(), '.docworks', 'cache');
5
+ const CACHE_TTL = 7 * 24 * 60 * 60 * 1000; // 7 days
6
+ // Ensure cache directory exists
7
+ if (!fs.existsSync(CACHE_DIR)) {
8
+ fs.mkdirSync(CACHE_DIR, { recursive: true });
9
+ }
10
+ export function getCached(key) {
11
+ const cachePath = path.join(CACHE_DIR, `${key}.json`);
12
+ if (!fs.existsSync(cachePath)) {
13
+ return null;
14
+ }
15
+ const cached = JSON.parse(fs.readFileSync(cachePath, 'utf-8'));
16
+ // Check if expired
17
+ if (Date.now() - cached.timestamp > CACHE_TTL) {
18
+ fs.unlinkSync(cachePath);
19
+ return null;
20
+ }
21
+ return cached.data;
22
+ }
23
+ export function setCached(key, data) {
24
+ const cachePath = path.join(CACHE_DIR, `${key}.json`);
25
+ fs.writeFileSync(cachePath, JSON.stringify({
26
+ timestamp: Date.now(),
27
+ data,
28
+ }));
29
+ }
30
+ //** */
31
+ //# sourceMappingURL=cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.js","sourceRoot":"","sources":["../../src/core/cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,MAAM,IAAI,CAAA;AAEnB,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,WAAW,EAAE,OAAO,CAAC,CAAA;AAC/D,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAA,CAAC,SAAS;AAEnD,gCAAgC;AAChC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;IAC9B,EAAE,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;AAC9C,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,CAAC,CAAA;IAErD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAA;IAE9D,mBAAmB;IACnB,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,GAAG,SAAS,EAAE,CAAC;QAC9C,EAAE,CAAC,UAAU,CAAC,SAAS,CAAC,CAAA;QACxB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAA;AACpB,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,GAAW,EAAE,IAAS;IAC9C,MAAM,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,CAAC,CAAA;IAErD,EAAE,CAAC,aAAa,CACd,SAAS,EACT,IAAI,CAAC,SAAS,CAAC;QACb,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;QACrB,IAAI;KACL,CAAC,CACH,CAAA;AACH,CAAC;AACD,OAAO"}
@@ -0,0 +1,4 @@
1
+ import { ValidationResult, JourneyResults } from '../types/config.js';
2
+ export declare function validateJourneys(journeys: Record<string, string[]>, docs: string, apiKey: string, useCache?: boolean): Promise<JourneyResults>;
3
+ export declare function validateQuestions(questions: string[], docs: string, apiKey: string, useCache?: boolean): Promise<ValidationResult[]>;
4
+ //# sourceMappingURL=validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/core/validator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAIrE,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAClC,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,QAAQ,UAAO,GACd,OAAO,CAAC,cAAc,CAAC,CAazB;AAED,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EAAE,EACnB,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,MAAM,EACd,QAAQ,UAAO,GACd,OAAO,CAAC,gBAAgB,EAAE,CAAC,CA4C7B"}
@@ -0,0 +1,47 @@
1
+ import crypto from 'crypto';
2
+ import { checkAnswerability } from './ai.js';
3
+ import { getCached, setCached } from './cache.js';
4
+ export async function validateJourneys(journeys, docs, apiKey, useCache = true) {
5
+ const results = {};
6
+ for (const [journey, questions] of Object.entries(journeys)) {
7
+ results[journey] = await validateQuestions(questions, docs, apiKey, useCache);
8
+ }
9
+ return results;
10
+ }
11
+ export async function validateQuestions(questions, docs, apiKey, useCache = true) {
12
+ const results = [];
13
+ for (const question of questions) {
14
+ // Generate cache key
15
+ const cacheKey = crypto
16
+ .createHash('md5')
17
+ .update(question + docs.substring(0, 1000)) // Use first 1KB for cache key
18
+ .digest('hex');
19
+ let result = null;
20
+ // Try cache first
21
+ if (useCache) {
22
+ result = getCached(cacheKey);
23
+ }
24
+ // If not cached, check with AI
25
+ if (!result) {
26
+ const validation = await checkAnswerability(question, docs, apiKey);
27
+ result = {
28
+ question,
29
+ ...validation,
30
+ };
31
+ // Cache the result
32
+ if (useCache) {
33
+ setCached(cacheKey, result);
34
+ }
35
+ }
36
+ results.push(result);
37
+ // Show progress
38
+ const icon = result.answerable === 'YES'
39
+ ? '✅'
40
+ : result.answerable === 'PARTIAL'
41
+ ? '⚠️'
42
+ : '❌';
43
+ console.log(` ${icon} ${question}`);
44
+ }
45
+ return results;
46
+ }
47
+ //# sourceMappingURL=validator.js.map