pinokiod 7.2.18 → 7.3.1
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-pins.js +53 -0
- package/kernel/bin/conda.js +35 -6
- package/kernel/bin/huggingface.js +1 -1
- package/kernel/bin/index.js +15 -2
- 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
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
const fs = require("fs")
|
|
2
2
|
const path = require("path")
|
|
3
3
|
const clearModule = require("clear-module")
|
|
4
|
-
const PluginSources = require("../../kernel/plugin_sources")
|
|
5
4
|
|
|
6
5
|
const {
|
|
7
6
|
TASK_CONFIG_FILENAME,
|
|
@@ -118,7 +117,23 @@ function createContentValidationService({ kernel }) {
|
|
|
118
117
|
}
|
|
119
118
|
|
|
120
119
|
const normalizePluginPath = (value) => {
|
|
121
|
-
|
|
120
|
+
let normalized = typeof value === "string" ? value.trim() : ""
|
|
121
|
+
if (!normalized) {
|
|
122
|
+
return ""
|
|
123
|
+
}
|
|
124
|
+
normalized = normalized.replace(/\\/g, "/")
|
|
125
|
+
normalized = normalized.replace(/^\/run(?=\/)/, "")
|
|
126
|
+
if (!normalized.startsWith("/")) {
|
|
127
|
+
normalized = `/${normalized}`
|
|
128
|
+
}
|
|
129
|
+
normalized = normalized.replace(/\/{2,}/g, "/").replace(/\/+$/, "")
|
|
130
|
+
if (!normalized) {
|
|
131
|
+
return ""
|
|
132
|
+
}
|
|
133
|
+
if (!normalized.endsWith("/pinokio.js")) {
|
|
134
|
+
normalized = `${normalized}/pinokio.js`
|
|
135
|
+
}
|
|
136
|
+
return normalized
|
|
122
137
|
}
|
|
123
138
|
|
|
124
139
|
const normalizeBundledPluginSpec = (value) => {
|
|
@@ -147,16 +162,16 @@ function createContentValidationService({ kernel }) {
|
|
|
147
162
|
absolutePath,
|
|
148
163
|
dir: pluginDir,
|
|
149
164
|
config,
|
|
150
|
-
hasInstall:
|
|
151
|
-
hasUpdate:
|
|
152
|
-
hasUninstall:
|
|
165
|
+
hasInstall: Array.isArray(config && config.install),
|
|
166
|
+
hasUpdate: Array.isArray(config && config.update),
|
|
167
|
+
hasUninstall: Array.isArray(config && config.uninstall),
|
|
153
168
|
image: null,
|
|
154
169
|
}
|
|
155
170
|
|
|
156
171
|
if (config && typeof config.icon === "string" && config.icon.trim()) {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
context.image =
|
|
172
|
+
if (normalizedPath.startsWith("/plugin/")) {
|
|
173
|
+
const relativeDir = path.posix.dirname(normalizedPath.slice(1))
|
|
174
|
+
context.image = `/asset/${relativeDir}/${config.icon.trim()}`
|
|
160
175
|
} else if (normalizedPath.startsWith("/api/")) {
|
|
161
176
|
const segments = normalizedPath.replace(/^\/+/, "").split("/")
|
|
162
177
|
const appName = segments[1] || ""
|
|
@@ -177,10 +192,7 @@ function createContentValidationService({ kernel }) {
|
|
|
177
192
|
const fallbackTitle = normalizedPath
|
|
178
193
|
? path.basename(path.posix.dirname(normalizedPath))
|
|
179
194
|
: "Plugin"
|
|
180
|
-
|
|
181
|
-
const isHomePlugin = normalizedPath.startsWith("/plugin/")
|
|
182
|
-
const isApiPlugin = normalizedPath.startsWith("/api/")
|
|
183
|
-
if (!normalizedPath || (!isSystemPlugin && !isHomePlugin && !isApiPlugin)) {
|
|
195
|
+
if (!normalizedPath || (!normalizedPath.startsWith("/plugin/") && !normalizedPath.startsWith("/api/"))) {
|
|
184
196
|
return buildInvalid({
|
|
185
197
|
type: "plugin",
|
|
186
198
|
subjectTitle: fallbackTitle,
|
|
@@ -193,21 +205,8 @@ function createContentValidationService({ kernel }) {
|
|
|
193
205
|
detailUrl: "/plugins",
|
|
194
206
|
})
|
|
195
207
|
}
|
|
196
|
-
if (PluginSources.isLegacyPluginCodePath(normalizedPath)) {
|
|
197
|
-
return buildInvalid({
|
|
198
|
-
type: "plugin",
|
|
199
|
-
subjectTitle: fallbackTitle,
|
|
200
|
-
errors: [
|
|
201
|
-
buildError(
|
|
202
|
-
"This managed plugin path is no longer used.",
|
|
203
|
-
"Open the built-in Pinokio plugin instead."
|
|
204
|
-
),
|
|
205
|
-
],
|
|
206
|
-
detailUrl: "/plugins",
|
|
207
|
-
})
|
|
208
|
-
}
|
|
209
208
|
|
|
210
|
-
const absolutePath =
|
|
209
|
+
const absolutePath = kernel.path(normalizedPath.replace(/^\/+/, ""))
|
|
211
210
|
const folderPath = path.dirname(absolutePath)
|
|
212
211
|
const loaded = await loadJsFile(absolutePath)
|
|
213
212
|
if (!loaded.exists) {
|
|
@@ -252,35 +251,25 @@ function createContentValidationService({ kernel }) {
|
|
|
252
251
|
{ file: absolutePath }
|
|
253
252
|
))
|
|
254
253
|
} else {
|
|
255
|
-
if (!
|
|
254
|
+
if (!Array.isArray(config.run)) {
|
|
256
255
|
errors.push(buildError(
|
|
257
|
-
"Plugins must define a top-level run array
|
|
258
|
-
"Add `run: [...]`
|
|
256
|
+
"Plugins must define a top-level run array.",
|
|
257
|
+
"Add `run: [...]` to pinokio.js.",
|
|
259
258
|
{ file: absolutePath }
|
|
260
259
|
))
|
|
261
260
|
}
|
|
262
|
-
const topLevelFunctionKeys = Object.keys(config).filter((key) =>
|
|
263
|
-
return typeof config[key] === "function" && !PluginSources.ACTION_KEYS.has(key)
|
|
264
|
-
})
|
|
261
|
+
const topLevelFunctionKeys = Object.keys(config).filter((key) => typeof config[key] === "function")
|
|
265
262
|
if (topLevelFunctionKeys.length > 0) {
|
|
266
263
|
errors.push(buildError(
|
|
267
264
|
`Top-level function fields are not supported: ${topLevelFunctionKeys.join(", ")}.`,
|
|
268
|
-
"
|
|
265
|
+
"Move those functions out of pinokio.js or replace them with data.",
|
|
269
266
|
{ file: absolutePath }
|
|
270
267
|
))
|
|
271
268
|
}
|
|
272
|
-
for (const key of PluginSources.ACTION_KEYS) {
|
|
273
|
-
if (key in config && !PluginSources.isAction(config[key])) {
|
|
274
|
-
errors.push(buildError(
|
|
275
|
-
`Plugin action ${key} must be an array or function.`,
|
|
276
|
-
`Set ${key} to an array or async function returning an array.`,
|
|
277
|
-
{ file: absolutePath }
|
|
278
|
-
))
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
269
|
if (normalizedPath.startsWith("/plugin/")) {
|
|
270
|
+
const isManagedDefaultPlugin = normalizedPath.startsWith("/plugin/code/")
|
|
282
271
|
const declaredPath = typeof config.path === "string" ? config.path.trim() : ""
|
|
283
|
-
if (declaredPath !== "plugin") {
|
|
272
|
+
if (!isManagedDefaultPlugin && declaredPath !== "plugin") {
|
|
284
273
|
errors.push(buildError(
|
|
285
274
|
'Standalone plugins must set `path: "plugin"`.',
|
|
286
275
|
'Add `path: "plugin"` to pinokio.js.',
|
|
@@ -578,7 +567,7 @@ function createContentValidationService({ kernel }) {
|
|
|
578
567
|
})
|
|
579
568
|
}
|
|
580
569
|
|
|
581
|
-
const validateRunPath = async (pathComponents
|
|
570
|
+
const validateRunPath = async (pathComponents) => {
|
|
582
571
|
if (!Array.isArray(pathComponents) || pathComponents.length === 0) {
|
|
583
572
|
return buildValid()
|
|
584
573
|
}
|
|
@@ -587,9 +576,6 @@ function createContentValidationService({ kernel }) {
|
|
|
587
576
|
return buildValid()
|
|
588
577
|
}
|
|
589
578
|
if (normalized[0] === "plugin") {
|
|
590
|
-
if (options && options.system) {
|
|
591
|
-
return validatePluginByPath(`${PluginSources.SYSTEM_RUN_PREFIX}/${normalized.join("/")}`)
|
|
592
|
-
}
|
|
593
579
|
return validatePluginByPath(`/${normalized.join("/")}`)
|
|
594
580
|
}
|
|
595
581
|
if (normalized[0] === "api" && normalized.length > 1) {
|
package/server/public/common.js
CHANGED
|
@@ -16,7 +16,6 @@ const requirementsGuardedRoutePrefixes = [
|
|
|
16
16
|
'/api/',
|
|
17
17
|
'/_api/',
|
|
18
18
|
'/run/',
|
|
19
|
-
'/pinokio/run/',
|
|
20
19
|
'/tools',
|
|
21
20
|
'/bundle/',
|
|
22
21
|
'/connect/',
|
|
@@ -105,96 +104,6 @@ function createMinimalLoadingSwal () {
|
|
|
105
104
|
});
|
|
106
105
|
return close;
|
|
107
106
|
}
|
|
108
|
-
|
|
109
|
-
const PINOKIO_WAIT_FOOTER_ID = 'pinokio-process-wait-footer-status'
|
|
110
|
-
const PINOKIO_INSTALL_SPINNER_VARIANTS = ["grid-shift", "single-vacancy", "pulse-swap", "corner-chase", "flip-2x2", "stack-ripple", "pixel-orbit", "binary-shuffle"]
|
|
111
|
-
const PINOKIO_INSTALL_STATUS_SPINNER_HTML = `
|
|
112
|
-
<span class="install-status-spinner" aria-hidden="true">
|
|
113
|
-
<span class="install-status-grid-anchor install-status-grid-anchor-1"></span>
|
|
114
|
-
<span class="install-status-grid-anchor install-status-grid-anchor-2"></span>
|
|
115
|
-
<span class="install-status-grid-anchor install-status-grid-anchor-3"></span>
|
|
116
|
-
<span class="install-status-grid-anchor install-status-grid-anchor-4"></span>
|
|
117
|
-
<span class="install-status-grid-tile install-status-grid-tile-1"></span>
|
|
118
|
-
<span class="install-status-grid-tile install-status-grid-tile-2"></span>
|
|
119
|
-
<span class="install-status-grid-tile install-status-grid-tile-3"></span>
|
|
120
|
-
<span class="install-status-grid-tile install-status-grid-tile-4"></span>
|
|
121
|
-
<span class="install-status-grid-chaser"></span>
|
|
122
|
-
<span class="install-status-grid-pixel"></span>
|
|
123
|
-
</span>`
|
|
124
|
-
let lastPinokioWaitSpinnerVariant = null
|
|
125
|
-
|
|
126
|
-
function escapePinokioStatusHtml(value) {
|
|
127
|
-
return String(value == null ? '' : value)
|
|
128
|
-
.replace(/&/g, '&')
|
|
129
|
-
.replace(/</g, '<')
|
|
130
|
-
.replace(/>/g, '>')
|
|
131
|
-
.replace(/"/g, '"')
|
|
132
|
-
.replace(/'/g, ''')
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
function ensurePinokioWaitFooterStatus() {
|
|
136
|
-
let status = document.getElementById(PINOKIO_WAIT_FOOTER_ID)
|
|
137
|
-
if (status) {
|
|
138
|
-
return status
|
|
139
|
-
}
|
|
140
|
-
status = document.createElement('div')
|
|
141
|
-
status.id = PINOKIO_WAIT_FOOTER_ID
|
|
142
|
-
status.className = 'pinokio-install-inline-status pinokio-process-wait-footer-status'
|
|
143
|
-
status.hidden = true
|
|
144
|
-
status.setAttribute('aria-live', 'polite')
|
|
145
|
-
|
|
146
|
-
const anchor = document.querySelector('.terminal-container')
|
|
147
|
-
|| document.querySelector('main')
|
|
148
|
-
|| document.querySelector('#terminal')?.parentElement
|
|
149
|
-
|| document.querySelector('footer')
|
|
150
|
-
|| document.body
|
|
151
|
-
|
|
152
|
-
if (anchor && anchor !== document.body) {
|
|
153
|
-
anchor.insertAdjacentElement('afterend', status)
|
|
154
|
-
} else {
|
|
155
|
-
document.body.appendChild(status)
|
|
156
|
-
}
|
|
157
|
-
return status
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function showPinokioWaitFooterStatus(data = {}) {
|
|
161
|
-
const title = data.title || 'Waiting'
|
|
162
|
-
const description = data.description || data.message || ''
|
|
163
|
-
const status = ensurePinokioWaitFooterStatus()
|
|
164
|
-
const candidates = PINOKIO_INSTALL_SPINNER_VARIANTS.filter((variant) => variant !== lastPinokioWaitSpinnerVariant)
|
|
165
|
-
const pool = candidates.length > 0 ? candidates : PINOKIO_INSTALL_SPINNER_VARIANTS
|
|
166
|
-
lastPinokioWaitSpinnerVariant = pool[Math.floor(Math.random() * pool.length)]
|
|
167
|
-
document.documentElement.dataset.installSpinnerVariant = lastPinokioWaitSpinnerVariant
|
|
168
|
-
status.className = 'pinokio-install-inline-status pinokio-process-wait-footer-status is-progress'
|
|
169
|
-
status.innerHTML = `
|
|
170
|
-
<div class="install-status-shell">
|
|
171
|
-
${PINOKIO_INSTALL_STATUS_SPINNER_HTML}
|
|
172
|
-
<div class="install-status-copy">
|
|
173
|
-
<div class="install-status-title">${escapePinokioStatusHtml(title)}</div>
|
|
174
|
-
${description ? `<div class="install-status-detail">${escapePinokioStatusHtml(description)}</div>` : ''}
|
|
175
|
-
</div>
|
|
176
|
-
</div>
|
|
177
|
-
`
|
|
178
|
-
status.hidden = false
|
|
179
|
-
document.body.classList.add('pinokio-install-status-visible')
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
function hidePinokioWaitFooterStatus() {
|
|
183
|
-
const status = document.getElementById(PINOKIO_WAIT_FOOTER_ID)
|
|
184
|
-
if (!status) {
|
|
185
|
-
return
|
|
186
|
-
}
|
|
187
|
-
status.hidden = true
|
|
188
|
-
status.innerHTML = ''
|
|
189
|
-
document.body.classList.remove('pinokio-install-status-visible')
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
if (typeof window !== 'undefined') {
|
|
193
|
-
window.PinokioWaitFooterStatus = {
|
|
194
|
-
show: showPinokioWaitFooterStatus,
|
|
195
|
-
hide: hidePinokioWaitFooterStatus
|
|
196
|
-
}
|
|
197
|
-
}
|
|
198
107
|
function check_ready (targetUrl = null, options = {}) {
|
|
199
108
|
createLauncherDebugLog('check_ready start');
|
|
200
109
|
return fetch("/pinokio/requirements_ready").then((res) => {
|
|
@@ -2419,14 +2328,6 @@ if (typeof hotkeys === 'function') {
|
|
|
2419
2328
|
playNextSound();
|
|
2420
2329
|
};
|
|
2421
2330
|
|
|
2422
|
-
window.PinokioPlayNotificationSound = (sound) => {
|
|
2423
|
-
if (sound === false || isFalseyString(sound)) {
|
|
2424
|
-
return false;
|
|
2425
|
-
}
|
|
2426
|
-
enqueueSound(typeof sound === 'string' && sound ? sound : '/chime.mp3');
|
|
2427
|
-
return true;
|
|
2428
|
-
};
|
|
2429
|
-
|
|
2430
2331
|
const handlePacket = (packet) => {
|
|
2431
2332
|
if (!packet || packet.id !== CHANNEL_ID || packet.type !== 'notification') {
|
|
2432
2333
|
return;
|
|
@@ -3581,6 +3482,32 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
3581
3482
|
tools: null,
|
|
3582
3483
|
toolsPromise: null
|
|
3583
3484
|
};
|
|
3485
|
+
const ASK_AI_FALLBACK_TOOLS = [
|
|
3486
|
+
{
|
|
3487
|
+
value: 'claude',
|
|
3488
|
+
label: 'Claude Code',
|
|
3489
|
+
iconSrc: '/asset/plugin/code/claude/claude.png',
|
|
3490
|
+
href: '/run/plugin/code/claude/pinokio.js',
|
|
3491
|
+
category: 'CLI',
|
|
3492
|
+
isDefault: true
|
|
3493
|
+
},
|
|
3494
|
+
{
|
|
3495
|
+
value: 'codex',
|
|
3496
|
+
label: 'OpenAI Codex',
|
|
3497
|
+
iconSrc: '/asset/plugin/code/codex/openai.webp',
|
|
3498
|
+
href: '/run/plugin/code/codex/pinokio.js',
|
|
3499
|
+
category: 'CLI',
|
|
3500
|
+
isDefault: false
|
|
3501
|
+
},
|
|
3502
|
+
{
|
|
3503
|
+
value: 'gemini',
|
|
3504
|
+
label: 'Google Gemini CLI',
|
|
3505
|
+
iconSrc: '/asset/plugin/code/gemini/gemini.jpeg',
|
|
3506
|
+
href: '/run/plugin/code/gemini/pinokio.js',
|
|
3507
|
+
category: 'CLI',
|
|
3508
|
+
isDefault: false
|
|
3509
|
+
}
|
|
3510
|
+
];
|
|
3584
3511
|
|
|
3585
3512
|
initializeUniversalLauncherIntegration();
|
|
3586
3513
|
initializeCreateLauncherIntegration();
|
|
@@ -3993,7 +3920,6 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
3993
3920
|
return typeof pathname === 'string'
|
|
3994
3921
|
&& (
|
|
3995
3922
|
pathname.startsWith('/run/plugin/')
|
|
3996
|
-
|| pathname.startsWith('/pinokio/run/plugin/')
|
|
3997
3923
|
|| (pathname.startsWith('/run/api/') && /\/pinokio\.js$/i.test(pathname))
|
|
3998
3924
|
);
|
|
3999
3925
|
}
|
|
@@ -4085,11 +4011,11 @@ document.addEventListener("DOMContentLoaded", () => {
|
|
|
4085
4011
|
})
|
|
4086
4012
|
.then((payload) => {
|
|
4087
4013
|
const mapped = mapPluginMenuToAskAiTools(payload && Array.isArray(payload.menu) ? payload.menu : []);
|
|
4088
|
-
return mapped;
|
|
4014
|
+
return mapped.length > 0 ? mapped : ASK_AI_FALLBACK_TOOLS.slice();
|
|
4089
4015
|
})
|
|
4090
4016
|
.catch((error) => {
|
|
4091
|
-
console.warn('Failed to load Ask AI plugins', error);
|
|
4092
|
-
return
|
|
4017
|
+
console.warn('Failed to load Ask AI plugins, using fallback list', error);
|
|
4018
|
+
return ASK_AI_FALLBACK_TOOLS.slice();
|
|
4093
4019
|
})
|
|
4094
4020
|
.finally(() => {
|
|
4095
4021
|
askAiState.toolsPromise = null;
|
|
@@ -5,6 +5,33 @@
|
|
|
5
5
|
return;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
const FALLBACK_TOOLS = [
|
|
9
|
+
{
|
|
10
|
+
value: 'claude',
|
|
11
|
+
label: 'Claude Code',
|
|
12
|
+
iconSrc: '/asset/plugin/code/claude/claude.png',
|
|
13
|
+
isDefault: true,
|
|
14
|
+
href: '/run/plugin/code/claude/pinokio.js',
|
|
15
|
+
category: 'CLI',
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
value: 'codex',
|
|
19
|
+
label: 'OpenAI Codex',
|
|
20
|
+
iconSrc: '/asset/plugin/code/codex/openai.webp',
|
|
21
|
+
isDefault: false,
|
|
22
|
+
href: '/run/plugin/code/codex/pinokio.js',
|
|
23
|
+
category: 'CLI',
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
value: 'gemini',
|
|
27
|
+
label: 'Google Gemini CLI',
|
|
28
|
+
iconSrc: '/asset/plugin/code/gemini/gemini.jpeg',
|
|
29
|
+
isDefault: false,
|
|
30
|
+
href: '/run/plugin/code/gemini/pinokio.js',
|
|
31
|
+
category: 'CLI',
|
|
32
|
+
},
|
|
33
|
+
];
|
|
34
|
+
|
|
8
35
|
const CATEGORY_ORDER = ['CLI', 'IDE'];
|
|
9
36
|
const MODAL_VARIANTS = {
|
|
10
37
|
CREATE: 'create',
|
|
@@ -56,7 +83,7 @@
|
|
|
56
83
|
|
|
57
84
|
let value = '';
|
|
58
85
|
if (href) {
|
|
59
|
-
// Normalize href to a
|
|
86
|
+
// Normalize href to a plugin-relative path for the backend (e.g., code/codex)
|
|
60
87
|
const normalized = href.replace(/^\/run/, '').replace(/^\/+/, '');
|
|
61
88
|
const parts = normalized.split('/').filter(Boolean);
|
|
62
89
|
// Expect /plugin/<path...>/pinokio.js -> want <path...>
|
|
@@ -112,11 +139,11 @@
|
|
|
112
139
|
.then((data) => {
|
|
113
140
|
const menu = data && Array.isArray(data.menu) ? data.menu : [];
|
|
114
141
|
const tools = mapPluginMenuToCreateLauncherTools(menu);
|
|
115
|
-
return tools;
|
|
142
|
+
return tools.length > 0 ? tools : FALLBACK_TOOLS.slice();
|
|
116
143
|
})
|
|
117
144
|
.catch((error) => {
|
|
118
|
-
console.warn('
|
|
119
|
-
return
|
|
145
|
+
console.warn('Falling back to default plugins for create launcher modal', error);
|
|
146
|
+
return FALLBACK_TOOLS.slice();
|
|
120
147
|
})
|
|
121
148
|
.finally(() => {
|
|
122
149
|
loadingTools = null;
|