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.
- package/Dockerfile +2 -0
- package/kernel/api/index.js +1 -42
- 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/index.js +11 -1
- package/kernel/environment.js +2 -182
- package/kernel/git.js +13 -0
- package/kernel/index.js +1 -64
- package/kernel/plugin.js +58 -6
- package/kernel/shell.js +2 -21
- package/kernel/util.js +0 -60
- package/package.json +1 -1
- package/server/index.js +149 -176
- package/server/lib/content_validation.js +25 -28
- 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.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 +33 -0
- package/server/views/editor.ejs +4 -25
- package/server/views/partials/main_sidebar.ejs +0 -1
- package/server/views/shell.ejs +3 -11
- package/server/views/terminal.ejs +3 -23
- package/server/views/terminals.ejs +0 -1
- package/spec/INSTRUCTION_SYNC.md +5 -5
- package/kernel/api/shell_run_template.js +0 -273
- package/kernel/api/uri/index.js +0 -51
- package/kernel/plugin_sources.js +0 -236
- 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 -158
- package/server/features/drafts/index.js +0 -41
- package/server/features/drafts/parser.js +0 -169
- package/server/features/drafts/public/drafts.js +0 -1504
- package/server/features/drafts/registry_import.js +0 -412
- package/server/features/drafts/routes.js +0 -68
- package/server/features/drafts/service.js +0 -261
- package/server/features/drafts/watcher.js +0 -76
- package/server/features/index.js +0 -13
- package/server/lib/workspace_catalog.js +0 -151
- package/server/lib/workspace_runtime.js +0 -390
- package/server/routes/workspaces.js +0 -44
- package/server/views/partials/workspace_row.ejs +0 -61
- package/server/views/workspaces.ejs +0 -812
- package/system/plugin/antigravity/antigravity.png +0 -0
- package/system/plugin/antigravity/pinokio.js +0 -37
- package/system/plugin/claude/claude.png +0 -0
- package/system/plugin/claude/pinokio.js +0 -63
- package/system/plugin/claude-auto/claude.png +0 -0
- package/system/plugin/claude-auto/pinokio.js +0 -74
- package/system/plugin/claude-desktop/icon.jpeg +0 -0
- package/system/plugin/claude-desktop/pinokio.js +0 -39
- package/system/plugin/codex/openai.webp +0 -0
- package/system/plugin/codex/pinokio.js +0 -58
- package/system/plugin/codex-auto/openai.webp +0 -0
- package/system/plugin/codex-auto/pinokio.js +0 -65
- package/system/plugin/codex-desktop/icon.png +0 -0
- package/system/plugin/codex-desktop/pinokio.js +0 -39
- package/system/plugin/crush/crush.png +0 -0
- package/system/plugin/crush/pinokio.js +0 -31
- package/system/plugin/cursor/cursor.jpeg +0 -0
- package/system/plugin/cursor/pinokio.js +0 -39
- package/system/plugin/gemini/gemini.jpeg +0 -0
- package/system/plugin/gemini/pinokio.js +0 -40
- package/system/plugin/gemini-auto/gemini.jpeg +0 -0
- package/system/plugin/gemini-auto/pinokio.js +0 -43
- package/system/plugin/qwen/pinokio.js +0 -50
- package/system/plugin/qwen/qwen.png +0 -0
- package/system/plugin/vscode/pinokio.js +0 -36
- package/system/plugin/vscode/vscode.png +0 -0
- package/system/plugin/windsurf/pinokio.js +0 -39
- package/system/plugin/windsurf/windsurf.png +0 -0
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",
|
|
@@ -2870,27 +2865,11 @@ class Server {
|
|
|
2870
2865
|
const protectionPreference = protectionAppId && this.appPreferences && typeof this.appPreferences.getPreference === "function"
|
|
2871
2866
|
? await this.appPreferences.getPreference(protectionAppId)
|
|
2872
2867
|
: null
|
|
2873
|
-
const draftWatchEnabled = this.kernel.watch && typeof this.kernel.watch.hasHandler === "function"
|
|
2874
|
-
? this.kernel.watch.hasHandler(resolved, "draft")
|
|
2875
|
-
: false
|
|
2876
|
-
const draftWatchCwd = draftWatchEnabled
|
|
2877
|
-
? (req.query.cwd || path.dirname(filepath))
|
|
2878
|
-
: ""
|
|
2879
|
-
const activeProcessWait = this.kernel.activeProcessWaits && this.kernel.activeProcessWaits[filepath]
|
|
2880
|
-
? this.kernel.activeProcessWaits[filepath]
|
|
2881
|
-
: null
|
|
2882
2868
|
const result = {
|
|
2883
2869
|
portal: this.portal,
|
|
2884
2870
|
projectName: (pathComponents.length > 0 ? pathComponents[0] : ''),
|
|
2885
2871
|
protection_app_id: protectionAppId,
|
|
2886
2872
|
protection_enabled: protectionPreference ? protectionPreference.protection_enabled !== false : false,
|
|
2887
|
-
draft_watch_enabled: draftWatchEnabled,
|
|
2888
|
-
draft_watch_cwd: draftWatchCwd,
|
|
2889
|
-
active_process_wait: activeProcessWait ? {
|
|
2890
|
-
title: activeProcessWait.title,
|
|
2891
|
-
description: activeProcessWait.description,
|
|
2892
|
-
message: activeProcessWait.message
|
|
2893
|
-
} : null,
|
|
2894
2873
|
kill_message,
|
|
2895
2874
|
callback,
|
|
2896
2875
|
callback_target,
|
|
@@ -2905,7 +2884,6 @@ class Server {
|
|
|
2905
2884
|
//run: true, // run mode by default
|
|
2906
2885
|
run: (req.query && req.query.mode === "source" ? false : true),
|
|
2907
2886
|
stop: (req.query && req.query.stop ? true : false),
|
|
2908
|
-
readonly: req.pinokioSystem === true,
|
|
2909
2887
|
pinokioPath,
|
|
2910
2888
|
action: actionKey,
|
|
2911
2889
|
runnable,
|
|
@@ -3122,7 +3100,6 @@ class Server {
|
|
|
3122
3100
|
if (pathComponents.length === 0) {
|
|
3123
3101
|
const normalizedApiRoot = path.normalize(this.kernel.path("api"))
|
|
3124
3102
|
const normalizedPluginRoot = path.normalize(this.kernel.path("plugin"))
|
|
3125
|
-
const normalizedSystemPluginRoot = path.normalize(PluginSources.systemPluginRoot(this.kernel))
|
|
3126
3103
|
const isPathWithinRoot = (candidatePath, rootPath) => {
|
|
3127
3104
|
if (typeof candidatePath !== "string" || typeof rootPath !== "string") {
|
|
3128
3105
|
return false
|
|
@@ -3148,9 +3125,6 @@ class Server {
|
|
|
3148
3125
|
if (isPathWithinRoot(normalizedCandidate, normalizedPluginRoot)) {
|
|
3149
3126
|
return true
|
|
3150
3127
|
}
|
|
3151
|
-
if (isPathWithinRoot(normalizedCandidate, normalizedSystemPluginRoot)) {
|
|
3152
|
-
return true
|
|
3153
|
-
}
|
|
3154
3128
|
const relativeToApiRoot = path.relative(normalizedApiRoot, normalizedCandidate)
|
|
3155
3129
|
if (!relativeToApiRoot || relativeToApiRoot.startsWith("..") || path.isAbsolute(relativeToApiRoot)) {
|
|
3156
3130
|
return false
|
|
@@ -3964,7 +3938,8 @@ class Server {
|
|
|
3964
3938
|
if (menuitem.href.startsWith("http")) {
|
|
3965
3939
|
menuitem.src = menuitem.href
|
|
3966
3940
|
} else if (menuitem.href.startsWith("/")) {
|
|
3967
|
-
|
|
3941
|
+
let run_path = "/run"
|
|
3942
|
+
if (menuitem.href.startsWith(run_path)) {
|
|
3968
3943
|
menuitem.src = menuitem.href
|
|
3969
3944
|
// u = new URL("http://localhost" + menuitem.href.slice(run_path.length))
|
|
3970
3945
|
// cwd = u.searchParams.get("cwd")
|
|
@@ -3984,14 +3959,7 @@ class Server {
|
|
|
3984
3959
|
}
|
|
3985
3960
|
|
|
3986
3961
|
// check running
|
|
3987
|
-
let
|
|
3988
|
-
try {
|
|
3989
|
-
srcPathname = new URL("http://localhost" + menuitem.src).pathname
|
|
3990
|
-
} catch (_) {
|
|
3991
|
-
}
|
|
3992
|
-
let fullpath = PluginSources.isRunPath(srcPathname)
|
|
3993
|
-
? PluginSources.resolveRunPath(this.kernel, srcPathname)
|
|
3994
|
-
: this.kernel.path(srcPathname.slice(1))
|
|
3962
|
+
let fullpath = this.kernel.path(menuitem.src.slice(1))
|
|
3995
3963
|
let relpath = path.relative(this.kernel.homedir, fullpath)
|
|
3996
3964
|
if (relpath.startsWith("api")) {
|
|
3997
3965
|
// api script
|
|
@@ -5705,6 +5673,7 @@ class Server {
|
|
|
5705
5673
|
"prototype/PTERM.md",
|
|
5706
5674
|
]
|
|
5707
5675
|
const managedRefreshTargets = [
|
|
5676
|
+
"plugin/code",
|
|
5708
5677
|
"prototype/system",
|
|
5709
5678
|
"network/system",
|
|
5710
5679
|
"prototype/PINOKIO.md",
|
|
@@ -5726,16 +5695,6 @@ class Server {
|
|
|
5726
5695
|
|
|
5727
5696
|
needsManagedRefresh = true
|
|
5728
5697
|
console.log("[TRY] Updating to the new version")
|
|
5729
|
-
let envPath = path.resolve(home, "ENVIRONMENT")
|
|
5730
|
-
let envExists = await this.kernel.exists(envPath)
|
|
5731
|
-
if (!envExists) {
|
|
5732
|
-
let str = await Environment.ENV("system", home, this.kernel)
|
|
5733
|
-
await fs.promises.writeFile(envPath, str)
|
|
5734
|
-
}
|
|
5735
|
-
await Environment.ensurePinokioCacheDirs(this.kernel, {
|
|
5736
|
-
throwOnFailure: true,
|
|
5737
|
-
elevatedRepair: this.kernel.elevatedCacheRepair.bind(this.kernel)
|
|
5738
|
-
})
|
|
5739
5698
|
this.kernel.store.set("version", this.version.pinokiod)
|
|
5740
5699
|
console.log("[DONE] Updating to the new version")
|
|
5741
5700
|
console.log("not up to date. update py.")
|
|
@@ -5748,6 +5707,9 @@ class Server {
|
|
|
5748
5707
|
let p2 = path.resolve(home, "prototype/system")
|
|
5749
5708
|
await fse.remove(p2)
|
|
5750
5709
|
|
|
5710
|
+
let p3 = path.resolve(home, "plugin/code")
|
|
5711
|
+
await fse.remove(p3)
|
|
5712
|
+
|
|
5751
5713
|
let p4 = path.resolve(home, "network/system")
|
|
5752
5714
|
await fse.remove(p4)
|
|
5753
5715
|
|
|
@@ -5816,6 +5778,10 @@ class Server {
|
|
|
5816
5778
|
await this.kernel.proto.init()
|
|
5817
5779
|
}
|
|
5818
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
|
+
}
|
|
5819
5785
|
const networkReady = await this.kernel.exists("network/system")
|
|
5820
5786
|
if (!networkReady && this.kernel.router && typeof this.kernel.router.init === "function") {
|
|
5821
5787
|
await this.kernel.router.init()
|
|
@@ -5996,10 +5962,6 @@ class Server {
|
|
|
5996
5962
|
})
|
|
5997
5963
|
this.app.use(express.static(path.resolve(__dirname, 'public')));
|
|
5998
5964
|
this.app.use("/web", express.static(path.resolve(__dirname, "..", "..", "web")))
|
|
5999
|
-
this.app.use(PluginSources.SYSTEM_ASSET_PREFIX, express.static(PluginSources.systemRoot(this.kernel), {
|
|
6000
|
-
index: false,
|
|
6001
|
-
fallthrough: true,
|
|
6002
|
-
}))
|
|
6003
5965
|
this.app.set('view engine', 'ejs');
|
|
6004
5966
|
this.app.use((req, res, next) => {
|
|
6005
5967
|
const peerForwarded = (req.get('X-Pinokio-Peer') || '').trim().toLowerCase()
|
|
@@ -6782,7 +6744,24 @@ class Server {
|
|
|
6782
6744
|
}
|
|
6783
6745
|
}
|
|
6784
6746
|
const normalizePluginPath = (value) => {
|
|
6785
|
-
|
|
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
|
|
6786
6765
|
}
|
|
6787
6766
|
const normalizePluginLookupKey = (value) => {
|
|
6788
6767
|
const normalized = normalizePluginPath(value)
|
|
@@ -6929,7 +6908,7 @@ class Server {
|
|
|
6929
6908
|
index: -1,
|
|
6930
6909
|
title: context.title || "Plugin",
|
|
6931
6910
|
description: typeof config.description === "string" ? config.description : "",
|
|
6932
|
-
href:
|
|
6911
|
+
href: `/run${normalizedPluginPath}`,
|
|
6933
6912
|
link: typeof config.link === "string" ? config.link : "",
|
|
6934
6913
|
image: context.image || null,
|
|
6935
6914
|
icon: null,
|
|
@@ -6954,31 +6933,24 @@ class Server {
|
|
|
6954
6933
|
}
|
|
6955
6934
|
const resolvePluginLocalState = async (plugin) => {
|
|
6956
6935
|
const pluginRoot = path.resolve(this.kernel.path("plugin"))
|
|
6936
|
+
const managedRoot = path.resolve(pluginRoot, "code")
|
|
6957
6937
|
const normalizedPath = normalizePluginPath(plugin && plugin.pluginPath ? plugin.pluginPath : "")
|
|
6958
6938
|
const emptyState = {
|
|
6959
6939
|
ownership: "bundled",
|
|
6960
6940
|
manageable: false,
|
|
6961
6941
|
canOpenFolder: false,
|
|
6962
6942
|
pluginRoot,
|
|
6943
|
+
managedRoot,
|
|
6963
6944
|
pluginFilePath: "",
|
|
6964
6945
|
pluginDir: "",
|
|
6965
6946
|
relativeDir: "",
|
|
6966
6947
|
relativeFile: "",
|
|
6967
6948
|
localLabel: "",
|
|
6968
|
-
|
|
6969
|
-
if (PluginSources.isSystemPluginPath(normalizedPath)) {
|
|
6970
|
-
return {
|
|
6971
|
-
...emptyState,
|
|
6972
|
-
ownership: "system",
|
|
6973
|
-
localLabel: normalizedPath.replace(/^\/pinokio\/run\//, ""),
|
|
6974
|
-
}
|
|
6949
|
+
managedPrefix: "",
|
|
6975
6950
|
}
|
|
6976
6951
|
if (!normalizedPath.startsWith("/plugin/")) {
|
|
6977
6952
|
return emptyState
|
|
6978
6953
|
}
|
|
6979
|
-
if (PluginSources.isLegacyPluginCodePath(normalizedPath)) {
|
|
6980
|
-
return emptyState
|
|
6981
|
-
}
|
|
6982
6954
|
const pluginFilePath = path.resolve(this.kernel.path(normalizedPath.slice(1)))
|
|
6983
6955
|
if (!isPathInsideRoot(pluginFilePath, pluginRoot)) {
|
|
6984
6956
|
return emptyState
|
|
@@ -6998,16 +6970,22 @@ class Server {
|
|
|
6998
6970
|
}
|
|
6999
6971
|
const relativeFile = path.relative(pluginRoot, pluginFilePath).split(path.sep).join("/")
|
|
7000
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
|
+
: ""
|
|
7001
6977
|
return {
|
|
7002
|
-
ownership: "local",
|
|
7003
|
-
manageable: Boolean(pluginFileExists && pluginDirExists),
|
|
6978
|
+
ownership: isManaged ? "managed" : "local",
|
|
6979
|
+
manageable: Boolean(pluginFileExists && pluginDirExists && !isManaged),
|
|
7004
6980
|
canOpenFolder: Boolean(pluginFileExists && pluginDirExists),
|
|
7005
6981
|
pluginRoot,
|
|
6982
|
+
managedRoot,
|
|
7006
6983
|
pluginFilePath,
|
|
7007
6984
|
pluginDir,
|
|
7008
6985
|
relativeDir,
|
|
7009
6986
|
relativeFile,
|
|
7010
6987
|
localLabel: relativeDir ? `plugin/${relativeDir}` : "plugin",
|
|
6988
|
+
managedPrefix,
|
|
7011
6989
|
}
|
|
7012
6990
|
}
|
|
7013
6991
|
const collectPluginApps = async (boundAppName = "") => {
|
|
@@ -7051,31 +7029,11 @@ class Server {
|
|
|
7051
7029
|
})
|
|
7052
7030
|
return apps
|
|
7053
7031
|
}
|
|
7054
|
-
|
|
7055
|
-
|
|
7056
|
-
if (localState.ownership === "
|
|
7032
|
+
const buildPluginShareState = async (plugin) => {
|
|
7033
|
+
const localState = await resolvePluginLocalState(plugin)
|
|
7034
|
+
if (localState.ownership === "bundled") {
|
|
7057
7035
|
return {
|
|
7058
|
-
ownership: "
|
|
7059
|
-
manageable: false,
|
|
7060
|
-
canOpenFolder: false,
|
|
7061
|
-
dir: "",
|
|
7062
|
-
localLabel: localState.localLabel || "",
|
|
7063
|
-
remoteUrl: "",
|
|
7064
|
-
remoteWebUrl: "",
|
|
7065
|
-
githubConnected: false,
|
|
7066
|
-
gitInitialized: false,
|
|
7067
|
-
hasCommit: false,
|
|
7068
|
-
changeCount: 0,
|
|
7069
|
-
changes: [],
|
|
7070
|
-
branch: "HEAD",
|
|
7071
|
-
commitUrl: "",
|
|
7072
|
-
createUrl: "",
|
|
7073
|
-
pushUrl: "",
|
|
7074
|
-
}
|
|
7075
|
-
}
|
|
7076
|
-
if (localState.ownership === "bundled") {
|
|
7077
|
-
return {
|
|
7078
|
-
ownership: "bundled",
|
|
7036
|
+
ownership: "bundled",
|
|
7079
7037
|
manageable: false,
|
|
7080
7038
|
canOpenFolder: false,
|
|
7081
7039
|
dir: "",
|
|
@@ -7095,21 +7053,49 @@ class Server {
|
|
|
7095
7053
|
}
|
|
7096
7054
|
|
|
7097
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
|
+
}
|
|
7098
7084
|
return {
|
|
7099
|
-
ownership: "
|
|
7085
|
+
ownership: "managed",
|
|
7100
7086
|
manageable: false,
|
|
7101
|
-
canOpenFolder:
|
|
7102
|
-
dir:
|
|
7103
|
-
localLabel:
|
|
7104
|
-
relativeDir:
|
|
7105
|
-
relativeFile:
|
|
7087
|
+
canOpenFolder: Boolean(localState.canOpenFolder),
|
|
7088
|
+
dir: localState.pluginDir,
|
|
7089
|
+
localLabel: localState.localLabel,
|
|
7090
|
+
relativeDir: localState.relativeDir,
|
|
7091
|
+
relativeFile: localState.relativeFile,
|
|
7106
7092
|
remoteUrl: "",
|
|
7107
7093
|
remoteWebUrl: "",
|
|
7108
7094
|
githubConnected: false,
|
|
7109
7095
|
gitInitialized: false,
|
|
7110
7096
|
hasCommit: false,
|
|
7111
|
-
changeCount:
|
|
7112
|
-
changes
|
|
7097
|
+
changeCount: changes.length,
|
|
7098
|
+
changes,
|
|
7113
7099
|
branch: "HEAD",
|
|
7114
7100
|
commitUrl: "",
|
|
7115
7101
|
createUrl: "",
|
|
@@ -7185,19 +7171,14 @@ class Server {
|
|
|
7185
7171
|
: ""
|
|
7186
7172
|
const remoteLabel = summarizeTaskRemoteLabel(remoteCandidate)
|
|
7187
7173
|
const badges = []
|
|
7188
|
-
|
|
7189
|
-
badges.push({
|
|
7190
|
-
label: "Local plugin",
|
|
7191
|
-
tone: "accent"
|
|
7192
|
-
})
|
|
7193
|
-
} else if (ownership === "system") {
|
|
7174
|
+
if (ownership === "local") {
|
|
7194
7175
|
badges.push({
|
|
7195
|
-
label: "
|
|
7196
|
-
tone: "
|
|
7176
|
+
label: "Local plugin",
|
|
7177
|
+
tone: "accent"
|
|
7197
7178
|
})
|
|
7198
|
-
|
|
7199
|
-
|
|
7200
|
-
|
|
7179
|
+
} else if (ownership === "managed") {
|
|
7180
|
+
badges.push({
|
|
7181
|
+
label: "Managed by Pinokio",
|
|
7201
7182
|
tone: "neutral"
|
|
7202
7183
|
})
|
|
7203
7184
|
} else {
|
|
@@ -7242,12 +7223,13 @@ class Server {
|
|
|
7242
7223
|
: (shareState.gitInitialized ? "No local changes" : "Not version tracked yet")
|
|
7243
7224
|
githubPanelTitle = "GitHub"
|
|
7244
7225
|
githubPanelCopy = ""
|
|
7245
|
-
} else if (ownership === "
|
|
7246
|
-
sourceLabel = "
|
|
7247
|
-
sourceValue = shareState.localLabel
|
|
7248
|
-
statusValue = "
|
|
7249
|
-
githubPanelTitle = "
|
|
7250
|
-
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."
|
|
7251
7233
|
}
|
|
7252
7234
|
const changePreview = changes.slice(0, 6).map((change) => ({
|
|
7253
7235
|
file: change && change.file ? change.file : "",
|
|
@@ -8112,7 +8094,24 @@ class Server {
|
|
|
8112
8094
|
}
|
|
8113
8095
|
return targetPath
|
|
8114
8096
|
}
|
|
8115
|
-
|
|
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
|
+
}
|
|
8116
8115
|
const persistLauncherPromptContext = async (targetPath, options = {}) => {
|
|
8117
8116
|
const prompt = typeof options.prompt === "string" ? options.prompt.trim() : ""
|
|
8118
8117
|
if (!prompt) {
|
|
@@ -8404,32 +8403,6 @@ class Server {
|
|
|
8404
8403
|
const taskWorkspaceLinks = createTaskWorkspaceLinkService({
|
|
8405
8404
|
kernel: this.kernel
|
|
8406
8405
|
})
|
|
8407
|
-
const workspaceRuntime = createWorkspaceRuntimeService({
|
|
8408
|
-
kernel: this.kernel
|
|
8409
|
-
})
|
|
8410
|
-
this.workspaceRuntime = workspaceRuntime
|
|
8411
|
-
const features = await mountFeatures({
|
|
8412
|
-
app: this.app,
|
|
8413
|
-
kernel: this.kernel,
|
|
8414
|
-
taskWorkspaceLinks,
|
|
8415
|
-
defaultRegistryUrl: DEFAULT_REGISTRY_URL
|
|
8416
|
-
})
|
|
8417
|
-
this.features = features
|
|
8418
|
-
const drafts = features.drafts.service
|
|
8419
|
-
this.drafts = drafts
|
|
8420
|
-
const workspaceCatalog = createWorkspaceCatalogService({
|
|
8421
|
-
kernel: this.kernel,
|
|
8422
|
-
workspaceRuntime,
|
|
8423
|
-
drafts
|
|
8424
|
-
})
|
|
8425
|
-
registerWorkspacesRoutes(this.app, {
|
|
8426
|
-
workspaceCatalog,
|
|
8427
|
-
composePeerAccessPayload: () => this.composePeerAccessPayload(),
|
|
8428
|
-
getTheme: () => this.theme,
|
|
8429
|
-
getPeers: () => this.getPeers(),
|
|
8430
|
-
getCurrentHost: () => this.kernel.peer.host,
|
|
8431
|
-
getPortal: () => this.portal
|
|
8432
|
-
})
|
|
8433
8406
|
const TASK_INPUT_NAME_PATTERN = /^[a-zA-Z0-9_][a-zA-Z0-9_.-]*$/
|
|
8434
8407
|
const suggestTaskFolderName = async (rootDir, preferredName) => {
|
|
8435
8408
|
const normalizedRoot = path.resolve(rootDir)
|
|
@@ -10100,8 +10073,7 @@ class Server {
|
|
|
10100
10073
|
}
|
|
10101
10074
|
}
|
|
10102
10075
|
|
|
10103
|
-
const
|
|
10104
|
-
const prompt = taskPackages.applyTemplateValues(task.template, filledInputValues).trim()
|
|
10076
|
+
const prompt = taskPackages.applyTemplateValues(task.template, filterFilledTaskInputValues(inputValues)).trim()
|
|
10105
10077
|
if (!prompt) {
|
|
10106
10078
|
await renderTaskLaunchPage(req, res, task, {
|
|
10107
10079
|
selectedTool,
|
|
@@ -10222,9 +10194,6 @@ class Server {
|
|
|
10222
10194
|
params.set("cwd", targetPath)
|
|
10223
10195
|
params.set("chrome", "full")
|
|
10224
10196
|
params.set("prompt", prompt)
|
|
10225
|
-
if (filledInputValues.url) {
|
|
10226
|
-
params.set("url", filledInputValues.url)
|
|
10227
|
-
}
|
|
10228
10197
|
res.redirect(`${pluginHref}?${params.toString()}`)
|
|
10229
10198
|
})
|
|
10230
10199
|
this.app.post("/task/start", handleTaskStartRequest)
|
|
@@ -10531,8 +10500,7 @@ class Server {
|
|
|
10531
10500
|
return
|
|
10532
10501
|
}
|
|
10533
10502
|
|
|
10534
|
-
const
|
|
10535
|
-
const prompt = taskPackages.applyTemplateValues(task.template, filledInputValues).trim()
|
|
10503
|
+
const prompt = taskPackages.applyTemplateValues(task.template, filterFilledTaskInputValues(inputValues)).trim()
|
|
10536
10504
|
if (!prompt) {
|
|
10537
10505
|
res.status(400).json({
|
|
10538
10506
|
ok: false,
|
|
@@ -10632,9 +10600,6 @@ class Server {
|
|
|
10632
10600
|
params.set("chrome", "full")
|
|
10633
10601
|
params.set("session", createUniversalLauncherSessionId())
|
|
10634
10602
|
params.set("prompt", prompt)
|
|
10635
|
-
if (filledInputValues.url) {
|
|
10636
|
-
params.set("url", filledInputValues.url)
|
|
10637
|
-
}
|
|
10638
10603
|
|
|
10639
10604
|
res.json({
|
|
10640
10605
|
ok: true,
|
|
@@ -11886,14 +11851,11 @@ class Server {
|
|
|
11886
11851
|
// but allow it when the request originates from the local machine
|
|
11887
11852
|
if (payload.audience === 'device' && typeof payload.device_id === 'string' && payload.device_id) {
|
|
11888
11853
|
try {
|
|
11889
|
-
|
|
11890
|
-
|
|
11891
|
-
|
|
11892
|
-
|
|
11893
|
-
|
|
11894
|
-
? this.socket.isLocalDevice(payload.device_id)
|
|
11895
|
-
: false
|
|
11896
|
-
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
|
+
}
|
|
11897
11859
|
} catch (_) {
|
|
11898
11860
|
payload.host = false
|
|
11899
11861
|
}
|
|
@@ -12794,6 +12756,23 @@ class Server {
|
|
|
12794
12756
|
})
|
|
12795
12757
|
}
|
|
12796
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
|
+
}))
|
|
12797
12776
|
this.app.post("/network/reset", ex(async (req, res) => {
|
|
12798
12777
|
let caddy_path = this.kernel.path("cache/XDG_DATA_HOME/caddy")
|
|
12799
12778
|
await rimraf(caddy_path)
|
|
@@ -14225,17 +14204,6 @@ class Server {
|
|
|
14225
14204
|
res.status(404).send(e.message)
|
|
14226
14205
|
}
|
|
14227
14206
|
}))
|
|
14228
|
-
this.app.get(`${PluginSources.SYSTEM_RUN_PREFIX}/*`, ex(async (req, res) => {
|
|
14229
|
-
const runPath = typeof req.params[0] === "string" ? req.params[0] : ""
|
|
14230
|
-
let pathComponents = runPath.split("/")
|
|
14231
|
-
req.base = PluginSources.systemRoot(this.kernel)
|
|
14232
|
-
req.pinokioSystem = true
|
|
14233
|
-
try {
|
|
14234
|
-
await this.render(req, res, pathComponents)
|
|
14235
|
-
} catch (e) {
|
|
14236
|
-
res.status(404).send(e.message)
|
|
14237
|
-
}
|
|
14238
|
-
}))
|
|
14239
14207
|
this.app.get("/run/*", ex(async (req, res) => {
|
|
14240
14208
|
const runPath = typeof req.params[0] === "string" ? req.params[0] : ""
|
|
14241
14209
|
let pathComponents = runPath.split("/")
|
|
@@ -15661,7 +15629,12 @@ class Server {
|
|
|
15661
15629
|
}))
|
|
15662
15630
|
this.app.get("/bin_ready", ex(async (req, res) => {
|
|
15663
15631
|
if (this.kernel.bin && !this.kernel.bin.requirements_pending) {
|
|
15664
|
-
|
|
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
|
+
}
|
|
15665
15638
|
} else {
|
|
15666
15639
|
res.json({ success: false })
|
|
15667
15640
|
}
|