From cabafb2b7feca33293a9a8c4a5d2ee8a4f4b831e Mon Sep 17 00:00:00 2001 From: Yevhen Tienkaiev Date: Sun, 26 Jul 2026 04:31:32 +0300 Subject: [PATCH] Add custom toolbar icon --- .github/ISSUE_TEMPLATE/bug_report.yml | 2 +- CHANGELOG.md | 5 +++ README.md | 6 ++-- assets/toolbar-dark.svg | 3 ++ assets/toolbar-light.svg | 3 ++ docs/RELEASING.md | 4 +-- extension.js | 22 ++++++++++++ package-lock.json | 4 +-- package.json | 25 +++++++++++-- scripts/validate.mjs | 51 ++++++++++++++++++++++++++- 10 files changed, 114 insertions(+), 11 deletions(-) create mode 100644 assets/toolbar-dark.svg create mode 100644 assets/toolbar-light.svg create mode 100644 extension.js diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index 0d6d617..be969e4 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -30,7 +30,7 @@ body: id: extras-version attributes: label: Codex Extras version - placeholder: "1.0.0" + placeholder: "1.0.1" validations: required: true diff --git a/CHANGELOG.md b/CHANGELOG.md index fcf654f..03b5793 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,11 @@ All notable changes to Codex Extras are documented in this file. +## 1.0.1 + +- Add an original code-brackets-and-plus icon for the New Codex Agent toolbar button. +- Delegate the custom toolbar action to the official `chatgpt.newCodexPanel` command. + ## 1.0.0 - Initial stable release. diff --git a/README.md b/README.md index 37945bd..d27a1a9 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Small, focused workflow improvements for the official Codex extension in Visual ### New Codex Agent toolbar button -Adds a visible `+` action to the editor toolbar. Select it to execute the official Codex command `chatgpt.newCodexPanel` and open a new Codex agent. +Adds a visible code-brackets-and-plus action to the editor toolbar. Select it to execute the official Codex command `chatgpt.newCodexPanel` and open a new Codex agent. The button is available without assigning a keyboard shortcut. @@ -42,12 +42,12 @@ For an unpublished development build: ```sh npm ci npm run package -code --install-extension codex-extras-1.0.0.vsix +code --install-extension codex-extras-1.0.1.vsix ``` ## Privacy -Codex Extras contains no telemetry, network requests, or runtime code. It contributes a menu item that invokes a command provided by the official Codex extension. +Codex Extras contains no telemetry or network requests. Its small runtime wrapper only delegates the toolbar action to a command provided by the official Codex extension. ## Contributing diff --git a/assets/toolbar-dark.svg b/assets/toolbar-dark.svg new file mode 100644 index 0000000..ef4bf0e --- /dev/null +++ b/assets/toolbar-dark.svg @@ -0,0 +1,3 @@ + + + diff --git a/assets/toolbar-light.svg b/assets/toolbar-light.svg new file mode 100644 index 0000000..e3835c2 --- /dev/null +++ b/assets/toolbar-light.svg @@ -0,0 +1,3 @@ + + + diff --git a/docs/RELEASING.md b/docs/RELEASING.md index 22bd86f..e572e2c 100644 --- a/docs/RELEASING.md +++ b/docs/RELEASING.md @@ -29,8 +29,8 @@ Never commit or paste the token into an issue, pull request, workflow file, or b 5. Tag the exact version and push it: ```sh - git tag v1.0.0 - git push origin v1.0.0 + git tag v1.0.1 + git push origin v1.0.1 ``` The release workflow verifies that the tag matches `package.json`, packages the VSIX, publishes it to the Visual Studio Marketplace, and creates a GitHub release containing the same VSIX. diff --git a/extension.js b/extension.js new file mode 100644 index 0000000..e859cf3 --- /dev/null +++ b/extension.js @@ -0,0 +1,22 @@ +"use strict"; + +const vscode = require("vscode"); + +const COMMAND_ID = "codexExtras.newCodexAgent"; +const OFFICIAL_CODEX_COMMAND_ID = "chatgpt.newCodexPanel"; + +/** + * Registers the branded toolbar action and delegates its behavior to the + * official Codex extension. + * + * @param {import("vscode").ExtensionContext} context + */ +function activate(context) { + const command = vscode.commands.registerCommand(COMMAND_ID, () => + vscode.commands.executeCommand(OFFICIAL_CODEX_COMMAND_ID), + ); + + context.subscriptions.push(command); +} + +module.exports = { activate }; diff --git a/package-lock.json b/package-lock.json index bd95b7c..4104fb9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "codex-extras", - "version": "1.0.0", + "version": "1.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "codex-extras", - "version": "1.0.0", + "version": "1.0.1", "license": "MIT", "devDependencies": { "@vscode/vsce": "^3.6.2" diff --git a/package.json b/package.json index d25ba49..d24346f 100644 --- a/package.json +++ b/package.json @@ -2,10 +2,14 @@ "name": "codex-extras", "displayName": "Codex Extras", "description": "Convenient toolbar actions and workflow enhancements for Codex in Visual Studio Code.", - "version": "1.0.0", + "version": "1.0.1", "publisher": "netroforge", "license": "MIT", "icon": "assets/icon.png", + "main": "./extension.js", + "activationEvents": [ + "onCommand:codexExtras.newCodexAgent" + ], "engines": { "vscode": "^1.96.2" }, @@ -49,6 +53,17 @@ } }, "contributes": { + "commands": [ + { + "command": "codexExtras.newCodexAgent", + "title": "New Codex Agent", + "category": "Codex Extras", + "icon": { + "light": "assets/toolbar-light.svg", + "dark": "assets/toolbar-dark.svg" + } + } + ], "configuration": { "title": "Codex Extras", "properties": { @@ -62,10 +77,16 @@ "menus": { "editor/title": [ { - "command": "chatgpt.newCodexPanel", + "command": "codexExtras.newCodexAgent", "group": "navigation@100", "when": "config.codexExtras.showNewAgentButton" } + ], + "commandPalette": [ + { + "command": "codexExtras.newCodexAgent", + "when": "false" + } ] } }, diff --git a/scripts/validate.mjs b/scripts/validate.mjs index 2236e46..65a4979 100644 --- a/scripts/validate.mjs +++ b/scripts/validate.mjs @@ -15,10 +15,24 @@ assert.match(manifest.version, /^\d+\.\d+\.\d+$/); assert.equal(manifest.license, "MIT"); assert.equal(manifest.repository.url, "https://github.com/netroforge/codex-extras.git"); assert.ok(manifest.extensionDependencies.includes("openai.chatgpt")); +assert.equal(manifest.main, "./extension.js"); +assert.ok( + manifest.activationEvents.includes("onCommand:codexExtras.newCodexAgent"), +); + +const newAgentCommand = manifest.contributes?.commands?.find( + ({ command }) => command === "codexExtras.newCodexAgent", +); + +assert.ok(newAgentCommand, "New Codex Agent command contribution is missing"); +assert.deepEqual(newAgentCommand.icon, { + light: "assets/toolbar-light.svg", + dark: "assets/toolbar-dark.svg", +}); const editorTitleItems = manifest.contributes?.menus?.["editor/title"] ?? []; const newAgentButton = editorTitleItems.find( - ({ command }) => command === "chatgpt.newCodexPanel", + ({ command }) => command === "codexExtras.newCodexAgent", ); assert.ok(newAgentButton, "New Codex Agent toolbar contribution is missing"); @@ -38,6 +52,41 @@ assert.equal( true, ); +const commandPaletteItems = + manifest.contributes?.menus?.commandPalette ?? []; +assert.ok( + commandPaletteItems.some( + ({ command, when }) => + command === "codexExtras.newCodexAgent" && when === "false", + ), + "Wrapper command must stay hidden from the Command Palette", +); + +const extensionSource = await readFile( + path.join(root, manifest.main), + "utf8", +); +assert.match( + extensionSource, + /registerCommand\(COMMAND_ID/, + "Extension must register its wrapper command", +); +assert.match( + extensionSource, + /executeCommand\(OFFICIAL_CODEX_COMMAND_ID\)/, + "Wrapper command must delegate to the official Codex command", +); + +for (const [theme, iconPath] of Object.entries(newAgentCommand.icon)) { + const toolbarIcon = await readFile(path.join(root, iconPath), "utf8"); + assert.match(toolbarIcon, /viewBox="0 0 16 16"/); + assert.match(toolbarIcon, /stroke-width="1\.5"/); + assert.match( + toolbarIcon, + theme === "light" ? /stroke="#424242"/ : /stroke="#C5C5C5"/, + ); +} + const icon = await readFile(path.join(root, manifest.icon)); assert.equal(icon.subarray(0, 8).toString("hex"), "89504e470d0a1a0a"); assert.ok(icon.length >= 24, "Icon is not a valid PNG");