@monoes/monomindcli 1.10.19 → 1.10.21

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@monoes/monomindcli",
3
- "version": "1.10.19",
3
+ "version": "1.10.21",
4
4
  "type": "module",
5
5
  "description": "Monomind CLI - Enterprise AI agent orchestration with 60+ specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
6
6
  "main": "dist/src/index.js",
@@ -30,7 +30,7 @@ import { readFileSync, writeFileSync, existsSync, mkdirSync } from 'node:fs';
30
30
  import { resolve, join, dirname, basename, relative } from 'node:path';
31
31
  import { createRequire } from 'node:module';
32
32
  import { fileURLToPath } from 'node:url';
33
- import { execFileSync } from 'node:child_process';
33
+ import { execFileSync, execSync, spawn } from 'node:child_process';
34
34
 
35
35
  const __dir = dirname(fileURLToPath(import.meta.url));
36
36
  const CWD = process.cwd();
@@ -128,12 +128,60 @@ function detectLayersHeuristic(fileNodes) {
128
128
  return layers;
129
129
  }
130
130
 
131
- // ── Anthropic API helpers (raw fetch — no SDK needed) ────────────────────────
131
+ // ── Anthropic API helpers ─────────────────────────────────────────────────────
132
+ // Two paths:
133
+ // 1. Direct API via ANTHROPIC_API_KEY (fastest, parallel-safe, requires key)
134
+ // 2. `claude -p` CLI passthrough (reuses Claude Code's auth — no key needed)
135
+ // Slower (CLI cold-start per call), but works inside any Claude Code
136
+ // session without extra setup.
132
137
  const ANTHROPIC_API_KEY = process.env.ANTHROPIC_API_KEY;
133
138
  const ANTHROPIC_URL = 'https://api.anthropic.com/v1/messages';
134
139
  const MODEL = 'claude-haiku-4-5-20251001'; // cheapest for bulk analysis
135
140
 
136
- async function callClaude(systemPrompt, userPrompt, maxTokens = 1024) {
141
+ // Detect `claude` CLI once at startup.
142
+ let _claudeCliPath = null;
143
+ function _detectClaudeCli() {
144
+ if (_claudeCliPath !== null) return _claudeCliPath;
145
+ try {
146
+ const out = execSync('command -v claude 2>/dev/null', { encoding: 'utf-8' }).trim();
147
+ _claudeCliPath = out || '';
148
+ } catch { _claudeCliPath = ''; }
149
+ return _claudeCliPath;
150
+ }
151
+
152
+ const USE_CLAUDE_CLI = !ANTHROPIC_API_KEY && !!_detectClaudeCli();
153
+
154
+ async function callClaudeViaCli(systemPrompt, userPrompt, maxTokens = 1024) {
155
+ return new Promise((resolveP, reject) => {
156
+ const args = [
157
+ '-p',
158
+ '--model', 'haiku',
159
+ '--output-format', 'text',
160
+ '--bare', // skip hooks/skills/auto-memory — we want a fast, clean call
161
+ // Combine system + user into a single prompt argument
162
+ `${systemPrompt}\n\n---\n\n${userPrompt}`,
163
+ ];
164
+ const child = spawn(_claudeCliPath, args, {
165
+ stdio: ['ignore', 'pipe', 'pipe'],
166
+ env: { ...process.env },
167
+ });
168
+ let out = '', err = '';
169
+ child.stdout.on('data', d => out += d.toString());
170
+ child.stderr.on('data', d => err += d.toString());
171
+ const timeout = setTimeout(() => {
172
+ child.kill('SIGKILL');
173
+ reject(new Error('claude -p timed out after 60s'));
174
+ }, 60000);
175
+ child.on('close', code => {
176
+ clearTimeout(timeout);
177
+ if (code !== 0) return reject(new Error(`claude -p exited ${code}: ${err.slice(0, 200)}`));
178
+ resolveP(out.trim());
179
+ });
180
+ child.on('error', e => { clearTimeout(timeout); reject(e); });
181
+ });
182
+ }
183
+
184
+ async function callClaudeViaApi(systemPrompt, userPrompt, maxTokens = 1024) {
137
185
  const body = JSON.stringify({
138
186
  model: MODEL,
139
187
  max_tokens: maxTokens,
@@ -153,7 +201,6 @@ async function callClaude(systemPrompt, userPrompt, maxTokens = 1024) {
153
201
  const data = await resp.json();
154
202
  return data.content?.[0]?.text ?? '';
155
203
  }
156
- // Retry on 429 (rate limit) and 5xx; fail fast on 4xx
157
204
  if (resp.status === 429 || resp.status >= 500) {
158
205
  const retryAfter = parseInt(resp.headers.get('retry-after') || '0', 10);
159
206
  const backoff = retryAfter > 0 ? retryAfter * 1000 : Math.min(2 ** attempt * 1000, 8000);
@@ -172,6 +219,16 @@ async function callClaude(systemPrompt, userPrompt, maxTokens = 1024) {
172
219
  throw lastError || new Error('Anthropic API failed after 3 attempts');
173
220
  }
174
221
 
222
+ async function callClaude(systemPrompt, userPrompt, maxTokens = 1024) {
223
+ if (ANTHROPIC_API_KEY) {
224
+ return callClaudeViaApi(systemPrompt, userPrompt, maxTokens);
225
+ }
226
+ if (USE_CLAUDE_CLI) {
227
+ return callClaudeViaCli(systemPrompt, userPrompt, maxTokens);
228
+ }
229
+ throw new Error('No LLM path available: set ANTHROPIC_API_KEY or install `claude` CLI');
230
+ }
231
+
175
232
  function parseJson(text) {
176
233
  try {
177
234
  const fenceMatch = text.match(/```(?:json)?\s*\n?([\s\S]*?)\n?\s*```/);
@@ -640,12 +697,13 @@ async function main() {
640
697
  const batch = toAnalyze.slice(0, limit);
641
698
  console.log(`[understand] Analyzing ${batch.length} files (${toAnalyze.length - batch.length} skipped/already enriched)`);
642
699
 
643
- if (!ANTHROPIC_API_KEY && !noLlm) {
644
- console.warn('[understand] ANTHROPIC_API_KEY not set falling back to --no-llm heuristic mode');
645
- // Fall through to heuristic only
700
+ const llmPath = ANTHROPIC_API_KEY ? 'api' : (USE_CLAUDE_CLI ? 'claude-cli' : 'none');
701
+ if (llmPath === 'none' && !noLlm) {
702
+ console.warn('[understand] No LLM path available (no ANTHROPIC_API_KEY and no `claude` CLI) — falling back to --no-llm heuristic mode');
703
+ } else if (llmPath === 'claude-cli' && !noLlm) {
704
+ console.log('[understand] Using `claude -p` CLI passthrough (no API key needed; reusing Claude Code auth)');
646
705
  }
647
-
648
- const useLlm = !noLlm && !!ANTHROPIC_API_KEY;
706
+ const useLlm = !noLlm && llmPath !== 'none';
649
707
 
650
708
  // ── Get project context for better prompts ────────────────────────────────
651
709
  let projectContext = `Project directory: ${basename(projectDir)}`;
@@ -798,7 +856,7 @@ async function main() {
798
856
  async function detectAndWriteLayers(db, fileNodes, forceHeuristic, dryRun, dir) {
799
857
  let layers;
800
858
 
801
- if (!forceHeuristic && ANTHROPIC_API_KEY) {
859
+ if (!forceHeuristic && (ANTHROPIC_API_KEY || USE_CLAUDE_CLI)) {
802
860
  console.log('[understand] Detecting architectural layers via LLM...');
803
861
  const filePaths = fileNodes.map(n => n.file_path).filter(Boolean);
804
862
  try {