nothumanallowed 8.4.2 → 8.5.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.
Files changed (2) hide show
  1. package/bin/nha.mjs +179 -0
  2. package/package.json +1 -1
package/bin/nha.mjs CHANGED
@@ -8207,11 +8207,190 @@ Or pass it directly during registration:
8207
8207
  },
8208
8208
  },
8209
8209
 
8210
+ // ============================================================================
8211
+ // ASK - Invoke any agent with optional file/image attachment
8212
+ // ============================================================================
8213
+
8214
+ async ask(args) {
8215
+ const agentName = args[0];
8216
+ const promptParts = args.slice(1);
8217
+ const prompt = promptParts.join(' ') || args['--prompt'] || '';
8218
+ const imagePath = args['--image'];
8219
+ const filePath = args['--file'];
8220
+
8221
+ if (!agentName) {
8222
+ console.log(`
8223
+ 🤖 ASK - Invoke any NHA agent
8224
+
8225
+ Usage:
8226
+ nha ask <agent> "your prompt"
8227
+ nha ask saber "audit this code for vulnerabilities"
8228
+ nha ask oracle "analyze Q1 revenue data" --file report.csv
8229
+ nha ask forge "what's in this screenshot?" --image screen.png
8230
+
8231
+ Options:
8232
+ --file FILE Attach a text file (txt, json, csv, md, log)
8233
+ --image IMAGE Attach an image for vision analysis (jpg, png, webp)
8234
+ --prompt TEXT Alternative way to provide the prompt
8235
+
8236
+ Available agents: saber, zero, veritas, forge, atlas, oracle, herald,
8237
+ echo, glitch, flux, babel, polyglot, cron, conductor, heimdall, logos...
8238
+ Run 'nha agent:find' to see all agents.
8239
+ `);
8240
+ return;
8241
+ }
8242
+
8243
+ const fs = await import('fs');
8244
+ const path = await import('path');
8245
+
8246
+ // Load AI config
8247
+ const config = loadConfig();
8248
+ const aiConfig = config.ai;
8249
+ if (!aiConfig?.apiKey) {
8250
+ console.log('❌ No AI API key configured. Run: nha ai:config --provider claude');
8251
+ return;
8252
+ }
8253
+
8254
+ console.log(`\n 🤖 Asking \x1b[36m${agentName.toUpperCase()}\x1b[0m...\n`);
8255
+
8256
+ try {
8257
+ // Get agent system prompt from NHA server
8258
+ const client = new NHAClient();
8259
+ let systemPrompt = '';
8260
+ try {
8261
+ const res = await fetch(`${client.baseUrl}/legion/agents/${agentName}/invoke`, {
8262
+ method: 'POST',
8263
+ headers: { 'Content-Type': 'application/json' },
8264
+ body: JSON.stringify({ prompt: prompt || 'help' }),
8265
+ });
8266
+ if (res.ok) {
8267
+ const data = await res.json();
8268
+ systemPrompt = data.data?.systemPrompt || data.systemPrompt || '';
8269
+ }
8270
+ } catch {}
8271
+ if (!systemPrompt) systemPrompt = `You are the ${agentName} AI agent. Be helpful, concise, and expert in your domain.`;
8272
+
8273
+ let userMessage = prompt;
8274
+
8275
+ // Handle file attachment
8276
+ if (filePath) {
8277
+ const absPath = path.default.resolve(filePath);
8278
+ if (!fs.default.existsSync(absPath)) {
8279
+ console.log(`❌ File not found: ${absPath}`);
8280
+ return;
8281
+ }
8282
+ const content = fs.default.readFileSync(absPath, 'utf-8');
8283
+ const fileName = path.default.basename(absPath);
8284
+ console.log(` 📎 Attached: ${fileName} (${Math.round(content.length / 1024)} KB)\n`);
8285
+ userMessage = prompt
8286
+ ? `User asks about file "${fileName}": ${prompt}\n\nFile content:\n${content.slice(0, 8000)}`
8287
+ : `Analyze this file "${fileName}":\n\n${content.slice(0, 8000)}`;
8288
+ }
8289
+
8290
+ // Handle image attachment
8291
+ if (imagePath) {
8292
+ const absPath = path.default.resolve(imagePath);
8293
+ if (!fs.default.existsSync(absPath)) {
8294
+ console.log(`❌ Image not found: ${absPath}`);
8295
+ return;
8296
+ }
8297
+ const imageBuffer = fs.default.readFileSync(absPath);
8298
+ const base64 = imageBuffer.toString('base64');
8299
+ const ext = path.default.extname(absPath).toLowerCase();
8300
+ const mimeMap = { '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.png': 'image/png', '.webp': 'image/webp', '.gif': 'image/gif' };
8301
+ const mimeType = mimeMap[ext] || 'image/jpeg';
8302
+ const fileName = path.default.basename(absPath);
8303
+ console.log(` 📷 Attached: ${fileName} (${Math.round(base64.length * 3 / 4 / 1024)} KB)\n`);
8304
+
8305
+ const imagePrompt = prompt || 'Describe this image in detail. Extract any text, data, or important information visible.';
8306
+
8307
+ // Call vision API based on provider
8308
+ let response = '';
8309
+ if (aiConfig.provider === 'claude' || aiConfig.provider === 'anthropic') {
8310
+ const res = await fetch('https://api.anthropic.com/v1/messages', {
8311
+ method: 'POST',
8312
+ headers: { 'Content-Type': 'application/json', 'x-api-key': aiConfig.apiKey, 'anthropic-version': '2023-06-01' },
8313
+ body: JSON.stringify({
8314
+ model: aiConfig.model || 'claude-sonnet-4-20250514',
8315
+ max_tokens: 4096,
8316
+ system: systemPrompt,
8317
+ messages: [{ role: 'user', content: [
8318
+ { type: 'image', source: { type: 'base64', media_type: mimeType, data: base64 } },
8319
+ { type: 'text', text: imagePrompt },
8320
+ ]}],
8321
+ }),
8322
+ });
8323
+ if (!res.ok) throw new Error(`Anthropic ${res.status}: ${(await res.text()).slice(0, 200)}`);
8324
+ const data = await res.json();
8325
+ response = data.content?.[0]?.text || '';
8326
+ } else if (aiConfig.provider === 'openai') {
8327
+ const res = await fetch('https://api.openai.com/v1/chat/completions', {
8328
+ method: 'POST',
8329
+ headers: { 'Content-Type': 'application/json', Authorization: `Bearer ${aiConfig.apiKey}` },
8330
+ body: JSON.stringify({
8331
+ model: aiConfig.model || 'gpt-4o-mini',
8332
+ max_tokens: 4096,
8333
+ messages: [
8334
+ { role: 'system', content: systemPrompt },
8335
+ { role: 'user', content: [
8336
+ { type: 'image_url', image_url: { url: `data:${mimeType};base64,${base64}` } },
8337
+ { type: 'text', text: imagePrompt },
8338
+ ]},
8339
+ ],
8340
+ }),
8341
+ });
8342
+ if (!res.ok) throw new Error(`OpenAI ${res.status}: ${(await res.text()).slice(0, 200)}`);
8343
+ const data = await res.json();
8344
+ response = data.choices?.[0]?.message?.content || '';
8345
+ } else if (aiConfig.provider === 'gemini') {
8346
+ const model = aiConfig.model || 'gemini-2.0-flash';
8347
+ const res = await fetch(`https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=${aiConfig.apiKey}`, {
8348
+ method: 'POST',
8349
+ headers: { 'Content-Type': 'application/json' },
8350
+ body: JSON.stringify({
8351
+ system_instruction: { parts: [{ text: systemPrompt }] },
8352
+ contents: [{ parts: [
8353
+ { inline_data: { mime_type: mimeType, data: base64 } },
8354
+ { text: imagePrompt },
8355
+ ]}],
8356
+ generationConfig: { maxOutputTokens: 4096 },
8357
+ }),
8358
+ });
8359
+ if (!res.ok) throw new Error(`Gemini ${res.status}: ${(await res.text()).slice(0, 200)}`);
8360
+ const data = await res.json();
8361
+ response = data.candidates?.[0]?.content?.parts?.[0]?.text || '';
8362
+ } else {
8363
+ console.log(`❌ Vision not supported for provider "${aiConfig.provider}". Use claude, openai, or gemini.`);
8364
+ return;
8365
+ }
8366
+
8367
+ console.log(` \x1b[32m${response}\x1b[0m\n`);
8368
+ return;
8369
+ }
8370
+
8371
+ // Text-only: call LLM via the standard chat function
8372
+ if (!userMessage) {
8373
+ console.log('❌ No prompt provided. Usage: nha ask <agent> "your prompt"');
8374
+ return;
8375
+ }
8376
+
8377
+ const response = await askAI({ ...aiConfig, provider: aiConfig.provider === 'anthropic' ? 'claude' : aiConfig.provider, maxTokens: 4096, systemPrompt }, userMessage, 'analysis');
8378
+ console.log(` \x1b[32m${response}\x1b[0m\n`);
8379
+ } catch (error) {
8380
+ console.error(`❌ Error: ${error.message}`);
8381
+ }
8382
+ },
8383
+
8210
8384
  async help() {
8211
8385
  console.log(`
8212
8386
  PIF v${PIF_VERSION} - Please Insert Floppy - NotHumanAllowed AI Agent
8213
8387
  https://nothumanallowed.com
8214
8388
 
8389
+ AGENTS:
8390
+ ask <agent> "prompt" Ask any agent (saber, oracle, forge, etc.)
8391
+ --file FILE Attach a text file for analysis
8392
+ --image IMAGE Attach an image for vision analysis (claude/openai/gemini)
8393
+
8215
8394
  SETUP & DIAGNOSTICS:
8216
8395
  setup Interactive onboarding wizard (first-time)
8217
8396
  register [--name NAME] Register a new agent on NHA
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nothumanallowed",
3
- "version": "8.4.2",
3
+ "version": "8.5.0",
4
4
  "description": "NotHumanAllowed — 38 AI agents + unified productivity suite. Gmail, Calendar, Drive, Contacts, Tasks, GitHub, Notion, Slack, voice chat, smart scheduler. Zero-dependency CLI.",
5
5
  "type": "module",
6
6
  "bin": {