@monoes/monograph 1.2.2 → 1.2.4
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/dist/src/claude-cli.d.ts +3 -0
- package/dist/src/claude-cli.d.ts.map +1 -0
- package/dist/src/claude-cli.js +61 -0
- package/dist/src/claude-cli.js.map +1 -0
- package/dist/src/mcp-tools/wiki-build.d.ts.map +1 -1
- package/dist/src/mcp-tools/wiki-build.js +0 -4
- package/dist/src/mcp-tools/wiki-build.js.map +1 -1
- package/dist/src/pipeline/phases/llm-extract.d.ts.map +1 -1
- package/dist/src/pipeline/phases/llm-extract.js +10 -22
- package/dist/src/pipeline/phases/llm-extract.js.map +1 -1
- package/dist/src/wiki/providers.js +5 -25
- package/dist/src/wiki/providers.js.map +1 -1
- package/dist/src/wiki/wiki-generator.d.ts.map +1 -1
- package/dist/src/wiki/wiki-generator.js +4 -12
- package/dist/src/wiki/wiki-generator.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/claude-cli.ts +59 -0
- package/src/mcp-tools/wiki-build.ts +0 -5
- package/src/pipeline/phases/llm-extract.ts +10 -21
- package/src/wiki/providers.ts +6 -32
- package/src/wiki/wiki-generator.ts +4 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@monoes/monograph",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Native TypeScript code intelligence engine for monomind",
|
|
6
6
|
"main": "dist/src/index.js",
|
|
@@ -57,4 +57,4 @@
|
|
|
57
57
|
"typescript": "^5.3.0",
|
|
58
58
|
"vitest": "^4.1.4"
|
|
59
59
|
}
|
|
60
|
-
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thin wrapper around `claude --print` for LLM calls inside monograph.
|
|
3
|
+
* Reuses Claude Code's existing auth — no ANTHROPIC_API_KEY needed.
|
|
4
|
+
*/
|
|
5
|
+
import { spawn, execSync } from 'child_process';
|
|
6
|
+
|
|
7
|
+
const DEFAULT_TIMEOUT_MS = 60_000;
|
|
8
|
+
let _available: boolean | null = null;
|
|
9
|
+
|
|
10
|
+
export function isClaudeCliAvailable(): boolean {
|
|
11
|
+
if (_available !== null) return _available;
|
|
12
|
+
try {
|
|
13
|
+
execSync('claude --version', { encoding: 'utf-8', stdio: 'pipe', timeout: 5000, windowsHide: true });
|
|
14
|
+
_available = true;
|
|
15
|
+
} catch {
|
|
16
|
+
_available = false;
|
|
17
|
+
}
|
|
18
|
+
return _available;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function claudeCliCall(prompt: string, timeoutMs = DEFAULT_TIMEOUT_MS): Promise<string> {
|
|
22
|
+
return new Promise((resolve, reject) => {
|
|
23
|
+
const child = spawn(
|
|
24
|
+
'claude',
|
|
25
|
+
['--print', '--model', 'haiku', '--strict-mcp-config', '--no-session-persistence', '--', prompt],
|
|
26
|
+
{ stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true },
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
let stdout = '';
|
|
30
|
+
let stderr = '';
|
|
31
|
+
let settled = false;
|
|
32
|
+
|
|
33
|
+
const timer = setTimeout(() => {
|
|
34
|
+
if (settled) return;
|
|
35
|
+
settled = true;
|
|
36
|
+
try { child.kill('SIGTERM'); } catch { /* ignore */ }
|
|
37
|
+
setTimeout(() => { try { child.kill('SIGKILL'); } catch { /* ignore */ } }, 3000);
|
|
38
|
+
reject(new Error(`claude --print timed out after ${timeoutMs}ms`));
|
|
39
|
+
}, timeoutMs);
|
|
40
|
+
|
|
41
|
+
child.stdout.on('data', (d: Buffer) => { stdout += d.toString(); });
|
|
42
|
+
child.stderr.on('data', (d: Buffer) => { stderr += d.toString(); });
|
|
43
|
+
|
|
44
|
+
child.on('close', (code) => {
|
|
45
|
+
if (settled) return;
|
|
46
|
+
settled = true;
|
|
47
|
+
clearTimeout(timer);
|
|
48
|
+
if (code === 0) resolve(stdout.trim());
|
|
49
|
+
else reject(new Error(stderr.trim() || `claude exited with code ${code}`));
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
child.on('error', (err) => {
|
|
53
|
+
if (settled) return;
|
|
54
|
+
settled = true;
|
|
55
|
+
clearTimeout(timer);
|
|
56
|
+
reject(err);
|
|
57
|
+
});
|
|
58
|
+
});
|
|
59
|
+
}
|
|
@@ -25,11 +25,6 @@ export async function runWikiBuildTool(
|
|
|
25
25
|
db: MonographDb,
|
|
26
26
|
input: WikiBuildToolInput,
|
|
27
27
|
): Promise<WikiBuildToolResult> {
|
|
28
|
-
const apiKey = process.env['ANTHROPIC_API_KEY'];
|
|
29
|
-
if (!apiKey && !input.llmClient) {
|
|
30
|
-
return { error: 'ANTHROPIC_API_KEY not set' };
|
|
31
|
-
}
|
|
32
|
-
|
|
33
28
|
const opts: GenerateAllWikiPagesOptions = {
|
|
34
29
|
force: input.force ?? false,
|
|
35
30
|
model: input.model,
|
|
@@ -37,25 +37,11 @@ interface Triple {
|
|
|
37
37
|
edge: string;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
async function callClaude(content: string
|
|
40
|
+
async function callClaude(content: string): Promise<Triple[] | null> {
|
|
41
41
|
try {
|
|
42
|
-
const
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
'x-api-key': apiKey,
|
|
46
|
-
'anthropic-version': '2023-06-01',
|
|
47
|
-
'content-type': 'application/json',
|
|
48
|
-
},
|
|
49
|
-
body: JSON.stringify({
|
|
50
|
-
model: 'claude-haiku-4-5-20251001',
|
|
51
|
-
max_tokens: 512,
|
|
52
|
-
system: SYSTEM_PROMPT,
|
|
53
|
-
messages: [{ role: 'user', content: content.slice(0, 1500) }],
|
|
54
|
-
}),
|
|
55
|
-
});
|
|
56
|
-
if (!res.ok) return null;
|
|
57
|
-
const data = await res.json() as { content: Array<{ text: string }> };
|
|
58
|
-
const text = data.content[0]?.text ?? '[]';
|
|
42
|
+
const { claudeCliCall } = await import('../../claude-cli.js');
|
|
43
|
+
const prompt = `${SYSTEM_PROMPT}\n\n${content.slice(0, 1500)}`;
|
|
44
|
+
const text = await claudeCliCall(prompt, 30_000);
|
|
59
45
|
const parsed = JSON.parse(text.match(/\[[\s\S]*\]/)?.[0] ?? '[]');
|
|
60
46
|
return Array.isArray(parsed) ? parsed as Triple[] : null;
|
|
61
47
|
} catch {
|
|
@@ -68,10 +54,14 @@ export const llmExtractPhase: PipelinePhase<LlmExtractOutput> = {
|
|
|
68
54
|
deps: ['docs-parse', 'pdf-parse'],
|
|
69
55
|
|
|
70
56
|
async execute(ctx: PipelineContext) {
|
|
71
|
-
const apiKey = process.env.ANTHROPIC_API_KEY;
|
|
72
57
|
const maxSections = ctx.options.llmMaxSections;
|
|
73
58
|
|
|
74
|
-
if (
|
|
59
|
+
if (maxSections <= 0 || ctx.options.codeOnly) {
|
|
60
|
+
return { triplesExtracted: 0, sectionsProcessed: 0 };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const { isClaudeCliAvailable } = await import('../../claude-cli.js');
|
|
64
|
+
if (!isClaudeCliAvailable()) {
|
|
75
65
|
return { triplesExtracted: 0, sectionsProcessed: 0 };
|
|
76
66
|
}
|
|
77
67
|
|
|
@@ -107,7 +97,6 @@ export const llmExtractPhase: PipelinePhase<LlmExtractOutput> = {
|
|
|
107
97
|
|
|
108
98
|
const triples = await callClaude(
|
|
109
99
|
`Section: "${section.name}"\n\n${content}`,
|
|
110
|
-
apiKey,
|
|
111
100
|
);
|
|
112
101
|
if (!triples || triples.length === 0) continue;
|
|
113
102
|
|
package/src/wiki/providers.ts
CHANGED
|
@@ -49,39 +49,13 @@ export async function callLLM(prompt: string, config: LLMConfig): Promise<LLMRes
|
|
|
49
49
|
|
|
50
50
|
async function callAnthropic(
|
|
51
51
|
prompt: string,
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
_config: LLMConfig,
|
|
53
|
+
_signal: AbortSignal,
|
|
54
54
|
): Promise<LLMResponse> {
|
|
55
|
-
|
|
56
|
-
const
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
headers: {
|
|
60
|
-
'x-api-key': apiKey ?? '',
|
|
61
|
-
'anthropic-version': '2023-06-01',
|
|
62
|
-
'content-type': 'application/json',
|
|
63
|
-
},
|
|
64
|
-
body: JSON.stringify({
|
|
65
|
-
model: config.model ?? 'claude-3-haiku-20240307',
|
|
66
|
-
max_tokens: config.maxTokens ?? 2048,
|
|
67
|
-
messages: [{ role: 'user', content: prompt }],
|
|
68
|
-
}),
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
if (!response.ok) {
|
|
72
|
-
throw new Error(`LLM provider anthropic error: ${response.status} ${response.statusText}`);
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const data = await response.json() as {
|
|
76
|
-
content: Array<{ text: string }>;
|
|
77
|
-
usage: { input_tokens: number; output_tokens: number };
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
return {
|
|
81
|
-
text: data.content[0].text,
|
|
82
|
-
inputTokens: data.usage.input_tokens,
|
|
83
|
-
outputTokens: data.usage.output_tokens,
|
|
84
|
-
};
|
|
55
|
+
// Route through Claude Code CLI — reuses host auth, no API key needed.
|
|
56
|
+
const { claudeCliCall } = await import('../claude-cli.js');
|
|
57
|
+
const text = await claudeCliCall(prompt);
|
|
58
|
+
return { text };
|
|
85
59
|
}
|
|
86
60
|
|
|
87
61
|
async function callOpenAI(
|
|
@@ -145,19 +145,11 @@ export async function generateWikiPage(
|
|
|
145
145
|
const result = await callLLM(prompt, options.llmConfig);
|
|
146
146
|
content = result.text;
|
|
147
147
|
} else {
|
|
148
|
-
const
|
|
149
|
-
if (!
|
|
150
|
-
throw new Error('
|
|
148
|
+
const { claudeCliCall, isClaudeCliAvailable } = await import('../claude-cli.js');
|
|
149
|
+
if (!isClaudeCliAvailable()) {
|
|
150
|
+
throw new Error('Claude Code CLI not found. Install with: npm install -g @anthropic-ai/claude-code');
|
|
151
151
|
}
|
|
152
|
-
|
|
153
|
-
const client = new Anthropic({ apiKey });
|
|
154
|
-
const msg = await client.messages.create({
|
|
155
|
-
model: options?.model ?? 'claude-haiku-4-5-20251001',
|
|
156
|
-
max_tokens: 1024,
|
|
157
|
-
messages: [{ role: 'user', content: prompt }],
|
|
158
|
-
});
|
|
159
|
-
const block = msg.content[0];
|
|
160
|
-
content = (block?.type === 'text') ? block.text : '';
|
|
152
|
+
content = await claudeCliCall(prompt);
|
|
161
153
|
}
|
|
162
154
|
|
|
163
155
|
// 7. Persist to DB — prepend OKF frontmatter if not already present
|