feat(codex): import local Codex sessions into Hapi (#796)

* local: add Codex Desktop session sync controls

* feat(codex): import local Codex sessions into Hapi

---------

Co-authored-by: Codex Local <codex-local@example.invalid>
This commit is contained in:
DolphinZZZZZ
2026-06-04 17:53:12 +08:00
committed by GitHub
co-authored by Codex Local
parent 39fba5292c
commit f9ef3a4489
25 changed files with 3156 additions and 15 deletions
+44
View File
@@ -1,6 +1,12 @@
import type {
AttachmentMetadata,
AuthResponse,
CodexLocalSessionsResponse,
CodexDuplicateSessionsResponse,
CodexMergeDuplicateSessionsResponse,
CodexDesktopScriptResponse,
CodexDesktopSyncRequest,
CodexDesktopStatusResponse,
CodexCollaborationMode,
FileSearchResponse,
MachinesResponse,
@@ -179,6 +185,44 @@ export class ApiClient {
})
}
async syncCodexSession(payload?: CodexDesktopSyncRequest): Promise<CodexDesktopScriptResponse> {
// 中文注释:当前按钮语义已改为“从 Codex 导入到 Hapi”;这里提交的是本地 transcript 对应的 Codex thread ID 列表。
return await this.request<CodexDesktopScriptResponse>('/api/codex/sync-session', {
method: 'POST',
...(payload ? { body: JSON.stringify(payload) } : {})
})
}
async getCodexSessions(): Promise<CodexLocalSessionsResponse> {
return await this.request<CodexLocalSessionsResponse>('/api/codex/sessions')
}
async getCodexDesktopStatus(): Promise<CodexDesktopStatusResponse> {
return await this.request<CodexDesktopStatusResponse>('/api/codex/status')
}
async getCodexDuplicateSessions(payload: CodexDesktopSyncRequest): Promise<CodexDuplicateSessionsResponse> {
// 中文注释:重复会话检测只传本次用户勾选导入的 codexSessionId,避免把未选中的历史会话也纳入提示。
return await this.request<CodexDuplicateSessionsResponse>('/api/codex/duplicate-sessions', {
method: 'POST',
body: JSON.stringify(payload)
})
}
async mergeCodexDuplicateSessions(payload: CodexDesktopSyncRequest): Promise<CodexMergeDuplicateSessionsResponse> {
// 中文注释:真正执行合并时沿用同一批选中 codexSessionId,保证检测范围与执行范围一致。
return await this.request<CodexMergeDuplicateSessionsResponse>('/api/codex/merge-duplicate-sessions', {
method: 'POST',
body: JSON.stringify(payload)
})
}
async restartCodexDesktop(): Promise<CodexDesktopScriptResponse> {
return await this.request<CodexDesktopScriptResponse>('/api/codex/restart-desktop', {
method: 'POST'
})
}
async unsubscribePushNotifications(payload: PushUnsubscribePayload): Promise<void> {
await this.request('/api/push/subscribe', {
method: 'DELETE',