df87f5f113
* docs: rename OmO agent to Sisyphus, OmO-Plan to Planner-Sisyphus 🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode) * refactor: rename OmO agent to Sisyphus with automatic config migration - Rename OmO agent to Sisyphus (uses mythological pushing-the-boulder concept) - Rename OmO-Plan to Planner-Sisyphus for consistency - Update config schema: omo_agent → sisyphus_agent - Add backward compatibility: automatically migrate user's oh-my-opencode.json files - Migration handles old keys (OmO, omo, OmO-Plan, omo-plan) and rewrites config when detected - Update agent name mappings, index files, and type definitions - Add Sisyphus PNG asset to brand identity 🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode) * docs: add Sisyphus mythology introduction and teammates concept to all READMEs 🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode) * feat(startup-toast): show Sisyphus steering message when enabled - Updated startup toast to show "Sisyphus on steroids is steering OpenCode" when Sisyphus agent is enabled - Refactored getToastMessage function to handle conditional message rendering - Pass isSisyphusEnabled flag from plugin configuration to auto-update-checker hook 🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode) * docs(sisyphus): add philosophical context to Sisyphus agent identity - Add "Why Sisyphus?" explanation connecting the daily work cycle of humans and AI agents - Emphasize code quality expectations: indistinguishable from senior engineer's work - Concise identity statement: work, delegate, verify, ship without AI slop This clarifies the agent's purpose and reinforces the principle that quality code should not reveal whether it was written by human or AI. 🤖 GENERATED WITH ASSISTANCE OF [OhMyOpenCode](https://github.com/code-yeongyu/oh-my-opencode)
124 lines
4.1 KiB
TypeScript
124 lines
4.1 KiB
TypeScript
import type { PluginInput } from "@opencode-ai/plugin"
|
|
import { checkForUpdate, getCachedVersion, getLocalDevVersion } from "./checker"
|
|
import { invalidatePackage } from "./cache"
|
|
import { PACKAGE_NAME } from "./constants"
|
|
import { log } from "../../shared/logger"
|
|
import { getConfigLoadErrors, clearConfigLoadErrors } from "../../shared/config-errors"
|
|
import type { AutoUpdateCheckerOptions } from "./types"
|
|
|
|
export function createAutoUpdateCheckerHook(ctx: PluginInput, options: AutoUpdateCheckerOptions = {}) {
|
|
const { showStartupToast = true, isSisyphusEnabled = false } = options
|
|
|
|
const getToastMessage = (isUpdate: boolean, latestVersion?: string): string => {
|
|
if (isSisyphusEnabled) {
|
|
return isUpdate
|
|
? `Sisyphus on steroids is steering OpenCode.\nv${latestVersion} available. Restart to apply.`
|
|
: `Sisyphus on steroids is steering OpenCode.`
|
|
}
|
|
return isUpdate
|
|
? `OpenCode is now on Steroids. oMoMoMoMo...\nv${latestVersion} available. Restart OpenCode to apply.`
|
|
: `OpenCode is now on Steroids. oMoMoMoMo...`
|
|
}
|
|
|
|
const showVersionToast = async (version: string | null): Promise<void> => {
|
|
const displayVersion = version ?? "unknown"
|
|
await ctx.client.tui
|
|
.showToast({
|
|
body: {
|
|
title: `OhMyOpenCode ${displayVersion}`,
|
|
message: getToastMessage(false),
|
|
variant: "info" as const,
|
|
duration: 5000,
|
|
},
|
|
})
|
|
.catch(() => {})
|
|
log(`[auto-update-checker] Startup toast shown: v${displayVersion}`)
|
|
}
|
|
|
|
let hasChecked = false
|
|
|
|
return {
|
|
event: async ({ event }: { event: { type: string; properties?: unknown } }) => {
|
|
if (event.type !== "session.created") return
|
|
if (hasChecked) return
|
|
|
|
const props = event.properties as { info?: { parentID?: string } } | undefined
|
|
if (props?.info?.parentID) return
|
|
|
|
hasChecked = true
|
|
|
|
try {
|
|
const result = await checkForUpdate(ctx.directory)
|
|
|
|
if (result.isLocalDev) {
|
|
log("[auto-update-checker] Skipped: local development mode")
|
|
if (showStartupToast) {
|
|
const version = getLocalDevVersion(ctx.directory) ?? getCachedVersion()
|
|
await showVersionToast(version)
|
|
}
|
|
return
|
|
}
|
|
|
|
if (result.isPinned) {
|
|
log(`[auto-update-checker] Skipped: version pinned to ${result.currentVersion}`)
|
|
if (showStartupToast) {
|
|
await showVersionToast(result.currentVersion)
|
|
}
|
|
return
|
|
}
|
|
|
|
if (!result.needsUpdate) {
|
|
log("[auto-update-checker] No update needed")
|
|
if (showStartupToast) {
|
|
await showVersionToast(result.currentVersion)
|
|
}
|
|
return
|
|
}
|
|
|
|
invalidatePackage(PACKAGE_NAME)
|
|
|
|
await ctx.client.tui
|
|
.showToast({
|
|
body: {
|
|
title: `OhMyOpenCode ${result.latestVersion}`,
|
|
message: getToastMessage(true, result.latestVersion ?? undefined),
|
|
variant: "info" as const,
|
|
duration: 8000,
|
|
},
|
|
})
|
|
.catch(() => {})
|
|
|
|
log(`[auto-update-checker] Update notification sent: v${result.currentVersion} → v${result.latestVersion}`)
|
|
} catch (err) {
|
|
log("[auto-update-checker] Error during update check:", err)
|
|
}
|
|
|
|
await showConfigErrorsIfAny(ctx)
|
|
},
|
|
}
|
|
}
|
|
|
|
async function showConfigErrorsIfAny(ctx: PluginInput): Promise<void> {
|
|
const errors = getConfigLoadErrors()
|
|
if (errors.length === 0) return
|
|
|
|
const errorMessages = errors.map(e => `${e.path}: ${e.error}`).join("\n")
|
|
await ctx.client.tui
|
|
.showToast({
|
|
body: {
|
|
title: "Config Load Error",
|
|
message: `Failed to load config:\n${errorMessages}`,
|
|
variant: "error" as const,
|
|
duration: 10000,
|
|
},
|
|
})
|
|
.catch(() => {})
|
|
|
|
log(`[auto-update-checker] Config load errors shown: ${errors.length} error(s)`)
|
|
clearConfigLoadErrors()
|
|
}
|
|
|
|
export type { UpdateCheckResult, AutoUpdateCheckerOptions } from "./types"
|
|
export { checkForUpdate } from "./checker"
|
|
export { invalidatePackage, invalidateCache } from "./cache"
|