pinokiod 3.337.0 → 3.339.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.
package/kernel/util.js CHANGED
@@ -311,9 +311,40 @@ const port_running = async (host, port) => {
311
311
  const parse_env = async (filename) => {
312
312
  try {
313
313
  const buf = await fs.promises.readFile(filename)
314
- const config = dotenv.parse(buf) // will return an object
314
+ let config = dotenv.parse(buf) // will return an object
315
+ console.warn(`[parse_env] initial parse keys=${config ? Object.keys(config).length : 0} for ${filename}`)
316
+
317
+ // Fallbacks for UTF-16 encodings (common from “Unicode” saves)
318
+ if ((!config || Object.keys(config).length === 0) && buf.length > 0) {
319
+ try {
320
+ const le = dotenv.parse(buf.toString('utf16le'))
321
+ if (le && Object.keys(le).length > 0) {
322
+ console.warn(`[parse_env] UTF-16LE fallback succeeded for ${filename}`)
323
+ config = le
324
+ } else {
325
+ console.warn(`[parse_env] UTF-16LE fallback empty for ${filename}`)
326
+ }
327
+ } catch (e) {
328
+ console.warn(`[parse_env] UTF-16LE fallback failed for ${filename}: ${e.message}`)
329
+ }
330
+ }
331
+ if ((!config || Object.keys(config).length === 0) && buf.length > 0) {
332
+ try {
333
+ const be = dotenv.parse(buf.toString('utf16be'))
334
+ if (be && Object.keys(be).length > 0) {
335
+ console.warn(`[parse_env] UTF-16BE fallback succeeded for ${filename}`)
336
+ config = be
337
+ } else {
338
+ console.warn(`[parse_env] UTF-16BE fallback empty for ${filename}`)
339
+ }
340
+ } catch (e) {
341
+ console.warn(`[parse_env] UTF-16BE fallback failed for ${filename}: ${e.message}`)
342
+ }
343
+ }
344
+
315
345
  return config
316
346
  } catch (e) {
347
+ console.warn(`[parse_env] failed to read/parse ${filename}: ${e.message}`)
317
348
  return {}
318
349
  }
319
350
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinokiod",
3
- "version": "3.337.0",
3
+ "version": "3.339.0",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/server/socket.js CHANGED
@@ -2,6 +2,7 @@ const querystring = require("querystring");
2
2
  const WebSocket = require('ws');
3
3
  const path = require('path')
4
4
  const os = require('os')
5
+ const fs = require('fs')
5
6
  const Util = require("../kernel/util")
6
7
  const Environment = require("../kernel/environment")
7
8
  const NOTIFICATION_CHANNEL = 'kernel.notifications'
@@ -364,12 +365,23 @@ class Socket {
364
365
  }
365
366
  }
366
367
  if (e.data && e.data.raw) {
368
+ const isShell = this.isShellLog(id, meta)
369
+ const isShellRun = meta && meta.method === 'shell.run'
370
+ if (meta.memory) {
371
+ this.appendEventLog(id, meta, e.data.raw)
372
+ } else if (meta.source === 'api' && !isShellRun) {
373
+ this.appendEventLog(id, meta, e.data.raw)
374
+ }
367
375
  if (e.type === "memory") {
368
376
  console.log("[memory event id]", id, "caller", e.caller)
369
377
  }
370
- const tagged = this.tagLines(meta, e.data.raw)
371
- this.rawLog[id] = (this.rawLog[id] || "") + (this.rawLog[id] ? "\n" : "") + tagged
372
- this.log_buffer(id, this.buffer[id], meta)
378
+ if (!isShell) {
379
+ const tagged = this.tagLines(meta, e.data.raw)
380
+ this.rawLog[id] = (this.rawLog[id] || "") + (this.rawLog[id] ? "\n" : "") + tagged
381
+ this.log_buffer(id, this.buffer[id], meta)
382
+ } else {
383
+ delete this.rawLog[id]
384
+ }
373
385
  }
374
386
  //if (e.data && e.data.raw) this.buffer[id] += e.data.raw
375
387
  if (e.data && e.data.buf) this.buffer[id] = e.data.buf
@@ -489,6 +501,64 @@ class Socket {
489
501
  }
490
502
  }
491
503
 
504
+ isShellLog(id, meta) {
505
+ const idStr = (typeof id === 'string') ? id : ''
506
+ if (meta && meta.method === 'shell.run') return true
507
+ if (idStr.startsWith('shell/')) return true
508
+ if (!path.isAbsolute(idStr) && !idStr.startsWith('http')) return true
509
+ return false
510
+ }
511
+
512
+ async resolveLogDir(key) {
513
+ if (path.isAbsolute(key)) {
514
+ let p = key.replace(/\?.*$/, '')
515
+ let relative = path.relative(this.parent.kernel.homedir, p)
516
+ if (relative.startsWith("plugin")) {
517
+ let m = /\?.*$/.exec(key)
518
+ if (m && m.length > 0) {
519
+ let paramStr = m[0]
520
+ let cwd = new URL("http://localhost" + paramStr).searchParams.get("cwd")
521
+ let root = await Environment.get_root({ path: cwd }, this.parent.kernel)
522
+ cwd = root.root
523
+ return path.resolve(cwd, "logs/dev", relative)
524
+ }
525
+ } else if (relative.startsWith("api")) {
526
+ let filepath_chunks = relative.split(path.sep).slice(2)
527
+ let cwd = this.parent.kernel.path(...relative.split(path.sep).slice(0, 2))
528
+ let root = await Environment.get_root({ path: cwd }, this.parent.kernel)
529
+ cwd = root.root
530
+ return path.resolve(cwd, "logs/api", ...filepath_chunks)
531
+ }
532
+ } else {
533
+ if (typeof key === 'string' && key.startsWith("shell/")) {
534
+ let unix_id = key.slice(6)
535
+ let unix_path = unix_id.split("_")[0]
536
+ let native_path = Util.u2p(unix_path)
537
+ let native_path_exists = await new Promise(r=>fs.access(native_path, fs.constants.F_OK, e => r(!e)))
538
+ if (native_path_exists) {
539
+ let cwd = native_path
540
+ let root = await Environment.get_root({ path: cwd }, this.parent.kernel)
541
+ cwd = root.root
542
+ return path.resolve(cwd, "logs/shell")
543
+ }
544
+ }
545
+ }
546
+ return null
547
+ }
548
+
549
+ async appendEventLog(key, meta, text) {
550
+ const dir = await this.resolveLogDir(key)
551
+ if (!dir || !text) return
552
+ try {
553
+ await fs.promises.mkdir(dir, { recursive: true })
554
+ const tag = this.logTag(meta)
555
+ const ts = new Date().toISOString()
556
+ const lines = String(text || '').split(/\r?\n/).map((line) => `${ts} ${tag} ${line}`).join("\n")
557
+ const eventPath = path.resolve(dir, "events")
558
+ await fs.promises.appendFile(eventPath, lines + "\n")
559
+ } catch (_) {}
560
+ }
561
+
492
562
  logTag(meta) {
493
563
  if (meta && meta.memory) {
494
564
  return `[memory]`
@@ -500,7 +570,11 @@ class Socket {
500
570
 
501
571
  tagLines(meta, text) {
502
572
  const tag = this.logTag(meta)
503
- return String(text || '').split(/\r?\n/).map((line) => `${tag} ${line}`).join("\n")
573
+ const message = String(text || '')
574
+ if (!message) {
575
+ return tag
576
+ }
577
+ return `${tag}\n${message}`
504
578
  }
505
579
 
506
580
  extractMeta(e) {
@@ -610,9 +684,7 @@ class Socket {
610
684
  cwd = root.root
611
685
  let session = this.sessions[key]
612
686
  let logpath = path.resolve(cwd, "logs/shell")
613
- const raw = this.rawLog[key] || ""
614
- const tagged = buf ? this.tagLines(resolvedMeta, buf) : ""
615
- const content = [raw, tagged].filter(Boolean).join("\n")
687
+ const content = buf || ""
616
688
  await Util.log(logpath, content, session)
617
689
  }
618
690
  }
@@ -4640,7 +4640,29 @@ const rerenderMenuSection = (container, html) => {
4640
4640
  // loaded[target.target] = true
4641
4641
  // }
4642
4642
  }
4643
- renderSelection()
4643
+
4644
+
4645
+ // Need to strip the plugin= query param when redirected from "ask ai", otherwise it will keep selecting the specified plugin even after closing
4646
+ let pluginQueryStripped = false
4647
+ const stripPluginQueryOnce = () => {
4648
+ if (pluginQueryStripped) return
4649
+ const url = new URL(window.location.href)
4650
+ if (!/\/dev(?:$|\/)/.test(url.pathname)) return
4651
+ if (!url.searchParams.has("plugin")) return
4652
+ url.searchParams.delete("plugin")
4653
+ const qs = url.searchParams.toString()
4654
+ const newUrl = `${url.origin}${url.pathname}${qs ? "?" + qs : ""}${url.hash}`
4655
+ if (window.location.href !== newUrl) {
4656
+ history.replaceState({}, "", newUrl)
4657
+ }
4658
+ const dynBase = "<%-dynamic%>".split("?")[0]
4659
+ const updatedDynamic = qs ? `${dynBase}?${qs}` : dynBase
4660
+ window.__pinokioDynamicUrl = updatedDynamic
4661
+ pluginQueryStripped = true
4662
+ }
4663
+ renderSelection().then(() => {
4664
+ stripPluginQueryOnce()
4665
+ })
4644
4666
  //renderCursor()
4645
4667
  //Reporter()
4646
4668
  <% if (agent === "electron") { %>
@@ -5457,7 +5479,8 @@ const rerenderMenuSection = (container, html) => {
5457
5479
  const try_dynamic = async () => {
5458
5480
  let rendered
5459
5481
  let status
5460
- const dynamic = await fetch("<%-dynamic%>").then((res) => {
5482
+ const dynamicUrl = window.__pinokioDynamicUrl || "<%-dynamic%>"
5483
+ const dynamic = await fetch(dynamicUrl).then((res) => {
5461
5484
  status = res.status
5462
5485
  return res.text()
5463
5486
  })