pinokiod 8.0.40 → 8.0.41
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/api/index.js +12 -3
- package/kernel/index.js +24 -0
- package/kernel/shell.js +2 -1
- package/kernel/vault/constants.js +13 -0
- package/kernel/vault/hash_worker.js +31 -0
- package/kernel/vault/index.js +2360 -0
- package/kernel/vault/registry.js +643 -0
- package/kernel/vault/snapshot.js +29 -0
- package/kernel/vault/sweeper.js +740 -0
- package/kernel/vault/walker.js +142 -0
- package/package.json +1 -1
- package/server/index.js +109 -0
- package/server/lib/privacy_filter_cache.js +4 -1
- package/server/public/storage-size.js +12 -0
- package/server/public/style.css +13 -0
- package/server/public/tab-link-popover.js +3 -0
- package/server/public/vault-nav.js +96 -0
- package/server/public/vault.css +1079 -0
- package/server/public/vault.js +1835 -0
- package/server/views/app.ejs +93 -16
- package/server/views/partials/main_sidebar.ejs +6 -0
- package/server/views/partials/vault_workspace.ejs +55 -0
- package/server/views/vault.ejs +29 -0
- package/server/views/vault_app.ejs +22 -0
- package/test/plugin-action-functions.test.js +19 -0
- package/test/privacy-filter-cache.test.js +1 -0
- package/test/vault-engine.test.js +1610 -0
- package/test/vault-sweep.test.js +1344 -0
- package/test/vault-ui.test.js +2443 -0
package/kernel/api/index.js
CHANGED
|
@@ -31,6 +31,7 @@ class Api {
|
|
|
31
31
|
this.listeners = {}
|
|
32
32
|
this.counter = 0;
|
|
33
33
|
this.running = {}
|
|
34
|
+
this.running_paths = {}
|
|
34
35
|
this.done = {}
|
|
35
36
|
this.waiter = {}
|
|
36
37
|
this.proxies = {}
|
|
@@ -419,12 +420,19 @@ class Api {
|
|
|
419
420
|
delete this.resolved_actions[id]
|
|
420
421
|
}
|
|
421
422
|
}
|
|
423
|
+
clearRunning(requestOrId) {
|
|
424
|
+
const id = typeof requestOrId === "string" ? requestOrId : this.requestId(requestOrId)
|
|
425
|
+
if (!id) return
|
|
426
|
+
delete this.running[id]
|
|
427
|
+
delete this.running_paths[id]
|
|
428
|
+
}
|
|
422
429
|
setRunning(request, done) {
|
|
423
430
|
const id = this.requestId(request)
|
|
424
431
|
if (!id) {
|
|
425
432
|
return
|
|
426
433
|
}
|
|
427
434
|
this.running[id] = true
|
|
435
|
+
this.running_paths[id] = request.path || null
|
|
428
436
|
this.done[id] = done
|
|
429
437
|
if (this.kernel && typeof this.kernel.markAppLaunchStarted === "function") {
|
|
430
438
|
this.kernel.markAppLaunchStarted(request.path)
|
|
@@ -634,7 +642,7 @@ class Api {
|
|
|
634
642
|
if (req.params.id) stoppedKeys.add(req.params.id)
|
|
635
643
|
stoppedKeys.add(requestPath)
|
|
636
644
|
for (const key of stoppedKeys) {
|
|
637
|
-
|
|
645
|
+
this.clearRunning(key)
|
|
638
646
|
delete this.kernel.memory.local[key]
|
|
639
647
|
}
|
|
640
648
|
if (this.kernel && typeof this.kernel.markAppLaunchStopped === "function") {
|
|
@@ -1994,7 +2002,7 @@ class Api {
|
|
|
1994
2002
|
})
|
|
1995
2003
|
} catch (e) {
|
|
1996
2004
|
this.clearResolvedAction(request)
|
|
1997
|
-
|
|
2005
|
+
this.clearRunning(request)
|
|
1998
2006
|
if (this.kernel && typeof this.kernel.markAppLaunchFailed === "function") {
|
|
1999
2007
|
this.kernel.markAppLaunchFailed(request.path, e)
|
|
2000
2008
|
}
|
|
@@ -2008,7 +2016,7 @@ class Api {
|
|
|
2008
2016
|
|
|
2009
2017
|
if (!Array.isArray(steps) || steps.length === 0) {
|
|
2010
2018
|
this.clearResolvedAction(request)
|
|
2011
|
-
|
|
2019
|
+
this.clearRunning(request)
|
|
2012
2020
|
if (this.kernel && typeof this.kernel.markAppLaunchFailed === "function") {
|
|
2013
2021
|
this.kernel.markAppLaunchFailed(request.path, new Error(`missing or invalid attribute: ${actionKey}`))
|
|
2014
2022
|
}
|
|
@@ -2070,6 +2078,7 @@ class Api {
|
|
|
2070
2078
|
let id = request.id ? request.id : request.method
|
|
2071
2079
|
if (request.id) {
|
|
2072
2080
|
this.running[request.id] = true
|
|
2081
|
+
delete this.running_paths[request.id]
|
|
2073
2082
|
}
|
|
2074
2083
|
try {
|
|
2075
2084
|
resolved.dirname = resolved.dirname
|
package/kernel/index.js
CHANGED
|
@@ -37,6 +37,7 @@ const PinokioDomainRouter = require("./router/pinokio_domain_router")
|
|
|
37
37
|
const Procs = require('./procs')
|
|
38
38
|
const Peer = require('./peer')
|
|
39
39
|
const Git = require('./git')
|
|
40
|
+
const Vault = require('./vault')
|
|
40
41
|
const Connect = require('./connect')
|
|
41
42
|
const Favicon = require('./favicon')
|
|
42
43
|
const AppLauncher = require('./app_launcher')
|
|
@@ -1216,6 +1217,29 @@ class Kernel {
|
|
|
1216
1217
|
await this.git.loadCheckpoints()
|
|
1217
1218
|
console.timeEnd("git.loadCheckpoints")
|
|
1218
1219
|
|
|
1220
|
+
// Shared model store: registry verification only at startup — never a
|
|
1221
|
+
// discovery walk (spec/requirements/shared-model-store.md, trigger 5).
|
|
1222
|
+
this.vault = new Vault(this)
|
|
1223
|
+
if (this.homedir) {
|
|
1224
|
+
this.vault.ready = this.vault.init({ existingOnly: true }).then(async (result) => {
|
|
1225
|
+
if (result && result.enabled && this.vault.initialized) {
|
|
1226
|
+
this.vault.verificationPending = true
|
|
1227
|
+
await this.vault.runExclusive(async () => {
|
|
1228
|
+
await this.vault.verify()
|
|
1229
|
+
await this.vault.registry.flush()
|
|
1230
|
+
})
|
|
1231
|
+
this.vault.verificationPending = false
|
|
1232
|
+
}
|
|
1233
|
+
return result
|
|
1234
|
+
}).catch((err) => {
|
|
1235
|
+
// Keep an enabled Vault retryable after transient registry or
|
|
1236
|
+
// filesystem errors. A genuinely disabled Vault already has
|
|
1237
|
+
// enabled=false from its environment check.
|
|
1238
|
+
console.warn("Vault init error:", err && err.message ? err.message : err)
|
|
1239
|
+
return { enabled: false, error: err && err.message ? err.message : String(err) }
|
|
1240
|
+
})
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1219
1243
|
// let contents = await fs.promises.readdir(this.homedir)
|
|
1220
1244
|
//await this.bin.init()
|
|
1221
1245
|
let ts = Date.now()
|
package/kernel/shell.js
CHANGED
|
@@ -1618,7 +1618,8 @@ class Shell {
|
|
|
1618
1618
|
|
|
1619
1619
|
|
|
1620
1620
|
if (this.kernel.api.running[this.id]) {
|
|
1621
|
-
|
|
1621
|
+
if (typeof this.kernel.api.clearRunning === "function") this.kernel.api.clearRunning(this.id)
|
|
1622
|
+
else delete this.kernel.api.running[this.id]
|
|
1622
1623
|
}
|
|
1623
1624
|
if (this.kernel.memory.local[this.id]) {
|
|
1624
1625
|
delete this.kernel.memory.local[this.id]
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const MB = 1000 * 1000
|
|
2
|
+
const CANDIDATE_SIZE_OPTIONS = [10, 50, 100, 500, 1000].map((value) => value * MB)
|
|
3
|
+
|
|
4
|
+
module.exports = {
|
|
5
|
+
SIZE_THRESHOLD: 100 * MB,
|
|
6
|
+
CANDIDATE_SIZE_OPTIONS,
|
|
7
|
+
TMP_SUFFIX: ".pinokio-dedup-tmp",
|
|
8
|
+
SHA256_RE: /^[0-9a-f]{64}$/,
|
|
9
|
+
ENTRY_BATCH_SIZE: 256,
|
|
10
|
+
DIR_CONCURRENCY: 8,
|
|
11
|
+
STAT_CONCURRENCY: 32,
|
|
12
|
+
HASH_QUEUE_LIMIT: 256
|
|
13
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
const { parentPort } = require('worker_threads')
|
|
2
|
+
const crypto = require('crypto')
|
|
3
|
+
const fs = require('fs')
|
|
4
|
+
|
|
5
|
+
// Large model files otherwise generate a very high number of 64 KiB stream
|
|
6
|
+
// events. This changes only the read granularity; every byte still feeds the
|
|
7
|
+
// same sha256 digest, one file at a time.
|
|
8
|
+
const HASH_READ_SIZE = 1024 * 1024
|
|
9
|
+
|
|
10
|
+
parentPort.on('message', ({ id, filePath }) => {
|
|
11
|
+
const hash = crypto.createHash('sha256')
|
|
12
|
+
let size = 0
|
|
13
|
+
const flags = fs.constants.O_RDONLY | (fs.constants.O_NOFOLLOW || 0)
|
|
14
|
+
const stream = fs.createReadStream(filePath, { flags, highWaterMark: HASH_READ_SIZE })
|
|
15
|
+
stream.on('data', (chunk) => {
|
|
16
|
+
size += chunk.length
|
|
17
|
+
hash.update(chunk)
|
|
18
|
+
})
|
|
19
|
+
stream.on('error', (error) => {
|
|
20
|
+
parentPort.postMessage({
|
|
21
|
+
id,
|
|
22
|
+
error: {
|
|
23
|
+
message: error && error.message ? error.message : String(error),
|
|
24
|
+
code: error && error.code ? error.code : null
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
})
|
|
28
|
+
stream.on('end', () => {
|
|
29
|
+
parentPort.postMessage({ id, hash: hash.digest('hex'), size })
|
|
30
|
+
})
|
|
31
|
+
})
|