Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
74ebc73
sessions: Use concise nested chat delete label (#333743)
sandy081 Sep 1, 2026
6ef4956
Add agents window capability (#333744)
alexr00 Sep 1, 2026
d264a09
sessions: Fix gaps in nested chat hierarchy guides (#333741)
sandy081 Sep 1, 2026
8098ed8
agentHost: isolate created sessions across projects (#333745)
sandy081 Sep 1, 2026
048977c
Fix multi-diff virtualization layout failures
hediet Sep 1, 2026
519f5fa
Restore multi-diff virtualization fixes
hediet Sep 1, 2026
df2411c
agentHost: update bundled Codex SDK to 0.149.1 (#333739)
Giuspepe Sep 1, 2026
8af52a5
Enhance keyboard focus styles for chat tab components (#333754)
mrleemurray Sep 1, 2026
c160486
Enhance chat question carousel with markdown link support (#333751)
mrleemurray Sep 1, 2026
8d032ea
Fix extensions.allowed schema flagging valid version arrays as invali…
RajeshKumar11 Sep 1, 2026
daf67bb
Update font size for session sections (#333762)
mrleemurray Sep 1, 2026
3d7597c
Enable Microsoft Entra ID sign-in for Private Marketplace access (#32…
mcumming Sep 1, 2026
22f76d2
agentHost: hide picker-disabled Codex models (#333756)
Giuspepe Sep 1, 2026
63f3201
Agents - left align the changeset picker with the tab (#333767)
lszomoru Sep 1, 2026
737ece2
Agent Host: Run Dev Containers on new worktrees (#333736)
chrmarti Sep 1, 2026
4735247
Agents - move the toggle details action (#333773)
lszomoru Sep 1, 2026
0ff22af
sessions: Count blocked sessions in application badge (#333774)
benibenj Sep 1, 2026
9f9213b
Honor HTTP proxy bypass settings in the agent host (#333614)
chrmarti Sep 1, 2026
f83aa9c
Agent Host: Gate Dev Container worktree sessions (#333782)
chrmarti Sep 1, 2026
58d8a14
Update distro commit (main) (#333748)
vs-code-engineering[bot] Sep 1, 2026
959f7db
Prevent hidden chats from rendering during custom view swaps (#333789)
benibenj Sep 1, 2026
bb41c6b
Fix model picker model persistence (#333800)
lramos15 Sep 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
88 changes: 88 additions & 0 deletions .agents/skills/update-codex-sdk/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
name: update-codex-sdk
description: Update VS Code's bundled @openai/codex dependency to a version available from the private VS Code npm feed, regenerate its protocol client, run the relevant tests, and verify the Codex Agent Host in a launched Code OSS window. Use for bundled Codex SDK/CLI version bumps in the VS Code repository.
---

# Update the bundled Codex SDK

The public npm `latest` version is not necessarily installable in VS Code CI. The Azure pipeline uses the private `vscode` feed, where CFS normally quarantines new third-party package versions for seven days. Select a version from that feed before changing files.

## Select a CI-available version

Run the helper from the repository root:

```bash
node --experimental-strip-types .agents/skills/update-codex-sdk/scripts/latest-private-version.ts
```

It obtains an Azure DevOps access token from the signed-in Azure CLI, queries the same feed used by `build/azure-pipelines/dependencies-check.yml`, and reports the newest stable release for which the root package and every platform binary alias declared by that release are present. It never prints the token. If Azure CLI authentication is missing or expired, ask the user to authenticate rather than falling back to the public registry.

To check a user-requested version explicitly:

```bash
node --experimental-strip-types .agents/skills/update-codex-sdk/scripts/latest-private-version.ts --version 0.149.1
```

Use `--raw` when only the latest complete version string is needed. Do not change the repository or global npm registry merely to probe availability.

## Update every pin

Set `CODEX_VERSION` to the selected exact version. Keep committed lockfile URLs on `https://registry.npmjs.org/`; the private feed determines CI eligibility but is not written into source lockfiles.

```bash
CODEX_VERSION=0.149.1
npm install --save-dev --save-exact --ignore-scripts --registry=https://registry.npmjs.org "@openai/codex@$CODEX_VERSION"
npm --prefix build/agent-sdk/agents/codex install --save-exact --package-lock-only --ignore-scripts --registry=https://registry.npmjs.org "@openai/codex@$CODEX_VERSION"
```

Use `apply_patch` to set `build/codex/codex-version.txt` to the same version, then regenerate the vendored app-server client:

```bash
npm run codex:gen-protocol
```

The expected version-bearing files are:

- `package.json` and `package-lock.json`
- `build/agent-sdk/agents/codex/package.json` and `package-lock.json`
- `build/codex/codex-version.txt`
- `src/vs/platform/agentHost/node/codex/protocol/generated/**`

Never hand-edit generated protocol files. Review their diff, then make the smallest necessary handwritten Agent Host or test changes for protocol additions or type changes. Confirm both package manifests use exact versions and that no private-feed URL entered either lockfile.

## Validate

Run the established checks from the repository root:

```bash
npm run codex:check-protocol
npm run compile
./scripts/test.sh --grep codex
(cd build && npm run test)
npm run test-agent-host-e2e -- --jobs 2
npm run hygiene
```

The Agent Host E2E run exercises the bundled provider SDKs in replay mode. If a Codex SDK change causes replay misses or stale fixtures, read `.github/skills/agent-host-e2e-tests/SKILL.md` before deciding whether to re-record; never weaken or silently skip a failing test.

## Verify a real Codex Agent Host session

After the build and tests pass, read and use `.agents/skills/launch/SKILL.md` to launch an isolated **Agents window** for this checkout. Take a fresh Playwright snapshot, explicitly start a Codex-backed session, and give it a deterministic tool-use task such as:

```text
Run node -p "require('@openai/codex/package.json').version" in this workspace. If it prints <VERSION>, reply exactly CODEX_SDK_<VERSION_WITH_UNDERSCORES>_OK.
```

Success requires all of the following, not merely a window that opened:

- the selected provider is Codex;
- the session invokes the command through the Agent Host and completes;
- the reported version matches every pin;
- the exact sentinel appears in the completed response;
- the Agent Host log shows no startup crash or protocol error.

Save the observed sentinel and test totals for the final report or pull-request description. Follow the launch skill's cleanup steps when finished.

## Deliver

Inspect the complete diff for unrelated changes, secrets, private registry URLs, and generated-file drift. Preserve unrelated user work. Commit, push, or create/update a pull request only when the user has authorized those actions; include the private-feed-selected version and validation evidence in the description.
4 changes: 4 additions & 0 deletions .agents/skills/update-codex-sdk/agents/openai.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
interface:
display_name: "Update Codex SDK"
short_description: "Update and verify VS Code's bundled Codex SDK"
default_prompt: "Use $update-codex-sdk to update VS Code to the newest private-feed-available Codex SDK and verify it end to end."
186 changes: 186 additions & 0 deletions .agents/skills/update-codex-sdk/scripts/latest-private-version.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/

import { spawnSync } from 'node:child_process';

const feedUrl = 'https://pkgs.dev.azure.com/monacotools/Monaco/_packaging/vscode/npm/registry';
const azureDevOpsResource = '499b84ac-1321-427f-aa17-267ca6975798';
const codexAliasPrefix = 'npm:@openai/codex@';

type OutputFormat = 'text' | 'raw' | 'json';

interface Options {
format: OutputFormat;
requestedVersion: string | undefined;
}

interface CodexVersionMetadata {
optionalDependencies?: Record<string, string>;
}

interface CodexPackument {
versions: Record<string, CodexVersionMetadata>;
}

function usage(): void {
console.error('Usage: node --experimental-strip-types latest-private-version.ts [--raw | --json] [--version <x.y.z>]');
}

function fail(message: string): never {
console.error(`Error: ${message}`);
process.exit(1);
}

function parseArgs(args: string[]): Options {
let format: OutputFormat = 'text';
let requestedVersion: string | undefined;

for (let index = 0; index < args.length; index++) {
const arg = args[index];
if (arg === '--raw') {
format = 'raw';
} else if (arg === '--json') {
format = 'json';
} else if (arg === '--version') {
requestedVersion = args[++index];
if (!requestedVersion) {
usage();
process.exit(2);
}
} else {
usage();
process.exit(2);
}
}

if (requestedVersion && !/^\d+\.\d+\.\d+$/.test(requestedVersion)) {
fail(`--version must be a stable x.y.z version, got ${requestedVersion}`);
}

return { format, requestedVersion };
}

function getAccessToken(): string {
const azureCli = process.platform === 'win32' ? 'az.cmd' : 'az';
const result = spawnSync(azureCli, [
'account',
'get-access-token',
'--resource',
azureDevOpsResource,
'--query',
'accessToken',
'--output',
'tsv',
], { encoding: 'utf8' });

if (result.error) {
fail(`could not run Azure CLI (${result.error.message}). Install it and sign in to the monacotools organization.`);
}
if (result.status !== 0) {
const detail = result.stderr?.trim();
fail(`Azure CLI could not obtain an Azure DevOps token${detail ? `: ${detail}` : ''}`);
}

const token = result.stdout?.trim();
if (!token) {
fail('Azure CLI returned an empty Azure DevOps token. Sign in and try again.');
}
return token;
}

function parseStableVersion(version: string): number[] | undefined {
const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(version);
return match ? match.slice(1).map(Number) : undefined;
}

function compareVersions(left: string, right: string): number {
const leftParts = parseStableVersion(left);
const rightParts = parseStableVersion(right);
if (!leftParts || !rightParts) {
throw new Error('compareVersions only accepts stable versions');
}
for (let index = 0; index < 3; index++) {
const difference = leftParts[index] - rightParts[index];
if (difference !== 0) {
return difference;
}
}
return 0;
}

function binaryVersions(packument: CodexPackument, version: string): string[] {
const optionalDependencies = packument.versions[version]?.optionalDependencies;
if (!optionalDependencies || typeof optionalDependencies !== 'object') {
return [];
}

return Object.values(optionalDependencies)
.filter(value => typeof value === 'string' && value.startsWith(codexAliasPrefix))
.map(value => value.slice(codexAliasPrefix.length));
}

function requiredVersions(packument: CodexPackument, version: string): string[] {
return [version, ...binaryVersions(packument, version)];
}

const { format, requestedVersion } = parseArgs(process.argv.slice(2));
const accessToken = getAccessToken();
const response = await fetch(`${feedUrl}/@openai%2Fcodex`, {
headers: { Authorization: `Bearer ${accessToken}` },
});

if (!response.ok) {
fail(`private VS Code feed returned HTTP ${response.status} ${response.statusText}`);
}

const packument = await response.json() as CodexPackument;
if (!packument || typeof packument !== 'object' || !packument.versions || typeof packument.versions !== 'object') {
fail('private VS Code feed returned an unexpected @openai/codex response');
}

const availableVersions = new Set(Object.keys(packument.versions));
const completeStableVersions = [...availableVersions]
.filter(version => parseStableVersion(version))
.filter(version => binaryVersions(packument, version).length > 0)
.filter(version => requiredVersions(packument, version).every(required => availableVersions.has(required)))
.sort(compareVersions);

const latestVersion = completeStableVersions.at(-1);
if (!latestVersion) {
fail('the private VS Code feed contains no stable Codex release with all platform binaries');
}

const checkedVersion = requestedVersion ?? latestVersion;
if (requestedVersion && availableVersions.has(requestedVersion) && binaryVersions(packument, requestedVersion).length === 0) {
fail(`Codex ${requestedVersion} metadata declares no platform binary aliases, so its availability cannot be verified`);
}
const missingVersions = requiredVersions(packument, checkedVersion).filter(version => !availableVersions.has(version));
const result = {
feed: feedUrl,
latestVersion,
checkedVersion,
available: missingVersions.length === 0,
missingVersions,
};

if (format === 'json') {
console.log(JSON.stringify(result, undefined, 2));
} else if (format === 'raw') {
console.log(latestVersion);
} else if (requestedVersion) {
if (result.available) {
console.log(`Codex ${requestedVersion} is fully available from the private VS Code feed.`);
} else {
console.log(`Codex ${requestedVersion} is not fully available from the private VS Code feed.`);
console.log(`Missing: ${missingVersions.join(', ')}`);
console.log(`Latest fully available stable version: ${latestVersion}`);
}
} else {
console.log(`Latest Codex stable fully available from the private VS Code feed: ${latestVersion}`);
}

if (requestedVersion && !result.available) {
process.exitCode = 1;
}
56 changes: 28 additions & 28 deletions build/agent-sdk/agents/codex/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading