pinokiod 7.1.73 → 7.1.75

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.
@@ -13,13 +13,13 @@ class Script {
13
13
  return null
14
14
  }
15
15
  currentSessionId(req) {
16
- if (req && typeof req.id === "string" && req.id.trim()) {
17
- return req.id
18
- }
19
16
  const parent = this.currentParent(req)
20
17
  if (parent && typeof parent.id === "string" && parent.id.trim()) {
21
18
  return parent.id
22
19
  }
20
+ if (req && typeof req.id === "string" && req.id.trim()) {
21
+ return req.id
22
+ }
23
23
  return undefined
24
24
  }
25
25
  currentCaller(req) {
@@ -192,14 +192,16 @@ class Script {
192
192
  input: req.params.params,
193
193
  client: this.currentClient(req),
194
194
  }
195
- if (req.id) {
196
- request.id = req.id
197
- }
198
195
  const caller = this.currentCaller(req)
199
196
  if (caller) {
200
197
  request.caller = caller
201
- } else if (req.parent && req.parent.path) {
202
- request.caller = req.parent.path
198
+ } else {
199
+ const parent = this.currentParent(req)
200
+ if (parent && typeof parent.id === "string" && parent.id.trim()) {
201
+ request.caller = parent.id
202
+ } else if (req.parent && req.parent.path) {
203
+ request.caller = req.parent.path
204
+ }
203
205
  }
204
206
  const origin = this.currentOrigin(req)
205
207
  if (origin) {
@@ -2,15 +2,35 @@ const path = require('path')
2
2
  const fs = require('fs')
3
3
  const os = require('os')
4
4
  class Shell {
5
- applyBluefairyDefault(req = {}) {
6
- if (!req.params || Object.prototype.hasOwnProperty.call(req.params, "bluefairy")) {
5
+ async applyBluefairyDefault(req = {}, kernel) {
6
+ if (!req.params) {
7
+ return
8
+ }
9
+ if (Object.prototype.hasOwnProperty.call(req.params, "bluefairy")) {
10
+ return
11
+ }
12
+ const preferences = kernel && kernel.appPreferences
13
+ if (
14
+ !preferences
15
+ || !kernel
16
+ || !kernel.api
17
+ || typeof kernel.api.resolvePath !== "function"
18
+ || typeof preferences.resolveAppIdFromPath !== "function"
19
+ || typeof preferences.getPreference !== "function"
20
+ ) {
21
+ req.params.bluefairy = "off"
7
22
  return
8
23
  }
9
- if (req.parent && Object.prototype.hasOwnProperty.call(req.parent, "protection_enabled")) {
10
- req.params.bluefairy = req.parent.protection_enabled === false ? "off" : "on"
11
- } else {
24
+ const cwd = req.cwd || kernel.homedir
25
+ const requestedPath = req.params.path || "."
26
+ const resolvedPath = kernel.api.resolvePath(cwd, requestedPath)
27
+ const appId = preferences.resolveAppIdFromPath(resolvedPath)
28
+ if (!appId) {
12
29
  req.params.bluefairy = "off"
30
+ return
13
31
  }
32
+ const preference = await preferences.getPreference(appId)
33
+ req.params.bluefairy = preference && preference.protection_enabled === true ? "on" : "off"
14
34
  }
15
35
  async start(req, ondata, kernel) {
16
36
  /*
@@ -50,7 +70,9 @@ class Shell {
50
70
  if (req.params) {
51
71
  req.params.$parent = req.parent
52
72
  }
53
- this.applyBluefairyDefault(req)
73
+ if (!Object.prototype.hasOwnProperty.call(req.params, "bluefairy")) {
74
+ req.params.bluefairy = "off"
75
+ }
54
76
 
55
77
  // // create a persistent session
56
78
  // req.params.persistent = true
@@ -136,10 +158,13 @@ class Shell {
136
158
  if (!req.params) {
137
159
  req.params = {}
138
160
  }
161
+ if (!req.params.path) {
162
+ req.params.path = req.cwd
163
+ }
139
164
  if (req.params) {
140
165
  req.params.$parent = req.parent
141
166
  }
142
- this.applyBluefairyDefault(req)
167
+ await this.applyBluefairyDefault(req, kernel)
143
168
  let options = {}
144
169
  if (req.cwd) options.cwd = req.cwd
145
170
  if (req.parent && req.parent.id) {
@@ -4,7 +4,7 @@ const semver = require('semver')
4
4
 
5
5
  class Bluefairy {
6
6
  description = "Installs Bluefairy, a standalone package freshness guard."
7
- version = ">=0.0.28"
7
+ version = ">=0.0.31"
8
8
 
9
9
  packageName() {
10
10
  return "bluefairy"
@@ -37,6 +37,10 @@ class Bluefairy {
37
37
  return this.kernel.bin.path("bluefairy")
38
38
  }
39
39
 
40
+ packageInstallPath() {
41
+ return path.resolve(this.moduleRoot(), this.packageName())
42
+ }
43
+
40
44
  env() {
41
45
  return {
42
46
  BLUEFAIRY_HOME: this.runtimeHome()
@@ -63,6 +67,20 @@ class Bluefairy {
63
67
  ]
64
68
  }
65
69
 
70
+ binLauncherArtifacts() {
71
+ const binDir = this.npmBinDir()
72
+ if (this.kernel.platform === "win32") {
73
+ return [
74
+ path.resolve(binDir, "bluefairy"),
75
+ path.resolve(binDir, "bluefairy.cmd"),
76
+ path.resolve(binDir, "bluefairy.ps1"),
77
+ ]
78
+ }
79
+ return [
80
+ path.resolve(binDir, "bluefairy"),
81
+ ]
82
+ }
83
+
66
84
  runtimeArtifacts() {
67
85
  const runtimeHome = this.runtimeHome()
68
86
  if (this.kernel.platform === "win32") {
@@ -97,18 +115,61 @@ class Bluefairy {
97
115
  }
98
116
  }
99
117
 
100
- async install(req, ondata) {
101
- const spec = this.packageSpec().replaceAll('"', '\\"')
102
- const runtimeHome = this.runtimeHome()
103
- if (fs.existsSync(runtimeHome)) {
104
- try {
105
- await fs.promises.rm(runtimeHome, { recursive: true, force: true })
106
- ondata({ raw: `Removed existing Bluefairy runtime: ${runtimeHome}\r\n` })
107
- } catch (error) {
108
- const message = error && error.message ? error.message : String(error)
109
- ondata({ raw: `Warning: failed to remove Bluefairy runtime ${runtimeHome}: ${message}\r\n` })
118
+ async removePath(target, ondata, label) {
119
+ if (!fs.existsSync(target)) {
120
+ return
121
+ }
122
+ try {
123
+ await fs.promises.rm(target, { recursive: true, force: true })
124
+ ondata({ raw: `Removed ${label}: ${target}\r\n` })
125
+ } catch (error) {
126
+ const message = error && error.message ? error.message : String(error)
127
+ ondata({ raw: `Warning: failed to remove ${label} ${target}: ${message}\r\n` })
128
+ }
129
+ }
130
+
131
+ async removeRetiredEntries(parentDir, ondata) {
132
+ let entries
133
+ try {
134
+ entries = await fs.promises.readdir(parentDir)
135
+ } catch (error) {
136
+ const message = error && error.message ? error.message : String(error)
137
+ ondata({ raw: `Warning: failed to list ${parentDir}: ${message}\r\n` })
138
+ return
139
+ }
140
+
141
+ const retiredPrefix = `.${this.packageName()}-`
142
+ for (const entry of entries) {
143
+ if (!entry.startsWith(retiredPrefix)) {
144
+ continue
110
145
  }
146
+ await this.removePath(
147
+ path.resolve(parentDir, entry),
148
+ ondata,
149
+ "stale Bluefairy install temp"
150
+ )
151
+ }
152
+ }
153
+
154
+ async cleanupInstallState(ondata) {
155
+ const cleanupTargets = new Set([
156
+ this.runtimeHome(),
157
+ this.packageInstallPath(),
158
+ ...this.installedArtifacts(),
159
+ ...this.binLauncherArtifacts(),
160
+ ])
161
+
162
+ for (const target of cleanupTargets) {
163
+ await this.removePath(target, ondata, "existing Bluefairy install state")
111
164
  }
165
+
166
+ await this.removeRetiredEntries(this.moduleRoot(), ondata)
167
+ await this.removeRetiredEntries(this.npmBinDir(), ondata)
168
+ }
169
+
170
+ async install(req, ondata) {
171
+ const spec = this.packageSpec().replaceAll('"', '\\"')
172
+ await this.cleanupInstallState(ondata)
112
173
  await this.kernel.exec({
113
174
  env: this.env(),
114
175
  message: `npm install -g "${spec}" --force`,
package/kernel/shell.js CHANGED
@@ -21,6 +21,51 @@ const AnsiStreamTracker = require('./ansi_stream_tracker')
21
21
  const ShellStateSync = require('./shell_state_sync')
22
22
  const home = os.homedir()
23
23
 
24
+ function normalizeComparablePath(filePath, platform) {
25
+ const normalized = path.normalize(filePath)
26
+ return platform === 'win32' ? normalized.toLowerCase() : normalized
27
+ }
28
+
29
+ function isBluefairyShimPath(filePath, platform) {
30
+ if (!filePath || typeof filePath !== "string") {
31
+ return false
32
+ }
33
+ const normalized = normalizeComparablePath(filePath.trim(), platform)
34
+ if (!normalized) {
35
+ return false
36
+ }
37
+ const shimDirName = path.basename(normalized)
38
+ if (shimDirName !== "shims") {
39
+ return false
40
+ }
41
+ const parentDirName = path.basename(path.dirname(normalized))
42
+ return parentDirName === "bluefairy" || parentDirName === ".bluefairy"
43
+ }
44
+
45
+ function stripBluefairyShimPaths(pathValue, platform) {
46
+ if (!pathValue || typeof pathValue !== "string") {
47
+ return pathValue
48
+ }
49
+ return pathValue
50
+ .split(path.delimiter)
51
+ .filter((entry) => entry && !isBluefairyShimPath(entry, platform))
52
+ .join(path.delimiter)
53
+ }
54
+
55
+ const CONDA_ACTIVATION_STATE_PATTERN = /^(?:_CE_(?:M|CONDA)|CONDA_(?:EXE|PYTHON_EXE|PREFIX(?:_\d+)?|DEFAULT_ENV|PROMPT_MODIFIER|SHLVL|PS1_BACKUP))$/
56
+
57
+ function isCondaActivationStateKey(key) {
58
+ return typeof key === "string" && CONDA_ACTIVATION_STATE_PATTERN.test(key)
59
+ }
60
+
61
+ function stripInheritedCondaActivationState(env) {
62
+ for (const key of Object.keys(env)) {
63
+ if (isCondaActivationStateKey(key)) {
64
+ delete env[key]
65
+ }
66
+ }
67
+ }
68
+
24
69
  // xterm.js currently ignores DECSYNCTERM (CSI ? 2026 h/l) and renders it as text on Windows.
25
70
  // filterDecsync() removes these sequences so they do not pollute the terminal output.
26
71
  class Shell {
@@ -91,6 +136,12 @@ class Shell {
91
136
  }
92
137
  async init_env(params) {
93
138
  this.env = Object.assign({}, process.env)
139
+ for (const key of Object.keys(this.env)) {
140
+ if (key.toUpperCase().startsWith("BLUEFAIRY_")) {
141
+ delete this.env[key]
142
+ }
143
+ }
144
+ stripInheritedCondaActivationState(this.env)
94
145
  // If the user has set PYTHONPATH, unset it.
95
146
  if (this.env.PYTHONPATH) {
96
147
  delete this.env.PYTHONPATH
@@ -166,6 +217,7 @@ class Shell {
166
217
  let app_env = await Environment.get(api_path, this.kernel)
167
218
  this.env = Object.assign(this.env, app_env)
168
219
  }
220
+ stripInheritedCondaActivationState(this.env)
169
221
  let PATH_KEY = Object.keys(this.env).find((key) => key.toLowerCase() === "path") || "PATH";
170
222
  if (!this.env[PATH_KEY]) {
171
223
  // fall back to whichever casing exists so we don't end up writing to an undefined key
@@ -232,6 +284,9 @@ class Shell {
232
284
  }
233
285
  }
234
286
 
287
+ stripInheritedCondaActivationState(this.env)
288
+ this.env[PATH_KEY] = stripBluefairyShimPaths(this.env[PATH_KEY], this.platform)
289
+
235
290
  for(let key in this.env) {
236
291
  if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(key) && key !== "ProgramFiles(x86)") {
237
292
  delete this.env[key]
package/kernel/shells.js CHANGED
@@ -301,6 +301,7 @@ class Shells {
301
301
  let liveEventBuffer = ""
302
302
  let liveEventOffset = 0
303
303
  let liveEventAnsiCarry = ""
304
+ let liveEventHandlersClosed = false
304
305
 
305
306
  // Keep cross-chunk event matching, but normalize terminal styling away first.
306
307
  // Preserve line boundaries so later shell banners cannot fuse onto prior matches.
@@ -428,7 +429,7 @@ class Shells {
428
429
  liveEventOffset += normalizedChunk.length
429
430
  }
430
431
  const liveEventBufferStart = Math.max(0, liveEventOffset - liveEventBuffer.length)
431
- if (params.on && Array.isArray(params.on)) {
432
+ if (!liveEventHandlersClosed && params.on && Array.isArray(params.on)) {
432
433
  for(let i=0; i<params.on.length; i++) {
433
434
  let handler = params.on[i]
434
435
  if (handler.once && onceHandlers.has(i)) {
@@ -476,11 +477,18 @@ class Shells {
476
477
  }
477
478
  const lastMatch = rendered_event[rendered_event.length - 1]
478
479
  handlerLastMatchEnd.set(i, liveEventBufferStart + lastMatch.index + lastMatch[0].length)
479
- stream.matches = rendered_event
480
- m = rendered_event[0]
481
- matched_index = i
482
- if (typeof handler.trigger === "string" && handler.trigger.trim()) {
483
- const triggerAction = handler.trigger.trim()
480
+ const triggerAction = typeof handler.trigger === "string" ? handler.trigger.trim() : ""
481
+ const shouldCaptureEvent =
482
+ handler.break !== false
483
+ || handler.done
484
+ || handler.kill
485
+ || !!triggerAction
486
+ if (shouldCaptureEvent) {
487
+ stream.matches = rendered_event
488
+ m = rendered_event[0]
489
+ matched_index = i
490
+ }
491
+ if (triggerAction) {
484
492
  queueTriggerAction(triggerAction, rendered_event[0]).catch((e) => {
485
493
  console.log("Trigger error", e)
486
494
  if (ondata) {
@@ -490,9 +498,13 @@ class Shells {
490
498
  }
491
499
  if (handler.kill) {
492
500
  sh.kill()
501
+ liveEventHandlersClosed = true
502
+ break
493
503
  }
494
504
  if (handler.done) {
495
505
  sh.continue()
506
+ liveEventHandlersClosed = true
507
+ break
496
508
  }
497
509
  }
498
510
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pinokiod",
3
- "version": "7.1.73",
3
+ "version": "7.1.75",
4
4
  "description": "",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/server/index.js CHANGED
@@ -213,6 +213,7 @@ class Server {
213
213
  })
214
214
  this.appRegistry = new AppRegistryService({ kernel: this.kernel })
215
215
  this.appPreferences = new AppPreferencesService({ kernel: this.kernel })
216
+ this.kernel.appPreferences = this.appPreferences
216
217
  this.appLogs = new AppLogService({ registry: this.appRegistry })
217
218
  this.appSearch = new AppSearchService({
218
219
  kernel: this.kernel,
@@ -1251,7 +1252,7 @@ class Server {
1251
1252
  path: 'remote.origin.url'
1252
1253
  })
1253
1254
  if (gitRemote && this.portal) {
1254
- community_url = `${this.portal}/resolve?url=${encodeURIComponent(gitRemote)}&embed=1&theme=${encodeURIComponent(this.theme)}`
1255
+ community_url = `${this.portal}/resolve?url=${encodeURIComponent(gitRemote)}&embed=1&theme=${encodeURIComponent(this.theme)}&pinokio_checkin_bridge=v1`
1255
1256
  }
1256
1257
  } catch (_) {
1257
1258
  community_url = ""
@@ -6417,8 +6418,6 @@ class Server {
6417
6418
  } else {
6418
6419
  registryOverride = null
6419
6420
  }
6420
- console.log("[registry/checkin] repo=%s return=%s registryRaw=%s registryOverride=%s", repoUrl || "", returnUrl || "", registryRaw || "", registryOverride || "")
6421
-
6422
6421
  let candidates = []
6423
6422
  if (repoUrl && this.kernel && this.kernel.git) {
6424
6423
  const apiRoot = this.kernel.path('api')
@@ -6538,7 +6537,6 @@ class Server {
6538
6537
  if (wantPublish) {
6539
6538
  const registry = await this.getRegistryConfig()
6540
6539
  const baseUrl = registryOverride || (registry && registry.url ? String(registry.url).replace(/\/$/, '') : null)
6541
- console.log("[checkpoints/snapshot] publish=1 registryOverride=%s baseUrl=%s hasToken=%s", registryOverride || "", baseUrl || "", registryToken ? "yes" : "no")
6542
6540
  if (!baseUrl || !registryToken) {
6543
6541
  await this.kernel.git.setCheckpointSync(created.remoteKey, created.id, { status: "needs_token", at: Date.now() }).catch(() => {})
6544
6542
  res.json({ ok: true, created: created || null, publish: { ok: false, code: "missing_token" } })
@@ -12714,12 +12712,14 @@ class Server {
12714
12712
  // }
12715
12713
  //
12716
12714
  res.render("setup", {
12715
+ mode: req.params.mode,
12717
12716
  wait,
12718
12717
  error,
12719
12718
  current,
12720
12719
  install_required,
12721
12720
  requirements,
12722
12721
  requirements_pending,
12722
+ portal: this.portal,
12723
12723
  logo: this.logo,
12724
12724
  theme: this.theme,
12725
12725
  agent: req.agent,