From 0d0e7f38f9cc800a85467b467ff8952e44f50a35 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 9 Nov 2026 01:15:57 +0000 Subject: [PATCH 1/3] release: feed for v2.0.1-experimental (#177) release: update feed for v2.0.1-experimental [skip ci] Co-authored-by: github-actions[bot] --- updates/experimental/whats-new.json | 4 ++++ updates/experimental/win32/x64/archive/latest.json | 14 +++++++------- updates/experimental/win32/x64/user/latest.json | 14 +++++++------- 3 files changed, 18 insertions(+), 14 deletions(-) diff --git a/updates/experimental/whats-new.json b/updates/experimental/whats-new.json index 62d334d9..abbb3da7 100644 --- a/updates/experimental/whats-new.json +++ b/updates/experimental/whats-new.json @@ -1,5 +1,9 @@ { "versions": [ + { + "version": "2.0.0-experimental", + "notes": "### ⭐ PiCode Pro\n\n- **GitHub and Jira issues in the editor.** See what was reported on the project you have open, right beside your code. Each folder shows its own repository or Jira space.\n- **A real Jira board.** The same columns as in Jira: drag cards between them, or open an issue to change its type, priority, people, labels or description. GitHub issues can be edited too.\n- **Fix with pi.** One button writes the issue into a new chat for you to review. Nothing is sent until you say so, and a report from outside your team is marked as such.\n- **An Account window.** Your plan, cloud sync, connections and Pro features in one place. Choose what syncs, part by part.\n- **Your connections are safer.** GitHub and Jira access now stays encrypted on our servers, not on your computer.\n- **Buying or cancelling Pro shows up by itself.** PiCode notices the change when you come back to the window, with no need to sign in again.\n\n### ✨ New for everyone\n\n- **What's New you can try.** A window explains each novelty, says if it is free or Pro, and lets you play with a small demo or press the button that does the real thing.\n- **A new About window.** Check for updates and get them from there, copy any detail with a click, and find what is hidden behind the mascot.\n- **See what the agent is doing.** On longer jobs, Status and Tasks show the plan, how far along it is and what is happening right now.\n- **Background jobs in view.** Long commands the agent leaves running appear in Tasks with their output, move to Finished by themselves, and the agent's reply reaches your chat even after its turn was over.\n- **Memory filters.** Filter your memories by type, scope and date, and search finds more results per project.\n- **A better empty chat.** New chats suggest where to start.\n\n### 🔒 Security\n\n- **Opening a folder no longer runs its code without your permission.** A project's own extensions, packages, settings and MCP servers only load once you trust the folder.\n- **Safer sign-in.** A web page can no longer sign the editor in to someone else's account.\n- **Signed updates.** PiCode checks that an update notice really comes from PiCode, and ignores it if it doesn't.\n\n### ⚡ Faster\n\n- **Issues don't reload** when you switch between panels: the last list appears at once.\n- **A quieter Status column.** It checks for changes less often and doesn't redraw when nothing changed.\n- **Lighter background work,** and the session list appears sooner after starting.\n\n### 🐛 Fixed and tidied\n\n- **Going back to the Editor layout** no longer leaves the bottom panel open.\n- **The Agent layout always opens on Status,** without an empty gap at the top of it.\n- **Updating the memory engine now takes effect:** PiCode offers to restart it, with no need to close every window.\n- **Undo these changes** asks first, and says so if they were already undone.\n- **Changes** in Status opens and closes its list with the same click, and **Tasks** lists only agents and tasks working for you.\n- **The chat's Ask / Allow all picker is gone.** It promised a choice that did not exist: the agent runs its tools without asking. MCP servers connected in the editor keep asking.\n- **Show Release Notes is gone** from the Help menu: Show What's New tells you what changed." + }, { "version": "1.0.8-experimental", "notes": "### 🔒 Security\n\n- **Safer sign-in:** a web page can no longer sign the editor in to someone else's account. Each sign-in now only accepts the answer to its own request.\n- **Signed updates:** PiCode now checks that an update notice really comes from PiCode, and ignores it if it doesn't." diff --git a/updates/experimental/win32/x64/archive/latest.json b/updates/experimental/win32/x64/archive/latest.json index eb569dcc..8aa33d59 100644 --- a/updates/experimental/win32/x64/archive/latest.json +++ b/updates/experimental/win32/x64/archive/latest.json @@ -1,10 +1,10 @@ { - "version": "e920ff007d758dd16c268f1737a667c484b956d0", - "productVersion": "1.144.9", - "picodeVersion": "2.0.0-experimental", + "version": "2f3746b558ed1494372eed1ab38c51f6d608cbb3", + "productVersion": "1.144.10", + "picodeVersion": "2.0.1-experimental", "kind": "release", - "timestamp": 1794174131420, - "url": "https://github.com/Tomas-Platero/PiCode/releases/download/v2.0.0-experimental/PiCode-win32-x64-2.0.0-experimental.zip", - "sha256hash": "01d7722da3803bf542700141026e70fb3f1417844a61edbf123a0451f7080903", - "signature": "aZCruNyzkrLI01zwH4AUzPwD6qihvM8LnzxrY/OnMUFpFyraV4Avrgg3Q0VScAWH2HR6yHFzJL7M5CHbZhlUBw==" + "timestamp": 1794186950260, + "url": "https://github.com/Tomas-Platero/PiCode/releases/download/v2.0.1-experimental/PiCode-win32-x64-2.0.1-experimental.zip", + "sha256hash": "7b18ac48a8f31aa3a6820f032d16034cd72e3a3115be5e0cc8e075bc9a0c65bd", + "signature": "tZ6yfwNqWv1ixW5vXx0S0M38rJ3oSMj86k36VFriHrYFl8dm32h01ufYy61wfKx3o/M2myLKcE0XRAxCi6TnDQ==" } diff --git a/updates/experimental/win32/x64/user/latest.json b/updates/experimental/win32/x64/user/latest.json index b2c40db1..549e135b 100644 --- a/updates/experimental/win32/x64/user/latest.json +++ b/updates/experimental/win32/x64/user/latest.json @@ -1,10 +1,10 @@ { - "version": "e920ff007d758dd16c268f1737a667c484b956d0", - "productVersion": "1.144.9", - "picodeVersion": "2.0.0-experimental", + "version": "2f3746b558ed1494372eed1ab38c51f6d608cbb3", + "productVersion": "1.144.10", + "picodeVersion": "2.0.1-experimental", "kind": "release", - "timestamp": 1794174131515, - "url": "https://github.com/Tomas-Platero/PiCode/releases/download/v2.0.0-experimental/PiCode-win32-x64-2.0.0-experimental-setup.exe", - "sha256hash": "8a80d9778f40581b809d2edcfc72c53bf18c5e0d12eab66488e9d5823c88a5c7", - "signature": "+cZPOAxW6CTreZxGlUuhRtp1EZZdWfXEv/BCFZ0t16QWLGm+vPlUDlocu1IuaKNK3umIkb/MVP6GY9aMEDvqBw==" + "timestamp": 1794186950381, + "url": "https://github.com/Tomas-Platero/PiCode/releases/download/v2.0.1-experimental/PiCode-win32-x64-2.0.1-experimental-setup.exe", + "sha256hash": "ce20d240653d5b4d93da348d21b701e783b3c72cb2fdfb4456b1242da7acc395", + "signature": "I4q+d15OAm/9Y6GJqz3W9a+e0FcNe6QqbnjVrKyWYj8P+NH4N69B+GV3fa909ovyr0Qa7AaiCwVMeOSaJ/w4AQ==" } From 98de48116cd28df1d70b3a3359e6729295ec83de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Platero?= <133709838+TomasPlatero@users.noreply.github.com> Date: Mon, 9 Nov 2026 08:42:21 +0100 Subject: [PATCH 2/3] release: v2.0.2-experimental (#180) * fix(whats-new): list fixes under "Bugs fixed" and never open a blank window * fix(update): stop the memory engine running from the install folder before installing * release: v2.0.2-experimental --- AGENTS.md | 1 + .../picode/test/update-memory-engine.test.ts | 83 ++++++++++++++++ package.json | 2 +- product.json | 4 +- .../electron-main/picodeMemoryEngine.ts | 96 +++++++++++++++++++ .../electron-main/updateService.win32.ts | 18 ++++ .../contrib/picode/browser/picodeWhatsNew.ts | 6 +- .../picode/browser/picodeWhatsNewData.ts | 11 +++ .../picode/browser/picodeWhatsNewWindow.ts | 18 +++- .../browser/test/picodeWhatsNewData.test.ts | 11 ++- src/vs/workbench/contrib/picode/l10n/cs.json | 1 + src/vs/workbench/contrib/picode/l10n/de.json | 1 + src/vs/workbench/contrib/picode/l10n/es.json | 1 + src/vs/workbench/contrib/picode/l10n/fr.json | 1 + src/vs/workbench/contrib/picode/l10n/it.json | 1 + src/vs/workbench/contrib/picode/l10n/ja.json | 1 + src/vs/workbench/contrib/picode/l10n/ko.json | 1 + src/vs/workbench/contrib/picode/l10n/pl.json | 1 + .../workbench/contrib/picode/l10n/pt-br.json | 1 + src/vs/workbench/contrib/picode/l10n/ru.json | 1 + .../workbench/contrib/picode/l10n/source.json | 1 + src/vs/workbench/contrib/picode/l10n/tr.json | 1 + .../workbench/contrib/picode/l10n/zh-cn.json | 1 + .../workbench/contrib/picode/l10n/zh-tw.json | 1 + 24 files changed, 253 insertions(+), 11 deletions(-) create mode 100644 extensions/picode/test/update-memory-engine.test.ts create mode 100644 src/vs/platform/update/electron-main/picodeMemoryEngine.ts diff --git a/AGENTS.md b/AGENTS.md index 07f41d64..29440e80 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -499,3 +499,4 @@ Si algo cambia en el proyecto, se actualiza la frase o se añade una nueva, pero * **2026-11-08** · Fuera el selector de permisos del chat («Sí, quítalo»): *Ask / Allow all* prometía una elección que no existía, porque pi ejecuta sin preguntar. Los MCP conectados en el propio editor siguen preguntando (ADR-040, adenda). La web y los términos ya dicen que el agente actúa sin preguntar. * **2026-11-09** · Conectar Jira ya no depende del navegador («no conecta jira», «Sí, arréglalo»): Edge no abría el editor al pulsar *Open PiCode*. Ahora el servidor sigue el intento y el editor le pregunta cómo va, como en GitHub. La página de vuelta enseña a qué cuenta se conecta y pide confirmar, para que nadie pueda llevarse el Jira de otra persona con un enlace (ADR-042, adenda 12). * **2026-11-09** · Release 2.0.1 en experimental («saca release no? para que probar esto»): lleva la conexión con Jira sin depender del navegador y las builds locales que ya no le quitan los enlaces a la copia instalada. +* **2026-11-09** · Las novedades salen también con los arreglos, con una parte «Bugs fixed» («de la 2.0.0 a la 2.0.1 mantenlo y vas añadiendo en una parte bugs arreglados»): las páginas con demo cambian solo al pasar de línea (2.0 a 2.1, con lo que tú me digas que lleva), y la última cifra son arreglos. Además, la ventana ya no sale en blanco cuando la versión no trae páginas propias. Y al actualizar, el editor cierra el motor de memoria que corre desde su carpeta justo antes de instalar («esto no es lo suyo»): se quedaba abierto y el actualizador no podía borrar `resources`. Solo cierra el de su propia carpeta; el de otro programa no se toca. diff --git a/extensions/picode/test/update-memory-engine.test.ts b/extensions/picode/test/update-memory-engine.test.ts new file mode 100644 index 00000000..2e3bd331 --- /dev/null +++ b/extensions/picode/test/update-memory-engine.test.ts @@ -0,0 +1,83 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) PiCode. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Closing the memory engine that PiCode carries before an update replaces its folder, run on its own. + * + * What matters: an engine running from the installation's own folder is stopped (whatever the case + * of the drive letter), and nothing else is: not the one another program installed, not a folder + * with a similar name, not an answer that is not a process. + */ + +import assert from 'assert'; +import { test } from 'node:test'; +import { isInsideFolder, memoryFolderOf, readRunningEngines, stopEnginesInside } from '../../../src/vs/platform/update/electron-main/picodeMemoryEngine.ts'; + +const INSTALL = 'C:\\Users\\tapla\\AppData\\Local\\Programs\\PiCode Experimental-win32-x64-experimental'; +const MEMORY = `${INSTALL}\\resources\\memory`; + +function processes(running: { pid: number; path: string }[], failing: number[] = []) { + const killed: number[] = []; + return { + killed, + io: { + list: () => running, + kill: (pid: number) => { + if (failing.includes(pid)) { + throw new Error('already gone'); + } + killed.push(pid); + } + } + }; +} + +test('the memory folder is the one next to the editor code', () => { + assert.strictEqual(memoryFolderOf(`${INSTALL}\\resources\\app`), MEMORY); +}); + +test('an engine running from the installation is stopped, whatever the case of its drive', () => { + const { io, killed } = processes([{ pid: 15460, path: MEMORY.replace('C:', 'c:') + '\\engram.exe' }]); + assert.deepStrictEqual(stopEnginesInside(MEMORY, io, true), [15460]); + assert.deepStrictEqual(killed, [15460]); +}); + +test('the engine another program installed is left alone', () => { + const { io, killed } = processes([ + { pid: 28732, path: 'C:\\Users\\tapla\\AppData\\Local\\engram\\bin\\engram.exe' }, + { pid: 15460, path: `${MEMORY}\\engram.exe` }, + ]); + assert.deepStrictEqual(stopEnginesInside(MEMORY, io, true), [15460]); + assert.deepStrictEqual(killed, [15460]); +}); + +test('a folder that only starts with the same name is not the installation', () => { + assert.strictEqual(isInsideFolder(`${MEMORY}-old\\engram.exe`, MEMORY, true), false); + assert.strictEqual(isInsideFolder(`${MEMORY}\\engram.exe`, MEMORY, true), true); + assert.strictEqual(isInsideFolder(`${MEMORY}\\`, MEMORY, true), false); +}); + +test('one that cannot be stopped does not keep the others from stopping', () => { + const { io, killed } = processes([ + { pid: 1, path: `${MEMORY}\\engram.exe` }, + { pid: 2, path: `${MEMORY}\\engram.exe` }, + ], [1]); + assert.deepStrictEqual(stopEnginesInside(MEMORY, io, true), [2]); + assert.deepStrictEqual(killed, [2]); +}); + +test('nothing running means nothing to stop', () => { + const { io, killed } = processes([]); + assert.deepStrictEqual(stopEnginesInside(MEMORY, io, true), []); + assert.deepStrictEqual(killed, []); +}); + +test('the system listing is read one process per line, and anything else is ignored', () => { + const output = `15460|${MEMORY}\\engram.exe\r\n\r\nnot a process\r\n|${MEMORY}\\x.exe\r\n0|${MEMORY}\\x.exe\r\nabc|${MEMORY}\\x.exe\r\n28732|C:\\other\\engram.exe\r\n`; + assert.deepStrictEqual(readRunningEngines(output), [ + { pid: 15460, path: `${MEMORY}\\engram.exe` }, + { pid: 28732, path: 'C:\\other\\engram.exe' }, + ]); +}); diff --git a/package.json b/package.json index a51ef731..770b39f6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "code-oss-dev", - "version": "1.144.10", + "version": "1.144.11", "distro": "c842171bd42ca4aef20b0a186c94d99edd763842", "author": { "name": "PiCode" diff --git a/product.json b/product.json index 307ce73a..c27e52eb 100644 --- a/product.json +++ b/product.json @@ -758,7 +758,7 @@ "default": false } }, - "version": "1.144.10", - "picodeVersion": "2.0.1-experimental", + "version": "1.144.11", + "picodeVersion": "2.0.2-experimental", "hotfixPublicKey": "MCowBQYDK2VwAyEAZes8irGrgqOvvCEWRBn3rwOG6qxSNp+zxWOX3HqXyjo=" } diff --git a/src/vs/platform/update/electron-main/picodeMemoryEngine.ts b/src/vs/platform/update/electron-main/picodeMemoryEngine.ts new file mode 100644 index 00000000..68f75f7c --- /dev/null +++ b/src/vs/platform/update/electron-main/picodeMemoryEngine.ts @@ -0,0 +1,96 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) PiCode. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +/** + * Closing PiCode's own memory engine before an update replaces the folder it runs from. + * + * The engine travels inside the installation (`/resources/memory/engram.exe`). The window that + * started it stops it when it closes, but when the editor quits to update, that window is told to + * stop and exits in a fraction of a second: an engine that outlives it keeps its files open, and the + * updater then cannot delete the folder ("Access denied"). So the main process, once every window is + * gone and right before the installer starts, closes any engine running from the folder being + * replaced. Only by where the program is: another program's engine (one installed on its own, under + * its own folder) is never touched, and neither is anything that is not the engine. + * + * Kept free of other PiCode modules so a test can load it on its own (`node --test`). + */ + +import { execFileSync } from 'child_process'; +import { dirname, join, resolve } from 'path'; + +/** A process running the engine, with the program it was started from. */ +export interface IRunningEngine { + readonly pid: number; + readonly path: string; +} + +export interface IMemoryEngineProcesses { + list(): readonly IRunningEngine[]; + kill(pid: number): void; +} + +/** Where the installation's engine lives, from the folder the editor's code is in (`/resources/app`). */ +export function memoryFolderOf(appRoot: string): string { + return join(dirname(appRoot), 'memory'); +} + +/** Whether `file` is inside `folder`. Windows paths are compared without regard to case. */ +export function isInsideFolder(file: string, folder: string, ignoreCase: boolean): boolean { + const normal = (value: string) => { + const full = resolve(value).replace(/[\\/]+$/, ''); + return ignoreCase ? full.toLowerCase() : full; + }; + const inside = normal(folder); + const candidate = normal(file); + return candidate.startsWith(inside + '\\') || candidate.startsWith(inside + '/'); +} + +/** Stops every engine started from `folder` and returns their process ids. A failure to stop one never stops the others. */ +export function stopEnginesInside(folder: string, processes: IMemoryEngineProcesses, ignoreCase = process.platform === 'win32'): number[] { + const stopped: number[] = []; + for (const engine of processes.list()) { + if (!Number.isInteger(engine.pid) || engine.pid <= 0 || !isInsideFolder(engine.path, folder, ignoreCase)) { + continue; + } + try { + processes.kill(engine.pid); + stopped.push(engine.pid); + } catch { + // Already gone, or not ours to stop: the updater will say so if it still cannot go on. + } + } + return stopped; +} + +/** Reads the output of the system listing: one `pid|path` per line, anything else is ignored. */ +export function readRunningEngines(output: string): IRunningEngine[] { + const engines: IRunningEngine[] = []; + for (const line of output.split(/\r?\n/)) { + const bar = line.indexOf('|'); + const pid = Number(line.slice(0, bar)); + const path = line.slice(bar + 1).trim(); + if (bar > 0 && Number.isInteger(pid) && pid > 0 && path !== '') { + engines.push({ pid, path }); + } + } + return engines; +} + +/** The real thing, on Windows: the engines the system is running, and a way to stop one. */ +export const systemMemoryEngines: IMemoryEngineProcesses = { + list: () => { + try { + const output = execFileSync('powershell.exe', [ + '-NoProfile', '-NonInteractive', '-Command', + // Where the program is comes from the system, not from anything the engine says about itself. + 'Get-Process -Name engram -ErrorAction SilentlyContinue | Where-Object { $_.Path } | ForEach-Object { \'{0}|{1}\' -f $_.Id, $_.Path }' + ], { encoding: 'utf8', windowsHide: true, timeout: 8000 }); + return readRunningEngines(output); + } catch { + return []; + } + }, + kill: pid => process.kill(pid) +}; diff --git a/src/vs/platform/update/electron-main/updateService.win32.ts b/src/vs/platform/update/electron-main/updateService.win32.ts index 8db1e9a0..49755200 100644 --- a/src/vs/platform/update/electron-main/updateService.win32.ts +++ b/src/vs/platform/update/electron-main/updateService.win32.ts @@ -24,6 +24,7 @@ import { killTree } from '../../../base/node/processes.js'; import { getWindowsRelease } from '../../../base/node/windowsVersion.js'; import { IConfigurationService } from '../../configuration/common/configuration.js'; import { IEnvironmentMainService } from '../../environment/electron-main/environmentMainService.js'; +import { memoryFolderOf, stopEnginesInside, systemMemoryEngines } from './picodeMemoryEngine.js'; import { IFileService } from '../../files/common/files.js'; import { ILifecycleMainService, IRelaunchHandler, IRelaunchOptions, LifecycleMainPhase } from '../../lifecycle/electron-main/lifecycleMainService.js'; import { ILogService } from '../../log/common/log.js'; @@ -845,12 +846,29 @@ export class Win32UpdateService extends AbstractUpdateService implements IRelaun this.availableUpdate = undefined; } + /** + * PiCode: every window is gone by now, and the installer is about to replace the folder the memory + * engine runs from. One that outlived its window would keep those files open and the update would + * stop at "Access denied", so it is closed here, by where it runs from, before anything else. + */ + private stopMemoryEngine(): void { + try { + const stopped = stopEnginesInside(memoryFolderOf(this.environmentMainService.appRoot), systemMemoryEngines); + if (stopped.length > 0) { + this.logService.info(`update#quitAndInstall(): stopped the memory engine still running from this installation (${stopped.join(', ')})`); + } + } catch (error) { + this.logService.warn('update#quitAndInstall(): could not check for a memory engine still running', error); + } + } + protected override doQuitAndInstall(): void { if ((this.state.type !== StateType.Ready && this.state.type !== StateType.Restarting) || !this.availableUpdate) { return; } this.logService.trace('update#quitAndInstall(): running raw#quitAndInstall()'); + this.stopMemoryEngine(); // The portable build has no installer to run: the staged copy is swapped in // by its script once this process quits, and the new build starts itself. diff --git a/src/vs/workbench/contrib/picode/browser/picodeWhatsNew.ts b/src/vs/workbench/contrib/picode/browser/picodeWhatsNew.ts index dad55018..a4be044e 100644 --- a/src/vs/workbench/contrib/picode/browser/picodeWhatsNew.ts +++ b/src/vs/workbench/contrib/picode/browser/picodeWhatsNew.ts @@ -20,7 +20,7 @@ import { IHostService } from '../../../services/host/browser/host.js'; import { IWorkbenchLayoutService } from '../../../services/layout/browser/layoutService.js'; import { IPaneCompositePartService } from '../../../services/panecomposite/browser/panecomposite.js'; import { ILifecycleService, LifecyclePhase } from '../../../services/lifecycle/common/lifecycle.js'; -import { composeWhatsNew, extractWhatChanged, highlightsSince, readHistory, shouldShowWhatsNew, whatsNewHistoryUrl, whatsNewSince, WhatsNewEntry } from './picodeWhatsNewData.js'; +import { composeWhatsNew, sameVersionLine, extractWhatChanged, highlightsSince, readHistory, shouldShowWhatsNew, whatsNewHistoryUrl, whatsNewSince, WhatsNewEntry } from './picodeWhatsNewData.js'; import { whatsNewHighlights } from './picodeWhatsNewHighlights.js'; import { IPicodeProEntitlement } from './account/picodeProEntitlement.js'; import { IWhatsNewWindowServices, showWhatsNewWindow } from './picodeWhatsNewWindow.js'; @@ -66,7 +66,9 @@ async function showWhatsNew(version: string, last: string, accessor: { readonly const subtitle = last ? localize('picodeWhatsNew.subtitleSince', "New since {0}", last) : localize('picodeWhatsNew.subtitleAll', "Try each one right here."); - showWhatsNewWindow({ version, subtitle, highlights, changes, releaseUrl }, services); + // Inside one line of versions (2.0.0 to 2.0.1) the list is the fixes that came since: the page says so. + const fixesOnly = !manual && sameVersionLine(last, version); + showWhatsNewWindow({ version, subtitle, highlights, changes, fixesOnly, releaseUrl }, services); return true; } diff --git a/src/vs/workbench/contrib/picode/browser/picodeWhatsNewData.ts b/src/vs/workbench/contrib/picode/browser/picodeWhatsNewData.ts index fa3b4ea2..2c6a2c35 100644 --- a/src/vs/workbench/contrib/picode/browser/picodeWhatsNewData.ts +++ b/src/vs/workbench/contrib/picode/browser/picodeWhatsNewData.ts @@ -85,6 +85,17 @@ export function composeWhatsNew(entries: readonly WhatsNewEntry[]): string | und return entries.map(entry => `## ${entry.version}\n\n${entry.notes.trim()}`).join('\n\n'); } +/** + * Whether two versions are in the same line of news (`2.0.0` and `2.0.1`): the first two numbers + * decide it. The last one is for fixes: their list comes under "Bugs fixed", and the news of the + * line (the pages with a demo) only change when the line does. + */ +export function sameVersionLine(a: string, b: string): boolean { + const line = (version: string) => /^(\d+)\.(\d+)/.exec(version)?.slice(1, 3).join('.'); + const left = line(a); + return left !== undefined && left === line(b); +} + /** * Whether the window opens after this start. * diff --git a/src/vs/workbench/contrib/picode/browser/picodeWhatsNewWindow.ts b/src/vs/workbench/contrib/picode/browser/picodeWhatsNewWindow.ts index 169b7bce..e05991bf 100644 --- a/src/vs/workbench/contrib/picode/browser/picodeWhatsNewWindow.ts +++ b/src/vs/workbench/contrib/picode/browser/picodeWhatsNewWindow.ts @@ -33,6 +33,8 @@ export interface IWhatsNewWindowOptions { readonly highlights: readonly IWhatsNewHighlight[]; /** The releases' list of changes, as Markdown; it may arrive after the window opened. */ readonly changes: Promise; + /** The update stays inside one line of versions (2.0.0 to 2.0.1): that list is the bugs fixed since. */ + readonly fixesOnly: boolean; readonly releaseUrl: string; } @@ -94,6 +96,7 @@ export function showWhatsNewWindow(options: IWhatsNewWindowOptions, services: IW const highlights = [...options.highlights.filter(h => h.plan === 'pro'), ...options.highlights.filter(h => h.plan === 'free')]; let changes: string | undefined; let active = 0; + const changesTitle = () => options.fixesOnly ? localize('picodeWhatsNew.bugsFixed', "Bugs fixed") : localize('picodeWhatsNew.allChanges', "All changes"); const pageCount = () => highlights.length + (changes ? 1 : 0); const renderNav = () => { @@ -109,7 +112,7 @@ export function showWhatsNewWindow(options: IWhatsNewWindowOptions, services: IW navRow(highlight.icon, highlight.title, index); }); if (changes) { - navRow(Codicon.listUnordered, localize('picodeWhatsNew.allChanges', "All changes"), highlights.length); + navRow(Codicon.listUnordered, changesTitle(), highlights.length); } }; const navRow = (icon: ThemeIcon, label: string, index: number) => { @@ -134,7 +137,7 @@ export function showWhatsNewWindow(options: IWhatsNewWindowOptions, services: IW if (highlight) { renderHighlight(page, highlight, pageStore, services, close, render); } else if (changes) { - append(page, $('h2.picode-whatsnew-page-title')).textContent = localize('picodeWhatsNew.allChanges', "All changes"); + append(page, $('h2.picode-whatsnew-page-title')).textContent = changesTitle(); const rendered = services.markdownRendererService.render(new MarkdownString(changes)); pageStore.add(rendered); page.appendChild(rendered.element).classList.add('picode-whatsnew-changes'); @@ -186,9 +189,14 @@ export function showWhatsNewWindow(options: IWhatsNewWindowOptions, services: IW void options.changes.then(markdown => { if (markdown && !disposables.isDisposed) { changes = markdown; - // One more page in the list; the one being read (and its demo) is left as it is. - renderNav(); - renderFooter(); + if (highlights[active]) { + // One more page in the list; the one being read (and its demo) is left as it is. + renderNav(); + renderFooter(); + } else { + // Nothing of our own to show: this is the only page, and it was blank until now. + render(); + } } }); diff --git a/src/vs/workbench/contrib/picode/browser/test/picodeWhatsNewData.test.ts b/src/vs/workbench/contrib/picode/browser/test/picodeWhatsNewData.test.ts index 9817df42..f016f290 100644 --- a/src/vs/workbench/contrib/picode/browser/test/picodeWhatsNewData.test.ts +++ b/src/vs/workbench/contrib/picode/browser/test/picodeWhatsNewData.test.ts @@ -13,7 +13,7 @@ import assert from 'assert'; import { test } from 'node:test'; -import { composeWhatsNew, extractWhatChanged, highlightsSince, readHistory, shouldShowWhatsNew, whatsNewHistoryUrl, whatsNewSince } from '../picodeWhatsNewData.js'; +import { composeWhatsNew, extractWhatChanged, highlightsSince, readHistory, sameVersionLine, shouldShowWhatsNew, whatsNewHistoryUrl, whatsNewSince } from '../picodeWhatsNewData.js'; test('returns the grouped summary without its heading or the sections after it', () => { const body = ['Channel text', '', '## What changed', '', '### ✨ New', '', '- A thing', '', '## What\'s Changed', '', '* raw changelog'].join('\n'); @@ -49,6 +49,15 @@ test('stays quiet on a first install', () => { assert.strictEqual(shouldShowWhatsNew({ last: '', current: '', editorLast: '1.142.14', editorCurrent: '1.142.15' }), false); }); +test('versions share their news when only the last number differs', () => { + assert.strictEqual(sameVersionLine('2.0.0-experimental', '2.0.1-experimental'), true); + assert.strictEqual(sameVersionLine('2.0.1', '2.0.12'), true); + assert.strictEqual(sameVersionLine('2.0.9', '2.1.0'), false); + assert.strictEqual(sameVersionLine('1.9.9', '2.0.0'), false); + assert.strictEqual(sameVersionLine('', '2.0.0'), false); + assert.strictEqual(sameVersionLine('junk', 'junk'), false); +}); + const entry = (version: string) => ({ version, notes: `- change in ${version}` }); test('after skipping versions, shows this one first and then each skipped one, newest first', () => { diff --git a/src/vs/workbench/contrib/picode/l10n/cs.json b/src/vs/workbench/contrib/picode/l10n/cs.json index 11d92993..5989ce28 100644 --- a/src/vs/workbench/contrib/picode/l10n/cs.json +++ b/src/vs/workbench/contrib/picode/l10n/cs.json @@ -637,6 +637,7 @@ "picodeWhatsNew.board.doing": "Probíhá", "picodeWhatsNew.board.done": "Hotovo", "picodeWhatsNew.board.todo": "K udělání", + "picodeWhatsNew.bugsFixed": "Opravené chyby", "picodeWhatsNew.close": "Zavřít", "picodeWhatsNew.command": "Zobrazit novinky", "picodeWhatsNew.connect": "Připojit GitHub nebo Jira", diff --git a/src/vs/workbench/contrib/picode/l10n/de.json b/src/vs/workbench/contrib/picode/l10n/de.json index ca86afa0..93b19e86 100644 --- a/src/vs/workbench/contrib/picode/l10n/de.json +++ b/src/vs/workbench/contrib/picode/l10n/de.json @@ -637,6 +637,7 @@ "picodeWhatsNew.board.doing": "In Arbeit", "picodeWhatsNew.board.done": "Erledigt", "picodeWhatsNew.board.todo": "Zu erledigen", + "picodeWhatsNew.bugsFixed": "Behobene Fehler", "picodeWhatsNew.close": "Schließen", "picodeWhatsNew.command": "Neuigkeiten anzeigen", "picodeWhatsNew.connect": "GitHub oder Jira verbinden", diff --git a/src/vs/workbench/contrib/picode/l10n/es.json b/src/vs/workbench/contrib/picode/l10n/es.json index 0b58fa6e..a15b44d1 100644 --- a/src/vs/workbench/contrib/picode/l10n/es.json +++ b/src/vs/workbench/contrib/picode/l10n/es.json @@ -637,6 +637,7 @@ "picodeWhatsNew.board.doing": "En curso", "picodeWhatsNew.board.done": "Hecho", "picodeWhatsNew.board.todo": "Por hacer", + "picodeWhatsNew.bugsFixed": "Errores corregidos", "picodeWhatsNew.close": "Cerrar", "picodeWhatsNew.command": "Mostrar las novedades", "picodeWhatsNew.connect": "Conectar GitHub o Jira", diff --git a/src/vs/workbench/contrib/picode/l10n/fr.json b/src/vs/workbench/contrib/picode/l10n/fr.json index 1eca554f..15c8b469 100644 --- a/src/vs/workbench/contrib/picode/l10n/fr.json +++ b/src/vs/workbench/contrib/picode/l10n/fr.json @@ -637,6 +637,7 @@ "picodeWhatsNew.board.doing": "En cours", "picodeWhatsNew.board.done": "Terminé", "picodeWhatsNew.board.todo": "À faire", + "picodeWhatsNew.bugsFixed": "Bugs corrigés", "picodeWhatsNew.close": "Fermer", "picodeWhatsNew.command": "Afficher les nouveautés", "picodeWhatsNew.connect": "Connecter GitHub ou Jira", diff --git a/src/vs/workbench/contrib/picode/l10n/it.json b/src/vs/workbench/contrib/picode/l10n/it.json index ec4e0ba8..50484ca5 100644 --- a/src/vs/workbench/contrib/picode/l10n/it.json +++ b/src/vs/workbench/contrib/picode/l10n/it.json @@ -637,6 +637,7 @@ "picodeWhatsNew.board.doing": "In corso", "picodeWhatsNew.board.done": "Fatto", "picodeWhatsNew.board.todo": "Da fare", + "picodeWhatsNew.bugsFixed": "Bug risolti", "picodeWhatsNew.close": "Chiudi", "picodeWhatsNew.command": "Mostra le novità", "picodeWhatsNew.connect": "Connetti GitHub o Jira", diff --git a/src/vs/workbench/contrib/picode/l10n/ja.json b/src/vs/workbench/contrib/picode/l10n/ja.json index e457d09c..952be6b9 100644 --- a/src/vs/workbench/contrib/picode/l10n/ja.json +++ b/src/vs/workbench/contrib/picode/l10n/ja.json @@ -637,6 +637,7 @@ "picodeWhatsNew.board.doing": "進行中", "picodeWhatsNew.board.done": "完了", "picodeWhatsNew.board.todo": "未着手", + "picodeWhatsNew.bugsFixed": "修正されたバグ", "picodeWhatsNew.close": "閉じる", "picodeWhatsNew.command": "新着情報を表示", "picodeWhatsNew.connect": "GitHub または Jira を接続", diff --git a/src/vs/workbench/contrib/picode/l10n/ko.json b/src/vs/workbench/contrib/picode/l10n/ko.json index c4d2a61e..52a447b0 100644 --- a/src/vs/workbench/contrib/picode/l10n/ko.json +++ b/src/vs/workbench/contrib/picode/l10n/ko.json @@ -637,6 +637,7 @@ "picodeWhatsNew.board.doing": "진행 중", "picodeWhatsNew.board.done": "완료", "picodeWhatsNew.board.todo": "할 일", + "picodeWhatsNew.bugsFixed": "수정된 버그", "picodeWhatsNew.close": "닫기", "picodeWhatsNew.command": "새 소식 보기", "picodeWhatsNew.connect": "GitHub 또는 Jira 연결", diff --git a/src/vs/workbench/contrib/picode/l10n/pl.json b/src/vs/workbench/contrib/picode/l10n/pl.json index 91db349f..11e1cbcb 100644 --- a/src/vs/workbench/contrib/picode/l10n/pl.json +++ b/src/vs/workbench/contrib/picode/l10n/pl.json @@ -637,6 +637,7 @@ "picodeWhatsNew.board.doing": "W toku", "picodeWhatsNew.board.done": "Gotowe", "picodeWhatsNew.board.todo": "Do zrobienia", + "picodeWhatsNew.bugsFixed": "Naprawione błędy", "picodeWhatsNew.close": "Zamknij", "picodeWhatsNew.command": "Pokaż nowości", "picodeWhatsNew.connect": "Połącz GitHub lub Jira", diff --git a/src/vs/workbench/contrib/picode/l10n/pt-br.json b/src/vs/workbench/contrib/picode/l10n/pt-br.json index 2a6aa467..de3f5802 100644 --- a/src/vs/workbench/contrib/picode/l10n/pt-br.json +++ b/src/vs/workbench/contrib/picode/l10n/pt-br.json @@ -637,6 +637,7 @@ "picodeWhatsNew.board.doing": "Em andamento", "picodeWhatsNew.board.done": "Concluído", "picodeWhatsNew.board.todo": "A fazer", + "picodeWhatsNew.bugsFixed": "Bugs corrigidos", "picodeWhatsNew.close": "Fechar", "picodeWhatsNew.command": "Mostrar novidades", "picodeWhatsNew.connect": "Conectar GitHub ou Jira", diff --git a/src/vs/workbench/contrib/picode/l10n/ru.json b/src/vs/workbench/contrib/picode/l10n/ru.json index 8db0b2ec..c827ed56 100644 --- a/src/vs/workbench/contrib/picode/l10n/ru.json +++ b/src/vs/workbench/contrib/picode/l10n/ru.json @@ -637,6 +637,7 @@ "picodeWhatsNew.board.doing": "В работе", "picodeWhatsNew.board.done": "Готово", "picodeWhatsNew.board.todo": "К выполнению", + "picodeWhatsNew.bugsFixed": "Исправленные ошибки", "picodeWhatsNew.close": "Закрыть", "picodeWhatsNew.command": "Показать «Что нового»", "picodeWhatsNew.connect": "Подключить GitHub или Jira", diff --git a/src/vs/workbench/contrib/picode/l10n/source.json b/src/vs/workbench/contrib/picode/l10n/source.json index b74e338b..49931d0b 100644 --- a/src/vs/workbench/contrib/picode/l10n/source.json +++ b/src/vs/workbench/contrib/picode/l10n/source.json @@ -637,6 +637,7 @@ "picodeWhatsNew.board.doing": "In progress", "picodeWhatsNew.board.done": "Done", "picodeWhatsNew.board.todo": "To do", + "picodeWhatsNew.bugsFixed": "Bugs fixed", "picodeWhatsNew.close": "Close", "picodeWhatsNew.command": "Show What's New", "picodeWhatsNew.connect": "Connect GitHub or Jira", diff --git a/src/vs/workbench/contrib/picode/l10n/tr.json b/src/vs/workbench/contrib/picode/l10n/tr.json index d5fdcc51..83f207de 100644 --- a/src/vs/workbench/contrib/picode/l10n/tr.json +++ b/src/vs/workbench/contrib/picode/l10n/tr.json @@ -637,6 +637,7 @@ "picodeWhatsNew.board.doing": "Devam ediyor", "picodeWhatsNew.board.done": "Bitti", "picodeWhatsNew.board.todo": "Yapılacak", + "picodeWhatsNew.bugsFixed": "Düzeltilen hatalar", "picodeWhatsNew.close": "Kapat", "picodeWhatsNew.command": "Yenilikleri göster", "picodeWhatsNew.connect": "GitHub veya Jira’yı bağla", diff --git a/src/vs/workbench/contrib/picode/l10n/zh-cn.json b/src/vs/workbench/contrib/picode/l10n/zh-cn.json index 50a70bec..8be10800 100644 --- a/src/vs/workbench/contrib/picode/l10n/zh-cn.json +++ b/src/vs/workbench/contrib/picode/l10n/zh-cn.json @@ -637,6 +637,7 @@ "picodeWhatsNew.board.doing": "进行中", "picodeWhatsNew.board.done": "已完成", "picodeWhatsNew.board.todo": "待办", + "picodeWhatsNew.bugsFixed": "已修复的问题", "picodeWhatsNew.close": "关闭", "picodeWhatsNew.command": "显示新增功能", "picodeWhatsNew.connect": "连接 GitHub 或 Jira", diff --git a/src/vs/workbench/contrib/picode/l10n/zh-tw.json b/src/vs/workbench/contrib/picode/l10n/zh-tw.json index 9694050e..531b4a22 100644 --- a/src/vs/workbench/contrib/picode/l10n/zh-tw.json +++ b/src/vs/workbench/contrib/picode/l10n/zh-tw.json @@ -637,6 +637,7 @@ "picodeWhatsNew.board.doing": "進行中", "picodeWhatsNew.board.done": "已完成", "picodeWhatsNew.board.todo": "待辦", + "picodeWhatsNew.bugsFixed": "已修復的問題", "picodeWhatsNew.close": "關閉", "picodeWhatsNew.command": "顯示新功能", "picodeWhatsNew.connect": "連接 GitHub 或 Jira", From 33d8762cb3dc0abc7fe067bc6b6a351f1f397722 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 9 Nov 2026 08:43:31 +0000 Subject: [PATCH 3/3] release: feed for v2.0.2-experimental (#181) release: update feed for v2.0.2-experimental [skip ci] Co-authored-by: github-actions[bot] --- updates/experimental/whats-new.json | 4 ++++ .../win32/x64/archive/latest.json | 21 ++++++++++++------- .../experimental/win32/x64/user/latest.json | 16 +++++++------- 3 files changed, 25 insertions(+), 16 deletions(-) diff --git a/updates/experimental/whats-new.json b/updates/experimental/whats-new.json index abbb3da7..dde40a5a 100644 --- a/updates/experimental/whats-new.json +++ b/updates/experimental/whats-new.json @@ -1,5 +1,9 @@ { "versions": [ + { + "version": "2.0.1-experimental", + "notes": "### 🐛 Fixed\n\n- **Connecting Jira no longer depends on your browser.** Some browsers never opened PiCode again after you agreed on Atlassian's page, so the connection never finished. Now a PiCode page shows which account gets the connection, you confirm it there, and the editor notices by itself." + }, { "version": "2.0.0-experimental", "notes": "### ⭐ PiCode Pro\n\n- **GitHub and Jira issues in the editor.** See what was reported on the project you have open, right beside your code. Each folder shows its own repository or Jira space.\n- **A real Jira board.** The same columns as in Jira: drag cards between them, or open an issue to change its type, priority, people, labels or description. GitHub issues can be edited too.\n- **Fix with pi.** One button writes the issue into a new chat for you to review. Nothing is sent until you say so, and a report from outside your team is marked as such.\n- **An Account window.** Your plan, cloud sync, connections and Pro features in one place. Choose what syncs, part by part.\n- **Your connections are safer.** GitHub and Jira access now stays encrypted on our servers, not on your computer.\n- **Buying or cancelling Pro shows up by itself.** PiCode notices the change when you come back to the window, with no need to sign in again.\n\n### ✨ New for everyone\n\n- **What's New you can try.** A window explains each novelty, says if it is free or Pro, and lets you play with a small demo or press the button that does the real thing.\n- **A new About window.** Check for updates and get them from there, copy any detail with a click, and find what is hidden behind the mascot.\n- **See what the agent is doing.** On longer jobs, Status and Tasks show the plan, how far along it is and what is happening right now.\n- **Background jobs in view.** Long commands the agent leaves running appear in Tasks with their output, move to Finished by themselves, and the agent's reply reaches your chat even after its turn was over.\n- **Memory filters.** Filter your memories by type, scope and date, and search finds more results per project.\n- **A better empty chat.** New chats suggest where to start.\n\n### 🔒 Security\n\n- **Opening a folder no longer runs its code without your permission.** A project's own extensions, packages, settings and MCP servers only load once you trust the folder.\n- **Safer sign-in.** A web page can no longer sign the editor in to someone else's account.\n- **Signed updates.** PiCode checks that an update notice really comes from PiCode, and ignores it if it doesn't.\n\n### ⚡ Faster\n\n- **Issues don't reload** when you switch between panels: the last list appears at once.\n- **A quieter Status column.** It checks for changes less often and doesn't redraw when nothing changed.\n- **Lighter background work,** and the session list appears sooner after starting.\n\n### 🐛 Fixed and tidied\n\n- **Going back to the Editor layout** no longer leaves the bottom panel open.\n- **The Agent layout always opens on Status,** without an empty gap at the top of it.\n- **Updating the memory engine now takes effect:** PiCode offers to restart it, with no need to close every window.\n- **Undo these changes** asks first, and says so if they were already undone.\n- **Changes** in Status opens and closes its list with the same click, and **Tasks** lists only agents and tasks working for you.\n- **The chat's Ask / Allow all picker is gone.** It promised a choice that did not exist: the agent runs its tools without asking. MCP servers connected in the editor keep asking.\n- **Show Release Notes is gone** from the Help menu: Show What's New tells you what changed." diff --git a/updates/experimental/win32/x64/archive/latest.json b/updates/experimental/win32/x64/archive/latest.json index 8aa33d59..40ab7f9c 100644 --- a/updates/experimental/win32/x64/archive/latest.json +++ b/updates/experimental/win32/x64/archive/latest.json @@ -1,10 +1,15 @@ { - "version": "2f3746b558ed1494372eed1ab38c51f6d608cbb3", - "productVersion": "1.144.10", - "picodeVersion": "2.0.1-experimental", - "kind": "release", - "timestamp": 1794186950260, - "url": "https://github.com/Tomas-Platero/PiCode/releases/download/v2.0.1-experimental/PiCode-win32-x64-2.0.1-experimental.zip", - "sha256hash": "7b18ac48a8f31aa3a6820f032d16034cd72e3a3115be5e0cc8e075bc9a0c65bd", - "signature": "tZ6yfwNqWv1ixW5vXx0S0M38rJ3oSMj86k36VFriHrYFl8dm32h01ufYy61wfKx3o/M2myLKcE0XRAxCi6TnDQ==" + "version": "991610d5b71860bf85279304c04139e528279915", + "productVersion": "1.144.11", + "picodeVersion": "2.0.2-experimental", + "kind": "hotfix", + "timestamp": 1794213804489, + "url": "https://github.com/Tomas-Platero/PiCode/releases/download/v2.0.2-experimental/PiCode-win32-x64-2.0.2-experimental.zip", + "sha256hash": "62a61b44e0c3b9a6e514fbaca3f15e4f13e7643016066c4a86b0e1d8b39802f0", + "delta": { + "url": "https://github.com/Tomas-Platero/PiCode/releases/download/v2.0.2-experimental/PiCode-win32-x64-2.0.2-experimental-update-from-2.0.1-experimental.zip", + "sha256hash": "ec7ace4c8874ccb07c23d18db9e1f16fb45ad741f6a0057f0ef0fbd8b8157c01", + "from": "2.0.1-experimental" + }, + "signature": "wSUXA4pgdukuDSyPMTWfsrIuK7/vUsbFwqrztV7Zp5CBcKsZNvOswxi1nP1+MNLJIWrsz0nOjuxtkPko4MFFAQ==" } diff --git a/updates/experimental/win32/x64/user/latest.json b/updates/experimental/win32/x64/user/latest.json index 549e135b..88f2577d 100644 --- a/updates/experimental/win32/x64/user/latest.json +++ b/updates/experimental/win32/x64/user/latest.json @@ -1,10 +1,10 @@ { - "version": "2f3746b558ed1494372eed1ab38c51f6d608cbb3", - "productVersion": "1.144.10", - "picodeVersion": "2.0.1-experimental", - "kind": "release", - "timestamp": 1794186950381, - "url": "https://github.com/Tomas-Platero/PiCode/releases/download/v2.0.1-experimental/PiCode-win32-x64-2.0.1-experimental-setup.exe", - "sha256hash": "ce20d240653d5b4d93da348d21b701e783b3c72cb2fdfb4456b1242da7acc395", - "signature": "I4q+d15OAm/9Y6GJqz3W9a+e0FcNe6QqbnjVrKyWYj8P+NH4N69B+GV3fa909ovyr0Qa7AaiCwVMeOSaJ/w4AQ==" + "version": "991610d5b71860bf85279304c04139e528279915", + "productVersion": "1.144.11", + "picodeVersion": "2.0.2-experimental", + "kind": "hotfix", + "timestamp": 1794213804602, + "url": "https://github.com/Tomas-Platero/PiCode/releases/download/v2.0.2-experimental/PiCode-win32-x64-2.0.2-experimental-setup.exe", + "sha256hash": "a39c3db6a9b56a2b41364116ed48722eae31ffb1edf52fbe2f39587714972a1e", + "signature": "Ky+btLVz8WxK5w2IdGgauwMbFUEA0mbkU1o602wAhd9cw5e77ajzdvOuZy5+rhF+PJ3GM8W1bYo4+0TfPMpOAA==" }