Something went wrong. Try again.
presents omp as codex for use with chatgpt remote
Something went wrong. Try again.
12 kB · 373 lines
JavaScript
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374import os from "node:os";import path from "node:path";import { BRIDGE_VERSION, PROTOCOL_COMPAT_VERSION, id, unixSeconds } from "./util.mjs";
export const ERROR = Object.freeze({ PARSE: -32700, INVALID_REQUEST: -32600, METHOD_NOT_FOUND: -32601, INVALID_PARAMS: -32602, INTERNAL: -32603, NOT_INITIALIZED: -32002, ALREADY_INITIALIZED: -32003, NOT_FOUND: -32004, BUSY: -32005, POLICY: -32006,});
export class RpcError extends Error { constructor(code, message, data) { super(message); this.name = "RpcError"; this.code = code; this.data = data; }}
export function errorResponse(requestId, error) { return { id: requestId ?? null, error: { code: Number.isInteger(error?.code) ? error.code : ERROR.INTERNAL, message: String(error?.message || error || "Internal error"), ...(error?.data === undefined ? {} : { data: error.data }), }, };}
export function successResponse(requestId, result) { return { id: requestId, result: result ?? {} };}
export function notification(method, params = {}) { return { method, params };}
export function resolveModelContextWindow(model) { const name = String(model || "").toLowerCase(); if (name.includes("gemini-1.5") || name.includes("gemini-2") || name.includes("gemini-3") || name.includes("gemini") || name.includes("fable") || name.includes("mythos")) { return 1_000_000; } if (name.includes("claude-sonnet-4") || name.includes("claude-opus-4") || name.includes("claude-opus-5") || name.includes("claude-sonnet-5")) { return 1_000_000; } if (name.includes("claude") || name.includes("sonnet") || name.includes("opus") || name.includes("haiku")) { return 200_000; } if (name.includes("gpt-5.6") || name.includes("gpt-5.4")) { return 1_000_000; } if (name.includes("gpt-5.5")) { return 272_000; } if (name.includes("gpt-4o") || name.includes("gpt-4.1") || name.includes("o1") || name.includes("o3") || name.includes("gpt-5")) { return 200_000; } if (name.includes("deepseek") || name.includes("qwen")) { return 128_000; } return 200_000;}
export function makeTokenUsage(usage = {}) { const input = Number(usage.input ?? usage.inputTokens ?? usage.prompt_tokens ?? usage.promptTokens ?? 0); const output = Number(usage.output ?? usage.outputTokens ?? usage.completion_tokens ?? usage.completionTokens ?? 0); const cachedInput = Number(usage.cacheRead ?? usage.cachedInputTokens ?? usage.cached_tokens ?? usage.cachedTokens ?? usage.cache_read_input_tokens ?? 0); const cacheWrite = Number(usage.cacheWrite ?? usage.cacheWriteInputTokens ?? usage.cache_creation_input_tokens ?? 0); const reasoning = Number(usage.reasoningTokens ?? usage.reasoning ?? usage.reasoningOutputTokens ?? usage.reasoning_tokens ?? 0); const rawTotal = usage.totalTokens ?? usage.total_tokens ?? usage.total; const total = Number(rawTotal != null ? rawTotal : (input + output + cachedInput)); const effectiveInput = input || (total > output ? total - output : 0); return { totalTokens: Math.max(0, total), inputTokens: Math.max(0, effectiveInput), cachedInputTokens: Math.max(0, cachedInput), cacheWriteInputTokens: Math.max(0, cacheWrite), outputTokens: Math.max(0, output), reasoningOutputTokens: Math.max(0, reasoning), };}
export function makeThread({ id: idParam = null, threadId = idParam || id("thread"), cwd = process.cwd(), model = null, modelProvider = null, reasoningEffort = null, name = null, preview = "", source = "appServer", ephemeral = false, section = null, sectionEnteredAt = null, projectId = null, sessionId = null, forkedFromId = null, parentThreadId = null, createdAt = unixSeconds(), updatedAt = createdAt, archived = false, status = "idle", turns = [], gitInfo = null, workspace = null, modelContextWindow = null, goal = null, modelAutoCompactTokenLimit = null,} = {}) { const rawModel = typeof model === "string" ? model : (model?.selector || model?.id || model?.model || "gemini-3.7-flash"); const rawModelId = typeof model === "object" ? (model?.id || model?.model || rawModel) : rawModel; const modelId = model?.selector && rawModelId === model.selector && String(rawModelId).includes("/") ? String(rawModelId).slice(String(rawModelId).indexOf("/") + 1) : (rawModelId || "gemini-3.7-flash"); const resolvedProvider = modelProvider || model?.provider || model?.modelProvider || (typeof model === "string" && model.includes("/") ? model.slice(0, model.indexOf("/")) : (typeof rawModel === "string" && rawModel.includes("/") ? rawModel.slice(0, rawModel.indexOf("/")) : "openai")); const contextWindow = modelContextWindow || resolveModelContextWindow(rawModel); const autoCompactLimit = modelAutoCompactTokenLimit || Math.floor(contextWindow * 0.9); return { id: threadId, extra: null, sessionId: sessionId || threadId, forkedFromId: forkedFromId || null, parentThreadId: parentThreadId || forkedFromId || null, preview, ephemeral, section: section || null, sectionEnteredAt: sectionEnteredAt || null, projectId: projectId || null, historyMode: "legacy", model: modelId, modelProvider: resolvedProvider, modelSelector: model?.selector || null, reasoningEffort: reasoningEffort || null, createdAt, updatedAt, recencyAt: updatedAt, status: typeof status === "string" ? { type: status } : status, path: null, cwd: path.resolve(cwd), cliVersion: PROTOCOL_COMPAT_VERSION, source, canAcceptDirectInput: true, threadSource: null, agentNickname: null, agentRole: null, gitInfo: gitInfo || null, workspace: workspace || null, name: name || null, modelContextWindow: contextWindow, modelAutoCompactTokenLimit: autoCompactLimit, goal: goal || null, turns, };}
export function makeTurn({ turnId = id("turn"), status = "inProgress", items = [], error = null, startedAt = unixSeconds(), completedAt = null, durationMs = null, tokenUsage = null,} = {}) { return { id: turnId, items, itemsView: "full", status, error, startedAt, completedAt, durationMs, tokenUsage: makeTokenUsage(tokenUsage || {}), };}
export function makeAgentMessageItem(itemId = id("item"), text = "") { return { id: itemId, type: "agentMessage", text, phase: null, memoryCitation: null, delivery: null, status: "completed", };}
export function makeReasoningItem(itemId = id("item"), summary = [], content = []) { return { id: itemId, type: "reasoning", summary: Array.isArray(summary) ? summary : [], content: Array.isArray(content) ? content : [], status: "completed", };}
export function makeUserMessageItem(itemId = id("item"), content = [], clientId = null) { const formattedContent = (Array.isArray(content) ? content : [{ type: "text", text: String(content || "") }]).map((c) => { if (typeof c === "string") return { type: "text", text: c, textElements: [] }; if (c.type === "text" && !c.textElements) return { ...c, textElements: [] }; return c; }); return { id: itemId, type: "userMessage", clientId, content: formattedContent, status: "completed", };}
/** * Native ChatGPT/Codex ask card. The client renders `questions` with * `answers[question.id]` and shows "No answer provided" for an empty answer * list. `completed: false` makes the client render a picker keyed to a live * request id, so a durable item MUST stay `completed: true` — otherwise the * card offers buttons whose submit target no longer exists. */export function makeUserInputResponseItem(itemId = id("item"), { requestId = itemId, turnId = null, questions = [], answers = {}, completed = true,} = {}) { return { id: itemId, type: "userInputResponse", requestId, turnId, questions: (Array.isArray(questions) ? questions : []).map((question) => ({ id: String(question?.id || ""), header: question?.header ?? null, question: String(question?.question || ""), options: (Array.isArray(question?.options) ? question.options : []).map((option) => ({ label: String(option?.label ?? option ?? ""), description: option?.description ?? null, })), })), answers: answers && typeof answers === "object" ? answers : {}, completed: Boolean(completed), status: completed ? "completed" : "inProgress", };}
export function makeCommandItem(itemId = id("item"), command = "", cwd = process.cwd()) { const commands = Array.isArray(command) ? command.map(String) : [String(command || "")]; return { id: itemId, type: "commandExecution", pluginId: null, scriptPath: null, command: commands.join(" "), cwd: path.resolve(cwd), processId: null, source: "agent", status: "inProgress", commandActions: commands.map((cmd) => ({ type: "unknown", command: cmd })), aggregatedOutput: "", exitCode: null, durationMs: null, };}
export function normalizePatchChangeKind(change = {}) { const raw = typeof change.kind === "object" && change.kind !== null ? change.kind : {}; const type = String(raw.type || change.kind || change.type || "update"); return type === "update" ? { ...raw, type, movePath: raw.movePath ?? null } : { type };}
export function makeFileChangeItem(itemId = id("item"), changes = []) { return { id: itemId, type: "fileChange", changes: changes.map((change) => ({ path: String(change.path || change.file || ""), kind: normalizePatchChangeKind(change), diff: change.diff || "", })), status: "inProgress", };}
export function makeMcpToolCallItem(itemId = id("item"), server = "oh-my-pi", tool = "tool", args = {}) { return { id: itemId, type: "mcpToolCall", server, tool, status: "inProgress", arguments: args ?? {}, appContext: null, mcpAppResourceUri: null, pluginId: null, result: null, error: null, durationMs: null, };}
export function makeDynamicToolCallItem(itemId = id("item"), tool = "tool", args = {}, namespace = "oh-my-pi") { return { id: itemId, type: "dynamicToolCall", namespace, tool, arguments: args ?? {}, status: "inProgress", contentItems: null, success: null, durationMs: null, };}
export function makeWebSearchItem(itemId = id("item"), args = {}) { const query = String(args.query || args.q || ""); return { id: itemId, type: "webSearch", query, action: { type: "search", query: query || null, queries: Array.isArray(args.queries) ? args.queries : null }, results: null, };}
export function makeImageViewItem(itemId = id("item"), imagePath = "") { return { id: itemId, type: "imageView", path: String(imagePath || ""), };}
export function makeContextCompactionItem(itemId = id("item")) { return { id: itemId, type: "contextCompaction", };}
export function initializeResult() { const plat = os.platform(); const platformFamily = plat === "win32" ? "windows" : "unix"; const platformOs = plat === "darwin" ? "macos" : plat === "win32" ? "windows" : plat === "linux" ? "linux" : plat; const codexHome = process.env.CODEX_HOME || path.join(os.homedir(), ".codex"); return { userAgent: `codex-cli/${PROTOCOL_COMPAT_VERSION} (${os.type()} ${os.release()}; ${os.arch()}) omp-codex-bridge/${BRIDGE_VERSION}`, codexHome, platformFamily, platformOs, serverInfo: { name: "codex-cli", title: "Oh My Pi Codex Bridge", version: PROTOCOL_COMPAT_VERSION }, platformInfo: { osType: os.type(), osName: plat, osVersion: os.release(), arch: os.arch(), }, protocolVersion: PROTOCOL_COMPAT_VERSION, };}