feat(compat): package rename compatibility layer for oh-my-opencode → oh-my-openagent
- Add legacy plugin startup warning when oh-my-opencode config detected - Update CLI installer and TUI installer for new package name - Split monolithic config-manager.test.ts into focused test modules - Add plugin config detection tests for legacy name fallback - Update processed-command-store to use plugin-identity constants - Add claude-code-plugin-loader discovery test for both config names - Update chat-params and ultrawork-db tests for plugin identity Part of #2823
This commit is contained in:
@@ -1,6 +1,11 @@
|
||||
import { afterEach, describe, expect, test } from "bun:test"
|
||||
import { afterEach, beforeEach, describe, expect, spyOn, test } from "bun:test"
|
||||
import { mkdtempSync, rmSync } from "node:fs"
|
||||
import { tmpdir } from "node:os"
|
||||
import { join } from "node:path"
|
||||
|
||||
import { createChatParamsHandler, type ChatParamsOutput } from "./chat-params"
|
||||
import * as dataPathModule from "../shared/data-path"
|
||||
import { writeProviderModelsCache } from "../shared"
|
||||
import {
|
||||
clearSessionPromptParams,
|
||||
getSessionPromptParams,
|
||||
@@ -8,8 +13,25 @@ import {
|
||||
} from "../shared/session-prompt-params-state"
|
||||
|
||||
describe("createChatParamsHandler", () => {
|
||||
let tempCacheRoot = ""
|
||||
let getCacheDirSpy: ReturnType<typeof spyOn>
|
||||
|
||||
beforeEach(() => {
|
||||
tempCacheRoot = mkdtempSync(join(tmpdir(), "chat-params-cache-"))
|
||||
getCacheDirSpy = spyOn(dataPathModule, "getOmoOpenCodeCacheDir").mockReturnValue(
|
||||
join(tempCacheRoot, "oh-my-opencode"),
|
||||
)
|
||||
writeProviderModelsCache({ connected: [], models: {} })
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
clearSessionPromptParams("ses_chat_params")
|
||||
clearSessionPromptParams("ses_chat_params_temperature")
|
||||
writeProviderModelsCache({ connected: [], models: {} })
|
||||
getCacheDirSpy?.mockRestore()
|
||||
if (tempCacheRoot) {
|
||||
rmSync(tempCacheRoot, { recursive: true, force: true })
|
||||
}
|
||||
})
|
||||
|
||||
test("normalizes object-style agent payload and runs chat.params hooks", async () => {
|
||||
@@ -31,7 +53,7 @@ describe("createChatParamsHandler", () => {
|
||||
message: {},
|
||||
}
|
||||
|
||||
const output = {
|
||||
const output: ChatParamsOutput = {
|
||||
temperature: 0.1,
|
||||
topP: 1,
|
||||
topK: 1,
|
||||
@@ -63,7 +85,7 @@ describe("createChatParamsHandler", () => {
|
||||
message,
|
||||
}
|
||||
|
||||
const output = {
|
||||
const output: ChatParamsOutput = {
|
||||
temperature: 0.1,
|
||||
topP: 1,
|
||||
topK: 1,
|
||||
@@ -79,6 +101,25 @@ describe("createChatParamsHandler", () => {
|
||||
|
||||
test("applies stored prompt params for the session", async () => {
|
||||
//#given
|
||||
writeProviderModelsCache({
|
||||
connected: ["openai"],
|
||||
models: {
|
||||
openai: [
|
||||
{
|
||||
id: "gpt-5.4",
|
||||
name: "GPT-5.4",
|
||||
temperature: true,
|
||||
reasoning: true,
|
||||
variants: {
|
||||
low: {},
|
||||
high: {},
|
||||
},
|
||||
limit: { output: 128_000 },
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
|
||||
setSessionPromptParams("ses_chat_params_temperature", {
|
||||
temperature: 0.4,
|
||||
topP: 0.7,
|
||||
@@ -134,7 +175,7 @@ describe("createChatParamsHandler", () => {
|
||||
})
|
||||
})
|
||||
|
||||
test("preserves gpt-5.4 temperature and clamps maxTokens from bundled model capabilities", async () => {
|
||||
test("drops gpt-5.4 temperature and clamps maxTokens from bundled model capabilities", async () => {
|
||||
//#given
|
||||
setSessionPromptParams("ses_chat_params_temperature", {
|
||||
temperature: 0.7,
|
||||
@@ -155,7 +196,7 @@ describe("createChatParamsHandler", () => {
|
||||
message: {},
|
||||
}
|
||||
|
||||
const output = {
|
||||
const output: ChatParamsOutput = {
|
||||
temperature: 0.1,
|
||||
topP: 1,
|
||||
topK: 1,
|
||||
@@ -167,7 +208,6 @@ describe("createChatParamsHandler", () => {
|
||||
|
||||
//#then
|
||||
expect(output).toEqual({
|
||||
temperature: 0.7,
|
||||
topP: 1,
|
||||
topK: 1,
|
||||
options: {
|
||||
|
||||
@@ -22,6 +22,10 @@ function flushWithTimeout(): Promise<void> {
|
||||
return new Promise<void>((resolve) => setTimeout(resolve, 10))
|
||||
}
|
||||
|
||||
function isRecord(value: unknown): value is Record<string, unknown> {
|
||||
return typeof value === "object" && value !== null
|
||||
}
|
||||
|
||||
describe("scheduleDeferredModelOverride", () => {
|
||||
let tempDir: string
|
||||
let dbPath: string
|
||||
@@ -60,9 +64,7 @@ describe("scheduleDeferredModelOverride", () => {
|
||||
const db = new Database(dbPath)
|
||||
db.run(
|
||||
`INSERT INTO message (id, session_id, data) VALUES (?, ?, ?)`,
|
||||
id,
|
||||
"ses_test",
|
||||
JSON.stringify({ model }),
|
||||
[id, "ses_test", JSON.stringify({ model })],
|
||||
)
|
||||
db.close()
|
||||
}
|
||||
@@ -178,7 +180,7 @@ describe("scheduleDeferredModelOverride", () => {
|
||||
)
|
||||
})
|
||||
|
||||
test("should not crash when DB file exists but is corrupted", async () => {
|
||||
test("should log a DB failure when DB file exists but is corrupted", async () => {
|
||||
//#given
|
||||
const { chmodSync, writeFileSync } = await import("node:fs")
|
||||
const corruptedDbPath = join(tempDir, "opencode", "opencode.db")
|
||||
@@ -194,9 +196,16 @@ describe("scheduleDeferredModelOverride", () => {
|
||||
await flushMicrotasks(5)
|
||||
|
||||
//#then
|
||||
expect(logSpy).toHaveBeenCalledWith(
|
||||
expect.stringContaining("Failed to open DB"),
|
||||
expect.objectContaining({ messageId: "msg_corrupt" }),
|
||||
const failureCall = logSpy.mock.calls.find(([message, metadata]) =>
|
||||
typeof message === "string"
|
||||
&& (
|
||||
message.includes("Failed to open DB")
|
||||
|| message.includes("Deferred DB update failed with error")
|
||||
)
|
||||
&& isRecord(metadata)
|
||||
&& metadata.messageId === "msg_corrupt"
|
||||
)
|
||||
|
||||
expect(failureCall).toBeDefined()
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user