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 +32 -1
- package/package.json +1 -1
- package/server/socket.js +79 -7
- package/server/views/app.ejs +25 -2
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
|
-
|
|
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
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
|
-
|
|
371
|
-
|
|
372
|
-
|
|
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
|
-
|
|
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
|
|
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
|
}
|
package/server/views/app.ejs
CHANGED
|
@@ -4640,7 +4640,29 @@ const rerenderMenuSection = (container, html) => {
|
|
|
4640
4640
|
// loaded[target.target] = true
|
|
4641
4641
|
// }
|
|
4642
4642
|
}
|
|
4643
|
-
|
|
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
|
|
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
|
})
|