pinokiod 3.8.68 → 3.8.69

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.
@@ -186,7 +186,7 @@ class Api {
186
186
  type: "disconnect"
187
187
  })
188
188
  console.timeEnd("stop 4")
189
- await this.kernel.router.refresh()
189
+ this.kernel.refresh()
190
190
  return true
191
191
  }
192
192
  async startScripts() {
@@ -1074,7 +1074,7 @@ class Api {
1074
1074
  })
1075
1075
  }
1076
1076
  }
1077
- await this.kernel.router.refresh()
1077
+ this.kernel.refresh()
1078
1078
  } catch (e) {
1079
1079
  ondata({ raw: e.toString() })
1080
1080
  }
@@ -44,7 +44,7 @@ class Caddy {
44
44
  }
45
45
  })
46
46
  })
47
- await this.kernel.router.refresh()
47
+ this.kernel.refresh()
48
48
  }
49
49
  // const config = {
50
50
  // "apps": {
@@ -347,12 +347,9 @@ class Bin {
347
347
  // process.stdout.write(stream.raw)
348
348
  // console.log("conda list check", { stream })
349
349
  })
350
- console.log("> res", res)
351
350
 
352
351
  let lines = res.response.split(/[\r\n]+/)
353
- console.log("> lines", lines)
354
352
  for(let line of lines) {
355
- console.log("> start", start)
356
353
  if (start) {
357
354
  let chunks = line.split(/\s+/).filter(x => x)
358
355
  if (chunks.length > 2) {
package/kernel/index.js CHANGED
@@ -258,6 +258,22 @@ class Kernel {
258
258
  log(data, group, info) {
259
259
  this.log_queue.push({ data, group, info })
260
260
  }
261
+ async refresh(broadcast) {
262
+ console.log("kernel.refresh", { broadcast })
263
+ await Promise.all([
264
+ // refresh proc info
265
+ this.processes.refresh(),
266
+ // refresh peer info
267
+ this.peer.refresh()
268
+ ])
269
+ // refresh router info
270
+ await this.router.refresh()
271
+
272
+ if (broadcast) {
273
+ // broadcast to peers
274
+ await this.peer.broadcast()
275
+ }
276
+ }
261
277
  async clearLog(group) {
262
278
  let relativePath = path.relative(this.homedir, group)
263
279
  for(let type of ["info", "buf", "cleaned"]) {
package/kernel/peer.js CHANGED
@@ -45,6 +45,24 @@ class PeerDiscovery {
45
45
  return null
46
46
  }
47
47
  }
48
+ async _broadcast(host) {
49
+ try {
50
+ let res = await axios.post(`http://${host}:${this.default_port}/pinokio/peer/refresh`, {
51
+ timeout: 2000
52
+ })
53
+ return res.data
54
+ } catch (e) {
55
+ return null
56
+ }
57
+ }
58
+ // notify peers to refresh my info
59
+ async braodcast() {
60
+ let res = await Promise.all(Array.from(this.peers).map((host) => {
61
+ return this._broadcast(host)
62
+ }))
63
+ return res
64
+ }
65
+ // refresh peer info
48
66
  async refresh() {
49
67
  this.info = {}
50
68
  let peer_info = await Promise.all(Array.from(this.peers).map((host) => {
package/kernel/procs.js CHANGED
@@ -23,8 +23,6 @@ class Procs {
23
23
  if (!line.startsWith(' TCP')) return;
24
24
  const parts = line.trim().split(/\s+/);
25
25
  const [ , localAddress, , state, pid ] = parts;
26
- if (pids.has(pid)) return;
27
- pids.add(pid)
28
26
  if (state !== 'LISTENING') return;
29
27
  const chunks = localAddress.split(":")
30
28
  const port = chunks.pop()
@@ -34,13 +32,13 @@ class Procs {
34
32
  } else {
35
33
  ip = localAddress
36
34
  }
35
+ if (pids.has(pid+"/"+port)) return;
36
+ pids.add(pid+"/"+port)
37
37
  results.push({ port, pid, ip });
38
38
  } else {
39
39
  if (!/LISTEN/.test(line)) return;
40
40
  const parts = line.trim().split(/\s+/);
41
41
  const pid = parts[1];
42
- if (pids.has(pid)) return;
43
- pids.add(pid)
44
42
 
45
43
  const match = line.match(/([^\s]+:\d+)\s/);
46
44
  const localAddress = match?.[1];
@@ -54,6 +52,8 @@ class Procs {
54
52
  }
55
53
  //const portMatch = line.match(/:(\d+)\s/);
56
54
  //const port = portMatch?.[1];
55
+ if (pids.has(pid+"/"+port)) return;
56
+ pids.add(pid+"/"+port)
57
57
  if (pid && port) results.push({ port, pid, ip });
58
58
  }
59
59
  });
@@ -100,14 +100,16 @@ class Procs {
100
100
  const name = fullname.split(path.sep).pop()
101
101
  return { port, pid , name, fullname, ip }
102
102
  })
103
+ list = list.filter((item) => {
104
+ return item.name.toLowerCase() !== "caddy"
105
+ })
103
106
  resolve(list)
104
107
  });
105
108
  });
106
109
  })
107
110
  console.log( { list } )
108
111
  console.timeEnd("Get list")
109
- this.list = list
110
- return this.list
112
+ this.info = list
111
113
  }
112
114
  }
113
115
  module.exports = Procs
@@ -24,7 +24,7 @@ class Router {
24
24
  this.default_port = "42000"
25
25
  this.default_host = "127.0.0.1"
26
26
 
27
- this._mapping = {}
27
+ this.mapping = {}
28
28
  this.port_mapping = {} // 127.0.0.1 => 192.168,..
29
29
  this.local_network_mapping = {}
30
30
  }
@@ -39,12 +39,12 @@ class Router {
39
39
  console.log(">this._mapping", this._mapping)
40
40
  }
41
41
  info() {
42
- console.log("#### this._mapping", this._mapping)
42
+ console.log("#### this.mapping", this.mapping)
43
43
 
44
44
 
45
45
  let mapping = {}
46
- for(let host in this._mapping) {
47
- let internal_maps = this._mapping[host]
46
+ for(let host in this.mapping) {
47
+ let internal_maps = this.mapping[host]
48
48
  if (!mapping[host]) {
49
49
  mapping[host] = {}
50
50
  }
@@ -115,6 +115,8 @@ class Router {
115
115
  */
116
116
 
117
117
  console.log("count", count)
118
+
119
+ let new_config
118
120
 
119
121
  if (count > 0) {
120
122
  let ports = await this.kernel.ports(count)
@@ -148,23 +150,27 @@ class Router {
148
150
  }
149
151
 
150
152
  async refresh() {
151
- // this._mapping = {}
153
+ console.log("router.refresh")
154
+ console.time("router.refresh")
155
+ console.log("> procs", this.kernel.processes.info)
156
+ console.log("> peers", this.kernel.peer.info)
157
+ this._mapping = {}
152
158
  // this.port_mapping = {} // 127.0.0.1 => 192.168,..
153
159
  // this.local_network_mapping = {}
154
160
 
161
+ let old_config = this.config
162
+
155
163
  // 1. Localhost handling
156
164
  this.localhost_home_router.handle()
157
165
  this.localhost_variable_router.handle(this.kernel.memory.local)
158
- let procs = await this.kernel.processes.refresh()
159
- for(let proc of procs) {
166
+ for(let proc of this.kernel.processes.info) {
160
167
  this.localhost_port_router.handle(proc)
161
168
  }
169
+ this.mapping = this._mapping
162
170
 
163
171
  // 2. Peers handling
164
- let peers = await this.kernel.peer.refresh()
165
- console.log(">3", { peers })
166
- for(let host in peers) {
167
- let peer = peers[host]
172
+ for(let host in this.kernel.peer.info) {
173
+ let peer = this.kernel.peer.info[host]
168
174
  if (peer.host === this.kernel.peer.host) {
169
175
  this.peer_home_router.handle(peer)
170
176
  this.peer_variable_router.handle(peer)
@@ -174,19 +180,28 @@ class Router {
174
180
  }
175
181
  }
176
182
  // replace :PORT_PLACEHOLDER with available ports
177
- console.log("CONFIG BEFORE", JSON.stringify(this.config, null, 2))
178
183
 
179
- await this.fill()
180
184
 
181
- console.log("CONFIG AFTER", JSON.stringify(this.config, null, 2))
182
-
183
-
184
- let response = await axios.post('http://127.0.0.1:2019/load', this.config, {
185
- headers: { 'Content-Type': 'application/json' }
186
- }).catch((e) => {
187
- console.log("EEEEEEEEEEEEE", e)
188
- })
189
- console.log("Caddy Response", { response })
185
+ await this.fill()
186
+ this.mapping = this._mapping
187
+ console.timeEnd("router.refresh")
188
+
189
+
190
+ // compare old config with new config
191
+ // if it hasn't changed, don't do anything
192
+ // if it has changed, refresh
193
+
194
+ if (JSON.stringify(this.config) === JSON.stringify(old_config)) {
195
+ console.log("config hasn't updated")
196
+ } else {
197
+ console.log("config has updated")
198
+ let response = await axios.post('http://127.0.0.1:2019/load', this.config, {
199
+ headers: { 'Content-Type': 'application/json' }
200
+ }).catch((e) => {
201
+ console.log("EEEEEEEEEEEEE", e)
202
+ })
203
+ console.log("Caddy Response", { response })
204
+ }
190
205
  }
191
206
  }
192
207
  module.exports = Router
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinokiod",
3
- "version": "3.8.68",
3
+ "version": "3.8.69",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/server/index.js CHANGED
@@ -2621,22 +2621,76 @@ class Server {
2621
2621
  id: req.params.id
2622
2622
  })
2623
2623
  }))
2624
- this.app.get("/proxy", ex(async (req, res) => {
2625
- await this.kernel.router.refresh()
2626
- let list = await this.kernel.processes.refresh()
2627
- list = list.map((item) => {
2628
- let internal_port = item.ip.split(":")[1]
2629
- let external_port = this.kernel.router.port_mapping[internal_port]
2630
- let external_ip = `${this.kernel.peer.host}:${external_port}`
2631
- console.log({ internal_port, external_port, external_ip })
2632
- return {
2633
- //proxy: this.kernel.caddy.mapping[item.ip] || [],
2634
- router: this.kernel.router.published()[external_ip] || [],
2635
- ...item
2624
+ this.app.get("/network", ex(async (req, res) => {
2625
+ let list = []
2626
+ let peers_info = await this.kernel.peer.refresh()
2627
+ console.log({ peers_info })
2628
+ let info = this.kernel.router.info()
2629
+ console.log("33 info", info)
2630
+ let remote_peers = Object.keys(this.kernel.peer.info).filter(x => x !== this.kernel.peer.host)
2631
+ let nodes = [this.kernel.peer.host].concat(remote_peers)
2632
+ for(let host of nodes) {
2633
+ let processes = []
2634
+ try {
2635
+ let procs = this.kernel.peer.info[host].proc
2636
+ let router = this.kernel.peer.info[host].router
2637
+ let port_mapping = this.kernel.peer.info[host].port_mapping
2638
+ console.log("&&", { procs })
2639
+ for(let proc of procs) {
2640
+ let internal_port = proc.ip.split(":")[1]
2641
+ let external_port = port_mapping[internal_port]
2642
+ if (external_port) {
2643
+ let external_ip = `${host}:${external_port}`
2644
+ console.log({ internal_port, external_port, external_ip })
2645
+ processes.push({
2646
+ //proxy: this.kernel.caddy.mapping[item.ip] || [],
2647
+ router: router[external_ip] || [],
2648
+ external_ip,
2649
+ ...proc
2650
+ })
2651
+ } else {
2652
+ processes.push({
2653
+ router: [],
2654
+ ...proc
2655
+ })
2656
+ }
2657
+ }
2658
+ } catch (e) {
2659
+ console.log(">>e", e)
2636
2660
  }
2637
- })
2661
+ list.push({
2662
+ host,
2663
+ name: this.kernel.peer.info[host].name,
2664
+ platform: this.kernel.peer.info[host].platform,
2665
+ processes
2666
+ })
2667
+ }
2668
+
2669
+ // if (this.kernel.processes.info) {
2670
+ // console.log("proc info", this.kernel.processes.info)
2671
+ // list = this.kernel.processes.info.map((item) => {
2672
+ // console.log("item", item)
2673
+ // console.log("item.ip", item.ip)
2674
+ // let internal_port = item.ip.split(":")[1]
2675
+ // let external_port = this.kernel.router.port_mapping[internal_port]
2676
+ // if (external_port) {
2677
+ // let external_ip = `${this.kernel.peer.host}:${external_port}`
2678
+ // console.log({ internal_port, external_port, external_ip })
2679
+ // return {
2680
+ // //proxy: this.kernel.caddy.mapping[item.ip] || [],
2681
+ // router: info[this.kernel.peer.host][external_ip] || [],
2682
+ // external_ip,
2683
+ // ...item
2684
+ // }
2685
+ // } else {
2686
+ // return {
2687
+ // router: [],
2688
+ // ...item
2689
+ // }
2690
+ // }
2691
+ // })
2692
+ // }
2638
2693
 
2639
- let peers_info = await this.kernel.peer.refresh()
2640
2694
  let peers = []
2641
2695
  for(let host in peers_info) {
2642
2696
  let peer_info = peers_info[host]
@@ -2728,12 +2782,13 @@ class Server {
2728
2782
  }
2729
2783
  }
2730
2784
 
2731
- console.log("LIST", JSON.stringify(list, null, 2))
2785
+ console.log("network", JSON.stringify(list, null, 2))
2732
2786
 
2733
- res.render("proxy", {
2787
+ res.render("network", {
2734
2788
  ip: this.kernel.peer.current_ip,
2735
2789
  peers,
2736
2790
  list,
2791
+ port_mapping: this.kernel.router.port_mapping,
2737
2792
  // port_mapping: this.kernel.caddy.port_mapping,
2738
2793
  // ip_mapping: this.kernel.caddy.ip_mapping,
2739
2794
  lan: this.kernel.router.local_network_mapping,
@@ -3263,14 +3318,22 @@ class Server {
3263
3318
  */
3264
3319
 
3265
3320
  }))
3321
+ this.app.post("/pinokio/peer/refresh", ex(async (req, res) => {
3322
+ // refresh and broadcast
3323
+ await this.kernel.refresh(true)
3324
+ res.json({ success: true })
3325
+ }))
3266
3326
  this.app.get("/pinokio/peer", ex((req, res) => {
3327
+ console.log("/pinokio/peer", { proc: this.kernel.processes.info })
3267
3328
  res.json({
3268
3329
  home: this.kernel.homedir,
3269
3330
  arch: this.kernel.arch,
3270
3331
  platform: this.kernel.platform,
3271
3332
  name: this.kernel.peer.name,
3272
3333
  host: this.kernel.peer.host,
3334
+ port_mapping: this.kernel.router.port_mapping,
3273
3335
  //router: this.kernel.router.info(),
3336
+ proc: this.kernel.processes.info,
3274
3337
  router: this.kernel.router.published(),
3275
3338
  memory: this.kernel.memory
3276
3339
  })
@@ -3862,6 +3925,8 @@ class Server {
3862
3925
  this.kernel.shell.reset(() => {
3863
3926
  process.exit()
3864
3927
  })
3928
+ } else {
3929
+ process.exit()
3865
3930
  }
3866
3931
  })
3867
3932
  process.on('SIGTERM', () => {
@@ -3870,6 +3935,8 @@ class Server {
3870
3935
  this.kernel.shell.reset(() => {
3871
3936
  process.exit()
3872
3937
  })
3938
+ } else {
3939
+ process.exit()
3873
3940
  }
3874
3941
  })
3875
3942
  // process.on('exit', () => {
@@ -235,7 +235,7 @@ body.dark .browser-options-row {
235
235
  </div>
236
236
  <% } %>
237
237
  <div class='browser-options-row'>
238
- <a href="/proxy" class='btn'><div><i class="fa-solid fa-gauge"></i> Configure</div></a>
238
+ <a href="/network" class='btn'><div><i class="fa-solid fa-gauge"></i> Configure</div></a>
239
239
  <div class='flexible'>
240
240
  <h3><i class="fa-solid fa-wifi"></i> Local Sharing</h3>
241
241
  <div>Serve Pinokio, installed apps, and even external apps (example: Ollama) to any device on the same network.</div>
@@ -228,7 +228,7 @@ body.dark .browser-options-row {
228
228
  <!--
229
229
  <a class='btn2' id='explore'><div><i class="fa-solid fa-globe"></i></div><div>Discover</div></a>
230
230
  -->
231
- <a href="/proxy" class='btn2'><div><i class="fa-solid fa-wifi"></i></div><div>Wifi Sharing</div></a>
231
+ <a href="/network" class='btn2'><div><i class="fa-solid fa-wifi"></i></div><div>Wifi Sharing</div></a>
232
232
  <a class='btn2' href="https://portal.pinokio.computer/" target="_blank"><div><i class="fa-solid fa-question"></i></div><div>Help</div></a>
233
233
  <% if (agent === "electron") { %>
234
234
  <a class='btn2' data-filepath="<%=filepath%>"><div><i class="fa-regular fa-folder-open"></i></div><div>Files</div></a>
@@ -288,7 +288,7 @@ body.dark .browser-options-row {
288
288
  </div>
289
289
  <% } %>
290
290
  <div class='browser-options-row'>
291
- <a href="/proxy" class='btn'><div><i class="fa-solid fa-gauge"></i> Configure</div></a>
291
+ <a href="/network" class='btn'><div><i class="fa-solid fa-gauge"></i> Configure</div></a>
292
292
  <div class='flexible'>
293
293
  <h3><i class="fa-solid fa-wifi"></i> Local Sharing</h3>
294
294
  <div>Serve Pinokio, installed apps, and even external apps (example: Ollama) to any device on the same network.</div>
@@ -173,7 +173,7 @@ body.dark .browser-options-row {
173
173
  }
174
174
  .container {
175
175
  display: grid;
176
- grid-template-columns: repeat(2, 1fr);
176
+ grid-template-columns: repeat(<%=list.length%>, 1fr);
177
177
  }
178
178
  .dark .container-row {
179
179
  background: rgba(255, 255, 255, 0.04);
@@ -209,7 +209,7 @@ td:first-child, th:first-child {
209
209
  }
210
210
  .container-row td {
211
211
  font-size: 14px;
212
- padding: 5px;
212
+ padding: 2px;
213
213
  }
214
214
  @media only screen and (max-width: 480px) {
215
215
  .btn2 {
@@ -244,6 +244,7 @@ td:first-child, th:first-child {
244
244
  <main>
245
245
  <div class='header-label'><i class='fa-solid fa-wifi'></i> Networking</div>
246
246
  <div class='desc'>Serve Pinokio, installed apps, and even external apps to any device on the same network.</div>
247
+ <!--
247
248
  <div class='header-container'>
248
249
  <div class='header-label-sub'><i class="fa-solid fa-podcast"></i> Local Network</div>
249
250
  <% peers.forEach((item) => { %>
@@ -252,39 +253,45 @@ td:first-child, th:first-child {
252
253
  </a>
253
254
  <% }) %>
254
255
  </div>
256
+ -->
255
257
  <div class='container'>
256
- <div class='container-row'>
257
- <div class='header-label-sub'><i class="fa-solid fa-microchip"></i> System</div>
258
- <table>
259
- <tr>
260
- <th>Server</th>
261
- <th>https</th>
262
- <th>http</th>
263
- </tr>
264
- <% list.forEach((item) => { %>
265
- <tr>
266
- <td class='title'><%=item.name%></td>
267
- <td>
268
- <% item.router.forEach((domain) => { %>
269
- <div>
270
- <a target="_blank" href="https://<%=domain%>">https://<%=domain%></a>
271
- </div>
272
- <% }) %>
273
- </td>
274
- <td>
275
- <div>
276
- <a target="_blank" href="http://localhost:<%=item.port%>">http://localhost:<%=item.port%></a>
277
- </div>
278
- <% if (lan[ip]) { %>
258
+ <% list.forEach(({ host, name, platform, processes }) => { %>
259
+ <div class='container-row'>
260
+ <!--
261
+ <div class='header-label-sub'><i class="fa-solid fa-microchip"></i> System</div>
262
+ -->
263
+ <div class='header-label-sub'><%=name%> (<%=platform%>, <%=host%>)</div>
264
+ <table>
265
+ <tr>
266
+ <th>Server</th>
267
+ <th>https</th>
268
+ <th>http</th>
269
+ </tr>
270
+ <% processes.forEach((item) => { %>
271
+ <tr>
272
+ <td class='title'><%=item.name%></td>
273
+ <td>
274
+ <% item.router.forEach((domain) => { %>
275
+ <div>
276
+ <a target="_blank" href="https://<%=domain%>">https://<%=domain%></a>
277
+ </div>
278
+ <% }) %>
279
+ </td>
280
+ <td>
279
281
  <div>
280
- <a target="_blank" href="http://<%=ip%>:<%=lan[ip][item.port]%>">http://<%=ip%>:<%=lan[ip][item.port]%></a>
282
+ <a target="_blank" href="http://localhost:<%=item.port%>">http://localhost:<%=item.port%></a>
281
283
  </div>
282
- <% } %>
283
- </td>
284
- </tr>
285
- <% }) %>
286
- </table>
287
- </div>
284
+ <% if (item.external_ip) { %>
285
+ <div>
286
+ <a target="_blank" href="http://<%=item.external_ip%>">http://<%=item.external_ip%></a>
287
+ </div>
288
+ <% } %>
289
+ </td>
290
+ </tr>
291
+ <% }) %>
292
+ </table>
293
+ </div>
294
+ <% }) %>
288
295
  <div class='container-row hidden'>
289
296
  <div class='header-label-sub'><i class="fa-solid fa-microchip"></i> System Programs</div>
290
297
  <div class='line align-top'>
@@ -333,6 +340,7 @@ td:first-child, th:first-child {
333
340
  </div>
334
341
  <% }) %>
335
342
  </div>
343
+ <!--
336
344
  <div class='container-row'>
337
345
  <div class='header-label-sub'><i class="fa-solid fa-dice-d6"></i> Pinokio</div>
338
346
  <% apps.forEach((item) => { %>
@@ -358,6 +366,7 @@ td:first-child, th:first-child {
358
366
  </a>
359
367
  <% }) %>
360
368
  </div>
369
+ -->
361
370
  </div>
362
371
  </main>
363
372
  <script>
@@ -196,7 +196,7 @@ body.dark .browser-options-row {
196
196
  <input type='search' class="flexible" placeholder='Filter downloaded apps'>
197
197
  </form>
198
198
  <div class='nav-btns'>
199
- <a href="/proxy" class='btn2'><div><i class="fa-solid fa-wifi"></i></div><div>Wifi Sharing</div></a>
199
+ <a href="/network" class='btn2'><div><i class="fa-solid fa-wifi"></i></div><div>Wifi Sharing</div></a>
200
200
  <a class='btn2' href="https://portal.pinokio.computer/" target="_blank"><div><i class="fa-solid fa-question"></i></div><div>Help</div></a>
201
201
  <button class='btn2' id='genlog'><div><i class="fa-solid fa-laptop-code"></i></div><div>Debug</div></button>
202
202
  <a id='downloadlogs' download class='hidden btn2' href="/pinokio/logs.zip"><div><i class="fa-solid fa-download"></i></div><div>Download logs</div></a>