neuronix-node 0.1.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.
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handlers = void 0;
4
+ exports.hasHandler = hasHandler;
5
+ exports.runHandler = runHandler;
6
+ const chart_js_1 = require("./chart.js");
7
+ const invoice_js_1 = require("./invoice.js");
8
+ const expense_js_1 = require("./expense.js");
9
+ const pnl_js_1 = require("./pnl.js");
10
+ const smart_route_js_1 = require("./smart-route.js");
11
+ const file_processor_js_1 = require("./file-processor.js");
12
+ const handlers = {
13
+ chart: chart_js_1.handleChart,
14
+ invoice: invoice_js_1.handleInvoice,
15
+ expense_report: expense_js_1.handleExpenseReport,
16
+ pnl: pnl_js_1.handlePnl,
17
+ smart_route: smart_route_js_1.handleSmartRoute,
18
+ process_file: file_processor_js_1.handleFileProcess,
19
+ };
20
+ exports.handlers = handlers;
21
+ /**
22
+ * Check if we have a specialized handler for this task type.
23
+ */
24
+ function hasHandler(type) {
25
+ return type in handlers;
26
+ }
27
+ /**
28
+ * Run the specialized handler for a task type.
29
+ */
30
+ async function runHandler(task) {
31
+ const handler = handlers[task.type];
32
+ if (!handler) {
33
+ throw new Error(`No handler for task type: ${task.type}`);
34
+ }
35
+ return handler(task);
36
+ }
@@ -0,0 +1,2 @@
1
+ import type { TaskInput, TaskOutput } from "./index.js";
2
+ export declare function handleInvoice(task: TaskInput): Promise<TaskOutput>;
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleInvoice = handleInvoice;
4
+ async function handleInvoice(task) {
5
+ const start = Date.now();
6
+ const input = task.input_payload;
7
+ const company = input.company || "Your Company";
8
+ const client = input.client || "Client Name";
9
+ const invoiceNumber = input.invoice_number || `INV-${Date.now().toString(36).toUpperCase()}`;
10
+ const taxRate = input.tax_rate ?? 0;
11
+ const dueDate = input.due_date || new Date(Date.now() + 30 * 86400000).toISOString().split("T")[0];
12
+ const notes = input.notes || "";
13
+ const items = input.items || [
14
+ { description: "Consulting Services", quantity: 10, unit_price: 150 },
15
+ { description: "Software License", quantity: 1, unit_price: 500 },
16
+ ];
17
+ // Calculate totals
18
+ const lineItems = items.map((item) => ({
19
+ ...item,
20
+ total: Math.round(item.quantity * item.unit_price * 100) / 100,
21
+ }));
22
+ const subtotal = Math.round(lineItems.reduce((sum, item) => sum + item.total, 0) * 100) / 100;
23
+ const tax = Math.round(subtotal * (taxRate / 100) * 100) / 100;
24
+ const total = Math.round((subtotal + tax) * 100) / 100;
25
+ // Generate HTML invoice
26
+ const itemRows = lineItems
27
+ .map((item) => `<tr>
28
+ <td style="padding:10px 12px;border-bottom:1px solid #1a1a2e">${item.description}</td>
29
+ <td style="padding:10px 12px;border-bottom:1px solid #1a1a2e;text-align:center">${item.quantity}</td>
30
+ <td style="padding:10px 12px;border-bottom:1px solid #1a1a2e;text-align:right">$${item.unit_price.toFixed(2)}</td>
31
+ <td style="padding:10px 12px;border-bottom:1px solid #1a1a2e;text-align:right;font-weight:600">$${item.total.toFixed(2)}</td>
32
+ </tr>`)
33
+ .join("\n");
34
+ const invoiceHtml = `<!DOCTYPE html>
35
+ <html>
36
+ <head><meta charset="utf-8"><title>Invoice ${invoiceNumber}</title></head>
37
+ <body style="margin:0;padding:40px;background:#0a0a0f;color:#d1d5db;font-family:-apple-system,sans-serif">
38
+ <div style="max-width:700px;margin:0 auto;background:#0d0d1a;border:1px solid rgba(255,255,255,0.08);border-radius:16px;padding:40px">
39
+ <div style="display:flex;justify-content:space-between;margin-bottom:40px">
40
+ <div>
41
+ <h1 style="color:#fff;font-size:24px;margin:0 0 4px">INVOICE</h1>
42
+ <p style="color:#6b7280;font-size:14px;margin:0">${invoiceNumber}</p>
43
+ </div>
44
+ <div style="text-align:right">
45
+ <p style="color:#fff;font-weight:700;margin:0">${company}</p>
46
+ ${input.company_address ? `<p style="color:#6b7280;font-size:13px;margin:4px 0 0">${input.company_address}</p>` : ""}
47
+ </div>
48
+ </div>
49
+
50
+ <div style="display:flex;justify-content:space-between;margin-bottom:32px">
51
+ <div>
52
+ <p style="color:#6b7280;font-size:12px;text-transform:uppercase;letter-spacing:0.1em;margin:0 0 4px">Bill To</p>
53
+ <p style="color:#fff;font-weight:600;margin:0">${client}</p>
54
+ ${input.client_address ? `<p style="color:#6b7280;font-size:13px;margin:4px 0 0">${input.client_address}</p>` : ""}
55
+ </div>
56
+ <div style="text-align:right">
57
+ <p style="color:#6b7280;font-size:12px;margin:0">Date: ${new Date().toISOString().split("T")[0]}</p>
58
+ <p style="color:#6b7280;font-size:12px;margin:4px 0 0">Due: ${dueDate}</p>
59
+ </div>
60
+ </div>
61
+
62
+ <table style="width:100%;border-collapse:collapse;margin-bottom:24px">
63
+ <thead>
64
+ <tr style="border-bottom:2px solid #0066FF">
65
+ <th style="padding:10px 12px;text-align:left;font-size:12px;text-transform:uppercase;letter-spacing:0.08em;color:#6b7280">Description</th>
66
+ <th style="padding:10px 12px;text-align:center;font-size:12px;text-transform:uppercase;letter-spacing:0.08em;color:#6b7280">Qty</th>
67
+ <th style="padding:10px 12px;text-align:right;font-size:12px;text-transform:uppercase;letter-spacing:0.08em;color:#6b7280">Price</th>
68
+ <th style="padding:10px 12px;text-align:right;font-size:12px;text-transform:uppercase;letter-spacing:0.08em;color:#6b7280">Total</th>
69
+ </tr>
70
+ </thead>
71
+ <tbody>
72
+ ${itemRows}
73
+ </tbody>
74
+ </table>
75
+
76
+ <div style="display:flex;justify-content:flex-end">
77
+ <div style="width:240px">
78
+ <div style="display:flex;justify-content:space-between;padding:8px 0;font-size:14px">
79
+ <span style="color:#6b7280">Subtotal</span><span>$${subtotal.toFixed(2)}</span>
80
+ </div>
81
+ ${taxRate > 0 ? `<div style="display:flex;justify-content:space-between;padding:8px 0;font-size:14px">
82
+ <span style="color:#6b7280">Tax (${taxRate}%)</span><span>$${tax.toFixed(2)}</span>
83
+ </div>` : ""}
84
+ <div style="display:flex;justify-content:space-between;padding:12px 0;font-size:18px;font-weight:800;border-top:2px solid #0066FF;margin-top:8px">
85
+ <span style="color:#fff">Total</span><span style="color:#0066FF">$${total.toFixed(2)}</span>
86
+ </div>
87
+ </div>
88
+ </div>
89
+
90
+ ${notes ? `<div style="margin-top:32px;padding-top:24px;border-top:1px solid rgba(255,255,255,0.06)">
91
+ <p style="color:#6b7280;font-size:12px;text-transform:uppercase;letter-spacing:0.1em;margin:0 0 8px">Notes</p>
92
+ <p style="color:#9ca3af;font-size:14px;line-height:1.6;margin:0">${notes}</p>
93
+ </div>` : ""}
94
+
95
+ <div style="margin-top:40px;text-align:center">
96
+ <p style="color:#4b5563;font-size:12px">Generated by Neuronix AccountBot</p>
97
+ </div>
98
+ </div>
99
+ </body>
100
+ </html>`;
101
+ const durationMs = Date.now() - start;
102
+ return {
103
+ invoice_html: invoiceHtml,
104
+ invoice_number: invoiceNumber,
105
+ subtotal,
106
+ tax,
107
+ total,
108
+ tax_rate: taxRate,
109
+ items: lineItems,
110
+ due_date: dueDate,
111
+ duration_ms: durationMs,
112
+ };
113
+ }
@@ -0,0 +1,2 @@
1
+ import type { TaskInput, TaskOutput } from "./index.js";
2
+ export declare function handlePnl(task: TaskInput): Promise<TaskOutput>;
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handlePnl = handlePnl;
4
+ async function handlePnl(task) {
5
+ const start = Date.now();
6
+ const input = task.input_payload;
7
+ const period = input.period || "Current Period";
8
+ const revenue = input.revenue || [
9
+ { description: "Product Sales", amount: 45000 },
10
+ { description: "Service Revenue", amount: 28000 },
11
+ { description: "Subscription Income", amount: 12000 },
12
+ ];
13
+ const expenses = input.expenses || [
14
+ { description: "Salaries & Wages", amount: 32000, category: "Personnel" },
15
+ { description: "Rent & Utilities", amount: 5500, category: "Overhead" },
16
+ { description: "Marketing", amount: 8000, category: "Marketing" },
17
+ { description: "Software & Tools", amount: 3200, category: "Technology" },
18
+ { description: "Insurance", amount: 1800, category: "Overhead" },
19
+ { description: "Office Supplies", amount: 650, category: "Operations" },
20
+ ];
21
+ const revenueTotal = Math.round(revenue.reduce((s, r) => s + r.amount, 0) * 100) / 100;
22
+ const expenseTotal = Math.round(expenses.reduce((s, e) => s + e.amount, 0) * 100) / 100;
23
+ const netIncome = Math.round((revenueTotal - expenseTotal) * 100) / 100;
24
+ const marginPct = revenueTotal > 0 ? Math.round((netIncome / revenueTotal) * 1000) / 10 : 0;
25
+ // Expense breakdown by category
26
+ const expenseByCategory = {};
27
+ for (const e of expenses) {
28
+ const cat = e.category || "Other";
29
+ expenseByCategory[cat] = (expenseByCategory[cat] || 0) + e.amount;
30
+ }
31
+ const sortedExpenseCategories = Object.entries(expenseByCategory)
32
+ .sort((a, b) => b[1] - a[1])
33
+ .map(([cat, amount]) => ({
34
+ category: cat,
35
+ amount: Math.round(amount * 100) / 100,
36
+ percentage: Math.round((amount / expenseTotal) * 1000) / 10,
37
+ }));
38
+ // Chart data: revenue vs expenses bar chart
39
+ const chartData = {
40
+ chart_type: "bar",
41
+ title: `Profit & Loss — ${period}`,
42
+ labels: ["Revenue", "Expenses", "Net Income"],
43
+ datasets: [{
44
+ label: "Amount ($)",
45
+ data: [revenueTotal, expenseTotal, netIncome],
46
+ backgroundColor: ["#10b981", "#ef4444", netIncome >= 0 ? "#0066FF" : "#f59e0b"],
47
+ }],
48
+ };
49
+ // Summary text
50
+ const lines = [
51
+ `Profit & Loss Statement: ${period}`,
52
+ `${"═".repeat(45)}`,
53
+ ``,
54
+ `REVENUE`,
55
+ ...revenue.map((r) => ` ${r.description.padEnd(30)} $${r.amount.toLocaleString("en-US", { minimumFractionDigits: 2 })}`),
56
+ ` ${"─".repeat(43)}`,
57
+ ` Total Revenue${" ".repeat(18)} $${revenueTotal.toLocaleString("en-US", { minimumFractionDigits: 2 })}`,
58
+ ``,
59
+ `EXPENSES`,
60
+ ...expenses.map((e) => ` ${e.description.padEnd(30)} $${e.amount.toLocaleString("en-US", { minimumFractionDigits: 2 })}`),
61
+ ` ${"─".repeat(43)}`,
62
+ ` Total Expenses${" ".repeat(17)} $${expenseTotal.toLocaleString("en-US", { minimumFractionDigits: 2 })}`,
63
+ ``,
64
+ `${"═".repeat(45)}`,
65
+ ` NET INCOME${" ".repeat(21)} $${netIncome.toLocaleString("en-US", { minimumFractionDigits: 2 })}`,
66
+ ` Profit Margin${" ".repeat(18)} ${marginPct}%`,
67
+ `${"═".repeat(45)}`,
68
+ ];
69
+ // Generate CSV output
70
+ const csvLines = [
71
+ `PROFIT & LOSS STATEMENT`,
72
+ `Period,${period}`,
73
+ "",
74
+ "REVENUE",
75
+ "Description,Amount",
76
+ ...revenue.map((r) => `${csvEscape(r.description)},$${r.amount.toFixed(2)}`),
77
+ `Total Revenue,$${revenueTotal.toFixed(2)}`,
78
+ "",
79
+ "EXPENSES",
80
+ "Description,Amount,Category",
81
+ ...expenses.map((e) => `${csvEscape(e.description)},$${e.amount.toFixed(2)},${csvEscape(e.category || "General")}`),
82
+ `Total Expenses,$${expenseTotal.toFixed(2)},`,
83
+ "",
84
+ "EXPENSE BREAKDOWN BY CATEGORY",
85
+ "Category,Amount,% of Expenses",
86
+ ...sortedExpenseCategories.map((c) => `${csvEscape(c.category)},$${c.amount.toFixed(2)},${c.percentage}%`),
87
+ "",
88
+ "SUMMARY",
89
+ "Metric,Value",
90
+ `Total Revenue,$${revenueTotal.toFixed(2)}`,
91
+ `Total Expenses,$${expenseTotal.toFixed(2)}`,
92
+ `Net Income,$${netIncome.toFixed(2)}`,
93
+ `Profit Margin,${marginPct}%`,
94
+ ];
95
+ const durationMs = Date.now() - start;
96
+ return {
97
+ text: lines.join("\n"),
98
+ output_csv: csvLines.join("\n"),
99
+ revenue_total: revenueTotal,
100
+ expense_total: expenseTotal,
101
+ net_income: netIncome,
102
+ margin_pct: marginPct,
103
+ revenue_items: revenue,
104
+ expense_items: expenses,
105
+ expense_breakdown: sortedExpenseCategories,
106
+ chart_data: chartData,
107
+ period,
108
+ duration_ms: durationMs,
109
+ };
110
+ }
111
+ function csvEscape(value) {
112
+ if (value.includes(",") || value.includes('"') || value.includes("\n")) {
113
+ return `"${value.replace(/"/g, '""')}"`;
114
+ }
115
+ return value;
116
+ }
@@ -0,0 +1,2 @@
1
+ import type { TaskInput, TaskOutput } from "./index.js";
2
+ export declare function handleSmartRoute(task: TaskInput): Promise<TaskOutput>;
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handleSmartRoute = handleSmartRoute;
4
+ const chart_js_1 = require("./chart.js");
5
+ const invoice_js_1 = require("./invoice.js");
6
+ const expense_js_1 = require("./expense.js");
7
+ const pnl_js_1 = require("./pnl.js");
8
+ const inference_js_1 = require("../inference.js");
9
+ /**
10
+ * Smart router: uses LLM to interpret natural language, then routes
11
+ * to the appropriate specialized handler.
12
+ *
13
+ * Example prompts:
14
+ * "Make a bar chart of Q1 sales"
15
+ * "Generate an invoice for $500 of consulting"
16
+ * "Show me my expense breakdown"
17
+ * "Create a P&L statement"
18
+ */
19
+ const ROUTE_SYSTEM_PROMPT = `You are a task router. Given a user request, output ONLY a JSON object with:
20
+ - "type": one of "chart", "invoice", "expense_report", "pnl", or "text"
21
+ - "params": extracted parameters for that type
22
+
23
+ For "chart": { "chart_type": "bar"|"line"|"pie"|"doughnut", "title": string, "labels": string[], "datasets": [{"label": string, "data": number[]}] }
24
+ For "invoice": { "company": string, "client": string, "items": [{"description": string, "quantity": number, "unit_price": number}], "tax_rate": number }
25
+ For "expense_report": { "expenses": [{"description": string, "amount": number, "category": string}], "period": string }
26
+ For "pnl": { "revenue": [{"description": string, "amount": number}], "expenses": [{"description": string, "amount": number, "category": string}], "period": string }
27
+ For "text": { "response": string }
28
+
29
+ Output ONLY valid JSON. No markdown, no explanation.`;
30
+ function tryParseJSON(text) {
31
+ // Try to extract JSON from the response
32
+ const jsonMatch = text.match(/\{[\s\S]*\}/);
33
+ if (!jsonMatch)
34
+ return null;
35
+ try {
36
+ return JSON.parse(jsonMatch[0]);
37
+ }
38
+ catch {
39
+ return null;
40
+ }
41
+ }
42
+ async function handleSmartRoute(task) {
43
+ const start = Date.now();
44
+ const prompt = task.input_payload.prompt || "";
45
+ // Quick keyword matching first (faster than LLM for obvious cases)
46
+ const lower = prompt.toLowerCase();
47
+ if (/\b(chart|graph|plot|bar chart|pie chart|line chart|doughnut)\b/.test(lower)) {
48
+ return (0, chart_js_1.handleChart)({
49
+ type: "chart",
50
+ input_payload: { prompt },
51
+ });
52
+ }
53
+ if (/\b(invoice|bill|billing)\b/.test(lower) && !/\b(expense|report|pnl|profit)\b/.test(lower)) {
54
+ return (0, invoice_js_1.handleInvoice)({
55
+ type: "invoice",
56
+ input_payload: { prompt },
57
+ });
58
+ }
59
+ if (/\b(expense|spending|spend breakdown|cost breakdown)\b/.test(lower)) {
60
+ return (0, expense_js_1.handleExpenseReport)({
61
+ type: "expense_report",
62
+ input_payload: { prompt },
63
+ });
64
+ }
65
+ if (/\b(p&l|profit.?loss|pnl|income statement|profit margin)\b/.test(lower)) {
66
+ return (0, pnl_js_1.handlePnl)({
67
+ type: "pnl",
68
+ input_payload: { prompt },
69
+ });
70
+ }
71
+ // If no keyword match, try using the LLM to route (if a model is loaded)
72
+ const modelIds = ["tinyllama-1.1b", "phi-2", "mistral-7b", "llama3-8b"];
73
+ const loadedModel = modelIds.find((id) => (0, inference_js_1.isModelLoaded)(id));
74
+ if (loadedModel) {
75
+ try {
76
+ const { text } = await (0, inference_js_1.runInference)(loadedModel, `${ROUTE_SYSTEM_PROMPT}\n\nUser request: "${prompt}"\n\nJSON:`, 512);
77
+ const parsed = tryParseJSON(text);
78
+ if (parsed && parsed.type) {
79
+ const routedType = parsed.type;
80
+ const params = (parsed.params || {});
81
+ if (routedType === "chart")
82
+ return (0, chart_js_1.handleChart)({ type: "chart", input_payload: params });
83
+ if (routedType === "invoice")
84
+ return (0, invoice_js_1.handleInvoice)({ type: "invoice", input_payload: params });
85
+ if (routedType === "expense_report")
86
+ return (0, expense_js_1.handleExpenseReport)({ type: "expense_report", input_payload: params });
87
+ if (routedType === "pnl")
88
+ return (0, pnl_js_1.handlePnl)({ type: "pnl", input_payload: params });
89
+ // "text" type — just return the LLM response
90
+ if (routedType === "text") {
91
+ const durationMs = Date.now() - start;
92
+ return {
93
+ text: params.response || text,
94
+ routed_type: "text",
95
+ duration_ms: durationMs,
96
+ };
97
+ }
98
+ }
99
+ }
100
+ catch {
101
+ // LLM routing failed, fall through to plain inference
102
+ }
103
+ }
104
+ // Fallback: just run regular inference
105
+ if (loadedModel) {
106
+ const { text, durationMs } = await (0, inference_js_1.runInference)(loadedModel, prompt, 256);
107
+ return { text, routed_type: "inference_fallback", duration_ms: durationMs };
108
+ }
109
+ // No model loaded at all
110
+ const durationMs = Date.now() - start;
111
+ return {
112
+ text: "Unable to process request — no AI model loaded. Please wait for the model to finish downloading.",
113
+ routed_type: "error",
114
+ duration_ms: durationMs,
115
+ };
116
+ }
@@ -0,0 +1,10 @@
1
+ export interface HardwareInfo {
2
+ hostname: string;
3
+ os: string;
4
+ arch: string;
5
+ cpuModel: string;
6
+ ramMb: number;
7
+ gpuModel: string;
8
+ gpuVramMb: number;
9
+ }
10
+ export declare function detectHardware(): Promise<HardwareInfo>;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.detectHardware = detectHardware;
7
+ const systeminformation_1 = __importDefault(require("systeminformation"));
8
+ const os_1 = require("os");
9
+ async function detectHardware() {
10
+ const [cpu, graphics] = await Promise.all([
11
+ systeminformation_1.default.cpu(),
12
+ systeminformation_1.default.graphics(),
13
+ ]);
14
+ // Find the best GPU (prefer discrete over integrated)
15
+ const gpus = graphics.controllers || [];
16
+ const discrete = gpus.find((g) => g.vram && g.vram > 512);
17
+ const bestGpu = discrete || gpus[0];
18
+ return {
19
+ hostname: (0, os_1.hostname)(),
20
+ os: `${(0, os_1.platform)()} ${process.platform === "win32" ? "Windows" : process.platform === "darwin" ? "macOS" : "Linux"}`,
21
+ arch: (0, os_1.arch)(),
22
+ cpuModel: `${cpu.manufacturer} ${cpu.brand}`,
23
+ ramMb: Math.round((0, os_1.totalmem)() / 1024 / 1024),
24
+ gpuModel: bestGpu?.model || "No GPU detected",
25
+ gpuVramMb: bestGpu?.vram || 0,
26
+ };
27
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};