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,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
- return PluginSources.normalizePluginPath(value)
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) => {
@@ -154,9 +169,9 @@ function createContentValidationService({ kernel }) {
154
169
  }
155
170
 
156
171
  if (config && typeof config.icon === "string" && config.icon.trim()) {
157
- const pluginImage = PluginSources.pluginAssetHrefForIcon(normalizedPath, config.icon)
158
- if (pluginImage) {
159
- context.image = pluginImage
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
- const isSystemPlugin = PluginSources.isSystemPluginPath(normalizedPath)
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 = PluginSources.pluginPathToAbsolute(kernel, normalizedPath)
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) {
@@ -268,8 +267,9 @@ function createContentValidationService({ kernel }) {
268
267
  ))
269
268
  }
270
269
  if (normalizedPath.startsWith("/plugin/")) {
270
+ const isManagedDefaultPlugin = normalizedPath.startsWith("/plugin/code/")
271
271
  const declaredPath = typeof config.path === "string" ? config.path.trim() : ""
272
- if (declaredPath !== "plugin") {
272
+ if (!isManagedDefaultPlugin && declaredPath !== "plugin") {
273
273
  errors.push(buildError(
274
274
  'Standalone plugins must set `path: "plugin"`.',
275
275
  'Add `path: "plugin"` to pinokio.js.',
@@ -567,7 +567,7 @@ function createContentValidationService({ kernel }) {
567
567
  })
568
568
  }
569
569
 
570
- const validateRunPath = async (pathComponents, options = {}) => {
570
+ const validateRunPath = async (pathComponents) => {
571
571
  if (!Array.isArray(pathComponents) || pathComponents.length === 0) {
572
572
  return buildValid()
573
573
  }
@@ -576,9 +576,6 @@ function createContentValidationService({ kernel }) {
576
576
  return buildValid()
577
577
  }
578
578
  if (normalized[0] === "plugin") {
579
- if (options && options.system) {
580
- return validatePluginByPath(`${PluginSources.SYSTEM_RUN_PREFIX}/${normalized.join("/")}`)
581
- }
582
579
  return validatePluginByPath(`/${normalized.join("/")}`)
583
580
  }
584
581
  if (normalized[0] === "api" && normalized.length > 1) {
@@ -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, '&amp;')
129
- .replace(/</g, '&lt;')
130
- .replace(/>/g, '&gt;')
131
- .replace(/"/g, '&quot;')
132
- .replace(/'/g, '&#39;')
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 launcher tool path for the backend.
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('Failed to load create launcher plugins', error);
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;
@@ -25,6 +25,12 @@ aside {
25
25
  -webkit-app-region: no-drag !important;
26
26
  cursor: auto !important;
27
27
  }
28
+ header.grabbable {
29
+ /*
30
+ padding: 32px 10px 0 !important;
31
+ padding: 26px 0px 0 !important;
32
+ */
33
+ }
28
34
  /*
29
35
  header {
30
36
  cursor: grab;