diff --git a/packages/coding-agent/CHANGELOG.md b/packages/coding-agent/CHANGELOG.md index 93f794f7fa..e80cc2ba0c 100644 --- a/packages/coding-agent/CHANGELOG.md +++ b/packages/coding-agent/CHANGELOG.md @@ -5,6 +5,10 @@ ### Fixed - Fixed all extension loading silently failing on the cross-compiled `omp-darwin-arm64` release binary (downloaded directly or via a Homebrew tap wrapper) because `__computeBunfsPackageRoot` mis-handled `import.meta.dir = "//root/omp-darwin-arm64"`. Bun 1.3.14 reports `/` for the compiled entry's `import.meta.dir`, but the pre-fix function joined `metaDir + "packages"` and produced `/root/omp-darwin-arm64/packages` — the binary basename was baked into every bunfs path, so the TypeBox/legacy-pi shims and every `@oh-my-pi/pi-*` package-root override failed `existsSync` validation and `resolveCanonicalPiSpecifier` fell through to a bunfs `Bun.resolveSync` that also could not find the module. The function now detects the bunfs-root + binary-basename shape (`path.basename(path.dirname(metaDir)) === "root"`) and strips the trailing binary segment by slicing the original `metaDir`; the production bunfs shim join path also preserves Bun's bunfs-native `//root` / `B:\~BUN\root` prefix that `path.join` would otherwise collapse. ([#3329](https://github.com/can1357/oh-my-pi/issues/3329)) +### Changed + +- Consolidated duplicate `formatProviderName` implementations from three files into a shared helper in `slash-commands/helpers/format.ts`. + ## [16.1.16] - 2026-06-23 ### Breaking Changes diff --git a/packages/coding-agent/src/cli/usage-cli.ts b/packages/coding-agent/src/cli/usage-cli.ts index e5b94250b3..c0d53a072e 100644 --- a/packages/coding-agent/src/cli/usage-cli.ts +++ b/packages/coding-agent/src/cli/usage-cli.ts @@ -19,6 +19,7 @@ import { formatDuration, formatNumber } from "@oh-my-pi/pi-utils"; import chalk from "chalk"; import { ModelRegistry } from "../config/model-registry"; import { discoverAuthStorage } from "../sdk"; +import { formatProviderName } from "../slash-commands/helpers/format"; const BAR_WIDTH = 28; @@ -175,13 +176,6 @@ function aggregateStatus(limits: UsageLimit[]): LimitStatus { return "unknown"; } -function formatProviderName(provider: string): string { - return provider - .split(/[-_]/g) - .map(part => (part ? part[0].toUpperCase() + part.slice(1) : "")) - .join(" "); -} - function formatUnitValue(value: number, unit: UsageUnit): string { if (unit === "usd") return `$${value.toFixed(2)}`; return formatNumber(value); diff --git a/packages/coding-agent/src/modes/controllers/command-controller.ts b/packages/coding-agent/src/modes/controllers/command-controller.ts index e85ba82621..bba65abe13 100644 --- a/packages/coding-agent/src/modes/controllers/command-controller.ts +++ b/packages/coding-agent/src/modes/controllers/command-controller.ts @@ -42,6 +42,7 @@ import type { CompactMode } from "../../session/compact-modes"; import type { NewSessionOptions } from "../../session/session-entries"; import { formatShakeSummary, type ShakeMode, type ShakeResult } from "../../session/shake-types"; import { limitMatchesActiveAccount } from "../../slash-commands/helpers/active-oauth-account"; +import { formatProviderName } from "../../slash-commands/helpers/format"; import { outputMeta } from "../../tools/output-meta"; import { resolveToCwd, stripOuterDoubleQuotes } from "../../tools/path-utils"; import { replaceTabs } from "../../tools/render-utils"; @@ -1270,13 +1271,6 @@ function truncateJobLabel(label: string, maxWidth: number): string { return `${out}…`; } -function formatProviderName(provider: string): string { - return provider - .split(/[-_]/g) - .map(part => (part ? part[0].toUpperCase() + part.slice(1) : "")) - .join(" "); -} - function formatNumber(value: number, maxFractionDigits = 1): string { return new Intl.NumberFormat("en-US", { maximumFractionDigits: maxFractionDigits }).format(value); } diff --git a/packages/coding-agent/src/slash-commands/helpers/format.ts b/packages/coding-agent/src/slash-commands/helpers/format.ts index e592f9805a..3ff3581eda 100644 --- a/packages/coding-agent/src/slash-commands/helpers/format.ts +++ b/packages/coding-agent/src/slash-commands/helpers/format.ts @@ -1,6 +1,14 @@ import { shimmerText } from "../../modes/theme/shimmer"; import { theme as currentTheme, type Theme } from "../../modes/theme/theme"; +/** Title-case a provider id for display (e.g. "opencode-go" → "Opencode Go"). */ +export function formatProviderName(provider: string): string { + return provider + .split(/[-_]/g) + .map(part => (part ? part[0]!.toUpperCase() + part.slice(1) : "")) + .join(" "); +} + /** Format a millisecond duration as a coarse-grained human label. */ export function formatDuration(ms: number): string { const seconds = Math.max(0, Math.round(ms / 1000)); diff --git a/packages/coding-agent/src/slash-commands/helpers/usage-report.ts b/packages/coding-agent/src/slash-commands/helpers/usage-report.ts index c3c06f35f1..a84734cacc 100644 --- a/packages/coding-agent/src/slash-commands/helpers/usage-report.ts +++ b/packages/coding-agent/src/slash-commands/helpers/usage-report.ts @@ -2,14 +2,7 @@ import type { UsageLimit, UsageReport } from "@oh-my-pi/pi-ai"; import type { OAuthAccountIdentity } from "../../session/auth-storage"; import type { SlashCommandRuntime } from "../types"; import { reportMatchesActiveAccount } from "./active-oauth-account"; -import { formatDuration, renderAsciiBar } from "./format"; - -function formatProviderName(provider: string): string { - return provider - .split(/[-_]/g) - .map(part => (part ? part[0].toUpperCase() + part.slice(1) : "")) - .join(" "); -} +import { formatDuration, formatProviderName, renderAsciiBar } from "./format"; function formatUsageAmount(limit: UsageLimit): string { const amount = limit.amount;