diff --git a/src/cli/get-local-version/formatter.ts b/src/cli/get-local-version/formatter.ts index 12fc3ee83..39b317f4f 100644 --- a/src/cli/get-local-version/formatter.ts +++ b/src/cli/get-local-version/formatter.ts @@ -1,4 +1,5 @@ import color from "picocolors" +import { PLUGIN_NAME, PUBLISHED_PACKAGE_NAME } from "../../shared" import type { VersionInfo } from "./types" const SYMBOLS = { @@ -15,7 +16,7 @@ export function formatVersionOutput(info: VersionInfo): string { const lines: string[] = [] lines.push("") - lines.push(color.bold(color.white("oh-my-opencode Version Information"))) + lines.push(color.bold(color.white(`${PLUGIN_NAME} Version Information`))) lines.push(color.dim("─".repeat(50))) lines.push("") @@ -37,7 +38,7 @@ export function formatVersionOutput(info: VersionInfo): string { break case "outdated": lines.push(` ${SYMBOLS.warn} ${color.yellow("Update available")}`) - lines.push(` ${color.dim("Run:")} ${color.cyan("cd ~/.config/opencode && bun update oh-my-opencode")}`) + lines.push(` ${color.dim("Run:")} ${color.cyan(`cd ~/.config/opencode && bun update ${PUBLISHED_PACKAGE_NAME}`)}`) break case "local-dev": lines.push(` ${SYMBOLS.dev} ${color.cyan("Running in local development mode")}`) diff --git a/src/cli/run/session-resolver.ts b/src/cli/run/session-resolver.ts index 9246f43d0..265de5733 100644 --- a/src/cli/run/session-resolver.ts +++ b/src/cli/run/session-resolver.ts @@ -1,4 +1,5 @@ import pc from "picocolors" +import { PUBLISHED_PACKAGE_NAME } from "../../shared" import type { OpencodeClient } from "./types" import { serializeError } from "./events" @@ -26,7 +27,7 @@ export async function resolveSession(options: { for (let attempt = 1; attempt <= SESSION_CREATE_MAX_RETRIES; attempt++) { const res = await client.session.create({ body: { - title: "oh-my-opencode run", + title: `${PUBLISHED_PACKAGE_NAME} run`, permission: [ { permission: "question", action: "deny" as const, pattern: "*" }, ], diff --git a/src/features/background-agent/task-poller.ts b/src/features/background-agent/task-poller.ts index 6fa179bd7..45263cc45 100644 --- a/src/features/background-agent/task-poller.ts +++ b/src/features/background-agent/task-poller.ts @@ -1,4 +1,5 @@ import { log } from "../../shared" +import { CONFIG_BASENAME } from "../../shared/plugin-identity" import type { BackgroundTaskConfig } from "../../config/schema" import type { BackgroundTask } from "./types" @@ -158,7 +159,7 @@ export async function checkAndInterruptStaleTasks(args: { const staleMinutes = Math.round(runtime / 60000) const reason = sessionGone ? "session gone from status registry" : "no activity" task.status = "cancelled" - task.error = `Stale timeout (${reason} for ${staleMinutes}min since start). This is a FINAL cancellation - do NOT create a replacement task. If the timeout is too short, increase 'background_task.${sessionGone ? "sessionGoneTimeoutMs" : "staleTimeoutMs"}' in .opencode/oh-my-opencode.json.` + task.error = `Stale timeout (${reason} for ${staleMinutes}min since start). This is a FINAL cancellation - do NOT create a replacement task. If the timeout is too short, increase 'background_task.${sessionGone ? "sessionGoneTimeoutMs" : "staleTimeoutMs"}' in .opencode/${CONFIG_BASENAME}.json.` task.completedAt = new Date() if (task.concurrencyKey) { @@ -196,7 +197,7 @@ export async function checkAndInterruptStaleTasks(args: { const staleMinutes = Math.round(timeSinceLastUpdate / 60000) const reason = sessionGone ? "session gone from status registry" : "no activity" task.status = "cancelled" - task.error = `Stale timeout (${reason} for ${staleMinutes}min). This is a FINAL cancellation - do NOT create a replacement task. If the timeout is too short, increase 'background_task.${sessionGone ? "sessionGoneTimeoutMs" : "staleTimeoutMs"}' in .opencode/oh-my-opencode.json.` + task.error = `Stale timeout (${reason} for ${staleMinutes}min). This is a FINAL cancellation - do NOT create a replacement task. If the timeout is too short, increase 'background_task.${sessionGone ? "sessionGoneTimeoutMs" : "staleTimeoutMs"}' in .opencode/${CONFIG_BASENAME}.json.` task.completedAt = new Date() if (task.concurrencyKey) { diff --git a/src/features/mcp-oauth/provider.ts b/src/features/mcp-oauth/provider.ts index 06fa7b393..3e5711374 100644 --- a/src/features/mcp-oauth/provider.ts +++ b/src/features/mcp-oauth/provider.ts @@ -1,5 +1,6 @@ import type { OAuthTokenData } from "./storage" import { loadToken, saveToken } from "./storage" +import { PLUGIN_NAME } from "../../shared/plugin-identity" import { discoverOAuthServerMetadata } from "./discovery" import type { OAuthServerMetadata } from "./discovery" import { getOrRegisterClient } from "./dcr" @@ -141,7 +142,7 @@ export class McpOAuthProvider { const clientInfo = await getOrRegisterClient({ registrationEndpoint: metadata.registrationEndpoint, serverIdentifier: this.serverUrl, - clientName: "oh-my-opencode", + clientName: PLUGIN_NAME, redirectUris: [this.redirectUrl()], tokenEndpointAuthMethod: "none", clientId: this.configClientId, diff --git a/src/hooks/auto-update-checker/constants.ts b/src/hooks/auto-update-checker/constants.ts index 9de9fb6a0..db956f607 100644 --- a/src/hooks/auto-update-checker/constants.ts +++ b/src/hooks/auto-update-checker/constants.ts @@ -2,8 +2,12 @@ import * as path from "node:path" import * as os from "node:os" import { getOpenCodeCacheDir } from "../../shared/data-path" import { getOpenCodeConfigDir } from "../../shared/opencode-config-dir" +import { + ACCEPTED_PACKAGE_NAMES as SHARED_ACCEPTED_PACKAGE_NAMES, + PUBLISHED_PACKAGE_NAME, +} from "../../shared/plugin-identity" -export const PACKAGE_NAME = "oh-my-opencode" +export const PACKAGE_NAME = PUBLISHED_PACKAGE_NAME /** * All package names the canonical plugin may be published under. * @@ -13,7 +17,7 @@ export const PACKAGE_NAME = "oh-my-opencode" * because the installed name depends on which package the user added to * their config. Code that *writes* continues to use {@link PACKAGE_NAME}. */ -export const ACCEPTED_PACKAGE_NAMES = ["oh-my-opencode", "oh-my-openagent"] as const +export const ACCEPTED_PACKAGE_NAMES = SHARED_ACCEPTED_PACKAGE_NAMES export const NPM_REGISTRY_URL = `https://registry.npmjs.org/-/package/${PACKAGE_NAME}/dist-tags` export const NPM_FETCH_TIMEOUT = 5000 diff --git a/src/hooks/comment-checker/downloader.ts b/src/hooks/comment-checker/downloader.ts index 8a0af844a..de062d6c9 100644 --- a/src/hooks/comment-checker/downloader.ts +++ b/src/hooks/comment-checker/downloader.ts @@ -12,6 +12,7 @@ import { getCachedBinaryPath as getCachedBinaryPathShared, } from "../../shared/binary-downloader" import { log } from "../../shared/logger" +import { CACHE_DIR_NAME, PUBLISHED_PACKAGE_NAME } from "../../shared/plugin-identity" const DEBUG = process.env.COMMENT_CHECKER_DEBUG === "1" const DEBUG_FILE = join(tmpdir(), "comment-checker-debug.log") @@ -48,12 +49,12 @@ export function getCacheDir(): string { if (process.platform === "win32") { const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA const base = localAppData || join(homedir(), "AppData", "Local") - return join(base, "oh-my-opencode", "bin") + return join(base, CACHE_DIR_NAME, "bin") } const xdgCache = process.env.XDG_CACHE_HOME const base = xdgCache || join(homedir(), ".cache") - return join(base, "oh-my-opencode", "bin") + return join(base, CACHE_DIR_NAME, "bin") } /** @@ -113,7 +114,7 @@ export async function downloadCommentChecker(): Promise { const downloadUrl = `https://github.com/${REPO}/releases/download/v${version}/${assetName}` debugLog(`Downloading from: ${downloadUrl}`) - log(`[oh-my-opencode] Downloading comment-checker binary...`) + log(`[${PUBLISHED_PACKAGE_NAME}] Downloading comment-checker binary...`) try { // Ensure cache directory exists @@ -139,14 +140,14 @@ export async function downloadCommentChecker(): Promise { ensureExecutable(binaryPath) debugLog(`Successfully downloaded binary to: ${binaryPath}`) - log(`[oh-my-opencode] comment-checker binary ready.`) + log(`[${PUBLISHED_PACKAGE_NAME}] comment-checker binary ready.`) return binaryPath } catch (err) { debugLog(`Failed to download: ${err}`) - log(`[oh-my-opencode] Failed to download comment-checker: ${err instanceof Error ? err.message : err}`) - log(`[oh-my-opencode] Comment checking disabled.`) + log(`[${PUBLISHED_PACKAGE_NAME}] Failed to download comment-checker: ${err instanceof Error ? err.message : err}`) + log(`[${PUBLISHED_PACKAGE_NAME}] Comment checking disabled.`) return null } } diff --git a/src/hooks/legacy-plugin-toast/hook.ts b/src/hooks/legacy-plugin-toast/hook.ts index 352925cc6..a4bbb07b2 100644 --- a/src/hooks/legacy-plugin-toast/hook.ts +++ b/src/hooks/legacy-plugin-toast/hook.ts @@ -2,7 +2,7 @@ import type { PluginInput } from "@opencode-ai/plugin" import { checkForLegacyPluginEntry } from "../../shared/legacy-plugin-warning" import { log } from "../../shared/logger" -import { LEGACY_PLUGIN_NAME, PLUGIN_NAME } from "../../shared/plugin-identity" +import { LEGACY_PLUGIN_NAME, PLUGIN_NAME, PUBLISHED_PACKAGE_NAME } from "../../shared/plugin-identity" import { autoMigrateLegacyPluginEntry } from "./auto-migrate-runner" type LegacyPluginToastDeps = { @@ -56,7 +56,7 @@ export function createLegacyPluginToastHook(ctx: PluginInput, deps: LegacyPlugin .showToast({ body: { title: "Legacy Plugin Name Detected", - message: `Update your opencode.json: "${LEGACY_PLUGIN_NAME}" has been renamed to "${PLUGIN_NAME}".\nRun: bunx ${PLUGIN_NAME} install`, + message: `Update your opencode.json: "${LEGACY_PLUGIN_NAME}" has been renamed to "${PLUGIN_NAME}".\nRun: bunx ${PUBLISHED_PACKAGE_NAME} install`, variant: "warning" as const, duration: 10000, }, diff --git a/src/shared/data-path.ts b/src/shared/data-path.ts index d46e6b1c6..e63ce3b03 100644 --- a/src/shared/data-path.ts +++ b/src/shared/data-path.ts @@ -2,6 +2,8 @@ import * as path from "node:path" import * as os from "node:os" import { accessSync, constants, mkdirSync } from "node:fs" +import { CACHE_DIR_NAME } from "./plugin-identity" + function resolveWritableDirectory(preferredDir: string, fallbackSuffix: string): string { try { mkdirSync(preferredDir, { recursive: true }) @@ -50,7 +52,7 @@ export function getCacheDir(): string { * All platforms: ~/.cache/oh-my-opencode */ export function getOmoOpenCodeCacheDir(): string { - return path.join(getCacheDir(), "oh-my-opencode") + return path.join(getCacheDir(), CACHE_DIR_NAME) } /** diff --git a/src/shared/external-plugin-detector.ts b/src/shared/external-plugin-detector.ts index 13a8a0d76..818d1c893 100644 --- a/src/shared/external-plugin-detector.ts +++ b/src/shared/external-plugin-detector.ts @@ -5,6 +5,7 @@ import { loadOpencodePlugins } from "./load-opencode-plugins" import { log } from "./logger" +import { CONFIG_BASENAME, PLUGIN_NAME } from "./plugin-identity" /** * Known notification plugins that conflict with oh-my-opencode's session-notification. @@ -110,29 +111,29 @@ export function detectExternalSkillPlugin(directory: string): ExternalSkillPlugi * Generate a warning message for users with conflicting notification plugins. */ export function getNotificationConflictWarning(pluginName: string): string { - return `[oh-my-opencode] External notification plugin detected: ${pluginName} + return `[${PLUGIN_NAME}] External notification plugin detected: ${pluginName} -Both oh-my-opencode and ${pluginName} listen to session.idle events. +Both ${PLUGIN_NAME} and ${pluginName} listen to session.idle events. Running both simultaneously can cause crashes on Windows. - oh-my-opencode's session-notification has been auto-disabled. + ${PLUGIN_NAME}'s session-notification has been auto-disabled. - To use oh-my-opencode's notifications instead, either: + To use ${PLUGIN_NAME}'s notifications instead, either: 1. Remove ${pluginName} from your opencode.json plugins - 2. Or set "notification": { "force_enable": true } in oh-my-opencode.json` + 2. Or set "notification": { "force_enable": true } in ${CONFIG_BASENAME}.json` } /** * Generate a warning message for users with conflicting skill plugins. */ export function getSkillPluginConflictWarning(pluginName: string): string { - return `[oh-my-opencode] External skill plugin detected: ${pluginName} + return `[${PLUGIN_NAME}] External skill plugin detected: ${pluginName} -Both oh-my-opencode and ${pluginName} scan ~/.config/opencode/skills/ and register tools independently. +Both ${PLUGIN_NAME} and ${pluginName} scan ~/.config/opencode/skills/ and register tools independently. Running both simultaneously causes "Duplicate tool names detected" warnings and HTTP 400 errors. Consider either: - 1. Remove ${pluginName} from your opencode.json plugins to use oh-my-opencode's skill loading - 2. Or disable oh-my-opencode's skill loading by setting "claude_code.skills": false in oh-my-opencode.json - 3. Or uninstall oh-my-opencode if you prefer ${pluginName}'s skill management` + 1. Remove ${pluginName} from your opencode.json plugins to use ${PLUGIN_NAME}'s skill loading + 2. Or disable ${PLUGIN_NAME}'s skill loading by setting "claude_code.skills": false in ${CONFIG_BASENAME}.json + 3. Or uninstall ${PLUGIN_NAME} if you prefer ${pluginName}'s skill management` } diff --git a/src/shared/logger.ts b/src/shared/logger.ts index 21effaf67..483d0269d 100644 --- a/src/shared/logger.ts +++ b/src/shared/logger.ts @@ -2,7 +2,9 @@ import * as fs from "fs" import * as os from "os" import * as path from "path" -const logFile = path.join(os.tmpdir(), "oh-my-opencode.log") +import { LOG_FILENAME } from "./plugin-identity" + +const logFile = path.join(os.tmpdir(), LOG_FILENAME) let buffer: string[] = [] let flushTimer: ReturnType | null = null diff --git a/src/tools/ast-grep/downloader.ts b/src/tools/ast-grep/downloader.ts index ca7dcd004..0c7389cf4 100644 --- a/src/tools/ast-grep/downloader.ts +++ b/src/tools/ast-grep/downloader.ts @@ -11,6 +11,7 @@ import { getCachedBinaryPath as getCachedBinaryPathShared, } from "../../shared/binary-downloader" import { log } from "../../shared/logger" +import { CACHE_DIR_NAME, PUBLISHED_PACKAGE_NAME } from "../../shared/plugin-identity" const REPO = "ast-grep/ast-grep" @@ -47,12 +48,12 @@ export function getCacheDir(): string { if (process.platform === "win32") { const localAppData = process.env.LOCALAPPDATA || process.env.APPDATA const base = localAppData || join(homedir(), "AppData", "Local") - return join(base, "oh-my-opencode", "bin") + return join(base, CACHE_DIR_NAME, "bin") } const xdgCache = process.env.XDG_CACHE_HOME const base = xdgCache || join(homedir(), ".cache") - return join(base, "oh-my-opencode", "bin") + return join(base, CACHE_DIR_NAME, "bin") } export function getBinaryName(): string { @@ -70,7 +71,7 @@ export async function downloadAstGrep(version: string = DEFAULT_VERSION): Promis const platformInfo = PLATFORM_MAP[platformKey] if (!platformInfo) { - log(`[oh-my-opencode] Unsupported platform for ast-grep: ${platformKey}`) + log(`[${PUBLISHED_PACKAGE_NAME}] Unsupported platform for ast-grep: ${platformKey}`) return null } @@ -86,7 +87,7 @@ export async function downloadAstGrep(version: string = DEFAULT_VERSION): Promis const assetName = `app-${arch}-${os}.zip` const downloadUrl = `https://github.com/${REPO}/releases/download/${version}/${assetName}` - log(`[oh-my-opencode] Downloading ast-grep binary...`) + log(`[${PUBLISHED_PACKAGE_NAME}] Downloading ast-grep binary...`) try { const archivePath = join(cacheDir, assetName) @@ -96,12 +97,12 @@ export async function downloadAstGrep(version: string = DEFAULT_VERSION): Promis cleanupArchive(archivePath) ensureExecutable(binaryPath) - log(`[oh-my-opencode] ast-grep binary ready.`) + log(`[${PUBLISHED_PACKAGE_NAME}] ast-grep binary ready.`) return binaryPath } catch (err) { log( - `[oh-my-opencode] Failed to download ast-grep: ${err instanceof Error ? err.message : err}` + `[${PUBLISHED_PACKAGE_NAME}] Failed to download ast-grep: ${err instanceof Error ? err.message : err}` ) return null } diff --git a/src/tools/call-omo-agent/tools.ts b/src/tools/call-omo-agent/tools.ts index 00358b8e1..d3e12f14d 100644 --- a/src/tools/call-omo-agent/tools.ts +++ b/src/tools/call-omo-agent/tools.ts @@ -10,6 +10,7 @@ import { getAgentConfigKey } from "../../shared/agent-display-names" import { normalizeFallbackModels } from "../../shared/model-resolver" import { buildFallbackChainFromModels } from "../../shared/fallback-chain-from-models" import { log } from "../../shared" +import { CONFIG_BASENAME } from "../../shared/plugin-identity" import { parseModelString } from "../delegate-task/model-string-parser" import { executeBackground } from "./background-executor" import { executeSync } from "./sync-executor" @@ -117,7 +118,7 @@ export function createCallOmoAgent( // Check if agent is disabled if (disabledAgents.some((disabled) => disabled.toLowerCase() === normalizedAgent)) { - return `Error: Agent "${normalizedAgent}" is disabled via disabled_agents configuration. Remove it from disabled_agents in your oh-my-opencode.json to use it.` + return `Error: Agent "${normalizedAgent}" is disabled via disabled_agents configuration. Remove it from disabled_agents in your ${CONFIG_BASENAME}.json to use it.` } const { model: resolvedModel, fallbackChain } = resolveModelAndFallbackChain({ diff --git a/src/tools/delegate-task/category-resolver.ts b/src/tools/delegate-task/category-resolver.ts index fa0f1475e..bfc4d1896 100644 --- a/src/tools/delegate-task/category-resolver.ts +++ b/src/tools/delegate-task/category-resolver.ts @@ -9,6 +9,7 @@ import { parseModelString } from "./model-string-parser" import { CATEGORY_MODEL_REQUIREMENTS } from "../../shared/model-requirements" import { normalizeFallbackModels, flattenToFallbackModelStrings } from "../../shared/model-resolver" import { buildFallbackChainFromModels, findMostSpecificFallbackEntry } from "../../shared/fallback-chain-from-models" +import { CONFIG_BASENAME } from "../../shared/plugin-identity" import { getAvailableModelsForDelegateTask } from "./available-models" import { resolveModelForDelegateTask } from "./model-selection" @@ -89,7 +90,7 @@ export async function resolveCategoryExecution( To use this category: 1. Connect a provider with this model: ${requirement.requiresModel} -2. Or configure an alternative model in your oh-my-opencode.json for this category +2. Or configure an alternative model in your ${CONFIG_BASENAME}.json for this category Available categories: ${allCategoryNames}`, } @@ -225,7 +226,7 @@ Available categories: ${allCategoryNames}`, Configure in one of: 1. OpenCode: Set "model" in opencode.json -2. Oh-My-OpenCode: Set category model in oh-my-opencode.json +2. Oh-My-OpenCode: Set category model in ${CONFIG_BASENAME}.json 3. Provider: Connect a provider with available models Current category: ${args.category} diff --git a/src/tools/grep/constants.ts b/src/tools/grep/constants.ts index f41284324..79db24c6b 100644 --- a/src/tools/grep/constants.ts +++ b/src/tools/grep/constants.ts @@ -4,6 +4,7 @@ import { spawnSync } from "node:child_process" import { getInstalledRipgrepPath, downloadAndInstallRipgrep } from "./downloader" import { getDataDir } from "../../shared/data-path" import { log } from "../../shared/logger" +import { PUBLISHED_PACKAGE_NAME } from "../../shared/plugin-identity" export type GrepBackend = "rg" | "grep" @@ -106,12 +107,12 @@ export async function resolveGrepCliWithAutoInstall(): Promise { return cachedCli } catch (error) { if (current.backend === "grep") { - log("[oh-my-opencode] Failed to auto-install ripgrep. Falling back to GNU grep.", { + log(`[${PUBLISHED_PACKAGE_NAME}] Failed to auto-install ripgrep. Falling back to GNU grep.`, { error: error instanceof Error ? error.message : String(error), grep_path: current.path, }) } else { - log("[oh-my-opencode] Failed to auto-install ripgrep and GNU grep was not found.", { + log(`[${PUBLISHED_PACKAGE_NAME}] Failed to auto-install ripgrep and GNU grep was not found.`, { error: error instanceof Error ? error.message : String(error), }) } diff --git a/src/tools/grep/downloader.ts b/src/tools/grep/downloader.ts index 774740b83..486ed18a5 100644 --- a/src/tools/grep/downloader.ts +++ b/src/tools/grep/downloader.ts @@ -1,6 +1,7 @@ import { existsSync, readdirSync } from "node:fs" import { join } from "node:path" import { extractZip as extractZipBase } from "../../shared" +import { CACHE_DIR_NAME } from "../../shared/plugin-identity" import { cleanupArchive, downloadArchive, @@ -39,7 +40,7 @@ function getPlatformKey(): string { function getInstallDir(): string { const homeDir = process.env.HOME || process.env.USERPROFILE || "." - return join(homeDir, ".cache", "oh-my-opencode", "bin") + return join(homeDir, ".cache", CACHE_DIR_NAME, "bin") } function getRgPath(): string { diff --git a/src/tools/lsp/lsp-client-wrapper.ts b/src/tools/lsp/lsp-client-wrapper.ts index b12a4c671..6c3f82265 100644 --- a/src/tools/lsp/lsp-client-wrapper.ts +++ b/src/tools/lsp/lsp-client-wrapper.ts @@ -5,6 +5,7 @@ import { existsSync, statSync } from "fs" import { LSPClient, lspManager } from "./client" import { findServerForExtension } from "./config" import type { ServerLookupResult } from "./types" +import { CONFIG_BASENAME } from "../../shared/plugin-identity" export function isDirectoryPath(filePath: string): boolean { if (!existsSync(filePath)) { @@ -63,7 +64,7 @@ export function formatServerLookupError(result: Exclude 10 ? "..." : ""}`, ``, - `To add a custom server, configure 'lsp' in oh-my-opencode.json:`, + `To add a custom server, configure 'lsp' in ${CONFIG_BASENAME}.json:`, ` {`, ` "lsp": {`, ` "my-server": {`,