pinokiod 7.2.8 → 7.2.9

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/server/index.js CHANGED
@@ -29,7 +29,7 @@ const serveIndex = require('./serveIndex')
29
29
  const registerFileRoutes = require('./routes/files')
30
30
  const registerAppRoutes = require('./routes/apps')
31
31
  const registerWorkspacesRoutes = require('./routes/workspaces')
32
- const registerDraftImportRoutes = require('./routes/draft_import')
32
+ const { mountFeatures } = require('./features')
33
33
  const Git = require("../kernel/git")
34
34
  const TerminalApi = require('../kernel/api/terminal')
35
35
 
@@ -80,7 +80,6 @@ const { createDesktopEventRouter } = require("./lib/desktop_event_router")
80
80
  const { createInjectRouter, resolveInjectList } = require("./lib/inject_router")
81
81
  const { createTaskPackageService } = require("./lib/task_packages")
82
82
  const { createTaskWorkspaceLinkService } = require("./lib/task_workspace_links")
83
- const { createDraftService } = require("./lib/drafts")
84
83
  const { createWorkspaceRuntimeService } = require("./lib/workspace_runtime")
85
84
  const { createWorkspaceCatalogService } = require("./lib/workspace_catalog")
86
85
  const { createContentValidationService } = require("./lib/content_validation")
@@ -2870,11 +2869,19 @@ class Server {
2870
2869
  const protectionPreference = protectionAppId && this.appPreferences && typeof this.appPreferences.getPreference === "function"
2871
2870
  ? await this.appPreferences.getPreference(protectionAppId)
2872
2871
  : null
2872
+ const draftWatchEnabled = this.kernel.watch && typeof this.kernel.watch.hasHandler === "function"
2873
+ ? this.kernel.watch.hasHandler(resolved, "draft")
2874
+ : false
2875
+ const draftWatchCwd = draftWatchEnabled
2876
+ ? (req.query.cwd || path.dirname(filepath))
2877
+ : ""
2873
2878
  const result = {
2874
2879
  portal: this.portal,
2875
2880
  projectName: (pathComponents.length > 0 ? pathComponents[0] : ''),
2876
2881
  protection_app_id: protectionAppId,
2877
2882
  protection_enabled: protectionPreference ? protectionPreference.protection_enabled !== false : false,
2883
+ draft_watch_enabled: draftWatchEnabled,
2884
+ draft_watch_cwd: draftWatchCwd,
2878
2885
  kill_message,
2879
2886
  callback,
2880
2887
  callback_target,
@@ -8412,23 +8419,20 @@ class Server {
8412
8419
  kernel: this.kernel
8413
8420
  })
8414
8421
  this.workspaceRuntime = workspaceRuntime
8415
- const drafts = createDraftService({
8422
+ const features = await mountFeatures({
8423
+ app: this.app,
8416
8424
  kernel: this.kernel,
8417
- taskWorkspaceLinks
8425
+ taskWorkspaceLinks,
8426
+ defaultRegistryUrl: DEFAULT_REGISTRY_URL
8418
8427
  })
8428
+ this.features = features
8429
+ const drafts = features.drafts.service
8419
8430
  this.drafts = drafts
8420
8431
  const workspaceCatalog = createWorkspaceCatalogService({
8421
8432
  kernel: this.kernel,
8422
8433
  workspaceRuntime,
8423
8434
  drafts
8424
8435
  })
8425
- drafts.start().catch((error) => {
8426
- console.warn("[drafts] failed to start", error && error.message ? error.message : error)
8427
- })
8428
- registerDraftImportRoutes(this.app, {
8429
- drafts,
8430
- defaultRegistryUrl: DEFAULT_REGISTRY_URL
8431
- })
8432
8436
  registerWorkspacesRoutes(this.app, {
8433
8437
  workspaceCatalog,
8434
8438
  composePeerAccessPayload: () => this.composePeerAccessPayload(),
@@ -9870,9 +9874,6 @@ class Server {
9870
9874
  }
9871
9875
  try {
9872
9876
  await taskWorkspaceLinks.touchTaskWorkspace(task.id, workspaceRef)
9873
- drafts.trackWorkspace({ taskId: task.id, ref: workspaceRef }).catch((error) => {
9874
- console.warn("[drafts] failed to track workspace", error && error.message ? error.message : error)
9875
- })
9876
9877
  } catch (error) {
9877
9878
  await taskPackages.deleteTaskPackage(task.id).catch(() => {})
9878
9879
  throw error
@@ -10110,7 +10111,8 @@ class Server {
10110
10111
  }
10111
10112
  }
10112
10113
 
10113
- const prompt = taskPackages.applyTemplateValues(task.template, filterFilledTaskInputValues(inputValues)).trim()
10114
+ const filledInputValues = filterFilledTaskInputValues(inputValues)
10115
+ const prompt = taskPackages.applyTemplateValues(task.template, filledInputValues).trim()
10114
10116
  if (!prompt) {
10115
10117
  await renderTaskLaunchPage(req, res, task, {
10116
10118
  selectedTool,
@@ -10216,9 +10218,6 @@ class Server {
10216
10218
  }
10217
10219
  try {
10218
10220
  await taskWorkspaceLinks.touchTaskWorkspace(task.id, workspaceRef)
10219
- drafts.trackWorkspace({ taskId: task.id, ref: workspaceRef }).catch((error) => {
10220
- console.warn("[drafts] failed to track workspace", error && error.message ? error.message : error)
10221
- })
10222
10221
  } catch (error) {
10223
10222
  await renderTaskLaunchPage(req, res, task, {
10224
10223
  selectedTool,
@@ -10234,24 +10233,13 @@ class Server {
10234
10233
  params.set("cwd", targetPath)
10235
10234
  params.set("chrome", "full")
10236
10235
  params.set("prompt", prompt)
10236
+ if (filledInputValues.url) {
10237
+ params.set("url", filledInputValues.url)
10238
+ }
10237
10239
  res.redirect(`${pluginHref}?${params.toString()}`)
10238
10240
  })
10239
10241
  this.app.post("/task/start", handleTaskStartRequest)
10240
10242
 
10241
- this.app.get("/drafts", ex(async (req, res) => {
10242
- const cwd = typeof req.query.cwd === "string" ? req.query.cwd : ""
10243
- const items = await drafts.listPending({ cwd })
10244
- res.json({
10245
- ok: true,
10246
- items
10247
- })
10248
- }))
10249
-
10250
- this.app.post("/drafts/:id/dismiss", ex(async (req, res) => {
10251
- const ok = await drafts.dismiss(req.params.id)
10252
- res.json({ ok })
10253
- }))
10254
-
10255
10243
  this.app.get("/home", renderHomePage)
10256
10244
 
10257
10245
  const normalizePathForComparison = (value) => {
@@ -10554,7 +10542,8 @@ class Server {
10554
10542
  return
10555
10543
  }
10556
10544
 
10557
- const prompt = taskPackages.applyTemplateValues(task.template, filterFilledTaskInputValues(inputValues)).trim()
10545
+ const filledInputValues = filterFilledTaskInputValues(inputValues)
10546
+ const prompt = taskPackages.applyTemplateValues(task.template, filledInputValues).trim()
10558
10547
  if (!prompt) {
10559
10548
  res.status(400).json({
10560
10549
  ok: false,
@@ -10648,15 +10637,15 @@ class Server {
10648
10637
  }
10649
10638
 
10650
10639
  await taskWorkspaceLinks.touchTaskWorkspace(task.id, workspaceRef)
10651
- drafts.trackWorkspace({ taskId: task.id, ref: workspaceRef }).catch((error) => {
10652
- console.warn("[drafts] failed to track workspace", error && error.message ? error.message : error)
10653
- })
10654
10640
 
10655
10641
  const params = new URLSearchParams()
10656
10642
  params.set("cwd", targetPath)
10657
10643
  params.set("chrome", "full")
10658
10644
  params.set("session", createUniversalLauncherSessionId())
10659
10645
  params.set("prompt", prompt)
10646
+ if (filledInputValues.url) {
10647
+ params.set("url", filledInputValues.url)
10648
+ }
10660
10649
 
10661
10650
  res.json({
10662
10651
  ok: true,
@@ -5222,9 +5222,6 @@ header.navheader .mode-selector .community-mode-toggle {
5222
5222
  <a class='btn mobile-sheet-action' href="/home" aria-label="Home" title="Home">
5223
5223
  <i class="fa-solid fa-house"></i>
5224
5224
  </a>
5225
- <a class='btn mobile-sheet-action' href="/workspaces" aria-label="Workspaces" title="Workspaces">
5226
- <i class="fa-solid fa-folder-tree"></i>
5227
- </a>
5228
5225
  <button type='button' class='btn mobile-sheet-action' data-mobile-proxy="#refresh-page" data-mobile-close-menu="true" aria-label="Refresh" title="Refresh">
5229
5226
  <i class="fa-solid fa-rotate-right"></i>
5230
5227
  </button>
@@ -5291,15 +5288,9 @@ header.navheader .mode-selector .community-mode-toggle {
5291
5288
  </a>
5292
5289
  <%})%>
5293
5290
  </div>
5291
+ <div class='active-nested-path hidden' id='active-nested-path'></div>
5294
5292
  </div>
5295
5293
  <div class='menu-actions'>
5296
- <a id='workspaces-tab' href="/workspaces" class="btn header-item" data-tippy-content="Workspaces">
5297
- <div class='tab'>
5298
- <i class="fa-solid fa-folder-tree menu-action-leading-icon"></i>
5299
- <div class='display'>Workspaces</div>
5300
- <div class='flexible'></div>
5301
- </div>
5302
- </a>
5303
5294
  <% if (type === 'run') { %>
5304
5295
  <button type='button' id='ask-ai-tab' class="btn header-item" data-static="ask-ai" data-workspace="<%=name%>" data-workspace-cwd="<%=path%>" data-ask-ai-trigger="true" data-tippy-content="Ask AI">
5305
5296
  <div class='tab'>
@@ -5615,9 +5606,6 @@ header.navheader .mode-selector .community-mode-toggle {
5615
5606
  <a class='btn mobile-sheet-action' href="/home" aria-label="Home" title="Home">
5616
5607
  <i class="fa-solid fa-house"></i>
5617
5608
  </a>
5618
- <a class='btn mobile-sheet-action' href="/workspaces" aria-label="Workspaces" title="Workspaces">
5619
- <i class="fa-solid fa-folder-tree"></i>
5620
- </a>
5621
5609
  <button type='button' class='btn mobile-sheet-action' data-mobile-proxy="#refresh-page" data-mobile-close-menu="true" aria-label="Refresh" title="Refresh">
5622
5610
  <i class="fa-solid fa-rotate-right"></i>
5623
5611
  </button>
@@ -7197,6 +7185,7 @@ const rerenderMenuSection = (container, html) => {
7197
7185
  }
7198
7186
 
7199
7187
  if (!target) {
7188
+ activeNestedFocusMenu = null
7200
7189
  syncActiveNestedPath()
7201
7190
  browserPopoutSurface.hide()
7202
7191
  document.querySelector(".container").classList.remove("active")
@@ -7230,6 +7219,7 @@ const rerenderMenuSection = (container, html) => {
7230
7219
  el.classList.remove("selected")
7231
7220
  })
7232
7221
  target.classList.add("selected")
7222
+ activeNestedFocusMenu = null
7233
7223
  syncActiveNestedPath({ selectedLink: target })
7234
7224
  if (skipPersistedSelection && target.hasAttribute('data-default')) {
7235
7225
  ignorePersistedSelection = false
@@ -8065,7 +8055,162 @@ const rerenderMenuSection = (container, html) => {
8065
8055
 
8066
8056
  const getSubmenu = (menu) => getDirectChild(menu, ".submenu")
8067
8057
  const getToggle = (menu) => getDirectChild(menu, ".reveal")
8068
- const syncActiveNestedPath = () => {}
8058
+ const activeNestedPathRoot = document.getElementById("active-nested-path")
8059
+ const activeNestedProxyMap = new WeakMap()
8060
+ let activeNestedFocusMenu = null
8061
+
8062
+ const getNestedMenuChain = (node) => {
8063
+ if (!node) {
8064
+ return []
8065
+ }
8066
+ let current = node
8067
+ if (!current.classList || !current.classList.contains("nested-menu")) {
8068
+ current = current.closest(".nested-menu")
8069
+ }
8070
+ const chain = []
8071
+ while (current) {
8072
+ chain.unshift(current)
8073
+ current = current.parentElement ? current.parentElement.closest(".nested-menu") : null
8074
+ }
8075
+ return chain
8076
+ }
8077
+
8078
+ const sanitizeActiveNestedProxy = (proxy) => {
8079
+ if (!proxy) {
8080
+ return null
8081
+ }
8082
+ proxy.removeAttribute("id")
8083
+ proxy.classList.remove("frame-link", "selected", "tab-link-popover-host")
8084
+ proxy.classList.add("active-nested-proxy")
8085
+ proxy.setAttribute("data-active-nested-proxy", "true")
8086
+ proxy.querySelectorAll(".tab-link-popover-trigger").forEach((node) => {
8087
+ node.remove()
8088
+ })
8089
+ return proxy
8090
+ }
8091
+
8092
+ const buildActiveNestedProxy = (child, isCurrent) => {
8093
+ if (!child) {
8094
+ return null
8095
+ }
8096
+ let proxy
8097
+ if (child.classList && child.classList.contains("nested-menu")) {
8098
+ const toggle = getToggle(child)
8099
+ if (!toggle) {
8100
+ return null
8101
+ }
8102
+ proxy = toggle.cloneNode(true)
8103
+ } else {
8104
+ proxy = child.cloneNode(true)
8105
+ }
8106
+ sanitizeActiveNestedProxy(proxy)
8107
+ if (child.classList && child.classList.contains("nested-menu")) {
8108
+ const loader = proxy.querySelector(".loader")
8109
+ if (loader) {
8110
+ loader.innerHTML = `<i class="fa-solid ${isCurrent ? "fa-angle-down" : "fa-angle-right"}"></i>`
8111
+ }
8112
+ }
8113
+ proxy.classList.toggle("is-current", Boolean(isCurrent))
8114
+ activeNestedProxyMap.set(proxy, child)
8115
+ return proxy
8116
+ }
8117
+
8118
+ const syncActiveNestedPath = ({ selectedLink = null } = {}) => {
8119
+ if (!activeNestedPathRoot) {
8120
+ return
8121
+ }
8122
+ if (activeNestedFocusMenu && !activeNestedFocusMenu.isConnected) {
8123
+ activeNestedFocusMenu = null
8124
+ }
8125
+ const currentSelectedLink = (selectedLink && selectedLink.isConnected)
8126
+ ? selectedLink
8127
+ : document.querySelector("aside .frame-link.selected")
8128
+ const chain = activeNestedFocusMenu
8129
+ ? getNestedMenuChain(activeNestedFocusMenu)
8130
+ : getNestedMenuChain(currentSelectedLink)
8131
+
8132
+ activeNestedPathRoot.replaceChildren()
8133
+
8134
+ if (!chain.length) {
8135
+ activeNestedPathRoot.classList.add("hidden")
8136
+ if (window.PinokioMenuScrollHints && typeof window.PinokioMenuScrollHints.update === "function") {
8137
+ window.PinokioMenuScrollHints.update()
8138
+ }
8139
+ return
8140
+ }
8141
+
8142
+ chain.forEach((menu, index) => {
8143
+ const submenu = getSubmenu(menu)
8144
+ if (!submenu) {
8145
+ return
8146
+ }
8147
+ const row = document.createElement("div")
8148
+ row.className = "m active-nested-row"
8149
+ row.dataset.activeNestedLevel = String(index)
8150
+ const nextMenu = chain[index + 1] || null
8151
+
8152
+ Array.from(submenu.children).forEach((child) => {
8153
+ let isCurrent = false
8154
+ if (child.classList && child.classList.contains("nested-menu")) {
8155
+ isCurrent = child === nextMenu || (!nextMenu && currentSelectedLink ? child.contains(currentSelectedLink) : false)
8156
+ } else {
8157
+ isCurrent = child === currentSelectedLink
8158
+ }
8159
+ const proxy = buildActiveNestedProxy(child, isCurrent)
8160
+ if (proxy) {
8161
+ row.appendChild(proxy)
8162
+ }
8163
+ })
8164
+
8165
+ if (row.childElementCount > 0) {
8166
+ activeNestedPathRoot.appendChild(row)
8167
+ }
8168
+ })
8169
+
8170
+ if (!activeNestedPathRoot.childElementCount) {
8171
+ activeNestedPathRoot.classList.add("hidden")
8172
+ if (window.PinokioMenuScrollHints && typeof window.PinokioMenuScrollHints.update === "function") {
8173
+ window.PinokioMenuScrollHints.update()
8174
+ }
8175
+ return
8176
+ }
8177
+
8178
+ activeNestedPathRoot.classList.remove("hidden")
8179
+ const currentProxy = activeNestedPathRoot.querySelector(".active-nested-proxy.is-current")
8180
+ if (currentProxy && typeof currentProxy.scrollIntoView === "function") {
8181
+ currentProxy.scrollIntoView({
8182
+ block: "nearest",
8183
+ inline: "nearest"
8184
+ })
8185
+ }
8186
+ if (window.PinokioMenuScrollHints && typeof window.PinokioMenuScrollHints.update === "function") {
8187
+ window.PinokioMenuScrollHints.update()
8188
+ }
8189
+ }
8190
+
8191
+ if (activeNestedPathRoot) {
8192
+ activeNestedPathRoot.addEventListener("click", (event) => {
8193
+ const proxy = event.target.closest("[data-active-nested-proxy='true']")
8194
+ if (!proxy || !activeNestedPathRoot.contains(proxy)) {
8195
+ return
8196
+ }
8197
+ const source = activeNestedProxyMap.get(proxy)
8198
+ if (!source || !source.isConnected) {
8199
+ return
8200
+ }
8201
+ event.preventDefault()
8202
+ event.stopPropagation()
8203
+ if (source.classList && source.classList.contains("nested-menu")) {
8204
+ activeNestedFocusMenu = source
8205
+ syncActiveNestedPath()
8206
+ return
8207
+ }
8208
+ activeNestedFocusMenu = null
8209
+ if (typeof source.click === "function") {
8210
+ source.click()
8211
+ }
8212
+ })
8213
+ }
8069
8214
 
8070
8215
  renderSelection()
8071
8216
 
@@ -3086,11 +3086,13 @@ const reloadMemory = async () => {
3086
3086
  </a>
3087
3087
  </div>
3088
3088
  </div>
3089
- <script>
3090
- window.PinokioDraftContext = {
3091
- cwd: <%- JSON.stringify((typeof cwd !== 'undefined' && cwd) ? cwd : '').replace(/</g, '\\u003c') %>
3092
- };
3093
- </script>
3094
- <script src="/drafts.js"></script>
3089
+ <% if (typeof draft_watch_enabled !== 'undefined' && draft_watch_enabled) { %>
3090
+ <script>
3091
+ window.PinokioDraftContext = {
3092
+ cwd: <%- JSON.stringify((typeof draft_watch_cwd !== 'undefined' && draft_watch_cwd) ? draft_watch_cwd : '').replace(/</g, '\\u003c') %>
3093
+ };
3094
+ </script>
3095
+ <script src="/drafts.js"></script>
3096
+ <% } %>
3095
3097
  </body>
3096
3098
  </html>