pinokiod 8.0.39 → 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/hf/index.js +2 -2
- package/kernel/api/index.js +12 -3
- package/kernel/connect/index.js +2 -2
- package/kernel/connect/providers/huggingface/index.js +14 -5
- package/kernel/index.js +14 -2
- package/kernel/shell.js +3 -2
- package/kernel/shells.js +6 -0
- package/kernel/vault/constants.js +13 -0
- package/kernel/vault/hash_worker.js +9 -2
- package/kernel/vault/index.js +1856 -316
- package/kernel/vault/registry.js +526 -52
- package/kernel/vault/snapshot.js +29 -0
- package/kernel/vault/sweeper.js +480 -210
- package/kernel/vault/walker.js +142 -0
- package/package.json +1 -1
- package/server/index.js +79 -90
- 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/connect/huggingface.ejs +7 -9
- package/server/views/partials/main_sidebar.ejs +6 -1
- package/server/views/partials/vault_workspace.ejs +55 -0
- package/server/views/vault.ejs +5 -1532
- package/server/views/vault_app.ejs +22 -0
- package/test/hf-api.test.js +4 -2
- package/test/huggingface-connect.test.js +7 -11
- package/test/huggingface-token-validity.test.js +135 -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 +1276 -26
- package/test/vault-sweep.test.js +1043 -35
- package/test/vault-ui.test.js +2184 -65
package/kernel/api/hf/index.js
CHANGED
|
@@ -214,7 +214,7 @@ class HF {
|
|
|
214
214
|
|
|
215
215
|
if (!force) {
|
|
216
216
|
const existing = await connect.keys("huggingface", authContext)
|
|
217
|
-
if (existing && existing.access_token) {
|
|
217
|
+
if (existing && existing.access_token && await connect.connected("huggingface", { timeout: 5000 }, authContext)) {
|
|
218
218
|
return {
|
|
219
219
|
status: "success",
|
|
220
220
|
already_logged_in: true,
|
|
@@ -273,7 +273,7 @@ class HF {
|
|
|
273
273
|
const startedAt = Date.now()
|
|
274
274
|
while (Date.now() - startedAt < timeout) {
|
|
275
275
|
const keys = await connect.keys("huggingface", authContext)
|
|
276
|
-
if (keys && keys.access_token) {
|
|
276
|
+
if (keys && keys.access_token && await connect.connected("huggingface", { timeout: 5000 }, authContext)) {
|
|
277
277
|
if (useModal) {
|
|
278
278
|
await this.closeLoginModal(req, ondata, kernel)
|
|
279
279
|
}
|
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/connect/index.js
CHANGED
|
@@ -42,9 +42,9 @@ class Connect {
|
|
|
42
42
|
let res = await this.clients[provider].keys(context)
|
|
43
43
|
return res
|
|
44
44
|
}
|
|
45
|
-
async connected(provider, options) {
|
|
45
|
+
async connected(provider, options, context) {
|
|
46
46
|
if (this.clients[provider] && this.clients[provider].connected) {
|
|
47
|
-
return await this.clients[provider].connected(options)
|
|
47
|
+
return await this.clients[provider].connected(options, context)
|
|
48
48
|
}
|
|
49
49
|
return false
|
|
50
50
|
}
|
|
@@ -32,10 +32,11 @@ class Huggingface {
|
|
|
32
32
|
try {
|
|
33
33
|
const stat = await fs.promises.lstat(tokenPath)
|
|
34
34
|
if (stat.isDirectory()) {
|
|
35
|
-
await fs.promises.
|
|
35
|
+
await fs.promises.rmdir(tokenPath)
|
|
36
36
|
}
|
|
37
37
|
} catch (error) {
|
|
38
|
-
if (
|
|
38
|
+
if (error.code !== "ENOENT") {
|
|
39
|
+
error.tokenPath = tokenPath
|
|
39
40
|
throw error
|
|
40
41
|
}
|
|
41
42
|
}
|
|
@@ -45,6 +46,7 @@ class Huggingface {
|
|
|
45
46
|
let env
|
|
46
47
|
if (context.parentPath) {
|
|
47
48
|
env = await Environment.get2(context.parentPath, this.kernel)
|
|
49
|
+
if (env.HF_TOKEN_PATH === this.kernel.path("cache", "HF_AUTH", "anonymous")) env.HF_TOKEN_PATH = this.defaultTokenPath()
|
|
48
50
|
} else {
|
|
49
51
|
let systemEnv = {}
|
|
50
52
|
try {
|
|
@@ -96,6 +98,7 @@ class Huggingface {
|
|
|
96
98
|
maxBuffer: 1024 * 1024,
|
|
97
99
|
}, (error, stdout, stderr) => {
|
|
98
100
|
if (error) {
|
|
101
|
+
error.tokenPath = env.HF_TOKEN_PATH
|
|
99
102
|
error.stdout = stdout
|
|
100
103
|
error.stderr = stderr
|
|
101
104
|
reject(error)
|
|
@@ -244,11 +247,17 @@ class Huggingface {
|
|
|
244
247
|
return null
|
|
245
248
|
}
|
|
246
249
|
}
|
|
247
|
-
async connected(options = {}) {
|
|
250
|
+
async connected(options = {}, context = {}) {
|
|
248
251
|
try {
|
|
249
|
-
await this.runHf(["auth", "whoami", "--format", "quiet"], options)
|
|
252
|
+
const result = await this.runHf(["auth", "whoami", "--format", "quiet"], options, context)
|
|
253
|
+
if (this.kernel.envs && result.env.HF_TOKEN_PATH === this.defaultTokenPath()) {
|
|
254
|
+
this.kernel.envs.HF_TOKEN_PATH = result.env.HF_TOKEN_PATH
|
|
255
|
+
}
|
|
250
256
|
return true
|
|
251
|
-
} catch (
|
|
257
|
+
} catch (error) {
|
|
258
|
+
if (this.kernel.envs && error.tokenPath === this.defaultTokenPath()) {
|
|
259
|
+
this.kernel.envs.HF_TOKEN_PATH = this.kernel.path("cache", "HF_AUTH", "anonymous")
|
|
260
|
+
}
|
|
252
261
|
return false
|
|
253
262
|
}
|
|
254
263
|
}
|
package/kernel/index.js
CHANGED
|
@@ -1221,10 +1221,22 @@ class Kernel {
|
|
|
1221
1221
|
// discovery walk (spec/requirements/shared-model-store.md, trigger 5).
|
|
1222
1222
|
this.vault = new Vault(this)
|
|
1223
1223
|
if (this.homedir) {
|
|
1224
|
-
this.vault.init().then((result) => {
|
|
1225
|
-
if (result && result.enabled
|
|
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
|
|
1226
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.
|
|
1227
1238
|
console.warn("Vault init error:", err && err.message ? err.message : err)
|
|
1239
|
+
return { enabled: false, error: err && err.message ? err.message : String(err) }
|
|
1228
1240
|
})
|
|
1229
1241
|
}
|
|
1230
1242
|
|
package/kernel/shell.js
CHANGED
|
@@ -291,7 +291,7 @@ class Shell {
|
|
|
291
291
|
}
|
|
292
292
|
|
|
293
293
|
setDefaultEnvValue(this.env, "HF_HUB_DISABLE_UPDATE_CHECK", "1")
|
|
294
|
-
setDefaultEnvValue(this.env, "HF_TOKEN_PATH", path.resolve(this.kernel.homedir, "cache", "HF_AUTH", "token"))
|
|
294
|
+
setDefaultEnvValue(this.env, "HF_TOKEN_PATH", this.kernel.envs?.HF_TOKEN_PATH || path.resolve(this.kernel.homedir, "cache", "HF_AUTH", "token"))
|
|
295
295
|
|
|
296
296
|
if (this.platform === "win32") {
|
|
297
297
|
const managedSslDir = path.resolve(this.kernel.homedir, "bin", "miniforge", "Library", "ssl")
|
|
@@ -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]
|
package/kernel/shells.js
CHANGED
|
@@ -47,6 +47,9 @@ class Shells {
|
|
|
47
47
|
}
|
|
48
48
|
*/
|
|
49
49
|
async init() {
|
|
50
|
+
const hfDisconnected = !this.kernel.envs?.HF_TOKEN_PATH &&
|
|
51
|
+
!(await this.kernel.connect.connected("huggingface", { timeout: 5000 }))
|
|
52
|
+
|
|
50
53
|
// iterate through all the envs
|
|
51
54
|
let sh = new Shell(this.kernel)
|
|
52
55
|
let m
|
|
@@ -58,6 +61,9 @@ class Shells {
|
|
|
58
61
|
await sh.init_env({
|
|
59
62
|
env: this.kernel.bin.envs({}),
|
|
60
63
|
})
|
|
64
|
+
if (hfDisconnected && sh.env.HF_TOKEN_PATH === this.kernel.path("cache", "HF_AUTH", "token")) {
|
|
65
|
+
sh.env.HF_TOKEN_PATH = this.kernel.path("cache", "HF_AUTH", "anonymous")
|
|
66
|
+
}
|
|
61
67
|
|
|
62
68
|
await this.ensureBracketedPasteSupport(sh.shell)
|
|
63
69
|
if (this.kernel.bracketedPasteSupport) {
|
|
@@ -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
|
+
}
|
|
@@ -10,13 +10,20 @@ const HASH_READ_SIZE = 1024 * 1024
|
|
|
10
10
|
parentPort.on('message', ({ id, filePath }) => {
|
|
11
11
|
const hash = crypto.createHash('sha256')
|
|
12
12
|
let size = 0
|
|
13
|
-
const
|
|
13
|
+
const flags = fs.constants.O_RDONLY | (fs.constants.O_NOFOLLOW || 0)
|
|
14
|
+
const stream = fs.createReadStream(filePath, { flags, highWaterMark: HASH_READ_SIZE })
|
|
14
15
|
stream.on('data', (chunk) => {
|
|
15
16
|
size += chunk.length
|
|
16
17
|
hash.update(chunk)
|
|
17
18
|
})
|
|
18
19
|
stream.on('error', (error) => {
|
|
19
|
-
parentPort.postMessage({
|
|
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
|
+
})
|
|
20
27
|
})
|
|
21
28
|
stream.on('end', () => {
|
|
22
29
|
parentPort.postMessage({ id, hash: hash.digest('hex'), size })
|