Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 4 additions & 2 deletions .github/workflows/build-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ jobs:
- name: Upload macOS artifacts
uses: actions/upload-artifact@v6
with:
name: opencodex-macos-${{ matrix.arch }}
# 外层 Artifact 名称携带完整提交哈希,内部 DMG 文件名保持不变。
name: opencodex-macos-${{ matrix.arch }}-${{ github.sha }}
path: release/*.dmg
if-no-files-found: error

Expand Down Expand Up @@ -136,7 +137,8 @@ jobs:
- name: Upload Windows artifact
uses: actions/upload-artifact@v6
with:
name: opencodex-windows
# 外层 Artifact 名称携带完整提交哈希,内部 EXE 文件名保持不变。
name: opencodex-windows-${{ github.sha }}
path: release/*.exe
if-no-files-found: error

Expand Down
4 changes: 4 additions & 0 deletions gateway/runtime/http/static-assets.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ const RUNTIME_COMPATIBILITY_SCRIPT_PATH = "/opencodex/runtime-compatibility.js";
const RUNTIME_COMPATIBILITY_STYLE_PATH = "/opencodex/runtime-compatibility.css";
const OPENCODEX_SIDEBAR_PREVIEW_PATH = "/codex-sidebar-preview.js";
const OPENCODEX_OFFSCREEN_ANIMATION_GUARD_PATH = "/codex-offscreen-animation-guard.js";
const CODEX_APP_HOST_MESSAGE_CODEC_PATH = "/codex-app-host-message-codec.js";
const CODEX_BRIDGE_POLYFILL_PATH = "/codex-bridge-polyfill.js";
const CODEX_REMOTE_FILE_ACTIONS_PATH = "/codex-remote-file-actions.js";
const CODEX_WORKSPACE_ROOT_PICKER_CSS_PATH = "/codex-workspace-root-picker.css";
Expand Down Expand Up @@ -278,6 +279,7 @@ const WEB_SHELL_STATIC_FILES = new Map([
[OPENCODEX_TOKEN_USAGE_CAPABILITY_PATH, path.join(INTERNAL_PROVIDER_DIR, "codex-token-usage-capability.js")],
[OPENCODEX_WINDOW_CONTROLS_OVERLAY_CSS_PATH, path.join(WEB_SHELL_DIR, "codex-window-controls-overlay.css")],
[OPENCODEX_WINDOW_CONTROLS_OVERLAY_PATH, path.join(INTERNAL_PROVIDER_DIR, "codex-window-controls-overlay.js")],
[CODEX_APP_HOST_MESSAGE_CODEC_PATH, path.join(WEB_SHELL_DIR, "codex-app-host-message-codec.js")],
[OPENCODEX_SIDEBAR_PREVIEW_PATH, path.join(INTERNAL_PROVIDER_DIR, "codex-sidebar-preview.js")],
[
OPENCODEX_OFFSCREEN_ANIMATION_GUARD_PATH,
Expand Down Expand Up @@ -690,6 +692,7 @@ function createStaticAssetService({
CODEX_SMART_SCHEDULING_SUMMARY_PATH,
OPENCODEX_TOKEN_USAGE_CAPABILITY_PATH,
OPENCODEX_WINDOW_CONTROLS_OVERLAY_PATH,
CODEX_APP_HOST_MESSAGE_CODEC_PATH,
CODEX_BRIDGE_POLYFILL_PATH,
CODEX_REMOTE_FILE_ACTIONS_PATH,
CODEX_WORKSPACE_ROOT_PICKER_PATH,
Expand Down Expand Up @@ -944,6 +947,7 @@ function createStaticAssetService({
`<script src="${CODEX_SMART_SCHEDULING_SUMMARY_PATH}"></script>`,
`<script src="${OPENCODEX_TOKEN_USAGE_CAPABILITY_PATH}"></script>`,
`<script src="${OPENCODEX_WINDOW_CONTROLS_OVERLAY_PATH}"></script>`,
`<script src="${CODEX_APP_HOST_MESSAGE_CODEC_PATH}"></script>`,
`<script src="${CODEX_BRIDGE_POLYFILL_PATH}"></script>`,
`<script src="${CODEX_REMOTE_FILE_ACTIONS_PATH}"></script>`,
`<script src="${CODEX_WORKSPACE_ROOT_PICKER_PATH}"></script>`,
Expand Down
45 changes: 26 additions & 19 deletions gateway/runtime/ipc/official-runtime.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2200,9 +2200,20 @@ async function connectOfficialAppHostPort(port, context = {}) {
return true;
}

function deliverOfficialAppHostMessage(event, onMessage, close) {
// renderer transport 只把 null 作为 peer close;undefined 是合法的结构化值。
const data = event ? event.data : undefined;
if (data === null) {
close("official_closed");
return false;
}
onMessage(data);
return true;
}

/**
* 在 gateway 进程里创建一条“浏览器 MessagePort <-> 官方 MessagePort”的透明中继。
* 这里不解析 app-host RPC 的 JSON 内容,只保证字符串帧和关闭信号按顺序穿过边界
* 这里不解析 AppHost RPC 内容,只保证结构化值和关闭信号按顺序穿过边界
*/
function createOfficialAppHostRelay(options = {}) {
const { clientId = "", onClose, onError, onMessage, portId = "", remoteAddress = "" } = options;
Expand All @@ -2213,6 +2224,7 @@ function createOfficialAppHostRelay(options = {}) {
// port1 交给官方 IPC listener;port2 留在 gateway,用来和浏览器 WebSocket 互转消息。
const { port1, port2 } = new electron.MessageChannelMain();
let closed = false;
let nullCloseScheduled = false;

function close(reason = "closed") {
if (closed) return;
Expand All @@ -2229,29 +2241,19 @@ function createOfficialAppHostRelay(options = {}) {
}

port2.on("message", (event) => {
// Electron MessageEvent.data 可能挂在原型 getter 上,必须直接读取,不能用 hasOwnProperty 判断。
const data = event ? event.data : undefined;
if (data == null) {
// app-host 约定 null 表示端口关闭,收到后要同步释放两端资源。
close("official_closed");
return;
}
if (typeof data !== "string") {
diagnosticWarn("official-app-host", "non_string_message_from_official", {
clientId: shortId(clientId),
payloadType: typeof data,
portId: shortId(portId),
});
return;
}
try {
onMessage && onMessage(data);
deliverOfficialAppHostMessage(event, (data) => onMessage && onMessage(data), close);
} catch (error) {
diagnosticWarn("official-app-host", "forward_to_browser_failed", {
clientId: shortId(clientId),
error: error instanceof Error ? error.message : String(error),
portId: shortId(portId),
});
try {
onError && onError(error);
} catch {}
// 编码或下行失败后继续保留 session 只会让双方永久等待,立即关闭以便页面重连恢复。
close("forward_to_browser_failed");
}
});
port2.on("close", () => close("official_port_closed"));
Expand Down Expand Up @@ -2285,9 +2287,13 @@ function createOfficialAppHostRelay(options = {}) {
postMessage(data) {
if (closed) return false;
try {
// 浏览器侧也用 null 作为关闭信号;其它 payload 必须保持官方 RPC 字符串原样
// main-process transport 在发送 nullish 后释放 relay,先交给官方 listener 消费 terminal 帧
port2.postMessage(data);
if (data == null) close("browser_closed");
if (data == null && !nullCloseScheduled) {
nullCloseScheduled = true;
const scheduleClose = typeof setImmediate === "function" ? setImmediate : (callback) => setTimeout(callback, 0);
scheduleClose(() => close("browser_closed"));
}
return true;
} catch (error) {
diagnosticWarn("official-app-host", "forward_to_official_failed", {
Expand Down Expand Up @@ -2563,6 +2569,7 @@ module.exports = {
startOfficialRuntime,
webConfigScript,
__test: {
deliverOfficialAppHostMessage,
compactOfficialAppCatalogPayload,
configureOfficialWebContentsListenerBudget,
fileManagerPathFromSpawn,
Expand Down
Loading