pinokiod 7.2.18 → 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.
- package/Dockerfile +2 -0
- package/kernel/api/index.js +13 -179
- package/kernel/api/process/index.js +44 -99
- package/kernel/bin/conda-python.js +30 -0
- package/kernel/bin/conda.js +22 -3
- package/kernel/bin/huggingface.js +1 -1
- package/kernel/bin/index.js +11 -1
- package/kernel/environment.js +11 -205
- package/kernel/git.js +13 -0
- package/kernel/index.js +1 -64
- package/kernel/plugin.js +58 -6
- package/kernel/prototype.js +0 -4
- package/kernel/shell.js +2 -23
- package/kernel/util.js +0 -60
- package/package.json +1 -1
- package/server/index.js +171 -229
- package/server/lib/content_validation.js +33 -47
- package/server/public/common.js +29 -103
- package/server/public/create-launcher.js +31 -4
- package/server/public/electron.css +6 -0
- package/server/public/style.css +0 -337
- package/server/public/task-launcher.css +3 -11
- package/server/public/task-launcher.js +32 -5
- package/server/public/universal-launcher.js +26 -3
- package/server/socket.js +11 -22
- package/server/views/app.ejs +30 -167
- package/server/views/d.ejs +35 -33
- package/server/views/editor.ejs +4 -25
- package/server/views/partials/main_sidebar.ejs +0 -1
- package/server/views/partials/menu.ejs +1 -1
- package/server/views/pre.ejs +1 -1
- package/server/views/shell.ejs +3 -11
- package/server/views/task_launch.ejs +10 -10
- package/server/views/terminal.ejs +5 -34
- package/spec/INSTRUCTION_SYNC.md +5 -5
- package/kernel/agent_instructions.js +0 -166
- package/kernel/api/shell_run_template.js +0 -273
- package/kernel/api/uri/index.js +0 -51
- package/kernel/plugin_sources.js +0 -289
- package/kernel/watch/context.js +0 -42
- package/kernel/watch/drivers/fs.js +0 -71
- package/kernel/watch/drivers/poll.js +0 -33
- package/kernel/watch/index.js +0 -185
- package/server/features/index.js +0 -13
- package/server/features/notes/index.js +0 -41
- package/server/features/notes/parser.js +0 -174
- package/server/features/notes/public/notes.css +0 -955
- package/server/features/notes/public/notes.js +0 -1149
- package/server/features/notes/registry_import.js +0 -412
- package/server/features/notes/routes.js +0 -156
- package/server/features/notes/service.js +0 -326
- package/server/features/notes/watcher.js +0 -74
- package/server/lib/workspace_catalog.js +0 -151
- package/server/lib/workspace_runtime.js +0 -390
- package/server/public/tasker.css +0 -336
- package/server/public/tasker.js +0 -407
- package/server/routes/workspaces.js +0 -44
- package/server/views/partials/workspace_row.ejs +0 -61
- package/server/views/tasker.ejs +0 -40
- package/server/views/workspaces.ejs +0 -813
- package/system/plugin/antigravity/antigravity.png +0 -0
- package/system/plugin/antigravity/pinokio.js +0 -35
- package/system/plugin/claude/claude.png +0 -0
- package/system/plugin/claude/pinokio.js +0 -61
- package/system/plugin/claude-auto/claude.png +0 -0
- package/system/plugin/claude-auto/pinokio.js +0 -72
- package/system/plugin/claude-desktop/icon.jpeg +0 -0
- package/system/plugin/claude-desktop/pinokio.js +0 -37
- package/system/plugin/codex/openai.webp +0 -0
- package/system/plugin/codex/pinokio.js +0 -56
- package/system/plugin/codex-auto/openai.webp +0 -0
- package/system/plugin/codex-auto/pinokio.js +0 -63
- package/system/plugin/codex-desktop/icon.png +0 -0
- package/system/plugin/codex-desktop/pinokio.js +0 -37
- package/system/plugin/crush/crush.png +0 -0
- package/system/plugin/crush/pinokio.js +0 -29
- package/system/plugin/cursor/cursor.jpeg +0 -0
- package/system/plugin/cursor/pinokio.js +0 -37
- package/system/plugin/gemini/gemini.jpeg +0 -0
- package/system/plugin/gemini/pinokio.js +0 -38
- package/system/plugin/gemini-auto/gemini.jpeg +0 -0
- package/system/plugin/gemini-auto/pinokio.js +0 -41
- package/system/plugin/qwen/pinokio.js +0 -48
- package/system/plugin/qwen/qwen.png +0 -0
- package/system/plugin/vscode/pinokio.js +0 -34
- package/system/plugin/vscode/vscode.png +0 -0
- package/system/plugin/windsurf/pinokio.js +0 -37
- package/system/plugin/windsurf/windsurf.png +0 -0
- package/test/plugin-sources.test.js +0 -45
package/server/index.js
CHANGED
|
@@ -28,8 +28,6 @@ const system = require('systeminformation')
|
|
|
28
28
|
const serveIndex = require('./serveIndex')
|
|
29
29
|
const registerFileRoutes = require('./routes/files')
|
|
30
30
|
const registerAppRoutes = require('./routes/apps')
|
|
31
|
-
const registerWorkspacesRoutes = require('./routes/workspaces')
|
|
32
|
-
const { mountFeatures } = require('./features')
|
|
33
31
|
const Git = require("../kernel/git")
|
|
34
32
|
const TerminalApi = require('../kernel/api/terminal')
|
|
35
33
|
|
|
@@ -78,11 +76,8 @@ const { createLauncherInstructionBootstrap } = require("./lib/launcher_instructi
|
|
|
78
76
|
const { createTerminalGitResetHandler } = require("./lib/terminal_git_reset")
|
|
79
77
|
const { createDesktopEventRouter } = require("./lib/desktop_event_router")
|
|
80
78
|
const { createInjectRouter, resolveInjectList } = require("./lib/inject_router")
|
|
81
|
-
const PluginSources = require("../kernel/plugin_sources")
|
|
82
79
|
const { createTaskPackageService } = require("./lib/task_packages")
|
|
83
80
|
const { createTaskWorkspaceLinkService } = require("./lib/task_workspace_links")
|
|
84
|
-
const { createWorkspaceRuntimeService } = require("./lib/workspace_runtime")
|
|
85
|
-
const { createWorkspaceCatalogService } = require("./lib/workspace_catalog")
|
|
86
81
|
const { createContentValidationService } = require("./lib/content_validation")
|
|
87
82
|
const { buildSecureRouterDebugSnapshot, createSecureRouterDebugStore } = require("./lib/secure_router_debug")
|
|
88
83
|
const AppRegistryService = require("./lib/app_registry")
|
|
@@ -496,12 +491,14 @@ class Server {
|
|
|
496
491
|
assignProjectSlug(obj)
|
|
497
492
|
running_dynamic.push(obj)
|
|
498
493
|
}
|
|
499
|
-
} else if (
|
|
500
|
-
let
|
|
494
|
+
} else if (href.startsWith("/run")) {
|
|
495
|
+
let uri_path = new URL("http://localhost" + href).pathname
|
|
496
|
+
let _filepath = uri_path.split("/").filter(x=>x).slice(1)
|
|
497
|
+
let filepath = this.kernel.path(..._filepath)
|
|
501
498
|
let id = `${filepath}?cwd=${cwd}`
|
|
502
499
|
obj.script_id = id
|
|
503
500
|
//if (this.kernel.api.running[filepath]) {
|
|
504
|
-
if (
|
|
501
|
+
if (obj.src.startsWith("/run" + selected_query.plugin)) {
|
|
505
502
|
obj.running = true
|
|
506
503
|
obj.display = "indent"
|
|
507
504
|
obj.default = true
|
|
@@ -2396,10 +2393,8 @@ class Server {
|
|
|
2396
2393
|
filepath = full_filepath
|
|
2397
2394
|
}
|
|
2398
2395
|
|
|
2399
|
-
if ((req.action ||
|
|
2400
|
-
const validation = await this.contentValidation.validateRunPath(pathComponents
|
|
2401
|
-
system: req.pinokioSystem === true,
|
|
2402
|
-
})
|
|
2396
|
+
if ((req.action || req.originalUrl.startsWith("/run/")) && this.contentValidation) {
|
|
2397
|
+
const validation = await this.contentValidation.validateRunPath(pathComponents)
|
|
2403
2398
|
if (validation && !validation.valid) {
|
|
2404
2399
|
await this.renderInvalidContentPage(req, res, validation, {
|
|
2405
2400
|
sidebarSelected: validation.type === "plugin" ? "plugins" : validation.type === "task" ? "tasks" : "home",
|
|
@@ -2758,12 +2753,10 @@ class Server {
|
|
|
2758
2753
|
} else {
|
|
2759
2754
|
resolved = runner(this.kernel, this.kernel.info)
|
|
2760
2755
|
}
|
|
2761
|
-
|
|
2762
|
-
runnable = typeof action === "function" || (Array.isArray(action) && action.length > 0)
|
|
2756
|
+
runnable = resolved && Array.isArray(resolved[actionKey]) && resolved[actionKey].length > 0
|
|
2763
2757
|
} else {
|
|
2758
|
+
runnable = runner && Array.isArray(runner[actionKey]) && runner[actionKey].length > 0
|
|
2764
2759
|
resolved = runner
|
|
2765
|
-
const action = resolved ? resolved[actionKey] : null
|
|
2766
|
-
runnable = typeof action === "function" || (Array.isArray(action) && action.length > 0)
|
|
2767
2760
|
}
|
|
2768
2761
|
|
|
2769
2762
|
let template = "terminal"
|
|
@@ -2872,27 +2865,11 @@ class Server {
|
|
|
2872
2865
|
const protectionPreference = protectionAppId && this.appPreferences && typeof this.appPreferences.getPreference === "function"
|
|
2873
2866
|
? await this.appPreferences.getPreference(protectionAppId)
|
|
2874
2867
|
: null
|
|
2875
|
-
const noteWatchEnabled = this.kernel.watch && typeof this.kernel.watch.hasHandler === "function"
|
|
2876
|
-
? this.kernel.watch.hasHandler(resolved, "note")
|
|
2877
|
-
: false
|
|
2878
|
-
const noteWatchCwd = noteWatchEnabled
|
|
2879
|
-
? (req.query.cwd || path.dirname(filepath))
|
|
2880
|
-
: ""
|
|
2881
|
-
const activeProcessWait = this.kernel.activeProcessWaits && this.kernel.activeProcessWaits[filepath]
|
|
2882
|
-
? this.kernel.activeProcessWaits[filepath]
|
|
2883
|
-
: null
|
|
2884
2868
|
const result = {
|
|
2885
2869
|
portal: this.portal,
|
|
2886
2870
|
projectName: (pathComponents.length > 0 ? pathComponents[0] : ''),
|
|
2887
2871
|
protection_app_id: protectionAppId,
|
|
2888
2872
|
protection_enabled: protectionPreference ? protectionPreference.protection_enabled !== false : false,
|
|
2889
|
-
note_watch_enabled: noteWatchEnabled,
|
|
2890
|
-
note_watch_cwd: noteWatchCwd,
|
|
2891
|
-
active_process_wait: activeProcessWait ? {
|
|
2892
|
-
title: activeProcessWait.title,
|
|
2893
|
-
description: activeProcessWait.description,
|
|
2894
|
-
message: activeProcessWait.message
|
|
2895
|
-
} : null,
|
|
2896
2873
|
kill_message,
|
|
2897
2874
|
callback,
|
|
2898
2875
|
callback_target,
|
|
@@ -2907,7 +2884,6 @@ class Server {
|
|
|
2907
2884
|
//run: true, // run mode by default
|
|
2908
2885
|
run: (req.query && req.query.mode === "source" ? false : true),
|
|
2909
2886
|
stop: (req.query && req.query.stop ? true : false),
|
|
2910
|
-
readonly: req.pinokioSystem === true,
|
|
2911
2887
|
pinokioPath,
|
|
2912
2888
|
action: actionKey,
|
|
2913
2889
|
runnable,
|
|
@@ -3124,7 +3100,6 @@ class Server {
|
|
|
3124
3100
|
if (pathComponents.length === 0) {
|
|
3125
3101
|
const normalizedApiRoot = path.normalize(this.kernel.path("api"))
|
|
3126
3102
|
const normalizedPluginRoot = path.normalize(this.kernel.path("plugin"))
|
|
3127
|
-
const normalizedSystemPluginRoot = path.normalize(PluginSources.systemPluginRoot(this.kernel))
|
|
3128
3103
|
const isPathWithinRoot = (candidatePath, rootPath) => {
|
|
3129
3104
|
if (typeof candidatePath !== "string" || typeof rootPath !== "string") {
|
|
3130
3105
|
return false
|
|
@@ -3150,9 +3125,6 @@ class Server {
|
|
|
3150
3125
|
if (isPathWithinRoot(normalizedCandidate, normalizedPluginRoot)) {
|
|
3151
3126
|
return true
|
|
3152
3127
|
}
|
|
3153
|
-
if (isPathWithinRoot(normalizedCandidate, normalizedSystemPluginRoot)) {
|
|
3154
|
-
return true
|
|
3155
|
-
}
|
|
3156
3128
|
const relativeToApiRoot = path.relative(normalizedApiRoot, normalizedCandidate)
|
|
3157
3129
|
if (!relativeToApiRoot || relativeToApiRoot.startsWith("..") || path.isAbsolute(relativeToApiRoot)) {
|
|
3158
3130
|
return false
|
|
@@ -3966,7 +3938,8 @@ class Server {
|
|
|
3966
3938
|
if (menuitem.href.startsWith("http")) {
|
|
3967
3939
|
menuitem.src = menuitem.href
|
|
3968
3940
|
} else if (menuitem.href.startsWith("/")) {
|
|
3969
|
-
|
|
3941
|
+
let run_path = "/run"
|
|
3942
|
+
if (menuitem.href.startsWith(run_path)) {
|
|
3970
3943
|
menuitem.src = menuitem.href
|
|
3971
3944
|
// u = new URL("http://localhost" + menuitem.href.slice(run_path.length))
|
|
3972
3945
|
// cwd = u.searchParams.get("cwd")
|
|
@@ -3986,14 +3959,7 @@ class Server {
|
|
|
3986
3959
|
}
|
|
3987
3960
|
|
|
3988
3961
|
// check running
|
|
3989
|
-
let
|
|
3990
|
-
try {
|
|
3991
|
-
srcPathname = new URL("http://localhost" + menuitem.src).pathname
|
|
3992
|
-
} catch (_) {
|
|
3993
|
-
}
|
|
3994
|
-
let fullpath = PluginSources.isRunPath(srcPathname)
|
|
3995
|
-
? PluginSources.resolveRunPath(this.kernel, srcPathname)
|
|
3996
|
-
: this.kernel.path(srcPathname.slice(1))
|
|
3962
|
+
let fullpath = this.kernel.path(menuitem.src.slice(1))
|
|
3997
3963
|
let relpath = path.relative(this.kernel.homedir, fullpath)
|
|
3998
3964
|
if (relpath.startsWith("api")) {
|
|
3999
3965
|
// api script
|
|
@@ -5313,7 +5279,15 @@ class Server {
|
|
|
5313
5279
|
return normalized
|
|
5314
5280
|
}
|
|
5315
5281
|
isValidBundledPluginConfig(pluginConfig) {
|
|
5316
|
-
|
|
5282
|
+
if (!pluginConfig || !Array.isArray(pluginConfig.run)) {
|
|
5283
|
+
return false
|
|
5284
|
+
}
|
|
5285
|
+
for (const key of Object.keys(pluginConfig)) {
|
|
5286
|
+
if (typeof pluginConfig[key] === "function") {
|
|
5287
|
+
return false
|
|
5288
|
+
}
|
|
5289
|
+
}
|
|
5290
|
+
return true
|
|
5317
5291
|
}
|
|
5318
5292
|
isPathInsideRootForBundledPlugin(candidatePath, rootPath) {
|
|
5319
5293
|
const relative = path.relative(rootPath, candidatePath)
|
|
@@ -5699,6 +5673,7 @@ class Server {
|
|
|
5699
5673
|
"prototype/PTERM.md",
|
|
5700
5674
|
]
|
|
5701
5675
|
const managedRefreshTargets = [
|
|
5676
|
+
"plugin/code",
|
|
5702
5677
|
"prototype/system",
|
|
5703
5678
|
"network/system",
|
|
5704
5679
|
"prototype/PINOKIO.md",
|
|
@@ -5720,16 +5695,6 @@ class Server {
|
|
|
5720
5695
|
|
|
5721
5696
|
needsManagedRefresh = true
|
|
5722
5697
|
console.log("[TRY] Updating to the new version")
|
|
5723
|
-
let envPath = path.resolve(home, "ENVIRONMENT")
|
|
5724
|
-
let envExists = await this.kernel.exists(envPath)
|
|
5725
|
-
if (!envExists) {
|
|
5726
|
-
let str = await Environment.ENV("system", home, this.kernel)
|
|
5727
|
-
await fs.promises.writeFile(envPath, str)
|
|
5728
|
-
}
|
|
5729
|
-
await Environment.ensurePinokioCacheDirs(this.kernel, {
|
|
5730
|
-
throwOnFailure: true,
|
|
5731
|
-
elevatedRepair: this.kernel.elevatedCacheRepair.bind(this.kernel)
|
|
5732
|
-
})
|
|
5733
5698
|
this.kernel.store.set("version", this.version.pinokiod)
|
|
5734
5699
|
console.log("[DONE] Updating to the new version")
|
|
5735
5700
|
console.log("not up to date. update py.")
|
|
@@ -5742,6 +5707,9 @@ class Server {
|
|
|
5742
5707
|
let p2 = path.resolve(home, "prototype/system")
|
|
5743
5708
|
await fse.remove(p2)
|
|
5744
5709
|
|
|
5710
|
+
let p3 = path.resolve(home, "plugin/code")
|
|
5711
|
+
await fse.remove(p3)
|
|
5712
|
+
|
|
5745
5713
|
let p4 = path.resolve(home, "network/system")
|
|
5746
5714
|
await fse.remove(p4)
|
|
5747
5715
|
|
|
@@ -5810,6 +5778,10 @@ class Server {
|
|
|
5810
5778
|
await this.kernel.proto.init()
|
|
5811
5779
|
}
|
|
5812
5780
|
if (needsManagedRefresh) {
|
|
5781
|
+
const pluginReady = await this.kernel.exists("plugin/code")
|
|
5782
|
+
if (!pluginReady && this.kernel.plugin && typeof this.kernel.plugin.init === "function") {
|
|
5783
|
+
await this.kernel.plugin.init()
|
|
5784
|
+
}
|
|
5813
5785
|
const networkReady = await this.kernel.exists("network/system")
|
|
5814
5786
|
if (!networkReady && this.kernel.router && typeof this.kernel.router.init === "function") {
|
|
5815
5787
|
await this.kernel.router.init()
|
|
@@ -5990,10 +5962,6 @@ class Server {
|
|
|
5990
5962
|
})
|
|
5991
5963
|
this.app.use(express.static(path.resolve(__dirname, 'public')));
|
|
5992
5964
|
this.app.use("/web", express.static(path.resolve(__dirname, "..", "..", "web")))
|
|
5993
|
-
this.app.use(PluginSources.SYSTEM_ASSET_PREFIX, express.static(PluginSources.systemRoot(this.kernel), {
|
|
5994
|
-
index: false,
|
|
5995
|
-
fallthrough: true,
|
|
5996
|
-
}))
|
|
5997
5965
|
this.app.set('view engine', 'ejs');
|
|
5998
5966
|
this.app.use((req, res, next) => {
|
|
5999
5967
|
const peerForwarded = (req.get('X-Pinokio-Peer') || '').trim().toLowerCase()
|
|
@@ -6776,7 +6744,24 @@ class Server {
|
|
|
6776
6744
|
}
|
|
6777
6745
|
}
|
|
6778
6746
|
const normalizePluginPath = (value) => {
|
|
6779
|
-
|
|
6747
|
+
let normalized = typeof value === "string" ? value.trim() : ""
|
|
6748
|
+
if (!normalized) {
|
|
6749
|
+
return ""
|
|
6750
|
+
}
|
|
6751
|
+
normalized = normalized.replace(/\\/g, "/")
|
|
6752
|
+
if (/^https?:\/\//i.test(normalized)) {
|
|
6753
|
+
try {
|
|
6754
|
+
const parsed = new URL(normalized)
|
|
6755
|
+
normalized = parsed.pathname || ""
|
|
6756
|
+
} catch (_) {
|
|
6757
|
+
}
|
|
6758
|
+
}
|
|
6759
|
+
normalized = normalized.replace(/^\/run(?=\/)/, "")
|
|
6760
|
+
if (!normalized.startsWith("/")) {
|
|
6761
|
+
normalized = `/${normalized}`
|
|
6762
|
+
}
|
|
6763
|
+
normalized = normalized.replace(/\/{2,}/g, "/").replace(/\/+$/, "")
|
|
6764
|
+
return normalized
|
|
6780
6765
|
}
|
|
6781
6766
|
const normalizePluginLookupKey = (value) => {
|
|
6782
6767
|
const normalized = normalizePluginPath(value)
|
|
@@ -6851,9 +6836,9 @@ class Server {
|
|
|
6851
6836
|
cwd: typeof pluginItem.ownerApp.cwd === "string" ? pluginItem.ownerApp.cwd : "",
|
|
6852
6837
|
}
|
|
6853
6838
|
: null,
|
|
6854
|
-
hasInstall:
|
|
6855
|
-
hasUninstall:
|
|
6856
|
-
hasUpdate:
|
|
6839
|
+
hasInstall: Array.isArray(pluginItem?.install),
|
|
6840
|
+
hasUninstall: Array.isArray(pluginItem?.uninstall),
|
|
6841
|
+
hasUpdate: Array.isArray(pluginItem?.update),
|
|
6857
6842
|
category,
|
|
6858
6843
|
categoryTitle: category === "ide" ? "Desktop Plugin" : "Terminal Plugin",
|
|
6859
6844
|
categorySubtitle: category === "ide" ? "Launch externally" : "Launch in Pinokio",
|
|
@@ -6923,7 +6908,7 @@ class Server {
|
|
|
6923
6908
|
index: -1,
|
|
6924
6909
|
title: context.title || "Plugin",
|
|
6925
6910
|
description: typeof config.description === "string" ? config.description : "",
|
|
6926
|
-
href:
|
|
6911
|
+
href: `/run${normalizedPluginPath}`,
|
|
6927
6912
|
link: typeof config.link === "string" ? config.link : "",
|
|
6928
6913
|
image: context.image || null,
|
|
6929
6914
|
icon: null,
|
|
@@ -6948,31 +6933,24 @@ class Server {
|
|
|
6948
6933
|
}
|
|
6949
6934
|
const resolvePluginLocalState = async (plugin) => {
|
|
6950
6935
|
const pluginRoot = path.resolve(this.kernel.path("plugin"))
|
|
6936
|
+
const managedRoot = path.resolve(pluginRoot, "code")
|
|
6951
6937
|
const normalizedPath = normalizePluginPath(plugin && plugin.pluginPath ? plugin.pluginPath : "")
|
|
6952
6938
|
const emptyState = {
|
|
6953
6939
|
ownership: "bundled",
|
|
6954
6940
|
manageable: false,
|
|
6955
6941
|
canOpenFolder: false,
|
|
6956
6942
|
pluginRoot,
|
|
6943
|
+
managedRoot,
|
|
6957
6944
|
pluginFilePath: "",
|
|
6958
6945
|
pluginDir: "",
|
|
6959
6946
|
relativeDir: "",
|
|
6960
6947
|
relativeFile: "",
|
|
6961
6948
|
localLabel: "",
|
|
6962
|
-
|
|
6963
|
-
if (PluginSources.isSystemPluginPath(normalizedPath)) {
|
|
6964
|
-
return {
|
|
6965
|
-
...emptyState,
|
|
6966
|
-
ownership: "system",
|
|
6967
|
-
localLabel: normalizedPath.replace(/^\/pinokio\/run\//, ""),
|
|
6968
|
-
}
|
|
6949
|
+
managedPrefix: "",
|
|
6969
6950
|
}
|
|
6970
6951
|
if (!normalizedPath.startsWith("/plugin/")) {
|
|
6971
6952
|
return emptyState
|
|
6972
6953
|
}
|
|
6973
|
-
if (PluginSources.isLegacyPluginCodePath(normalizedPath)) {
|
|
6974
|
-
return emptyState
|
|
6975
|
-
}
|
|
6976
6954
|
const pluginFilePath = path.resolve(this.kernel.path(normalizedPath.slice(1)))
|
|
6977
6955
|
if (!isPathInsideRoot(pluginFilePath, pluginRoot)) {
|
|
6978
6956
|
return emptyState
|
|
@@ -6992,16 +6970,22 @@ class Server {
|
|
|
6992
6970
|
}
|
|
6993
6971
|
const relativeFile = path.relative(pluginRoot, pluginFilePath).split(path.sep).join("/")
|
|
6994
6972
|
const relativeDir = path.relative(pluginRoot, pluginDir).split(path.sep).join("/")
|
|
6973
|
+
const isManaged = isPathInsideRoot(pluginFilePath, managedRoot)
|
|
6974
|
+
const managedPrefix = isManaged
|
|
6975
|
+
? path.relative(managedRoot, pluginDir).split(path.sep).join("/")
|
|
6976
|
+
: ""
|
|
6995
6977
|
return {
|
|
6996
|
-
ownership: "local",
|
|
6997
|
-
manageable: Boolean(pluginFileExists && pluginDirExists),
|
|
6978
|
+
ownership: isManaged ? "managed" : "local",
|
|
6979
|
+
manageable: Boolean(pluginFileExists && pluginDirExists && !isManaged),
|
|
6998
6980
|
canOpenFolder: Boolean(pluginFileExists && pluginDirExists),
|
|
6999
6981
|
pluginRoot,
|
|
6982
|
+
managedRoot,
|
|
7000
6983
|
pluginFilePath,
|
|
7001
6984
|
pluginDir,
|
|
7002
6985
|
relativeDir,
|
|
7003
6986
|
relativeFile,
|
|
7004
6987
|
localLabel: relativeDir ? `plugin/${relativeDir}` : "plugin",
|
|
6988
|
+
managedPrefix,
|
|
7005
6989
|
}
|
|
7006
6990
|
}
|
|
7007
6991
|
const collectPluginApps = async (boundAppName = "") => {
|
|
@@ -7045,31 +7029,11 @@ class Server {
|
|
|
7045
7029
|
})
|
|
7046
7030
|
return apps
|
|
7047
7031
|
}
|
|
7048
|
-
|
|
7049
|
-
|
|
7050
|
-
if (localState.ownership === "
|
|
7032
|
+
const buildPluginShareState = async (plugin) => {
|
|
7033
|
+
const localState = await resolvePluginLocalState(plugin)
|
|
7034
|
+
if (localState.ownership === "bundled") {
|
|
7051
7035
|
return {
|
|
7052
|
-
ownership: "
|
|
7053
|
-
manageable: false,
|
|
7054
|
-
canOpenFolder: false,
|
|
7055
|
-
dir: "",
|
|
7056
|
-
localLabel: localState.localLabel || "",
|
|
7057
|
-
remoteUrl: "",
|
|
7058
|
-
remoteWebUrl: "",
|
|
7059
|
-
githubConnected: false,
|
|
7060
|
-
gitInitialized: false,
|
|
7061
|
-
hasCommit: false,
|
|
7062
|
-
changeCount: 0,
|
|
7063
|
-
changes: [],
|
|
7064
|
-
branch: "HEAD",
|
|
7065
|
-
commitUrl: "",
|
|
7066
|
-
createUrl: "",
|
|
7067
|
-
pushUrl: "",
|
|
7068
|
-
}
|
|
7069
|
-
}
|
|
7070
|
-
if (localState.ownership === "bundled") {
|
|
7071
|
-
return {
|
|
7072
|
-
ownership: "bundled",
|
|
7036
|
+
ownership: "bundled",
|
|
7073
7037
|
manageable: false,
|
|
7074
7038
|
canOpenFolder: false,
|
|
7075
7039
|
dir: "",
|
|
@@ -7089,21 +7053,49 @@ class Server {
|
|
|
7089
7053
|
}
|
|
7090
7054
|
|
|
7091
7055
|
if (localState.ownership === "managed") {
|
|
7056
|
+
let changes = []
|
|
7057
|
+
try {
|
|
7058
|
+
const headStatus = await this.getRepoHeadStatusByDir(localState.managedRoot)
|
|
7059
|
+
const allChanges = Array.isArray(headStatus && headStatus.changes) ? headStatus.changes : []
|
|
7060
|
+
const managedPrefix = typeof localState.managedPrefix === "string" ? localState.managedPrefix.trim() : ""
|
|
7061
|
+
changes = allChanges
|
|
7062
|
+
.filter((change) => {
|
|
7063
|
+
const file = change && typeof change.file === "string" ? change.file : ""
|
|
7064
|
+
if (!managedPrefix) {
|
|
7065
|
+
return true
|
|
7066
|
+
}
|
|
7067
|
+
return file === managedPrefix || file.startsWith(`${managedPrefix}/`)
|
|
7068
|
+
})
|
|
7069
|
+
.map((change) => {
|
|
7070
|
+
const file = change && typeof change.file === "string" ? change.file : ""
|
|
7071
|
+
if (!managedPrefix || !file) {
|
|
7072
|
+
return change
|
|
7073
|
+
}
|
|
7074
|
+
const relativeFile = file === managedPrefix
|
|
7075
|
+
? path.posix.basename(managedPrefix)
|
|
7076
|
+
: file.slice(managedPrefix.length + 1)
|
|
7077
|
+
return {
|
|
7078
|
+
...change,
|
|
7079
|
+
file: relativeFile || file
|
|
7080
|
+
}
|
|
7081
|
+
})
|
|
7082
|
+
} catch (_) {
|
|
7083
|
+
}
|
|
7092
7084
|
return {
|
|
7093
|
-
ownership: "
|
|
7085
|
+
ownership: "managed",
|
|
7094
7086
|
manageable: false,
|
|
7095
|
-
canOpenFolder:
|
|
7096
|
-
dir:
|
|
7097
|
-
localLabel:
|
|
7098
|
-
relativeDir:
|
|
7099
|
-
relativeFile:
|
|
7087
|
+
canOpenFolder: Boolean(localState.canOpenFolder),
|
|
7088
|
+
dir: localState.pluginDir,
|
|
7089
|
+
localLabel: localState.localLabel,
|
|
7090
|
+
relativeDir: localState.relativeDir,
|
|
7091
|
+
relativeFile: localState.relativeFile,
|
|
7100
7092
|
remoteUrl: "",
|
|
7101
7093
|
remoteWebUrl: "",
|
|
7102
7094
|
githubConnected: false,
|
|
7103
7095
|
gitInitialized: false,
|
|
7104
7096
|
hasCommit: false,
|
|
7105
|
-
changeCount:
|
|
7106
|
-
changes
|
|
7097
|
+
changeCount: changes.length,
|
|
7098
|
+
changes,
|
|
7107
7099
|
branch: "HEAD",
|
|
7108
7100
|
commitUrl: "",
|
|
7109
7101
|
createUrl: "",
|
|
@@ -7179,19 +7171,14 @@ class Server {
|
|
|
7179
7171
|
: ""
|
|
7180
7172
|
const remoteLabel = summarizeTaskRemoteLabel(remoteCandidate)
|
|
7181
7173
|
const badges = []
|
|
7182
|
-
|
|
7183
|
-
badges.push({
|
|
7184
|
-
label: "Local plugin",
|
|
7185
|
-
tone: "accent"
|
|
7186
|
-
})
|
|
7187
|
-
} else if (ownership === "system") {
|
|
7174
|
+
if (ownership === "local") {
|
|
7188
7175
|
badges.push({
|
|
7189
|
-
label: "
|
|
7190
|
-
tone: "
|
|
7176
|
+
label: "Local plugin",
|
|
7177
|
+
tone: "accent"
|
|
7191
7178
|
})
|
|
7192
|
-
|
|
7193
|
-
|
|
7194
|
-
|
|
7179
|
+
} else if (ownership === "managed") {
|
|
7180
|
+
badges.push({
|
|
7181
|
+
label: "Managed by Pinokio",
|
|
7195
7182
|
tone: "neutral"
|
|
7196
7183
|
})
|
|
7197
7184
|
} else {
|
|
@@ -7236,12 +7223,13 @@ class Server {
|
|
|
7236
7223
|
: (shareState.gitInitialized ? "No local changes" : "Not version tracked yet")
|
|
7237
7224
|
githubPanelTitle = "GitHub"
|
|
7238
7225
|
githubPanelCopy = ""
|
|
7239
|
-
} else if (ownership === "
|
|
7240
|
-
sourceLabel = "
|
|
7241
|
-
sourceValue = shareState.localLabel
|
|
7242
|
-
statusValue = "
|
|
7243
|
-
githubPanelTitle = "
|
|
7244
|
-
githubPanelCopy = "This plugin
|
|
7226
|
+
} else if (ownership === "managed") {
|
|
7227
|
+
sourceLabel = "Managed folder"
|
|
7228
|
+
sourceValue = shareState.localLabel
|
|
7229
|
+
statusValue = changes.length > 0 ? pluralizeTaskFiles(changes.length) : "Updated with Pinokio"
|
|
7230
|
+
githubPanelTitle = "Managed by Pinokio"
|
|
7231
|
+
githubPanelCopy = "This plugin lives inside <code>plugin/code</code>, which Pinokio refreshes as part of its managed source. Open the folder if you need to inspect it, but don't treat it as your own publishable repo."
|
|
7232
|
+
localChangesCopy = "These edits live inside Pinokio-managed source and may be overwritten by future Pinokio updates."
|
|
7245
7233
|
}
|
|
7246
7234
|
const changePreview = changes.slice(0, 6).map((change) => ({
|
|
7247
7235
|
file: change && change.file ? change.file : "",
|
|
@@ -8106,7 +8094,24 @@ class Server {
|
|
|
8106
8094
|
}
|
|
8107
8095
|
return targetPath
|
|
8108
8096
|
}
|
|
8109
|
-
|
|
8097
|
+
const resolveUniversalLauncherPluginHref = (toolValue) => {
|
|
8098
|
+
let normalizedTool = typeof toolValue === "string" ? toolValue.trim() : ""
|
|
8099
|
+
normalizedTool = normalizedTool.replace(/^https?:\/\/[^/]+/i, "")
|
|
8100
|
+
normalizedTool = normalizedTool.replace(/^\/+|\/+$/g, "")
|
|
8101
|
+
normalizedTool = normalizedTool.replace(/^run\//, "")
|
|
8102
|
+
if (!normalizedTool || normalizedTool.includes("..") || !/^[A-Za-z0-9._/-]+$/.test(normalizedTool)) {
|
|
8103
|
+
const error = new Error("Invalid plugin.")
|
|
8104
|
+
error.status = 400
|
|
8105
|
+
throw error
|
|
8106
|
+
}
|
|
8107
|
+
if (normalizedTool.startsWith("plugin/") || normalizedTool.startsWith("api/")) {
|
|
8108
|
+
const scriptPath = normalizedTool.endsWith(".js")
|
|
8109
|
+
? normalizedTool
|
|
8110
|
+
: `${normalizedTool}/pinokio.js`
|
|
8111
|
+
return `/run/${scriptPath}`
|
|
8112
|
+
}
|
|
8113
|
+
return `/run/plugin/${normalizedTool}/pinokio.js`
|
|
8114
|
+
}
|
|
8110
8115
|
const persistLauncherPromptContext = async (targetPath, options = {}) => {
|
|
8111
8116
|
const prompt = typeof options.prompt === "string" ? options.prompt.trim() : ""
|
|
8112
8117
|
if (!prompt) {
|
|
@@ -8398,32 +8403,6 @@ class Server {
|
|
|
8398
8403
|
const taskWorkspaceLinks = createTaskWorkspaceLinkService({
|
|
8399
8404
|
kernel: this.kernel
|
|
8400
8405
|
})
|
|
8401
|
-
const workspaceRuntime = createWorkspaceRuntimeService({
|
|
8402
|
-
kernel: this.kernel
|
|
8403
|
-
})
|
|
8404
|
-
this.workspaceRuntime = workspaceRuntime
|
|
8405
|
-
const features = await mountFeatures({
|
|
8406
|
-
app: this.app,
|
|
8407
|
-
kernel: this.kernel,
|
|
8408
|
-
taskWorkspaceLinks,
|
|
8409
|
-
defaultRegistryUrl: DEFAULT_REGISTRY_URL
|
|
8410
|
-
})
|
|
8411
|
-
this.features = features
|
|
8412
|
-
const notes = features.notes.service
|
|
8413
|
-
this.notes = notes
|
|
8414
|
-
const workspaceCatalog = createWorkspaceCatalogService({
|
|
8415
|
-
kernel: this.kernel,
|
|
8416
|
-
workspaceRuntime,
|
|
8417
|
-
notes
|
|
8418
|
-
})
|
|
8419
|
-
registerWorkspacesRoutes(this.app, {
|
|
8420
|
-
workspaceCatalog,
|
|
8421
|
-
composePeerAccessPayload: () => this.composePeerAccessPayload(),
|
|
8422
|
-
getTheme: () => this.theme,
|
|
8423
|
-
getPeers: () => this.getPeers(),
|
|
8424
|
-
getCurrentHost: () => this.kernel.peer.host,
|
|
8425
|
-
getPortal: () => this.portal
|
|
8426
|
-
})
|
|
8427
8406
|
const TASK_INPUT_NAME_PATTERN = /^[a-zA-Z0-9_][a-zA-Z0-9_.-]*$/
|
|
8428
8407
|
const suggestTaskFolderName = async (rootDir, preferredName) => {
|
|
8429
8408
|
const normalizedRoot = path.resolve(rootDir)
|
|
@@ -9738,13 +9717,6 @@ class Server {
|
|
|
9738
9717
|
})
|
|
9739
9718
|
}))
|
|
9740
9719
|
|
|
9741
|
-
this.app.get("/tasker", ex(async (req, res) => {
|
|
9742
|
-
res.render("tasker", {
|
|
9743
|
-
theme: this.theme,
|
|
9744
|
-
agent: req.agent,
|
|
9745
|
-
})
|
|
9746
|
-
}))
|
|
9747
|
-
|
|
9748
9720
|
this.app.get("/tasks/new", ex(async (req, res) => {
|
|
9749
9721
|
const sourceWorkspace = normalizeTaskBuilderSourceWorkspace(req.query.sourceWorkspaceCwd)
|
|
9750
9722
|
const lockTargetSelection = req.query.lockTarget === "1" || req.query.lockTarget === "true"
|
|
@@ -10101,8 +10073,7 @@ class Server {
|
|
|
10101
10073
|
}
|
|
10102
10074
|
}
|
|
10103
10075
|
|
|
10104
|
-
const
|
|
10105
|
-
const prompt = taskPackages.applyTemplateValues(task.template, filledInputValues).trim()
|
|
10076
|
+
const prompt = taskPackages.applyTemplateValues(task.template, filterFilledTaskInputValues(inputValues)).trim()
|
|
10106
10077
|
if (!prompt) {
|
|
10107
10078
|
await renderTaskLaunchPage(req, res, task, {
|
|
10108
10079
|
selectedTool,
|
|
@@ -10223,9 +10194,6 @@ class Server {
|
|
|
10223
10194
|
params.set("cwd", targetPath)
|
|
10224
10195
|
params.set("chrome", "full")
|
|
10225
10196
|
params.set("prompt", prompt)
|
|
10226
|
-
if (filledInputValues.url) {
|
|
10227
|
-
params.set("url", filledInputValues.url)
|
|
10228
|
-
}
|
|
10229
10197
|
res.redirect(`${pluginHref}?${params.toString()}`)
|
|
10230
10198
|
})
|
|
10231
10199
|
this.app.post("/task/start", handleTaskStartRequest)
|
|
@@ -10532,8 +10500,7 @@ class Server {
|
|
|
10532
10500
|
return
|
|
10533
10501
|
}
|
|
10534
10502
|
|
|
10535
|
-
const
|
|
10536
|
-
const prompt = taskPackages.applyTemplateValues(task.template, filledInputValues).trim()
|
|
10503
|
+
const prompt = taskPackages.applyTemplateValues(task.template, filterFilledTaskInputValues(inputValues)).trim()
|
|
10537
10504
|
if (!prompt) {
|
|
10538
10505
|
res.status(400).json({
|
|
10539
10506
|
ok: false,
|
|
@@ -10633,9 +10600,6 @@ class Server {
|
|
|
10633
10600
|
params.set("chrome", "full")
|
|
10634
10601
|
params.set("session", createUniversalLauncherSessionId())
|
|
10635
10602
|
params.set("prompt", prompt)
|
|
10636
|
-
if (filledInputValues.url) {
|
|
10637
|
-
params.set("url", filledInputValues.url)
|
|
10638
|
-
}
|
|
10639
10603
|
|
|
10640
10604
|
res.json({
|
|
10641
10605
|
ok: true,
|
|
@@ -11887,14 +11851,11 @@ class Server {
|
|
|
11887
11851
|
// but allow it when the request originates from the local machine
|
|
11888
11852
|
if (payload.audience === 'device' && typeof payload.device_id === 'string' && payload.device_id) {
|
|
11889
11853
|
try {
|
|
11890
|
-
|
|
11891
|
-
|
|
11892
|
-
|
|
11893
|
-
|
|
11894
|
-
|
|
11895
|
-
? this.socket.isLocalDevice(payload.device_id)
|
|
11896
|
-
: false
|
|
11897
|
-
payload.host = !!(isLocalRequest || isLocalDevice)
|
|
11854
|
+
if (this.socket && typeof this.socket.isLocalDevice === 'function') {
|
|
11855
|
+
payload.host = !!this.socket.isLocalDevice(payload.device_id)
|
|
11856
|
+
} else {
|
|
11857
|
+
payload.host = false
|
|
11858
|
+
}
|
|
11898
11859
|
} catch (_) {
|
|
11899
11860
|
payload.host = false
|
|
11900
11861
|
}
|
|
@@ -12795,6 +12756,23 @@ class Server {
|
|
|
12795
12756
|
})
|
|
12796
12757
|
}
|
|
12797
12758
|
}))
|
|
12759
|
+
this.app.post("/plugin/update", ex(async (req, res) => {
|
|
12760
|
+
try {
|
|
12761
|
+
await this.kernel.exec({
|
|
12762
|
+
message: "git pull",
|
|
12763
|
+
path: this.kernel.path("plugin/code")
|
|
12764
|
+
}, (e) => {
|
|
12765
|
+
console.log(e)
|
|
12766
|
+
})
|
|
12767
|
+
res.json({
|
|
12768
|
+
success: true
|
|
12769
|
+
})
|
|
12770
|
+
} catch (e) {
|
|
12771
|
+
res.json({
|
|
12772
|
+
error: e.stack
|
|
12773
|
+
})
|
|
12774
|
+
}
|
|
12775
|
+
}))
|
|
12798
12776
|
this.app.post("/network/reset", ex(async (req, res) => {
|
|
12799
12777
|
let caddy_path = this.kernel.path("cache/XDG_DATA_HOME/caddy")
|
|
12800
12778
|
await rimraf(caddy_path)
|
|
@@ -13416,21 +13394,9 @@ class Server {
|
|
|
13416
13394
|
// }
|
|
13417
13395
|
// }))
|
|
13418
13396
|
this.app.post("/env", ex(async (req, res) => {
|
|
13419
|
-
|
|
13420
|
-
const requestRoot = path.resolve(this.kernel.homedir, requestFilepath)
|
|
13421
|
-
let fullpath = path.resolve(requestRoot, "ENVIRONMENT")
|
|
13422
|
-
if (!(await this.kernel.exists(fullpath))) {
|
|
13423
|
-
const normalizedFilepath = requestFilepath.replace(/\\/g, "/")
|
|
13424
|
-
const filepathParts = normalizedFilepath.split("/").filter(Boolean)
|
|
13425
|
-
if (filepathParts[0] === "api" && filepathParts[1] && filepathParts.length === 2) {
|
|
13426
|
-
const launcher = await this.kernel.api.launcher(filepathParts[1])
|
|
13427
|
-
if (launcher && launcher.launcher_root) {
|
|
13428
|
-
fullpath = path.resolve(launcher.root, launcher.launcher_root, "ENVIRONMENT")
|
|
13429
|
-
}
|
|
13430
|
-
}
|
|
13431
|
-
}
|
|
13397
|
+
let fullpath = path.resolve(this.kernel.homedir, req.body.filepath, "ENVIRONMENT")
|
|
13432
13398
|
let updated = req.body.vals
|
|
13433
|
-
let hosts = req.body.hosts
|
|
13399
|
+
let hosts = req.body.hosts
|
|
13434
13400
|
await Util.update_env(fullpath, updated)
|
|
13435
13401
|
const normalizedFilepath = typeof req.body.filepath === "string"
|
|
13436
13402
|
? req.body.filepath.replace(/\\/g, "/")
|
|
@@ -13583,15 +13549,14 @@ class Server {
|
|
|
13583
13549
|
this.app.get("/pre/api/:name", ex(async (req, res) => {
|
|
13584
13550
|
let launcher = await this.kernel.api.launcher(req.params.name)
|
|
13585
13551
|
let config = launcher.script
|
|
13586
|
-
if (config &&
|
|
13587
|
-
|
|
13588
|
-
|
|
13589
|
-
if (typeof item.icon === "string" && item.icon) {
|
|
13552
|
+
if (config && config.pre) {
|
|
13553
|
+
config.pre.forEach((item) => {
|
|
13554
|
+
if (item.icon) {
|
|
13590
13555
|
item.icon = `/api/${req.params.name}/${item.icon}?raw=true`
|
|
13591
13556
|
} else {
|
|
13592
13557
|
item.icon = "/pinokio-black.png"
|
|
13593
13558
|
}
|
|
13594
|
-
if (
|
|
13559
|
+
if (!item.href.startsWith("http")) {
|
|
13595
13560
|
item.href = path.resolve(this.kernel.homedir, "api", req.params.name, item.href)
|
|
13596
13561
|
}
|
|
13597
13562
|
})
|
|
@@ -13602,7 +13567,7 @@ class Server {
|
|
|
13602
13567
|
theme: this.theme,
|
|
13603
13568
|
agent: req.agent,
|
|
13604
13569
|
name: req.params.name,
|
|
13605
|
-
items,
|
|
13570
|
+
items: config.pre,
|
|
13606
13571
|
env
|
|
13607
13572
|
})
|
|
13608
13573
|
} else {
|
|
@@ -14088,7 +14053,7 @@ class Server {
|
|
|
14088
14053
|
mode = "launch_type.desktop"
|
|
14089
14054
|
} else if (launchType === "terminal") {
|
|
14090
14055
|
mode = "launch_type.terminal"
|
|
14091
|
-
} else
|
|
14056
|
+
} else {
|
|
14092
14057
|
for(let step of item.run) {
|
|
14093
14058
|
if (step.method === "exec") {
|
|
14094
14059
|
mode = "exec"
|
|
@@ -14103,8 +14068,6 @@ class Server {
|
|
|
14103
14068
|
break
|
|
14104
14069
|
}
|
|
14105
14070
|
}
|
|
14106
|
-
} else if (typeof item.run === "function") {
|
|
14107
|
-
mode = "shell"
|
|
14108
14071
|
}
|
|
14109
14072
|
if (mode === "launch_type.desktop" || mode === "exec" || mode === "launch") {
|
|
14110
14073
|
item.type = "Open"
|
|
@@ -14157,20 +14120,6 @@ class Server {
|
|
|
14157
14120
|
spec = await fs.promises.readFile(path.resolve(filepath, "SPEC.md"), "utf8")
|
|
14158
14121
|
} catch (e) {
|
|
14159
14122
|
}
|
|
14160
|
-
const registryEnabled = await this.isRegistryEnabled().catch(() => false)
|
|
14161
|
-
let registry_parent_url = ""
|
|
14162
|
-
if (registryEnabled) {
|
|
14163
|
-
try {
|
|
14164
|
-
registry_parent_url = await git.getConfig({
|
|
14165
|
-
fs,
|
|
14166
|
-
http,
|
|
14167
|
-
dir: filepath,
|
|
14168
|
-
path: "remote.origin.url"
|
|
14169
|
-
}) || ""
|
|
14170
|
-
} catch (_) {
|
|
14171
|
-
registry_parent_url = ""
|
|
14172
|
-
}
|
|
14173
|
-
}
|
|
14174
14123
|
res.render("d", {
|
|
14175
14124
|
filepath,
|
|
14176
14125
|
spec,
|
|
@@ -14181,7 +14130,6 @@ class Server {
|
|
|
14181
14130
|
install: this.install,
|
|
14182
14131
|
agent: req.agent,
|
|
14183
14132
|
theme: this.theme,
|
|
14184
|
-
registry_parent_url,
|
|
14185
14133
|
//dynamic: plugin_menu
|
|
14186
14134
|
dynamic,
|
|
14187
14135
|
})
|
|
@@ -14256,17 +14204,6 @@ class Server {
|
|
|
14256
14204
|
res.status(404).send(e.message)
|
|
14257
14205
|
}
|
|
14258
14206
|
}))
|
|
14259
|
-
this.app.get(`${PluginSources.SYSTEM_RUN_PREFIX}/*`, ex(async (req, res) => {
|
|
14260
|
-
const runPath = typeof req.params[0] === "string" ? req.params[0] : ""
|
|
14261
|
-
let pathComponents = runPath.split("/")
|
|
14262
|
-
req.base = PluginSources.systemRoot(this.kernel)
|
|
14263
|
-
req.pinokioSystem = true
|
|
14264
|
-
try {
|
|
14265
|
-
await this.render(req, res, pathComponents)
|
|
14266
|
-
} catch (e) {
|
|
14267
|
-
res.status(404).send(e.message)
|
|
14268
|
-
}
|
|
14269
|
-
}))
|
|
14270
14207
|
this.app.get("/run/*", ex(async (req, res) => {
|
|
14271
14208
|
const runPath = typeof req.params[0] === "string" ? req.params[0] : ""
|
|
14272
14209
|
let pathComponents = runPath.split("/")
|
|
@@ -15692,7 +15629,12 @@ class Server {
|
|
|
15692
15629
|
}))
|
|
15693
15630
|
this.app.get("/bin_ready", ex(async (req, res) => {
|
|
15694
15631
|
if (this.kernel.bin && !this.kernel.bin.requirements_pending) {
|
|
15695
|
-
|
|
15632
|
+
let code_exists = await this.kernel.exists("plugin/code")
|
|
15633
|
+
if (code_exists) {
|
|
15634
|
+
res.json({ success: true })
|
|
15635
|
+
} else {
|
|
15636
|
+
res.json({ success: false })
|
|
15637
|
+
}
|
|
15696
15638
|
} else {
|
|
15697
15639
|
res.json({ success: false })
|
|
15698
15640
|
}
|