Oh My OpenAgent for VS Code
A VS Code companion extension for Oh My OpenAgent — a community-driven enhancement layer for OpenAI Codex CLI. It gives you a visual tree of agents, categories, and profiles, and a form-based editor for model overrides without hand-editing JSONC files.
Screenshots
The sidebar view shows your active config, all built-in agents and categories with their assigned models, and saved profiles. The editor panel opens on demand for any agent or category — it supports model selection, sampling parameters, thinking budgets, and fallback models.
| Sidebar overview |
Agent editor in action |
 |
 |
Features
- Agent and category model overrides: see all 11 built-in agents and 8 built-in categories in a hierarchical tree. Edit any item in the webview form. Saving an edit to a built-in item creates its override. The tree renders labels like
sisyphus → opencode-go/kimi-k2.7-code so you always know which model is assigned.
- Ordered model cards: position 1 is Main and every later card is a fallback. Drag any fallback into position 1 to replace Main. The
Drag handle explains this on hover and supports keyboard reordering: press Space or Enter to pick up, use Arrow Up or Arrow Down to move, press Space or Enter to drop, or Escape to cancel. Main settings are shared defaults. In each card's Advanced section, a blank select shows Inherit (<default>), a selected value is an override, an empty numeric input inherits the value shown by its placeholder, and a populated numeric input is an override. Shared Temperature and Top-p defaults remain editable when a model reports no sampling support; that model's card inputs are disabled with an explanatory tooltip, and inherited values are not serialized as card overrides.
- Lazy model picker — the Model field is populated asynchronously from the local
opencode models --verbose CLI, with a free-form fallback when the CLI is unavailable. The discovered model IDs appear as autocomplete suggestions alongside each model's capabilities and variants. A reload button lets you re-run discovery at any time.
- JSONC preservation — all writes go through
jsonc-parser via a per-path diff engine. The ConfigStore compares the original and modified config recursively, then calls modify() on each changed JSON path individually. Comments, trailing commas, and formatting on untouched keys survive every edit.
- Profiles — canonical internal snapshots of the current
agents and categories, stored in a sidecar file (omo.profiles.json). A profile remains the source of truth when activated: edits update the profile first and then project it to omo.jsonc using the selected harness and routing model. Each profile can carry an optional description. The active profile is marked with a check icon and (active) label.
- Profile import and export — move individual profiles or your whole sidecar in and out as JSON or JSONC. Import a single
{ agents, categories } fragment, or import a full { version: 1, profiles: [...] } sidecar and choose whether to extend the existing list or replace it. Export one profile or every profile at once.
- JSON profile editing — open a saved profile or the active config's
agents/categories as JSON in an untitled editor, edit freely, and save to apply. Useful for bulk changes that the form editor does not expose.
- Selectable harness and routing model — one settings flow sequentially selects the config scope (
global, opencode, senpi, codex) and disk routing model (latest, mainline). Both selections appear side by side on the config item. Changing either selection reprojects the active profile; switching to global first reconciles omo.jsonc, because harness blocks would otherwise shadow every global edit.
- Sidebar integration — the
Oh My OpenAgent activity bar view puts everything one click away. Three collapsible groups (Agents, Categories, Profiles) with inline edit buttons, context menu actions, and tooltips that show configured parameters on hover.
- Commands where they belong:
Open Agent Manager, Configure Harness and Routing Model, Refresh, Create Profile, Import Profiles, and Export All Profiles are available from the Command Palette and view title. Editing, override management, profile actions, and JSON editing appear only when their sidebar context applies.
Requirements
- VS Code 1.85 or newer
- An existing Oh My OpenAgent configuration, or a first-run scenario where the extension will create one for you
Development and packaging require Node.js 22 or newer.
Development and packaging require Node.js 22 or newer.
Config scope
The extension can edit different parts of the unified omo.jsonc config. Choose the active config scope to control where agent and category overrides are written:
global — the shared base of omo.jsonc. Use this for settings that apply to every harness. Only agents and categories are written here; agent_order and disabled_agents are ignored/stripped if present.
opencode — the [opencode] harness block. This is the default scope. All OmO keys (agents, categories, agent_order, disabled_agents) can be written here.
senpi — the [senpi] harness block. Only agents and categories are written here.
codex — the [codex] harness block. Only agents and categories are written here.
Choose the scope in the first step of Oh My OpenAgent: Configure Harness and Routing Model, available from the Command Palette and the Models view-title gear. The picker lists all four scopes and marks the current one before the routing-model step.
Switching to the global scope
Harness blocks take precedence over the shared base, so while [opencode], [senpi], or [codex] defines agents or categories, nothing written to the base can reach that harness. When you pick global and such a block exists, the command asks how to update omo.jsonc before switching:
- Remove Harness Blocks — delete every
[<harness>] block, leaving the shared base as the only source of overrides. This is the durable choice: later global edits keep applying everywhere.
- Copy Global to All Harnesses — make every harness block's
agents and categories match the shared base: a key the base defines replaces the harness copy, and a key it leaves undefined is dropped from the block so it cannot shadow a value you add later. Harness-only keys such as agent_order are kept. This reconciles the file once; a later global edit to a key the blocks now define is shadowed again.
Both rewrites preserve comments and formatting. Cancelling the prompt leaves the scope and omo.jsonc untouched. Switching to a harness scope never rewrites the file, because that block already wins on read.
Your choice is persisted as a configScope field inside the omo.profiles.json sidecar file, next to the user config. It is not stored as a VS Code setting. On activation the extension restores the persisted scope, falling back to opencode when none is saved.
The sidebar config item shows both selections side by side (for example, opencode · latest). Switching scope closes any open agent editor and reports the change, so stale edits cannot be saved into the wrong block.
The active scope controls all writes: agent/category editor saves, profile activation, and the active-profile JSON editor all target the selected scope. Project-layer reads still merge the shared base with the selected harness block; sibling harness blocks and base keys outside the selected scope are preserved untouched.
Config file layers
- User layer —
~/.omo/omo.jsonc (falling back to omo.json) on every platform. This is where all writes go.
- Project layers —
.omo/omo.jsonc (then .omo/omo.json) in every directory from the workspace root up to your home directory. The nearest project file wins on read and beats the user layer; the extension never writes to project files.
On a fresh install the extension creates ~/.omo/omo.jsonc on first write. Legacy oh-my-openagent.json[c] / oh-my-opencode.json[c] files are no longer read — run bunx oh-my-openagent config migrate once to import them into the unified file.
Profiles live next to the user config in omo.profiles.json. A legacy oh-my-openagent.profiles.json sidecar is renamed automatically on first access.
Routing dialect
The extension can write agent and category routing to omo.jsonc in either of two dialects. Choose the active routing dialect to match the version of Oh My OpenAgent you are running:
mainline — the omo ≥ 5.0.0 dialect. Writes one ordered models array per agent or category. The first entry is the main model merged with its overrides, and later entries are fallbacks. A reasoning-level variant is stored as reasoning.
latest — the omo 4.x stable dialect, and the default. In the opencode scope it writes model plus flattened top-level overrides plus fallback_models; in the senpi and codex scopes it writes the models array; in the global scope it writes model-only entries and drops fallback chains, with an editor warning when a chain cannot be represented.
Select both the harness and routing model with Oh My OpenAgent: Configure Harness and Routing Model, available from the Command Palette and the gear icon in the Models view title. The two sequential pickers mark their current values; the config item displays the result as <harness> · <routing model>.
The choices are persisted as configScope and routingDialect fields inside the omo.profiles.json sidecar file, next to the user config. They are not stored as VS Code settings. On activation the extension restores them, defaulting to opencode and latest. When an active profile exists, changing either choice immediately reprojects that unchanged internal profile to omo.jsonc; without an active profile, the choice applies on the next config write.
Why two dialects?
The 4.x and 5.x runtimes disagree on which routing keys are valid. In omo 4.19.4 the plugin schema rejects agents.*.models (unknown key, doctor fails), while its strict unified core schema rejects agents.*.fallback_models and agents.*.category at the root and inside [senpi] and [codex]. The [opencode] block is opaque to the core schema, so [opencode].agents.*.fallback_models is the only agent-chain encoding that passes doctor on 4.x stable (with a harmless "deprecated key" warning) and is honored by both the 4.x and 5.x runtimes. categories.*.models is valid on both versions. The latest dialect keeps configs compatible with omo 4.x stable; the mainline dialect opts into the newer models-array schema for omo ≥ 5.0.0.
Requirements
- VS Code 1.85 or newer
- An existing Oh My OpenAgent configuration, or a first-run scenario where the extension will create one for you
Installation
From a .vsix file
- Download
oh-my-openagent-vscode-X.Y.Z.vsix from the release page.
- Open VS Code and run
Extensions: Install from VSIX... from the Command Palette.
- Select the downloaded file.
Development build
Clone the repository:
git clone https://github.com/oh-my-openagent/oh-my-openagent-vscode.git
cd oh-my-openagent-vscode
Install dependencies:
npm install
Compile:
npm run compile
Press F5 to open the Extension Development Host with the extension loaded.
Usage
Opening the view
- Click the
Oh My OpenAgent activity bar icon (robot symbol).
- Or run the command
Oh My OpenAgent: Open Agent Manager from the Command Palette.
The sidebar nests the tree under the active config file:
- Active config file — the name of the user-layer file (e.g.
omo.jsonc). Hover to see the full resolved path. It expands to show the active profile (when one is active) and, nested under it, the Agents and Categories groups. When no profile is active, Agents and Categories appear directly under the config file.
- Agents — built-in agents; overridden agents are shown as override items.
- Categories — built-in categories; overridden categories are shown as override items.
- Profiles — saved snapshots of your agents and categories. A root-level sibling of the config file.
Agents, categories, and profiles are expandable when they contain configured values:
- An expanded agent or category shows its configured parameters (
variant, reasoning, temperature, top_p, maxTokens, thinking, verbosity, disabled) and a fallbacks (N) group with each fallback model.
- An expanded profile shows nested Agents and Categories subgroups with the same
name → model leaves you see in the main tree, so you can inspect what the profile captured before activating it.
The Profiles group always shows the active state: when no profile is active, a No active profile indicator appears at the top of the group. The active profile is marked with a check icon and an (active) description.
Editing an agent or category
- Hover over the agent or category and click the pencil inline action, or right-click and choose
Edit Agent / Edit Category. Both built-in items, existing override items, and profile-contained items can be edited.
- The webview editor opens one ordered Model routing list plus shared Default generation settings.
- The cards form one ordered model list. Position 1 is Main, and later cards are fallbacks. Drag any fallback into position 1 to replace Main. Hover over a
Drag handle for this reminder. For keyboard reordering, focus a handle, press Space or Enter to pick up, use Arrow Up or Arrow Down to move, press Space or Enter to drop, or Escape to cancel. There are no separate promotion or move controls.
- The main Model field is a free-form text input with a lazy datalist. While the editor loads, the extension runs
opencode models --verbose locally and offers the returned model IDs as autocomplete suggestions, together with each model's capabilities and variants. Any existing model value is preserved, even if it is not in the discovered list.
- The defaults section sets shared Reasoning effort, Thinking, Temperature, Top-p, and Max tokens values.
variant and the legacy reasoningEffort field remain preserved in stored data but are not exposed as editable generation controls.
- Each card's Advanced section has one control per setting. For Reasoning effort and Thinking, the blank option reads
Inherit (<default>); selecting another option creates an override. For numeric settings, an empty input inherits the placeholder value and a populated input creates an override. Clearing a control returns it to inheritance.
- Hover over the reload button next to the Model field to re-run discovery and refresh the model list at any time. If discovered capabilities do not support an effective setting, including an inherited setting, the editor marks the conflict and blocks saving until you clear or change it.
- Use a fallback's Remove button to remove it. Removing the final fallback explicitly removes the fallback chain from the saved config.
- Change values and click Save. Saving a built-in agent or category creates its override in the active config. The sidebar refreshes after the JSONC-preserving write completes. Fields that are not exposed in the form, such as
permission, tools, prompt, and providerOptions, are preserved rather than overwritten.
- The upstream config can store only top-level defaults and fallback entries. It cannot represent the fallback intent attached to the model that is currently Main after the editor is closed and reopened. Transient webview restoration preserves dirty in-panel state, but a saved config cannot preserve that Main model's fallback intent across a new editor session.
- Hover over any agent or category leaf in the sidebar to see a tooltip with the configured parameters (temperature, top-p, max tokens, reasoning effort, thinking budget, variant, and fallback models).
Right-click items in the Models view for more options:
- On a built-in agent:
Edit Agent opens the editor. Saving creates the agent override.
- On a built-in category:
Edit Category opens the editor. Saving creates the category override.
- On an override item:
Edit Agent / Edit Category opens the editor.
- On a profile:
Activate, Rename, Duplicate, Delete, Export Profile, or Edit Profile JSON.
- Profile-contained agent/category leaves reuse the same
Edit Agent / Edit Category commands as the main tree.
- On a modified active profile:
Save Active Profile snapshots the current config back into that profile.
- On the active config file item:
Edit Active Profile JSON opens the active config's agents/categories as JSON.
- On the Profiles group header:
Create Profile from Config File…, Import Profiles, or Export All Profiles.
The view title also provides one Configure Harness and Routing Model settings button, plus Refresh, Create Profile, Import Profiles, and Export All Profiles.
Commands
The extension contributes 17 commands. All are prefixed with Oh My OpenAgent. Open Agent Manager, Configure Harness and Routing Model, Refresh, Create Profile, Create Profile from Config File…, Import Profiles, and Export All Profiles are visible in the Command Palette and view title. The remaining commands are contextual sidebar actions.
| Command |
Availability |
What it does |
Open Agent Manager |
Command Palette |
Focuses the Oh My OpenAgent sidebar view. |
Configure Harness and Routing Model |
Command Palette and view title |
Sequentially selects the active harness (global, opencode, senpi, codex) and routing model (latest, mainline). The config item shows both selections side by side. Command id: ohMyOpenAgent.configureSettings. |
Edit Agent |
Contextual |
Opens the editor for the selected agent. |
Edit Category |
Contextual |
Opens the editor for the selected category. |
Refresh |
Command Palette and view title |
Refreshes the Models tree from disk. |
Create Profile |
Command Palette and view title |
Creates a new profile from the current config. |
Create Profile from Config File… |
Command Palette |
Creates a profile from a .json or .jsonc Oh My OpenAgent config file's agents and categories sections. The active config is not modified. |
Activate Profile |
Contextual |
Applies the selected profile to the active config. |
Rename Profile |
Contextual |
Renames the selected profile. |
Duplicate Profile |
Contextual |
Creates a copy of the selected profile. |
Delete Profile |
Contextual |
Deletes the selected profile after confirmation. |
Save Active Profile |
Contextual |
Saves the current config into the modified active profile. |
Import Profiles |
Command Palette and view title |
Imports one .json or .jsonc file as a single profile fragment or a full sidecar. |
Export All Profiles |
Command Palette and view title |
Exports the full sidecar to a JSON file. |
Export Profile |
Contextual |
Exports the selected profile as a single { agents, categories } fragment. |
Edit Profile JSON |
Contextual |
Opens the selected saved profile's agents/categories as JSON for editing. |
Edit Active Profile JSON |
Contextual |
Opens the active config's agents/categories as JSON for editing. |
Profiles
Profiles are named snapshots of the agents and categories sections of your active config. They are stored in omo.profiles.json, next to the user config file.
Create a profile
- Click the
Create Profile icon in the Models view title, or run Oh My OpenAgent: Create Profile.
- Enter a unique profile name.
- Optionally enter a description.
The new profile captures the current agents and categories exactly as they are on disk.
To create a profile from another config file instead of the active config, use Create Profile from Config File… (Command Palette or right-click the Profiles group header). It extracts agents and categories from any Oh My OpenAgent .json/.jsonc config — a full omo.jsonc works (the [opencode] block is merged over the shared base); other top-level keys are ignored — and never modifies the active config.
Activate a profile
- Right-click the profile in the sidebar and choose
Activate.
- The active config's
agents and categories sections are replaced with the profile's values.
Activation preserves comments and trailing commas in the active config because it reuses the same JSONC-preserving write path as the editor.
Rename, duplicate, or delete a profile
- Rename updates the profile name. If it was the active profile,
lastActiveProfile is updated automatically.
- Duplicate creates a deep copy under a new name; the original is unchanged.
- Delete asks for confirmation and removes the profile. If it was the active profile, the active marker is cleared.
The transfer layer accepts both single-profile fragments and full sidecar files. Input may be JSON or JSONC (comments and trailing commas are allowed). Output is always canonical JSON with two-space indentation and sorted object keys.
A single-profile fragment contains only the profile payload:
{
"agents": {
"sisyphus": {
"model": "opencode-go/kimi-k2.7-code"
}
},
"categories": {
}
}
At least one of agents or categories must be present. The top-level keys version and profiles are reserved for sidecar files; a fragment cannot mix them with agents or categories.
A full sidecar follows this shape:
{
"version": 1,
"profiles": [
{
"name": "fast",
"agents": {
"sisyphus": {
"model": "opencode-go/kimi-k2.7-code"
}
},
"createdAt": "2026-07-23T12:00:00Z",
"updatedAt": "2026-07-23T12:00:00Z"
}
],
"lastActiveProfile": "fast"
}
version must be 1. profiles is required. lastActiveProfile is optional. Each profile object may contain name, description, agents, categories, createdAt, and updatedAt. Timestamps must be valid ISO 8601 strings.
Import semantics:
- JSONC input is accepted; the parser allows comments and trailing commas. Canonical JSON is produced on export.
- Semantic losslessness: values and structure survive, but comments, formatting, and key order are normalized. Export sorts object keys alphabetically.
- Extend (default) appends imported profiles to the existing list. Replace overwrites the existing list.
- Name collisions are resolved with exact case-sensitive matching. If
fast already exists, the imported profile becomes fast-2, then fast-3, and so on.
- Size limit: transfer inputs are rejected when they exceed 5 MiB. UTF-8 is required; a leading UTF-8 BOM is accepted and stripped.
- Imported
lastActiveProfile is ignored. Your local active marker is preserved only when a profile with that exact name still exists after the import.
- No auto-activation: importing a profile or sidecar updates the sidecar file only; the active config is not changed.
Export semantics:
- Single-profile export writes
{ agents?, categories? } as a fragment file.
- Full sidecar export writes
{ version: 1, profiles: [...], lastActiveProfile? }.
- Provider options warning: export warns when a profile contains non-empty
providerOptions, because provider options often hold credentials or API keys. The warning is informational; you can cancel or proceed.
- Active saved-profile save: when you save a modified active profile, the active config is updated first, then the profile is snapshotted. If snapshotting fails, the config change remains and the sidecar stays unchanged, so partial failures leave the live config in the intended state.
Architecture
The extension follows a clean layered architecture with strict separation of concerns:
extension.ts (activation orchestrator)
|
├── commands.ts (17 command registrations)
|
├── profileTransferCommands.ts (import/export/JSON-edit handlers)
│ ├── profileTransferCommandHandlers.ts
│ └── profileTransferFiles.ts (VS Code open/save dialog helpers)
|
├── ui/
│ ├── agentModelTreeProvider.ts (sidebar TreeDataProvider)
│ ├── agentEditorPanel.ts (webview panel singleton and JSON editor host)
│ ├── profileJsonEditorHost.ts (active/saved profile JSON editing protocol)
│ └── webview/ (ordered model routing, capability validation, and ProfileJsonEditor)
│ ├── App.svelte / AgentFormEditor.svelte
│ └── ProfileJsonEditor.svelte
│
└── config/
├── schema.ts (TypeScript types for OmO config)
├── routingConversion.ts (internal ↔ public model routing)
├── configStore.ts (JSONC read/write, file watching)
├── profileStore.ts (profile CRUD, activation, import/export)
├── profileTransfer.ts (parser and byte-limit/UTF-8 validation)
├── profileValidation.ts (fragment/sidecar runtime validator)
├── profileEntryValidation.ts (per-field validation rules)
└── profileTransferSerialization.ts (canonical JSON, name collision, export helpers)
Key design decisions
- ConfigStore is pure Node.js — zero VS Code dependency, making it testable in isolation with vitest. File watching uses
fs.watch with 150 ms debounce and a suppressWatch flag to ignore self-triggered events during atomic writes.
- Profiles are canonical; routing is a projection — the editor and every saved profile keep the internal routing shape (
model, main_overrides, fallback_models). ProfileStore canonicalizes public inputs before every sidecar write. Comparisons project both the profile and live config through the selected harness/routing model first, so equivalent shapes do not appear modified. mainline (omo ≥ 5.0.0) writes one ordered models array whose first entry is the main model merged with its overrides; latest (omo 4.x stable, the default) writes model plus flattened overrides and scope-dependent fallback routing. routingConversion.ts owns both directions, and ConfigStore converts at the omo.jsonc boundary.
- Atomic writes everywhere — both
ConfigStore and ProfileStore write via temp-file + fs.renameSync, guaranteeing no partial content even on crash.
- Per-path JSONC diffing —
updateConfig() deep-clones the parsed config, runs the updater callback, then diffConfigs() recursively compares original and draft. Each changed JSON path gets its own jsonc-parser modify() call, so comments and formatting on untouched keys are never disturbed.
- Webview security — strict CSP with
default-src 'none', per-render nonces via crypto.randomBytes(16), local resource roots restricted to out/ only, and all DOM text insertion uses .textContent (never innerHTML).
- Singleton editor panel —
AgentEditorPanel uses a static currentPanel reference to prevent multiple webview instances. Panel state survives tab switches via retainContextWhenHidden: true.
- Sidecar profiles and config projection — profiles are stored in
omo.profiles.json so the main OmO config stays schema-clean. Activation and active-profile edits project the saved profile through the JSONC-preserving ConfigStore.updateConfig() path without mutating the profile for the selected routing model. The chosen harness and routing model are persisted in the sidecar and restored on activation.
- Transfer canonical JSON — export serializes only JSON-safe values (null, booleans, finite numbers, strings, dense arrays, and plain objects), sorts keys, and appends a trailing newline. This prevents accidental disclosure of getters, symbols, or cyclic structures.
- Profile JSON editor host —
profileJsonEditorHost.ts isolates the active/saved target protocol from the UI, while ProfileJsonEditor.svelte provides a focused textarea with save, dirty tracking, and error display.
- Scope-aware writes —
ConfigStore carries a ConfigScope value (global, opencode, senpi, or codex). Reads merge the shared base with the selected harness block; writes prefix each JSONC patch with the matching harness block or target the root for global. The active scope is saved to and restored from omo.profiles.json via ProfileStore, so the same scope is active across extension restarts without touching VS Code settings.
- Global-scope reconciliation — because harness blocks outrank the shared base, selecting
global while one of them defines agents or categories would make every global edit a no-op. ConfigStore.getShadowingHarnessScopes() detects that state and the command offers the two fixes, removeHarnessBlocks() or copyBaseToHarnessBlocks(), before the scope changes. Both go through the same JSONC-preserving edit path as ordinary writes.
Built-in inventory
| Domain |
Items |
| Agents |
sisyphus, hephaestus, prometheus, oracle, librarian, explore, multimodal-looker, metis, momus, atlas, sisyphus-junior (11 total) |
| Categories |
visual-engineering, ultrabrain, deep, artistry, quick, unspecified-low, unspecified-high, writing (8 total) |
Development
This extension is built with TypeScript and esbuild. Development and packaging require Node.js 22 or newer. The extension itself runs on VS Code 1.85 or newer.
# Install dependencies
npm install
# One-shot compile
npm run compile
# Watch mode
npm run watch
# Run tests
npm test
# Package for release
npm run package
To run the extension locally, press F5 in VS Code. This opens the Extension Development Host with the compiled extension loaded.
Tests
Tests are written with Vitest. The suite covers the extension's main behaviors:
| Suite |
What it covers |
modelDiscovery.test.ts |
opencode models parsing, fallback handling, metadata normalization, and cache behavior |
agentModelTreeProvider.test.ts |
Tree structure, context values, override detection, active profile indicators, refresh, and disposal |
agentEditorPanel.test.ts |
Webview lifecycle, messages, save writes, profile creation, and model discovery reloads |
profileStore.test.ts |
Profile creation, rename, duplicate, isolation, activation, save-back, import, export, and change events |
profileTransfer.test.ts |
Byte limits, UTF-8 handling, JSONC parsing, duplicate-key detection, and fragment/sidecar classification |
profileTransferSerialization.test.ts |
Canonical JSON serialization, name derivation, collision resolution, and provider-options detection |
profileValidation.test.ts |
Fragment and sidecar validation, timestamp checks, nested field policies, and unknown-key rejection |
profileTransferCommands.test.ts |
Import/export/JSON-edit command handlers, dialogs, cancellation, and error reporting |
profileTransferFiles.test.ts |
VS Code open/save dialog helpers and successful transfer-file operations |
profileTransferFiles.rejections.test.ts |
Primitive rejection contract for transfer-file dialog failures |
smoke.test.ts |
End-to-end editor saves across stores, panel, tree, JSONC writes, profile transfer round-trips, and JSON editing |
packageMenus.test.ts |
The 17-command contribution surface and contextual menu visibility |
configStore.test.ts |
Config discovery, JSONC parsing, formatting-preserving updates, key removal, and file watching |
routingConversion.test.ts |
Internal ↔ public routing conversion for both dialects: models chains, model/fallback_models chains, main overrides, reasoning-style variants, precedence, and idempotency |
routingBoundary.test.ts |
End-to-end routing projection at the disk boundary: one canonical profile across mainline/latest, scope-specific hidden routing, legacy activation, inverse reads, snapshots, and JSON-editor saves |
modelRouting.test.ts |
Ordered-card promotion, shared defaults, fallback inheritance and overrides, serialization, removal, and session-bound routing intent |
modelCapabilities.test.ts |
Capability validation for explicit card overrides, including inherited sampling defaults that unsupported models do not serialize as overrides |
webview.test.ts |
Model picker behavior, simplified inherit/override controls, legacy-field preservation, drag promotion, fallback editing, profile JSON editor UI, and persisted state |
editorPayloadValidation.test.ts |
Structured-editor allow-lists for agent and category save payloads |
reorder.test.ts |
Fallback list reordering via drag and keyboard |
schema.test.ts |
Profile schema contract and shape invariants |
The JSONC preservation tests verify that comments, trailing commas, and formatting survive round-trips through updateConfig() and profile activation — confirmed against real config fixtures with inline comments and trailing commas.
npm test
Release / packaging
Update the version in package.json.
Run the packaging command:
npm run package
npm run package produces a .vsix file in the current directory.
The resulting .vsix file can be uploaded to a release page or installed directly.
The package script uses the maintained @vscode/vsce packaging tool. The packaging rules in .vscodeignore make sure out/extension.js, out/webview.js, src/ui/webview/webview.html, and src/ui/webview/webview.css are included, while source maps, tests, and node_modules are excluded. Generated VSIX files and verification evidence are kept in .omo/evidence and are not committed.
License
MIT License
| |