pinokiod 7.2.17 → 7.3.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.
Files changed (78) hide show
  1. package/Dockerfile +2 -0
  2. package/kernel/api/index.js +1 -42
  3. package/kernel/api/process/index.js +44 -99
  4. package/kernel/bin/conda-python.js +30 -0
  5. package/kernel/bin/conda.js +22 -3
  6. package/kernel/bin/index.js +11 -1
  7. package/kernel/environment.js +2 -182
  8. package/kernel/git.js +13 -0
  9. package/kernel/index.js +1 -64
  10. package/kernel/plugin.js +58 -6
  11. package/kernel/shell.js +2 -21
  12. package/kernel/util.js +0 -60
  13. package/package.json +1 -1
  14. package/server/index.js +149 -176
  15. package/server/lib/content_validation.js +25 -28
  16. package/server/public/common.js +29 -103
  17. package/server/public/create-launcher.js +31 -4
  18. package/server/public/electron.css +6 -0
  19. package/server/public/style.css +0 -337
  20. package/server/public/task-launcher.js +32 -5
  21. package/server/public/universal-launcher.js +26 -3
  22. package/server/socket.js +11 -22
  23. package/server/views/app.ejs +30 -167
  24. package/server/views/d.ejs +33 -0
  25. package/server/views/editor.ejs +4 -25
  26. package/server/views/partials/main_sidebar.ejs +0 -1
  27. package/server/views/shell.ejs +3 -11
  28. package/server/views/terminal.ejs +3 -23
  29. package/server/views/terminals.ejs +0 -1
  30. package/spec/INSTRUCTION_SYNC.md +5 -5
  31. package/kernel/api/shell_run_template.js +0 -273
  32. package/kernel/api/uri/index.js +0 -51
  33. package/kernel/plugin_sources.js +0 -236
  34. package/kernel/watch/context.js +0 -42
  35. package/kernel/watch/drivers/fs.js +0 -71
  36. package/kernel/watch/drivers/poll.js +0 -33
  37. package/kernel/watch/index.js +0 -158
  38. package/server/features/drafts/index.js +0 -41
  39. package/server/features/drafts/parser.js +0 -169
  40. package/server/features/drafts/public/drafts.js +0 -1504
  41. package/server/features/drafts/registry_import.js +0 -412
  42. package/server/features/drafts/routes.js +0 -68
  43. package/server/features/drafts/service.js +0 -261
  44. package/server/features/drafts/watcher.js +0 -76
  45. package/server/features/index.js +0 -13
  46. package/server/lib/workspace_catalog.js +0 -151
  47. package/server/lib/workspace_runtime.js +0 -390
  48. package/server/routes/workspaces.js +0 -44
  49. package/server/views/partials/workspace_row.ejs +0 -61
  50. package/server/views/workspaces.ejs +0 -812
  51. package/system/plugin/antigravity/antigravity.png +0 -0
  52. package/system/plugin/antigravity/pinokio.js +0 -37
  53. package/system/plugin/claude/claude.png +0 -0
  54. package/system/plugin/claude/pinokio.js +0 -63
  55. package/system/plugin/claude-auto/claude.png +0 -0
  56. package/system/plugin/claude-auto/pinokio.js +0 -74
  57. package/system/plugin/claude-desktop/icon.jpeg +0 -0
  58. package/system/plugin/claude-desktop/pinokio.js +0 -39
  59. package/system/plugin/codex/openai.webp +0 -0
  60. package/system/plugin/codex/pinokio.js +0 -58
  61. package/system/plugin/codex-auto/openai.webp +0 -0
  62. package/system/plugin/codex-auto/pinokio.js +0 -65
  63. package/system/plugin/codex-desktop/icon.png +0 -0
  64. package/system/plugin/codex-desktop/pinokio.js +0 -39
  65. package/system/plugin/crush/crush.png +0 -0
  66. package/system/plugin/crush/pinokio.js +0 -31
  67. package/system/plugin/cursor/cursor.jpeg +0 -0
  68. package/system/plugin/cursor/pinokio.js +0 -39
  69. package/system/plugin/gemini/gemini.jpeg +0 -0
  70. package/system/plugin/gemini/pinokio.js +0 -40
  71. package/system/plugin/gemini-auto/gemini.jpeg +0 -0
  72. package/system/plugin/gemini-auto/pinokio.js +0 -43
  73. package/system/plugin/qwen/pinokio.js +0 -50
  74. package/system/plugin/qwen/qwen.png +0 -0
  75. package/system/plugin/vscode/pinokio.js +0 -36
  76. package/system/plugin/vscode/vscode.png +0 -0
  77. package/system/plugin/windsurf/pinokio.js +0 -39
  78. package/system/plugin/windsurf/windsurf.png +0 -0
@@ -1,273 +0,0 @@
1
- function isCmdShellName(shellName) {
2
- const name = (shellName || '').toLowerCase()
3
- return name.includes('cmd.exe') || name === 'cmd'
4
- }
5
-
6
- function isPowerShellName(shellName) {
7
- const name = (shellName || '').toLowerCase()
8
- return name.includes('powershell') || name.includes('pwsh')
9
- }
10
-
11
- const ENV_ARG_MARKER_RE = /__PINOKIO_ENVARG_(\d+)__/g
12
-
13
- function envArgMarker(index) {
14
- return `__PINOKIO_ENVARG_${index}__`
15
- }
16
-
17
- function isPinokioEnvArgKey(key) {
18
- return /^PINOKIO_ARG_\d+$/.test(key || "")
19
- }
20
-
21
- function hasEnvArgMarker(value) {
22
- ENV_ARG_MARKER_RE.lastIndex = 0
23
- return ENV_ARG_MARKER_RE.test(String(value))
24
- }
25
-
26
- function quotePosixLiteral(value) {
27
- const input = value == null ? "" : String(value)
28
- return `'${input.split("'").join("'\"'\"'")}'`
29
- }
30
-
31
- function quotePowerShellComposite(value) {
32
- const input = value == null ? "" : String(value)
33
- ENV_ARG_MARKER_RE.lastIndex = 0
34
- let output = '"'
35
- let lastIndex = 0
36
- for (const match of input.matchAll(ENV_ARG_MARKER_RE)) {
37
- const literal = input.slice(lastIndex, match.index)
38
- output += literal.replace(/[`"$]/g, (char) => "`" + char)
39
- output += "${env:PINOKIO_ARG_" + match[1] + "}"
40
- lastIndex = match.index + match[0].length
41
- }
42
- output += input.slice(lastIndex).replace(/[`"$]/g, (char) => "`" + char)
43
- output += '"'
44
- return output
45
- }
46
-
47
- function quoteCmdComposite(value) {
48
- const input = value == null ? "" : String(value)
49
- ENV_ARG_MARKER_RE.lastIndex = 0
50
- let output = '"'
51
- let lastIndex = 0
52
- for (const match of input.matchAll(ENV_ARG_MARKER_RE)) {
53
- const literal = input.slice(lastIndex, match.index)
54
- output += literal.replace(/([()%!^"<>&|])/g, '^$1')
55
- output += "!PINOKIO_ARG_" + match[1] + "!"
56
- lastIndex = match.index + match[0].length
57
- }
58
- output += input.slice(lastIndex).replace(/([()%!^"<>&|])/g, '^$1')
59
- output += '"'
60
- return output
61
- }
62
-
63
- function quoteEnvArgComposite(value, shellName) {
64
- const input = value == null ? "" : String(value)
65
- if (isCmdShellName(shellName)) {
66
- return quoteCmdComposite(input)
67
- }
68
- if (isPowerShellName(shellName)) {
69
- return quotePowerShellComposite(input)
70
- }
71
-
72
- ENV_ARG_MARKER_RE.lastIndex = 0
73
- const parts = []
74
- let lastIndex = 0
75
- for (const match of input.matchAll(ENV_ARG_MARKER_RE)) {
76
- const literal = input.slice(lastIndex, match.index)
77
- if (literal) {
78
- parts.push(quotePosixLiteral(literal))
79
- }
80
- parts.push('"$PINOKIO_ARG_' + match[1] + '"')
81
- lastIndex = match.index + match[0].length
82
- }
83
- const tail = input.slice(lastIndex)
84
- if (tail) {
85
- parts.push(quotePosixLiteral(tail))
86
- }
87
- return parts.length > 0 ? parts.join("") : "''"
88
- }
89
-
90
- function shellNameFor(kernel, params) {
91
- let shellName = kernel && kernel.platform === "win32" ? "cmd.exe" : "bash"
92
- if (params && typeof params.shell === "string" && params.shell.trim()) {
93
- shellName = params.shell
94
- }
95
- return shellName
96
- }
97
-
98
- function isPlainObject(value) {
99
- return value && value.constructor === Object
100
- }
101
-
102
- function hasMultiline(value) {
103
- return typeof value === "string" && /[\r\n]/.test(value)
104
- }
105
-
106
- function isStructuredArgvMessage(value) {
107
- return isPlainObject(value) && Array.isArray(value._)
108
- }
109
-
110
- function hasStructuredArgvMessage(value) {
111
- if (isStructuredArgvMessage(value)) {
112
- return true
113
- }
114
- if (Array.isArray(value)) {
115
- return value.some((item) => isStructuredArgvMessage(item))
116
- }
117
- return false
118
- }
119
-
120
- function protectStructuredString(value, state) {
121
- if (!hasMultiline(value)) {
122
- return value
123
- }
124
- const name = `PINOKIO_ARG_${state.args.length}`
125
- state.args.push({
126
- name,
127
- value: value == null ? "" : String(value)
128
- })
129
- return envArgMarker(state.args.length - 1)
130
- }
131
-
132
- function protectStructuredValue(value, state) {
133
- if (typeof value === "string") {
134
- return protectStructuredString(value, state)
135
- }
136
- if (Array.isArray(value)) {
137
- return value.map((item) => protectStructuredValue(item, state))
138
- }
139
- if (isPlainObject(value)) {
140
- const rendered = {}
141
- for (const [key, item] of Object.entries(value)) {
142
- rendered[key] = protectStructuredValue(item, state)
143
- }
144
- return rendered
145
- }
146
- return value
147
- }
148
-
149
- function protectStructuredMessage(value, state) {
150
- if (isStructuredArgvMessage(value)) {
151
- return protectStructuredValue(value, state)
152
- }
153
- if (Array.isArray(value)) {
154
- return value.map((item) => isStructuredArgvMessage(item) ? protectStructuredValue(item, state) : item)
155
- }
156
- return value
157
- }
158
-
159
- function renderEnvArgs(kernel, rpc, memory) {
160
- if (!rpc || rpc.method !== "shell.run" || !rpc.params || !hasStructuredArgvMessage(rpc.params.message)) {
161
- return rpc
162
- }
163
-
164
- const shellName = shellNameFor(kernel, rpc.params)
165
- const state = { args: [] }
166
- const message = protectStructuredMessage(rpc.params.message, state)
167
-
168
- if (state.args.length === 0) {
169
- return rpc
170
- }
171
-
172
- const env = Object.assign({}, rpc.params.env || {})
173
- for (const arg of state.args) {
174
- env[arg.name] = arg.value
175
- }
176
-
177
- return {
178
- ...rpc,
179
- params: {
180
- ...rpc.params,
181
- message,
182
- env,
183
- _pinokio_env_args: state.args,
184
- _pinokio_cmd_delayed_expansion: isCmdShellName(shellName)
185
- }
186
- }
187
- }
188
-
189
- function envArgDetails(value) {
190
- const normalized = String(value == null ? "" : value)
191
- .replace(/\r\n/g, "\n")
192
- .replace(/\r/g, "\n")
193
- .replace(/[\x00-\x08\x0B\x0C\x0E-\x1F\x7F]/g, "?")
194
- const lines = normalized.split("\n")
195
- const previewLines = []
196
- const maxLines = 8
197
- const maxChars = 800
198
- let used = 0
199
-
200
- for (const line of lines.slice(0, maxLines)) {
201
- const remaining = maxChars - used
202
- if (remaining <= 0) {
203
- break
204
- }
205
- if (line.length > remaining) {
206
- previewLines.push(line.slice(0, remaining) + "...")
207
- used = maxChars
208
- break
209
- }
210
- previewLines.push(line)
211
- used += line.length + 1
212
- }
213
-
214
- const preview = previewLines.join("\n")
215
- const truncated = lines.length > previewLines.length || normalized.length > preview.length
216
- if (truncated && previewLines[previewLines.length - 1] !== "...") {
217
- previewLines.push("...")
218
- }
219
-
220
- return {
221
- lineCount: normalized.length === 0 ? 0 : lines.length,
222
- previewLines,
223
- truncated
224
- }
225
- }
226
-
227
- function formatEnvArgsPreview(args) {
228
- if (!Array.isArray(args) || args.length === 0) {
229
- return ""
230
- }
231
- const lines = ["\r\nPinokio shell args", ""]
232
- for (const arg of args) {
233
- const details = envArgDetails(arg.value)
234
- lines.push(`${arg.name} ${details.lineCount} lines`)
235
- for (const previewLine of details.previewLines) {
236
- lines.push(` ${previewLine}`)
237
- }
238
- lines.push("")
239
- }
240
- return lines.join("\r\n") + "\r\n"
241
- }
242
-
243
- function envArgSummary(value) {
244
- const details = envArgDetails(value)
245
- return {
246
- type: "pinokio env arg",
247
- lines: details.lineCount,
248
- preview: details.previewLines.join("\n"),
249
- truncated: details.truncated
250
- }
251
- }
252
-
253
- function redactEnvArgs(env) {
254
- if (!env || typeof env !== "object") {
255
- return env
256
- }
257
- const redacted = { ...env }
258
- for (const key of Object.keys(redacted)) {
259
- if (isPinokioEnvArgKey(key)) {
260
- redacted[key] = envArgSummary(redacted[key])
261
- }
262
- }
263
- return redacted
264
- }
265
-
266
- module.exports = {
267
- renderEnvArgs,
268
- quoteEnvArgComposite,
269
- hasEnvArgMarker,
270
- isPinokioEnvArgKey,
271
- formatEnvArgsPreview,
272
- redactEnvArgs
273
- }
@@ -1,51 +0,0 @@
1
- const Util = require('../../util')
2
-
3
- const appendQueryParams = (uri, params) => {
4
- if (!params || typeof params !== 'object' || Array.isArray(params)) {
5
- return uri
6
- }
7
-
8
- const entries = []
9
- for (const [key, value] of Object.entries(params)) {
10
- const values = Array.isArray(value) ? value : [value]
11
- for (const item of values) {
12
- if (item === undefined || item === null) {
13
- continue
14
- }
15
- const serialized = typeof item === 'object' ? JSON.stringify(item) : String(item)
16
- entries.push(`${encodeURIComponent(key)}=${encodeURIComponent(serialized)}`)
17
- }
18
- }
19
-
20
- if (entries.length === 0) {
21
- return uri
22
- }
23
-
24
- const hashIndex = uri.indexOf('#')
25
- const base = hashIndex === -1 ? uri : uri.slice(0, hashIndex)
26
- const hash = hashIndex === -1 ? '' : uri.slice(hashIndex)
27
- const separator = base.includes('?')
28
- ? (base.endsWith('?') || base.endsWith('&') ? '' : '&')
29
- : '?'
30
-
31
- return `${base}${separator}${entries.join('&')}${hash}`
32
- }
33
-
34
- class URI {
35
- build(params = {}) {
36
- const uri = typeof params.uri === 'string' ? params.uri.trim() : ''
37
- if (!uri) {
38
- throw new Error('uri.open requires params.uri')
39
- }
40
- return appendQueryParams(uri, params.params)
41
- }
42
-
43
- async open(req, ondata, kernel) {
44
- const uri = this.build(req.params)
45
- ondata({ raw: `\r\nopening uri: ${uri}\r\n` })
46
- const result = await Util.openURI(uri)
47
- return { uri, result }
48
- }
49
- }
50
-
51
- module.exports = URI
@@ -1,236 +0,0 @@
1
- const fs = require("fs")
2
- const path = require("path")
3
- const { glob } = require("glob")
4
-
5
- const LOCAL_RUN_PREFIX = "/run"
6
- const LOCAL_ASSET_PREFIX = "/asset"
7
- const SYSTEM_RUN_PREFIX = "/pinokio/run"
8
- const SYSTEM_ASSET_PREFIX = "/pinokio/asset"
9
- const LOCAL_PLUGIN_RUN_PREFIX = `${LOCAL_RUN_PREFIX}/plugin`
10
- const LOCAL_PLUGIN_ASSET_PREFIX = `${LOCAL_ASSET_PREFIX}/plugin`
11
- const SYSTEM_PLUGIN_RUN_PREFIX = `${SYSTEM_RUN_PREFIX}/plugin`
12
- const SYSTEM_PLUGIN_ASSET_PREFIX = `${SYSTEM_ASSET_PREFIX}/plugin`
13
-
14
- const toPathname = (value) => {
15
- const raw = typeof value === "string" ? value.trim() : ""
16
- if (!raw) return ""
17
- try {
18
- if (/^https?:\/\//i.test(raw)) return new URL(raw).pathname
19
- if (raw.startsWith("/")) return new URL(`http://localhost${raw}`).pathname
20
- } catch (_) {
21
- }
22
- return raw.split("?")[0].split("#")[0]
23
- }
24
-
25
- const normalizeSlashes = (value) => String(value || "").replace(/\\/g, "/").replace(/\/{2,}/g, "/")
26
-
27
- const systemRoot = (kernel) => {
28
- if (kernel && typeof kernel.systemPath === "function") {
29
- return kernel.systemPath()
30
- }
31
- return path.resolve(__dirname, "..", "system")
32
- }
33
-
34
- const systemPluginRoot = (kernel) => {
35
- if (kernel && typeof kernel.systemPath === "function") {
36
- return kernel.systemPath("plugin")
37
- }
38
- return path.resolve(__dirname, "..", "system", "plugin")
39
- }
40
-
41
- const isSystemRunPath = (value) => toPathname(value).startsWith(`${SYSTEM_RUN_PREFIX}/`)
42
- const isLocalRunPath = (value) => toPathname(value).startsWith(`${LOCAL_RUN_PREFIX}/`)
43
- const isRunPath = (value) => isLocalRunPath(value) || isSystemRunPath(value)
44
- const isSystemPluginPath = (value) => normalizeSlashes(value).startsWith(`${SYSTEM_PLUGIN_RUN_PREFIX}/`)
45
- const isLegacyPluginCodePath = (value) => {
46
- const normalized = normalizeSlashes(value).replace(/^\/+/, "")
47
- return normalized.startsWith("plugin/code/") || normalized.startsWith("code/")
48
- }
49
-
50
- const normalizePluginPath = (value) => {
51
- let normalized = toPathname(value)
52
- if (!normalized) return ""
53
- normalized = normalizeSlashes(normalized)
54
- if (!normalized.startsWith(`${SYSTEM_RUN_PREFIX}/`)) {
55
- normalized = normalized.replace(/^\/run(?=\/)/, "")
56
- }
57
- if (!normalized.startsWith("/")) {
58
- normalized = `/${normalized}`
59
- }
60
- normalized = normalized.replace(/\/+$/, "")
61
- if (!normalized.endsWith("/pinokio.js")) {
62
- normalized = `${normalized}/pinokio.js`
63
- }
64
- return normalized
65
- }
66
-
67
- const pluginSelectionMatches = (src, selectedValue) => {
68
- const selectedPlugin = normalizeSlashes(typeof selectedValue === "string" ? selectedValue.trim() : "")
69
- if (!selectedPlugin || !src) return false
70
- const selectedRunPath = selectedPlugin.startsWith(`${SYSTEM_RUN_PREFIX}/`)
71
- ? selectedPlugin
72
- : `${LOCAL_RUN_PREFIX}${selectedPlugin}`
73
- return src === selectedPlugin || src.startsWith(selectedRunPath)
74
- }
75
-
76
- const resolveRunPath = (kernel, value) => {
77
- const pathname = toPathname(value)
78
- if (isSystemRunPath(pathname)) {
79
- const parts = pathname.split("/").filter(Boolean).slice(2)
80
- return kernel.systemPath(...parts)
81
- }
82
- if (isLocalRunPath(pathname)) {
83
- const parts = pathname.split("/").filter(Boolean).slice(1)
84
- return kernel.path(...parts)
85
- }
86
- return ""
87
- }
88
-
89
- const resolvePinokioPath = (kernel, value) => {
90
- const runPath = resolveRunPath(kernel, value)
91
- if (runPath) return runPath
92
- const pathname = toPathname(value)
93
- return pathname ? kernel.path(pathname.replace(/^\/+/, "")) : ""
94
- }
95
-
96
- const systemRelativeFromPluginPath = (normalizedPath) => {
97
- return normalizeSlashes(normalizedPath).replace(/^\/pinokio\/run\/+/, "")
98
- }
99
-
100
- const pluginPathToAbsolute = (kernel, normalizedPath) => {
101
- if (isSystemPluginPath(normalizedPath)) {
102
- return kernel.systemPath(systemRelativeFromPluginPath(normalizedPath))
103
- }
104
- return kernel.path(normalizeSlashes(normalizedPath).replace(/^\/+/, ""))
105
- }
106
-
107
- const pluginRunHrefForPath = (normalizedPath) => {
108
- if (typeof normalizedPath !== "string" || !normalizedPath) return ""
109
- if (isSystemPluginPath(normalizedPath)) return normalizedPath
110
- return `${LOCAL_RUN_PREFIX}${normalizedPath}`
111
- }
112
-
113
- const pluginAssetHrefForIcon = (normalizedPath, icon) => {
114
- const trimmedIcon = typeof icon === "string" ? icon.trim() : ""
115
- if (!trimmedIcon) return ""
116
- if (isSystemPluginPath(normalizedPath)) {
117
- const relativeDir = path.posix.dirname(systemRelativeFromPluginPath(normalizedPath))
118
- return `${SYSTEM_ASSET_PREFIX}/${relativeDir}/${trimmedIcon}`
119
- }
120
- if (normalizeSlashes(normalizedPath).startsWith("/plugin/")) {
121
- const relativeDir = path.posix.dirname(normalizeSlashes(normalizedPath).slice(1))
122
- return `${LOCAL_ASSET_PREFIX}/${relativeDir}/${trimmedIcon}`
123
- }
124
- return ""
125
- }
126
-
127
- const normalizeLauncherTool = (toolValue) => {
128
- let normalizedTool = typeof toolValue === "string" ? toolValue.trim() : ""
129
- normalizedTool = normalizedTool.replace(/^https?:\/\/[^/]+/i, "")
130
- normalizedTool = normalizedTool.replace(/^\/+|\/+$/g, "")
131
- if (!normalizedTool || normalizedTool.includes("..") || !/^[A-Za-z0-9._/-]+$/.test(normalizedTool)) {
132
- const error = new Error("Invalid plugin.")
133
- error.status = 400
134
- throw error
135
- }
136
- if (!normalizedTool.startsWith("pinokio/run/")) {
137
- normalizedTool = normalizedTool.replace(/^run\//, "")
138
- }
139
- if (isLegacyPluginCodePath(normalizedTool)) {
140
- const error = new Error("The managed plugin/code path is no longer used.")
141
- error.status = 400
142
- throw error
143
- }
144
- return normalizedTool
145
- }
146
-
147
- const resolveLauncherPluginHref = (toolValue) => {
148
- const normalizedTool = normalizeLauncherTool(toolValue)
149
- if (normalizedTool.startsWith("pinokio/run/")) {
150
- const scriptPath = normalizedTool.endsWith(".js")
151
- ? normalizedTool
152
- : `${normalizedTool}/pinokio.js`
153
- return `/${scriptPath}`
154
- }
155
- if (normalizedTool.startsWith("plugin/") || normalizedTool.startsWith("api/")) {
156
- const scriptPath = normalizedTool.endsWith(".js")
157
- ? normalizedTool
158
- : `${normalizedTool}/pinokio.js`
159
- return `${LOCAL_RUN_PREFIX}/${scriptPath}`
160
- }
161
- return `${LOCAL_PLUGIN_RUN_PREFIX}/${normalizedTool}/pinokio.js`
162
- }
163
-
164
- const loadPluginsFromRoot = async ({ kernel, root, runPrefix, assetPrefix, source, ignore = [] }) => {
165
- const exists = await fs.promises.stat(root).then((stat) => stat.isDirectory()).catch(() => false)
166
- if (!exists) return []
167
-
168
- const pluginPaths = await glob("**/pinokio.js", { cwd: root, ignore })
169
- const plugins = []
170
- for (const pluginPath of pluginPaths) {
171
- const normalizedPluginPath = normalizeSlashes(pluginPath)
172
- const config = await kernel.require(path.resolve(root, pluginPath))
173
- if (!config || !Array.isArray(config.run)) continue
174
- const invalid = Object.keys(config).some((key) => typeof config[key] === "function")
175
- if (invalid) continue
176
-
177
- const cwd = normalizedPluginPath.split("/").slice(0, -1).join("/")
178
- const href = `${runPrefix}/${normalizedPluginPath}`
179
- const image = config.icon ? `${assetPrefix}/${cwd}/${config.icon}` : config.image
180
- plugins.push({
181
- ...config,
182
- href,
183
- src: href,
184
- image,
185
- source,
186
- system: source === "system",
187
- })
188
- }
189
- return plugins
190
- }
191
-
192
- const loadPluginMenu = async (kernel) => {
193
- const systemPlugins = await loadPluginsFromRoot({
194
- kernel,
195
- root: systemPluginRoot(kernel),
196
- runPrefix: SYSTEM_PLUGIN_RUN_PREFIX,
197
- assetPrefix: SYSTEM_PLUGIN_ASSET_PREFIX,
198
- source: "system",
199
- })
200
- const localPlugins = await loadPluginsFromRoot({
201
- kernel,
202
- root: path.resolve(kernel.homedir, "plugin"),
203
- runPrefix: LOCAL_PLUGIN_RUN_PREFIX,
204
- assetPrefix: LOCAL_PLUGIN_ASSET_PREFIX,
205
- source: "local",
206
- ignore: ["code/**"],
207
- })
208
- return systemPlugins.concat(localPlugins)
209
- }
210
-
211
- module.exports = {
212
- LOCAL_RUN_PREFIX,
213
- LOCAL_ASSET_PREFIX,
214
- SYSTEM_RUN_PREFIX,
215
- SYSTEM_ASSET_PREFIX,
216
- LOCAL_PLUGIN_RUN_PREFIX,
217
- SYSTEM_PLUGIN_RUN_PREFIX,
218
- SYSTEM_PLUGIN_ASSET_PREFIX,
219
- systemRoot,
220
- systemPluginRoot,
221
- toPathname,
222
- isSystemRunPath,
223
- isLocalRunPath,
224
- isRunPath,
225
- isSystemPluginPath,
226
- isLegacyPluginCodePath,
227
- normalizePluginPath,
228
- pluginSelectionMatches,
229
- resolveRunPath,
230
- resolvePinokioPath,
231
- pluginPathToAbsolute,
232
- pluginRunHrefForPath,
233
- pluginAssetHrefForIcon,
234
- resolveLauncherPluginHref,
235
- loadPluginMenu,
236
- }
@@ -1,42 +0,0 @@
1
- const path = require("path")
2
- const { watchFs } = require("./drivers/fs")
3
- const { poll } = require("./drivers/poll")
4
-
5
- class WatchContext {
6
- constructor(options = {}) {
7
- this.kernel = options.kernel
8
- this.manager = options.manager
9
- this.id = options.id
10
- this.cwd = path.resolve(options.cwd)
11
- this.dirname = path.resolve(options.dirname || options.cwd)
12
- this.request = options.request
13
- this.script = options.script
14
- this.declaration = options.declaration
15
- this.input = options.input || {}
16
- this.args = options.args || this.input
17
- this.watch = {
18
- fs: (targetPath, callback, watchOptions = {}) => {
19
- return watchFs(this.resolve(targetPath), callback, {
20
- ...watchOptions,
21
- onError: watchOptions.onError || ((error) => {
22
- console.warn("[watch.fs]", error && error.message ? error.message : error)
23
- })
24
- })
25
- }
26
- }
27
- }
28
-
29
- resolve(targetPath) {
30
- return this.kernel.api.resolvePath(this.cwd, String(targetPath || "."))
31
- }
32
-
33
- resolveModule(targetPath) {
34
- return this.kernel.api.resolvePath(this.dirname, String(targetPath || "."))
35
- }
36
-
37
- poll(interval, callback, options = {}) {
38
- return poll(interval, callback, options)
39
- }
40
- }
41
-
42
- module.exports = WatchContext
@@ -1,71 +0,0 @@
1
- const fs = require("fs")
2
- const path = require("path")
3
- const ParcelWatcher = require("@parcel/watcher")
4
-
5
- const DEFAULT_IGNORE = [
6
- "**/.git/**",
7
- "**/node_modules/**",
8
- "**/__pycache__/**",
9
- "**/.venv/**",
10
- "**/venv/**",
11
- "**/env/**"
12
- ]
13
-
14
- function isInside(candidate, parent) {
15
- const relative = path.relative(parent, candidate)
16
- return relative === "" || (!!relative && !relative.startsWith("..") && !path.isAbsolute(relative))
17
- }
18
-
19
- async function nearestExistingDirectory(targetPath) {
20
- let current = path.resolve(targetPath)
21
- while (current && current !== path.dirname(current)) {
22
- const stats = await fs.promises.stat(current).catch(() => null)
23
- if (stats && stats.isDirectory()) {
24
- return current
25
- }
26
- current = path.dirname(current)
27
- }
28
- return current || path.parse(path.resolve(targetPath)).root
29
- }
30
-
31
- async function watchFs(targetPath, callback, options = {}) {
32
- const resolvedTarget = path.resolve(targetPath)
33
- const targetStats = await fs.promises.stat(resolvedTarget).catch(() => null)
34
- const watchRoot = targetStats && targetStats.isDirectory()
35
- ? resolvedTarget
36
- : await nearestExistingDirectory(resolvedTarget)
37
- const filterToTarget = watchRoot !== resolvedTarget
38
-
39
- const subscription = await ParcelWatcher.subscribe(
40
- watchRoot,
41
- (error, events) => {
42
- if (error) {
43
- if (typeof options.onError === "function") {
44
- options.onError(error)
45
- }
46
- return
47
- }
48
- const normalizedEvents = Array.isArray(events) ? events : []
49
- const filteredEvents = filterToTarget
50
- ? normalizedEvents.filter((event) => event && event.path && isInside(path.resolve(event.path), resolvedTarget))
51
- : normalizedEvents
52
- if (filteredEvents.length === 0) {
53
- return
54
- }
55
- callback(filteredEvents)
56
- },
57
- {
58
- ignore: Array.isArray(options.ignore) ? options.ignore : DEFAULT_IGNORE
59
- }
60
- )
61
-
62
- return async () => {
63
- if (subscription && typeof subscription.unsubscribe === "function") {
64
- await subscription.unsubscribe().catch(() => {})
65
- }
66
- }
67
- }
68
-
69
- module.exports = {
70
- watchFs
71
- }
@@ -1,33 +0,0 @@
1
- function poll(interval, callback, options = {}) {
2
- const delay = Math.max(100, Number(interval || options.interval || 1000))
3
- let stopped = false
4
- let running = false
5
-
6
- const tick = async () => {
7
- if (stopped || running) return
8
- running = true
9
- try {
10
- await callback()
11
- } catch (error) {
12
- if (typeof options.onError === "function") {
13
- options.onError(error)
14
- }
15
- } finally {
16
- running = false
17
- }
18
- }
19
-
20
- if (options.immediate !== false) {
21
- setTimeout(tick, 0)
22
- }
23
- const timer = setInterval(tick, delay)
24
-
25
- return async () => {
26
- stopped = true
27
- clearInterval(timer)
28
- }
29
- }
30
-
31
- module.exports = {
32
- poll
33
- }