nothumanallowed 13.2.72 → 13.2.73

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": "nothumanallowed",
3
- "version": "13.2.72",
3
+ "version": "13.2.73",
4
4
  "description": "NotHumanAllowed — 38 AI agents, 80 tools, Studio (visual agentic workflows). Email, calendar, browser automation, screen capture, canvas, cron/heartbeat, Alexandria E2E messaging, GitHub, Notion, Slack, voice chat, free AI (Liara), 28 languages. Zero-dependency CLI.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -2852,35 +2852,73 @@ export async function cmdUI(args) {
2852
2852
 
2853
2853
  // ── Fetch REAL data for each agent type ──────────────────────
2854
2854
  if (agent === 'DocumentReaderAgent') {
2855
- // Extract text from attached PDF and return it as the step output.
2856
- // This becomes context for all subsequent steps (WebSearchAgent etc.)
2855
+ // Extract text from attached PDF, then ask the LLM to structure it cleanly.
2856
+ // The structured output becomes context for all subsequent steps.
2857
2857
  sendToken('[Reading attached document...] ');
2858
+ let rawText = '';
2858
2859
  if (stepPdfBase64) {
2859
2860
  try {
2860
2861
  const b64 = stepPdfBase64.includes(',') ? stepPdfBase64.split(',')[1] : stepPdfBase64;
2861
2862
  const pdfBuffer = Buffer.from(b64, 'base64');
2862
- const extracted = extractTextFromPdf(pdfBuffer);
2863
- if (extracted && extracted.length > 20) {
2864
- toolData = `## Document: ${stepPdfName || 'attached'}\n\n${extracted.slice(0, 20000)}`;
2865
- } else {
2866
- // Fallback: ask vision model to describe/OCR the document
2867
- sendToken('[No text found — using vision OCR...] ');
2863
+ rawText = extractTextFromPdf(pdfBuffer) || '';
2864
+ if (!rawText || rawText.length < 20) {
2865
+ // Scanned PDF use vision OCR
2866
+ sendToken('[No text layer — using vision OCR...] ');
2868
2867
  try {
2869
- const visionText = await callLLMVision(config, stepPdfBase64, 'application/pdf',
2870
- `Extract ALL text, technical specifications, model numbers, part codes, product names, manufacturer details, dimensions, ratings, and any other data from this document. List every detail exactly as printed.`);
2871
- toolData = `## Document (OCR): ${stepPdfName || 'attached'}\n\n${visionText}`;
2872
- } catch (ve) {
2873
- toolData = `Could not extract text from document: ${ve.message}`;
2874
- }
2868
+ rawText = await callLLMVision(config, stepPdfBase64, 'application/pdf',
2869
+ 'Extract ALL text from this document exactly as printed, preserving all numbers, codes, and values.');
2870
+ } catch (ve) { rawText = ''; }
2875
2871
  }
2876
- } catch (e) { toolData = `Document read failed: ${e.message}`; }
2877
- } else {
2878
- toolData = 'No document attached.';
2872
+ } catch (e) { rawText = ''; }
2873
+ }
2874
+ if (!rawText) {
2875
+ sendToken('Could not extract text from the attached document.');
2876
+ clearInterval(keepalive);
2877
+ sendEvent({ done: true, usage: { input: 0, output: 0 } });
2878
+ res.end();
2879
+ logRequest(method, pathname, 200, Date.now() - start);
2880
+ return;
2881
+ }
2882
+ // Ask LLM to structure the raw extracted text into readable markdown
2883
+ sendToken('[Structuring document content...] ');
2884
+ const LANG_MAP_DOC = {en:'English',it:'Italian',es:'Spanish',fr:'French',de:'German',pt:'Portuguese',zh:'Chinese',ja:'Japanese',ar:'Arabic',hi:'Hindi',ru:'Russian',nl:'Dutch',pl:'Polish',tr:'Turkish',ko:'Korean',sv:'Swedish',da:'Danish',fi:'Finnish',no:'Norwegian',cs:'Czech'};
2885
+ const docLang = LANG_MAP_DOC[(config?.language||'it').toLowerCase().slice(0,2)] || 'Italian';
2886
+ const docSys = `You are a technical document analyst. Extract and structure the content of this document into clear, readable markdown. Respond in ${docLang}.
2887
+ Rules:
2888
+ - List ALL technical specifications with their exact values (codes, voltages, pressures, temperatures, dimensions, flow rates, etc.)
2889
+ - Use markdown headers (##), bullet points (-), and tables where appropriate
2890
+ - Do NOT invent, interpret, or add anything not present in the raw text
2891
+ - Include all product/part codes exactly as written
2892
+ - Keep all numeric values with their units`;
2893
+ const docUser = `Here is the raw text extracted from "${stepPdfName || 'document.pdf'}". Structure it into clean, readable markdown:\n\n${rawText.slice(0, 18000)}`;
2894
+ let structuredOutput = '';
2895
+ let inThink = false;
2896
+ try {
2897
+ await withTimeout(
2898
+ callLLMStream(config, docSys, docUser,
2899
+ (token) => {
2900
+ // Strip <think> blocks
2901
+ let buf = token;
2902
+ if (inThink) {
2903
+ const ci = buf.indexOf('</think>');
2904
+ if (ci >= 0) { buf = buf.slice(ci + 8); inThink = false; }
2905
+ else return;
2906
+ }
2907
+ const oi = buf.indexOf('<think>');
2908
+ if (oi >= 0) { buf = buf.slice(0, oi); inThink = true; }
2909
+ if (buf) { structuredOutput += buf; sendToken(buf); }
2910
+ },
2911
+ { max_tokens: 3000 }
2912
+ ),
2913
+ 90000
2914
+ );
2915
+ } catch (e) {
2916
+ // LLM failed — fall back to raw text
2917
+ structuredOutput = `## ${stepPdfName || 'Document'}\n\n${rawText.slice(0, 8000)}`;
2918
+ sendToken(structuredOutput);
2879
2919
  }
2880
- // Stream the extracted content as the step output directly — no LLM rewrite needed
2881
- sendToken(toolData);
2882
2920
  clearInterval(keepalive);
2883
- sendEvent({ done: true, usage: { input: 0, output: Math.ceil(toolData.length / 4) } });
2921
+ sendEvent({ done: true, usage: { input: Math.ceil(rawText.length / 4), output: Math.ceil(structuredOutput.length / 4) } });
2884
2922
  res.end();
2885
2923
  logRequest(method, pathname, 200, Date.now() - start);
2886
2924
  return;
package/src/constants.mjs CHANGED
@@ -5,7 +5,7 @@ import { fileURLToPath } from 'url';
5
5
  const __filename = fileURLToPath(import.meta.url);
6
6
  const __dirname = path.dirname(__filename);
7
7
 
8
- export const VERSION = '13.2.72';
8
+ export const VERSION = '13.2.73';
9
9
  export const BASE_URL = 'https://nothumanallowed.com/cli';
10
10
  export const API_BASE = 'https://nothumanallowed.com/api/v1';
11
11