totem-llm 0.5.1 → 0.7.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.
@@ -71,6 +71,10 @@
71
71
  "transcription": {
72
72
  "label": "Audio Transcription",
73
73
  "tier": "L2"
74
+ },
75
+ "appIntegrations": {
76
+ "label": "3rd Party App Integrations",
77
+ "tier": "L2"
74
78
  }
75
79
  },
76
80
  "PROFILES": {
@@ -92,7 +96,8 @@
92
96
  "vectorDB": false,
93
97
  "embedder": false,
94
98
  "textSplitter": false,
95
- "transcription": false
99
+ "transcription": false,
100
+ "appIntegrations": false
96
101
  },
97
102
  "L1": {
98
103
  "communityHub": false,
@@ -112,7 +117,8 @@
112
117
  "vectorDB": false,
113
118
  "embedder": false,
114
119
  "textSplitter": false,
115
- "transcription": false
120
+ "transcription": false,
121
+ "appIntegrations": false
116
122
  },
117
123
  "L2": {
118
124
  "communityHub": false,
@@ -132,7 +138,8 @@
132
138
  "vectorDB": false,
133
139
  "embedder": false,
134
140
  "textSplitter": false,
135
- "transcription": false
141
+ "transcription": false,
142
+ "appIntegrations": false
136
143
  },
137
144
  "source": {
138
145
  "communityHub": true,
@@ -152,7 +159,8 @@
152
159
  "vectorDB": false,
153
160
  "embedder": false,
154
161
  "textSplitter": false,
155
- "transcription": false
162
+ "transcription": false,
163
+ "appIntegrations": false
156
164
  }
157
165
  }
158
166
  }
package/lib/launcher.js CHANGED
@@ -16,6 +16,9 @@ import {
16
16
  error,
17
17
  divider,
18
18
  } from "./formatter.js";
19
+ import os from "os";
20
+ import qrcode from "qrcode-terminal"
21
+
19
22
 
20
23
  /**
21
24
  * Create a simple progress bar for terminal output.
@@ -68,6 +71,23 @@ function spawnService(nodeExe, cwd, env, label, logFile) {
68
71
  return child;
69
72
  }
70
73
 
74
+ /**
75
+ * Get the local network IPv4 address.
76
+ * @returns {string|null} Local IP address or null if not found
77
+ */
78
+ function getLocalIP() {
79
+ const interfaces = os.networkInterfaces();
80
+ for (const name of Object.keys(interfaces)) {
81
+ for (const iface of interfaces[name]) {
82
+ // Skip internal (loopback) and non-IPv4 addresses
83
+ if (iface.family === "IPv4" && !iface.internal) {
84
+ return iface.address;
85
+ }
86
+ }
87
+ }
88
+ return null;
89
+ }
90
+
71
91
  /**
72
92
  * Launch the server (and optionally the collector), wire up graceful shutdown,
73
93
  * and keep the process alive until the user presses Ctrl+C.
@@ -125,14 +145,38 @@ export async function launch({ packageRoot, noCollector = false, port } = {}) {
125
145
  }
126
146
  }, 300);
127
147
 
148
+ // Display UI access information
149
+ process.stdout.write(
150
+ highlightBox(
151
+ `Open UI in browser:\n${urlStyle(`http://localhost:${serverPort}/`)}`,
152
+ "brightGreen"
153
+ )
154
+ );
155
+
156
+ // Get local network details
157
+ const localIP = getLocalIP();
158
+ const networkUrl = localIP ? `http://${localIP}:${serverPort}/` : null;
159
+ const localUrlLine = networkUrl ? `\nNetwork: ${urlStyle(networkUrl)}` : "";
160
+
161
+ // Generate QR code for mobile devices if network URL is available
162
+ let qrCodeBox = "";
163
+ if (networkUrl) {
164
+ qrcode.generate(networkUrl, { small: true }, (qrcodeStr) => {
165
+ // Add a small header and spacing around the generated QR code string
166
+ qrCodeBox = `\n\n${info("Scan to open on mobile:")}\n${qrcodeStr}`;
167
+ });
168
+ }
169
+
128
170
  // Display UI access information
129
171
  process.stdout.write(
130
172
  highlightBox(
131
- `Open UI in browser:\n${urlStyle(`http://localhost:${serverPort}/`)}`,
173
+ `Open UI in browser:\nLocal: ${urlStyle(`http://localhost:${serverPort}/`)}${localUrlLine}${qrCodeBox}`,
132
174
  "brightGreen"
133
175
  )
134
176
  );
135
177
 
178
+
179
+
136
180
  // Display logs information
137
181
  process.stdout.write(
138
182
  section("Configuration", [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "totem-llm",
3
- "version": "0.5.1",
3
+ "version": "0.7.0",
4
4
  "description": "Totem LLM – Your Private AI. Run a self-hosted AI assistant locally on Linux, macOS, or Windows.",
5
5
  "main": "bin/totem-llm.js",
6
6
  "type": "module",
@@ -63,5 +63,8 @@
63
63
  "devDependencies": {
64
64
  "concurrently": "^9.1.2",
65
65
  "jest": "^29.7.0"
66
+ },
67
+ "dependencies": {
68
+ "qrcode-terminal": "^0.12.0"
66
69
  }
67
70
  }
package/server/.env CHANGED
@@ -63,9 +63,9 @@ OLLAMA_RESPONSE_TIMEOUT=72000000 # Optional response timeout in ms for Ollama AP
63
63
  # DEEPSEEK_API_KEY=YOUR_API_KEY
64
64
  # DEEPSEEK_MODEL_PREF='deepseek-chat'
65
65
 
66
- # LLM_PROVIDER='openrouter'
67
- # OPENROUTER_API_KEY='my-openrouter-key'
68
- # OPENROUTER_MODEL_PREF='openrouter/auto'
66
+ LLM_PROVIDER='openrouter'
67
+ OPENROUTER_API_KEY='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'
68
+ OPENROUTER_MODEL_PREF='openrouter/auto'
69
69
 
70
70
  # LLM_PROVIDER='mistral'
71
71
  # MISTRAL_API_KEY='example-mistral-ai-api-key'
@@ -1 +1 @@
1
- import{d as c,j as s,e as d,f as g,i as f,l as S,r as a,W as i,L as x}from"../index.js";import{W as h}from"./index-e8c55d16.js";import{a as w}from"./index-ed14fe75.js";import"./files-40998f84.js";import"./purify-17c89583.js";/* empty css */import"./Check-7e83fb0d.js";import"./Copy-d323e545.js";import"./truncate-dd7b0c29.js";import"./mcpServers-9495fe60.js";import"./admin-04b020fe.js";import"./Database-f1a76329.js";import"./File-b92df2f3.js";import"./XCircle-edfe554c.js";import"./Trans-308f36d6.js";import"./Brain-24e386d5.js";import"./Browser-1820fad0.js";import"./index-14be6ea8.js";import"./agentFlows-e4124dd3.js";import"./index-36acf56a.js";import"./communityHub-aba61686.js";import"./WarningCircle-27467274.js";import"./index-8ba96f42.js";import"./Hammer-05b5ccc7.js";import"./react-beautiful-dnd.esm-149a7a55.js";import"./moment-49fc1b76.js";import"./Eye-9f033dc0.js";import"./index-4fb4d421.js";function Q(){const{loading:t,requiresAuth:r,mode:e}=c();return t?s.jsx(d,{}):r!==!1?s.jsx(s.Fragment,{children:r!==null&&s.jsx(g,{mode:e})}):s.jsxs("div",{className:"w-screen h-screen overflow-hidden bg-zinc-950 light:bg-slate-50 flex",children:[!f&&s.jsx(w,{}),s.jsx(j,{})]})}function j(){const{slug:t}=S(),[r,e]=a.useState(null),[n,m]=a.useState(null);return a.useEffect(()=>{async function p(){if(!t)return;const o=await i.bySlug(t);if(!o){e(null),m(t);return}const[l,{showAgentCommand:u}]=await Promise.all([i.getSuggestedMessages(t),i.agentCommandAvailable(t)]);e({...o,suggestedMessages:l,showAgentCommand:u}),m(t),localStorage.setItem(x,JSON.stringify({slug:o.slug,name:o.name}))}p()},[t]),s.jsx(h,{loading:n!==t,workspace:r})}export{Q as default};
1
+ import{d as c,j as s,e as d,f as g,i as f,l as S,r as a,W as i,L as x}from"../index.js";import{W as h}from"./index-4327f7b5.js";import{a as w}from"./index-ed14fe75.js";import"./files-40998f84.js";import"./purify-17c89583.js";/* empty css */import"./Check-7e83fb0d.js";import"./Copy-d323e545.js";import"./truncate-dd7b0c29.js";import"./mcpServers-9495fe60.js";import"./admin-04b020fe.js";import"./Database-f1a76329.js";import"./File-b92df2f3.js";import"./XCircle-edfe554c.js";import"./Trans-308f36d6.js";import"./Brain-24e386d5.js";import"./Browser-1820fad0.js";import"./index-5dd1b6d2.js";import"./agentFlows-e4124dd3.js";import"./index-36acf56a.js";import"./communityHub-aba61686.js";import"./WarningCircle-27467274.js";import"./index-8ba96f42.js";import"./Hammer-05b5ccc7.js";import"./react-beautiful-dnd.esm-149a7a55.js";import"./moment-49fc1b76.js";import"./Eye-9f033dc0.js";import"./index-4fb4d421.js";function Q(){const{loading:t,requiresAuth:r,mode:e}=c();return t?s.jsx(d,{}):r!==!1?s.jsx(s.Fragment,{children:r!==null&&s.jsx(g,{mode:e})}):s.jsxs("div",{className:"w-screen h-screen overflow-hidden bg-zinc-950 light:bg-slate-50 flex",children:[!f&&s.jsx(w,{}),s.jsx(j,{})]})}function j(){const{slug:t}=S(),[r,e]=a.useState(null),[n,m]=a.useState(null);return a.useEffect(()=>{async function p(){if(!t)return;const o=await i.bySlug(t);if(!o){e(null),m(t);return}const[l,{showAgentCommand:u}]=await Promise.all([i.getSuggestedMessages(t),i.agentCommandAvailable(t)]);e({...o,suggestedMessages:l,showAgentCommand:u}),m(t),localStorage.setItem(x,JSON.stringify({slug:o.slug,name:o.name}))}p()},[t]),s.jsx(h,{loading:n!==t,workspace:r})}export{Q as default};