@openclaw/codex 2026.8.1-beta.3 → 2026.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.js +5 -6
- package/dist/{attempt-client-cleanup-URjUlCHg.js → attempt-client-cleanup-CpVfwctT.js} +47 -5
- package/dist/{auth-binding-B4FfbcCg.js → auth-binding-Ds_QVm-X.js} +18 -3
- package/dist/{binding-connection-DAvZwp96.js → binding-connection-CF7BmrDk.js} +2 -2
- package/dist/{bounded-turn-4BjrZEwW.js → bounded-turn-DRC3hcjm.js} +16 -20
- package/dist/{capabilities-CH3K57v4.js → capabilities-D6m_TdVy.js} +1 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-D0nZ3qtd.js → command-formatters--UToCokS.js} +4 -3
- package/dist/{command-handlers-DC86lgT4.js → command-handlers-CLFx2Ypa.js} +114 -79
- package/dist/{compact-COqgBRny.js → compact-5xqW1oCh.js} +13 -12
- package/dist/{config-CpNeo5AE.js → config-CcYL77O6.js} +350 -288
- package/dist/{conversation-binding-data-CW2GuupV.js → conversation-binding-data-BiodpIzq.js} +2 -1
- package/dist/doctor-contract-api.js +121 -16
- package/dist/{dynamic-tools-fJZhl4CE.js → dynamic-tools-BmeXjwNZ.js} +243 -1002
- package/dist/{effective-mcp-catalog-4YKn51aG.js → effective-mcp-catalog-XXQKgK1U.js} +2 -2
- package/dist/{event-projector-assistant-message-BwxV4d6N.js → event-projector-assistant-message-C5-Ds8mA.js} +18 -1
- package/dist/{event-projector-usage-CLwNEJqW.js → event-projector-usage-B2r5vhWH.js} +9 -14
- package/dist/{harness-DoKQcF8n.js → harness-BgeB7LnD.js} +42 -52
- package/dist/harness.js +1 -1
- package/dist/index.js +308 -306
- package/dist/{isolated-completion-DPMtlH9r.js → isolated-completion-CxTus3vZ.js} +4 -4
- package/dist/launch-args-sXOAg0SX.js +84 -0
- package/dist/{managed-binary-By4FZC6i.js → managed-binary-ZkGodW19.js} +43 -7
- package/dist/media-understanding-provider.js +1 -1
- package/dist/model-catalog-DULBcniB.js +101 -0
- package/dist/{models-CZw1wClT.js → models-DaWfETQk.js} +27 -29
- package/dist/{native-subagent-monitor-GGq3RnOo.js → native-subagent-monitor-vXYUZH37.js} +226 -129
- package/dist/{node-exec-server.runtime-Bsu1LdFZ.js → node-exec-server.runtime-DirKVZ5h.js} +9 -6
- package/dist/{plugin-approval-roundtrip-C75Yiiwc.js → plugin-approval-roundtrip-CCWQGlAI.js} +2 -1
- package/dist/{plugin-marketplace-discovery-CSWDkMrP.js → plugin-marketplace-discovery-BXjIFEiw.js} +38 -46
- package/dist/{plugin-metadata-cache-BXH5NF-4.js → plugin-metadata-cache-DQQm4gWT.js} +163 -136
- package/dist/{protocol-validators-VAVyEnDp.js → protocol-validators-Bg5rpNxk.js} +148 -5
- package/dist/{rate-limits-BI1dMHDG.js → rate-limits-BqHEHXQJ.js} +3 -2
- package/dist/{sandbox-guard-C1qEeZ5C.js → request-BWxweEdK.js} +183 -2
- package/dist/{run-attempt-BV3HzuCf.js → run-attempt-BVLE4Gbi.js} +706 -517
- package/dist/{runtime-artifact-BvyT1uyd.js → runtime-artifact-D9pYp4zL.js} +3 -3
- package/dist/{session-binding-BTrLf9Qm.js → session-binding-D0zinCP1.js} +195 -122
- package/dist/{session-catalog-ezP_UcRM.js → session-catalog-eMhVm0Ql.js} +448 -313
- package/dist/session-catalog-home-id-Dt2GiG5o.js +112 -0
- package/dist/{session-cli-B1hKvfkI.js → session-cli-B2lyjJA0.js} +1 -1
- package/dist/session-history-C5J1AKzG.js +87 -0
- package/dist/session-permission-policy-ScnAyG90.js +160 -0
- package/dist/session-retirement-CtUtUTr9.js +90 -0
- package/dist/{session-upstream-marker-D_2npHlA.js → session-upstream-marker-gqrYIRHk.js} +2 -3
- package/dist/settled-turn-context-Bk3IUwod.js +290 -0
- package/dist/settled-turn-finalizer-BXLN9PfJ.js +104 -0
- package/dist/{shared-client-Dw-rzii0.js → shared-client-B1tT5U6r.js} +1738 -806
- package/dist/{side-question-DbXkJZzg.js → side-question-CZ-mCw-t.js} +76 -43
- package/dist/{thread-lifecycle-DKdrnTMX.js → thread-lifecycle-CGGKP720.js} +991 -455
- package/dist/{thread-ownership-i2NBwDUL.js → thread-ownership-RkaoZCmQ.js} +18 -8
- package/dist/{plugin-app-cache-key-DMNQ8Zi8.js → thread-resume-BFt1-ZDa.js} +55 -8
- package/dist/{transcript-mirror-BU0_LKAL.js → transcript-mirror-1ep4XjzF.js} +124 -18
- package/dist/transport-stdio-NT_Dpd9V.js +724 -0
- package/dist/{upstream-prompt-provenance-CFmsKwr9.js → upstream-prompt-provenance-LphB8slG.js} +8 -4
- package/dist/{upstream-session-fork-BDVJCLAD.js → upstream-session-fork-Dc8BFExw.js} +76 -90
- package/dist/{usage-9dKJCgcy.js → usage-DUhd58gI.js} +3 -3
- package/dist/{web-search-provider.runtime-DCdx4DGu.js → web-search-provider.runtime-BEmlE7ov.js} +3 -3
- package/openclaw.plugin.json +19 -1
- package/package.json +8 -8
- package/dist/app-server-policy-bg5QPSVP.js +0 -25
- package/dist/command-rpc-xUIIonsO.js +0 -90
- package/dist/incognito-session-ET_ufDH-.js +0 -2
- package/dist/model-catalog-CmGoqVKB.js +0 -48
- package/dist/request-DSK0W6YI.js +0 -157
- package/dist/session-catalog-home-id-BNwAJ9D7.js +0 -18
- package/dist/session-retirement-CE4iMiLh.js +0 -36
- package/dist/settled-turn-finalizer-Dx1onIqg.js +0 -328
- package/dist/thread-resume-CdJk2Ehf.js +0 -30
- package/dist/transport-stdio-DhoGy33Z.js +0 -99
package/dist/index.js
CHANGED
|
@@ -1,30 +1,27 @@
|
|
|
1
1
|
import { registerCodexCliMetadata } from "./cli-metadata.js";
|
|
2
|
-
import { n as createCodexAppServerNativeCompaction, t as createCodexAppServerAgentHarness } from "./harness-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
2
|
+
import { n as createCodexAppServerNativeCompaction, t as createCodexAppServerAgentHarness } from "./harness-BgeB7LnD.js";
|
|
3
|
+
import { D as resolveOpenClawExecPolicyForCodexAppServer, T as readCodexPluginConfig, c as assertCodexAppServerConnectionSecurity, i as resolveCodexAppServerRuntimeOptions, j as CODEX_PLUGINS_MARKETPLACE_NAME, n as codexSandboxPolicyForTurn, p as canUseCodexModelBackedApprovalsReviewerForModel, s as resolveCodexSupervisionAppServerRuntimeOptions, t as codexAppServerStartOptionsKey, v as readCodexRequirementsToml } from "./config-CcYL77O6.js";
|
|
4
|
+
import { C as withLeasedCodexAppServerClientStartSelectionRetry, Ft as resolveCodexAppServerFallbackApiKeyCacheKey, Ht as isJsonObject, J as isCodexAppServerOverloadError, K as isCodexAppServerIndeterminateRequestCancellationError, Nt as resolveCodexAppServerAuthProfileIdForAgent, St as releaseCodexAppServerLiveThread, Z as isUnsupportedCodexAppServerVersionError, _ as retainSharedCodexAppServerClientByInstanceId, b as retireSharedCodexAppServerClientsBeforeDesktopGeneration, bt as isCodexAppServerLiveThreadClaimed, c as getLeasedSharedCodexAppServerClient, gt as consumeCodexAppServerLiveThread, h as releaseLeasedSharedCodexAppServerClient, jt as resolveCodexAppServerAuthAccountCacheKey, k as createCodexDesktopGenerationService, m as releaseCodexAppServerClientLease, o as clearSharedCodexAppServerClientIfCurrentAndWait, vt as hasCodexAppServerLiveThread, yt as isCodexAppServerClientRuntimeLive, zt as CODEX_INTERACTIVE_THREAD_SOURCE_KINDS } from "./shared-client-B1tT5U6r.js";
|
|
5
|
+
import { i as setManagedCodexPluginRoot } from "./managed-binary-ZkGodW19.js";
|
|
5
6
|
import { n as CODEX_APP_SERVER_BINDING_NAMESPACE, t as CODEX_APP_SERVER_BINDING_MAX_ENTRIES } from "./session-binding-meta-B7aEMU7g.js";
|
|
6
|
-
import { d as sessionBindingIdentity, n as assertCodexBindingMayBeReplaced, o as isCodexAppServerNativeAuthProfile, s as normalizeCodexAppServerBindingModelProvider } from "./session-binding-
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
7
|
+
import { d as sessionBindingIdentity, n as assertCodexBindingMayBeReplaced, o as isCodexAppServerNativeAuthProfile, s as normalizeCodexAppServerBindingModelProvider } from "./session-binding-D0zinCP1.js";
|
|
8
|
+
import { o as createCodexAppServerProcessReaperService } from "./transport-stdio-NT_Dpd9V.js";
|
|
9
|
+
import { r as assertCodexThreadAcceptsDirectInput, s as assertCodexThreadStartResponse, t as CodexThreadDirectInputError } from "./protocol-validators-Bg5rpNxk.js";
|
|
10
|
+
import { a as closeCodexStartupClientBestEffort, c as isCodexAppServerUnsafeSubscriptionError, f as unsubscribeCodexThreadBestEffort, g as isCodexNotificationForTurn, m as getCodexAppServerTurnRouter, o as interruptCodexTurnAndWaitBestEffort, u as retireUnsafeCodexTurnClientBestEffort } from "./attempt-client-cleanup-CpVfwctT.js";
|
|
11
|
+
import { s as isAssistantCommentaryCompletionNotification } from "./event-projector-usage-B2r5vhWH.js";
|
|
12
|
+
import { i as buildCodexPluginAppCacheKey, s as defaultCodexAppInventoryCache, t as resumeCodexAppServerThread } from "./thread-resume-BFt1-ZDa.js";
|
|
13
|
+
import { C as buildCodexProjectDocThreadConfig, E as resolveCodexAppServerRequestModelSelection, M as CODEX_MANAGED_THREAD_NAMESPACE, N as createCodexManagedThreadStore, ct as ensureCodexPluginActivation, ft as pluginReadParams, it as buildDisabledAppsConfigPatch, j as CODEX_MANAGED_THREAD_MAX_ENTRIES, ot as mergeCodexThreadConfigs, ut as isOpenAiCuratedMarketplace, w as CODEX_NATIVE_PERSONALITY_NONE } from "./thread-lifecycle-CGGKP720.js";
|
|
14
|
+
import { a as rollbackCodexAppServerBindingSubscription, c as withExclusiveCodexAppServerThread, i as retireCodexConversationThreadBinding, l as isIncognitoSessionKey, n as releaseCodexAppServerBindingSubscription, r as retainCodexAppServerBindingSubscription, s as withCodexConversationThreadActivity, t as isSameCodexAppServerThreadOwner } from "./thread-ownership-RkaoZCmQ.js";
|
|
15
|
+
import { c as resolveCodexNativeSandboxBlock, i as requestCodexAppServerJson, o as withCodexAppServerJsonClient, s as resolveCodexNativeExecutionBlock } from "./request-BWxweEdK.js";
|
|
16
|
+
import { p as projectBoundedCodexVisibleSessionHistory } from "./transcript-mirror-1ep4XjzF.js";
|
|
16
17
|
import { buildCodexMediaUnderstandingProvider } from "./media-understanding-provider.js";
|
|
17
|
-
import { n as describeControlFailure, t as CODEX_CONTROL_METHODS } from "./capabilities-
|
|
18
|
-
import { r as formatCodexDisplayText } from "./command-formatters
|
|
19
|
-
import {
|
|
20
|
-
import {
|
|
21
|
-
import { a as
|
|
22
|
-
import {
|
|
23
|
-
import {
|
|
24
|
-
import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-DAvZwp96.js";
|
|
25
|
-
import { c as createCodexCliSessionNodeInvokePolicies, d as resolveCodexCliSessionForBindingOnNode, f as resumeCodexCliSessionOnNode, i as createCodexSessionCatalogNodeHostCommands, n as createCodexSessionCatalogNodeInvokePolicies, o as assertCodexArchiveDescendantsUnowned, r as createCodexSessionCatalogControl, s as createCodexCliSessionNodeHostCommands, t as codexSessionCatalogRuntime, u as listCodexCliSessionsOnNode } from "./session-catalog-ezP_UcRM.js";
|
|
26
|
-
import { i as withCodexAppServerJsonClient, r as requestCodexAppServerJson } from "./request-DSK0W6YI.js";
|
|
27
|
-
import { t as codexControlRequest } from "./command-rpc-xUIIonsO.js";
|
|
18
|
+
import { n as describeControlFailure, t as CODEX_CONTROL_METHODS } from "./capabilities-D6m_TdVy.js";
|
|
19
|
+
import { r as formatCodexDisplayText } from "./command-formatters--UToCokS.js";
|
|
20
|
+
import { a as resolveCodexAppServerForModelProvider, i as resolveCodexSessionPermissionCwd, n as applyCodexSessionPermissionPolicy, t as CODEX_SESSION_PERMISSION_EXEC_MODES } from "./session-permission-policy-ScnAyG90.js";
|
|
21
|
+
import { f as trackCodexConversationActiveTurn, g as canMutateCodexHost, h as CODEX_NATIVE_EXECUTION_AUTH_ERROR, t as discoverCodexMarketplacePlugins } from "./plugin-marketplace-discovery-BXjIFEiw.js";
|
|
22
|
+
import { a as readCodexConversationBindingDataRecord, i as readCodexConversationBindingData, o as resolveCodexDefaultWorkspaceDir, r as createCodexConversationBindingData } from "./conversation-binding-data-BiodpIzq.js";
|
|
23
|
+
import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-CF7BmrDk.js";
|
|
24
|
+
import { d as createCodexCliSessionNodeHostCommands, f as createCodexCliSessionNodeInvokePolicies, g as resumeCodexCliSessionOnNode, h as resolveCodexCliSessionForBindingOnNode, i as createCodexSessionCatalogNodeHostCommands, m as listCodexCliSessionsOnNode, n as createCodexSessionCatalogNodeInvokePolicies, o as assertCodexArchiveDescendantsUnowned, r as createCodexSessionCatalogControl, s as codexControlRequest, t as codexSessionCatalogRuntime } from "./session-catalog-eMhVm0Ql.js";
|
|
28
25
|
import { t as createCodexWebSearchProviderBase } from "./web-search-provider.shared-BrZmlqyR.js";
|
|
29
26
|
import { mutateConfigFile } from "openclaw/plugin-sdk/config-mutation";
|
|
30
27
|
import { normalizePluginsConfig, resolveEffectiveEnableState, resolveLivePluginConfigObject, resolvePluginConfigObject } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
@@ -37,18 +34,17 @@ import { embeddedAgentLog, formatErrorMessage, resolveActiveEmbeddedRunSessionId
|
|
|
37
34
|
import os from "node:os";
|
|
38
35
|
import { loadAuthProfileStoreWithoutExternalProfiles, resolveAgentConfig, resolveAgentWorkspaceDir, resolveDefaultAgentDir, resolveDefaultAgentId } from "openclaw/plugin-sdk/agent-runtime";
|
|
39
36
|
import { applyAuthProfileConfig, buildApiKeyCredential, buildOauthProviderAuthResult, buildOpenAICodexCredentialExtra, readCodexCliCredentialsCached, resolveOpenAICodexAuthIdentity, resolveOpenAICodexImportProfileName, updateAuthProfileStoreWithLock } from "openclaw/plugin-sdk/provider-auth";
|
|
40
|
-
import { resolveSessionAgentIds as resolveSessionAgentIds$2, tryResolveDefaultAgentId } from "openclaw/plugin-sdk/agent-scope-runtime";
|
|
41
|
-
import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
|
|
42
37
|
import { extractErrorCode, pathExists } from "openclaw/plugin-sdk/security-runtime";
|
|
38
|
+
import { resolveSessionAgentIdsStrict } from "openclaw/plugin-sdk/agent-scope-runtime";
|
|
39
|
+
import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
|
|
43
40
|
import { getSessionEntry, resolveStorePath, resolveTranscriptSessionKeyBySessionId } from "openclaw/plugin-sdk/session-store-runtime";
|
|
44
41
|
import { coerceErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
45
42
|
import { fileURLToPath } from "node:url";
|
|
46
43
|
import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
|
|
47
|
-
import { normalizeAgentId } from "openclaw/plugin-sdk/routing";
|
|
48
44
|
import { canonicalPathFromExistingAncestor, isPathInside } from "openclaw/plugin-sdk/file-access-runtime";
|
|
45
|
+
import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
|
|
49
46
|
import { readVisibleSessionTranscriptMessageEntries } from "openclaw/plugin-sdk/session-transcript-runtime";
|
|
50
47
|
import { getSessionBindingService } from "openclaw/plugin-sdk/conversation-binding-runtime";
|
|
51
|
-
import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
|
|
52
48
|
import { ModelSelectionLockedError, isModelSelectionLocked } from "openclaw/plugin-sdk/model-session-runtime";
|
|
53
49
|
import { MIGRATION_REASON_TARGET_EXISTS, applyMigrationManualItem, createMigrationItem, createMigrationManualItem, hasMigrationConfigPatchConflict, markMigrationItemConflict, markMigrationItemError, markMigrationItemSkipped, mergeMigrationConfigValue, readMigrationConfigPath, resolveMigrationConfigRuntime, summarizeMigrationItems, writeMigrationConfigPath } from "openclaw/plugin-sdk/migration";
|
|
54
50
|
import { archiveMigrationItem, copyMemoryMigrationFileItem, copyMigrationFileItem, withCachedMigrationConfigRuntime, writeMigrationReport } from "openclaw/plugin-sdk/migration-runtime";
|
|
@@ -185,17 +181,18 @@ function waitForReconnect(delayMs, signal) {
|
|
|
185
181
|
/** Defers schema compilation and auth loading until the first binding operation. */
|
|
186
182
|
function createLazyCodexAppServerBindingStore(state, managedThreadState) {
|
|
187
183
|
let resolved;
|
|
188
|
-
const store = () => resolved ??= import("./session-binding-
|
|
184
|
+
const store = () => resolved ??= import("./session-binding-D0zinCP1.js").then((n) => n.f).then(({ createCodexAppServerBindingStore }) => createCodexAppServerBindingStore(state));
|
|
189
185
|
const managedThreads = managedThreadState ? createCodexManagedThreadStore(managedThreadState) : void 0;
|
|
190
186
|
return {
|
|
191
187
|
...managedThreads ? { managedThreads } : {},
|
|
192
188
|
read: async (identity) => (await store()).read(identity),
|
|
193
189
|
hasOtherThreadOwner: async (threadId, currentIdentity) => (await store()).hasOtherThreadOwner(threadId, currentIdentity),
|
|
194
|
-
mutate: async (identity, mutation) => (await store()).mutate(identity, mutation),
|
|
190
|
+
mutate: async (identity, mutation, assertCurrent) => (await store()).mutate(identity, mutation, assertCurrent),
|
|
195
191
|
prepareSessionGenerationReclaim: async (identity) => (await store()).prepareSessionGenerationReclaim(identity),
|
|
196
192
|
adoptSessionGeneration: async (identity, previousSessionId) => (await store()).adoptSessionGeneration(identity, previousSessionId),
|
|
197
193
|
resetSessionGeneration: async (identity) => (await store()).resetSessionGeneration(identity),
|
|
198
194
|
retireSessionGeneration: async (identity) => (await store()).retireSessionGeneration(identity),
|
|
195
|
+
withSessionDeletion: async (identity, assertCurrent, run) => (await store()).withSessionDeletion(identity, assertCurrent, run),
|
|
199
196
|
withThreadArchiveFence: async (run) => (await store()).withThreadArchiveFence(run),
|
|
200
197
|
withLease: async (identity, run) => (await store()).withLease(identity, run)
|
|
201
198
|
};
|
|
@@ -215,7 +212,7 @@ async function handleCodexCommand(ctx, options) {
|
|
|
215
212
|
}
|
|
216
213
|
}
|
|
217
214
|
async function loadDefaultCodexSubcommandHandler() {
|
|
218
|
-
const { handleCodexSubcommand } = await import("./command-handlers-
|
|
215
|
+
const { handleCodexSubcommand } = await import("./command-handlers-CLFx2Ypa.js");
|
|
219
216
|
return handleCodexSubcommand;
|
|
220
217
|
}
|
|
221
218
|
//#endregion
|
|
@@ -397,7 +394,7 @@ function isImageMedia(media) {
|
|
|
397
394
|
return IMAGE_EXTENSIONS.has(path.extname(candidate.split(/[?#]/, 1)[0] ?? "").toLowerCase());
|
|
398
395
|
}
|
|
399
396
|
function normalizeFileUrl(value) {
|
|
400
|
-
if (
|
|
397
|
+
if (!/^file:\/\//iu.test(value)) return value;
|
|
401
398
|
try {
|
|
402
399
|
return fileURLToPath(value);
|
|
403
400
|
} catch {
|
|
@@ -406,36 +403,83 @@ function normalizeFileUrl(value) {
|
|
|
406
403
|
}
|
|
407
404
|
function readLocalMediaPath(value) {
|
|
408
405
|
if (!value) return;
|
|
409
|
-
if (
|
|
406
|
+
if (/^file:\/\//iu.test(value)) return value;
|
|
410
407
|
if (value.startsWith("//")) return;
|
|
411
408
|
if (path.isAbsolute(value) || path.win32.isAbsolute(value)) return value;
|
|
412
409
|
return /^[a-z][a-z0-9+.-]*:/i.test(value) ? void 0 : value;
|
|
413
410
|
}
|
|
414
411
|
//#endregion
|
|
415
412
|
//#region extensions/codex/src/conversation-binding.ts
|
|
416
|
-
const DEFAULT_BOUND_TURN_TIMEOUT_MS =
|
|
413
|
+
const DEFAULT_BOUND_TURN_TIMEOUT_MS = 12e5;
|
|
417
414
|
const NATIVE_CONVERSATION_INTERACTIVE_APPROVALS_UNAVAILABLE = "OpenClaw native Codex conversation binding cannot route interactive approvals yet; use the Codex harness or explicit /acp spawn codex for that workflow.";
|
|
418
415
|
async function resolveConversationAppServerRuntime(params) {
|
|
419
|
-
const
|
|
416
|
+
const source = params.source;
|
|
417
|
+
const agentId = source?.agentId ?? params.agentId ?? (params.config ? resolveSessionAgentIdsStrict({
|
|
418
|
+
sessionKey: params.sessionKey,
|
|
419
|
+
config: params.config
|
|
420
|
+
}).sessionAgentId : void 0);
|
|
421
|
+
const storePath = agentId && (source || params.sessionKey) ? resolveStorePath(params.config?.session?.store, { agentId }) : void 0;
|
|
422
|
+
const sessionKey = source ? source.sessionKey ?? (storePath ? resolveTranscriptSessionKeyBySessionId({
|
|
423
|
+
agentId: source.agentId,
|
|
424
|
+
sessionId: source.sessionId,
|
|
425
|
+
storePath
|
|
426
|
+
}) : void 0) : params.sessionKey;
|
|
427
|
+
const storedEntry = sessionKey && storePath ? getSessionEntry({
|
|
428
|
+
agentId,
|
|
429
|
+
storePath,
|
|
430
|
+
sessionKey,
|
|
431
|
+
readConsistency: "latest"
|
|
432
|
+
}) : void 0;
|
|
433
|
+
const entry = !source || storedEntry?.sessionId === source.sessionId ? storedEntry : void 0;
|
|
434
|
+
if (source && !entry) throw new Error("Codex conversation source session is missing or no longer current; rebind this conversation before retrying.");
|
|
435
|
+
const permissionMode = entry?.permissionMode;
|
|
436
|
+
const sessionRoot = permissionMode ? entry?.sessionRoot : void 0;
|
|
437
|
+
const agentWorkspaceDir = params.config && agentId ? resolveAgentWorkspaceDir(params.config, agentId) : resolveCodexDefaultWorkspaceDir(params.pluginConfig);
|
|
438
|
+
const execPolicy = resolveOpenClawExecPolicyForCodexAppServer({
|
|
420
439
|
config: params.config,
|
|
421
|
-
agentId
|
|
422
|
-
|
|
440
|
+
agentId,
|
|
441
|
+
permissionMode,
|
|
442
|
+
execOverrides: permissionMode ? { mode: CODEX_SESSION_PERMISSION_EXEC_MODES[permissionMode] } : void 0,
|
|
443
|
+
approvals: permissionMode === "full" ? void 0 : loadExecApprovals()
|
|
423
444
|
});
|
|
424
445
|
const sandboxForPolicy = execPolicy.touched && execPolicy.security === "full" && execPolicy.ask !== "off" ? await resolveSandboxContext({
|
|
425
446
|
config: params.config,
|
|
426
|
-
sessionKey
|
|
427
|
-
workspaceDir:
|
|
447
|
+
sessionKey,
|
|
448
|
+
workspaceDir: agentWorkspaceDir
|
|
428
449
|
}) : void 0;
|
|
429
|
-
|
|
450
|
+
const configuredRuntime = resolveCodexAppServerRuntimeOptions({
|
|
451
|
+
pluginConfig: params.pluginConfig,
|
|
430
452
|
execPolicy,
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
453
|
+
modelProvider: params.modelProvider,
|
|
454
|
+
model: params.model,
|
|
455
|
+
config: params.config,
|
|
456
|
+
agentDir: params.agentDir,
|
|
457
|
+
openClawSandboxActive: Boolean(sandboxForPolicy?.enabled)
|
|
458
|
+
});
|
|
459
|
+
const canUseAutoReview = canUseCodexModelBackedApprovalsReviewerForModel({
|
|
460
|
+
modelProvider: params.modelProvider,
|
|
461
|
+
model: params.model,
|
|
462
|
+
config: params.config,
|
|
463
|
+
env: process.env,
|
|
464
|
+
agentDir: params.agentDir
|
|
465
|
+
});
|
|
466
|
+
return {
|
|
467
|
+
runtime: applyCodexSessionPermissionPolicy({
|
|
468
|
+
appServer: configuredRuntime,
|
|
469
|
+
permissionMode,
|
|
470
|
+
sessionRoot,
|
|
471
|
+
defaultRoot: agentWorkspaceDir,
|
|
472
|
+
pluginConfig: readCodexPluginConfig(params.pluginConfig),
|
|
473
|
+
canUseAutoReview,
|
|
474
|
+
requirementsToml: readCodexRequirementsToml({}),
|
|
475
|
+
execMode: execPolicy.mode
|
|
476
|
+
}),
|
|
477
|
+
workspaceDir: resolveCodexSessionPermissionCwd({
|
|
478
|
+
permissionMode,
|
|
479
|
+
sessionRoot,
|
|
480
|
+
defaultRoot: agentWorkspaceDir,
|
|
481
|
+
requestedCwd: params.workspaceDir,
|
|
482
|
+
fallbackCwd: params.workspaceDir
|
|
439
483
|
})
|
|
440
484
|
};
|
|
441
485
|
}
|
|
@@ -465,42 +509,27 @@ async function startCodexConversationThread(params) {
|
|
|
465
509
|
authProfileId: params.authProfileId ?? existingBinding?.authProfileId,
|
|
466
510
|
...agentLookup
|
|
467
511
|
});
|
|
468
|
-
const
|
|
469
|
-
if (params.threadId?.trim()) await attachExistingThread({
|
|
512
|
+
const bindingParams = {
|
|
470
513
|
pluginConfig: params.pluginConfig,
|
|
471
514
|
bindingStore: params.bindingStore,
|
|
472
515
|
identity,
|
|
473
|
-
threadId: params.threadId.trim(),
|
|
474
516
|
workspaceDir,
|
|
475
517
|
...agentDir ? { agentDir } : {},
|
|
476
518
|
model: params.model,
|
|
477
519
|
modelProvider: params.modelProvider,
|
|
478
520
|
authProfileId,
|
|
479
|
-
approvalPolicy: params.approvalPolicy,
|
|
480
|
-
sandbox: params.sandbox,
|
|
481
521
|
serviceTier: params.serviceTier,
|
|
482
522
|
config: params.config,
|
|
483
523
|
sessionKey: params.sessionKey,
|
|
484
|
-
incognito,
|
|
485
|
-
agentId: params.agentId
|
|
486
|
-
});
|
|
487
|
-
else await createThread({
|
|
488
|
-
pluginConfig: params.pluginConfig,
|
|
489
|
-
bindingStore: params.bindingStore,
|
|
490
|
-
identity,
|
|
491
|
-
workspaceDir,
|
|
492
|
-
...agentDir ? { agentDir } : {},
|
|
493
|
-
model: params.model,
|
|
494
|
-
modelProvider: params.modelProvider,
|
|
495
|
-
authProfileId,
|
|
496
|
-
approvalPolicy: params.approvalPolicy,
|
|
497
|
-
sandbox: params.sandbox,
|
|
498
|
-
serviceTier: params.serviceTier,
|
|
499
|
-
config: params.config,
|
|
500
|
-
sessionKey: params.sessionKey,
|
|
501
|
-
incognito,
|
|
524
|
+
incognito: isIncognitoSessionKey(params.sessionKey),
|
|
502
525
|
agentId: params.agentId
|
|
526
|
+
};
|
|
527
|
+
const threadId = params.threadId?.trim();
|
|
528
|
+
if (threadId) await attachExistingThread({
|
|
529
|
+
...bindingParams,
|
|
530
|
+
threadId
|
|
503
531
|
});
|
|
532
|
+
else await bindThread(bindingParams);
|
|
504
533
|
const storedBinding = await params.bindingStore.read(identity);
|
|
505
534
|
if (!storedBinding) throw new Error("Codex session binding disappeared while starting its conversation thread.");
|
|
506
535
|
return createCodexConversationBindingData({
|
|
@@ -639,11 +668,12 @@ async function resolveThreadBindingRuntime(params) {
|
|
|
639
668
|
modelProvider: params.modelProvider,
|
|
640
669
|
...agentLookup
|
|
641
670
|
});
|
|
642
|
-
const {
|
|
671
|
+
const { runtime, workspaceDir } = await resolveConversationAppServerRuntime({
|
|
643
672
|
pluginConfig: params.pluginConfig,
|
|
644
673
|
config: params.config,
|
|
645
674
|
agentId: params.agentId,
|
|
646
675
|
sessionKey: params.sessionKey,
|
|
676
|
+
source: params.source,
|
|
647
677
|
workspaceDir: params.workspaceDir,
|
|
648
678
|
modelProvider: reviewerModelProvider,
|
|
649
679
|
model: params.model,
|
|
@@ -657,43 +687,32 @@ async function resolveThreadBindingRuntime(params) {
|
|
|
657
687
|
env: process.env,
|
|
658
688
|
agentDir: params.agentDir
|
|
659
689
|
});
|
|
660
|
-
assertNativeConversationApprovalPolicySupported(
|
|
661
|
-
execPolicy,
|
|
662
|
-
approvalPolicy: execPolicy?.touched ? modelScopedRuntime.approvalPolicy : params.approvalPolicy ?? modelScopedRuntime.approvalPolicy,
|
|
663
|
-
approvalsReviewer: modelScopedRuntime.approvalsReviewer,
|
|
664
|
-
modelBackedApprovalsReviewerUnavailable: !canUseCodexModelBackedApprovalsReviewerForModel({
|
|
665
|
-
modelProvider: reviewerModelProvider,
|
|
666
|
-
model: params.model,
|
|
667
|
-
config: params.config,
|
|
668
|
-
env: process.env,
|
|
669
|
-
agentDir: params.agentDir
|
|
670
|
-
})
|
|
671
|
-
});
|
|
690
|
+
assertNativeConversationApprovalPolicySupported(modelScopedRuntime);
|
|
672
691
|
const clientOptions = {
|
|
673
692
|
startOptions: runtime.start,
|
|
674
693
|
timeoutMs: runtime.requestTimeoutMs,
|
|
675
694
|
authProfileId: params.authProfileId,
|
|
676
695
|
...agentLookup
|
|
677
696
|
};
|
|
678
|
-
const client = await getLeasedSharedCodexAppServerClient(clientOptions);
|
|
679
697
|
return {
|
|
680
|
-
execPolicy,
|
|
681
698
|
runtime: modelScopedRuntime,
|
|
699
|
+
workspaceDir,
|
|
682
700
|
agentLookup,
|
|
683
701
|
model: modelSelection?.model,
|
|
684
702
|
modelProvider: modelSelection?.modelProvider ?? modelProvider,
|
|
685
|
-
client,
|
|
686
|
-
clientLease: { client },
|
|
687
703
|
clientOptions
|
|
688
704
|
};
|
|
689
705
|
}
|
|
690
|
-
function
|
|
691
|
-
const serviceTier = params.serviceTier ?? resolved.runtime.serviceTier;
|
|
692
|
-
const sandbox = resolved.execPolicy?.touched ? resolved.runtime.sandbox : params.sandbox ?? resolved.runtime.sandbox;
|
|
706
|
+
function buildConversationThreadRequest(resolved, serviceTier) {
|
|
693
707
|
return {
|
|
694
|
-
|
|
708
|
+
cwd: resolved.workspaceDir,
|
|
709
|
+
...resolved.model ? { model: resolved.model } : {},
|
|
710
|
+
...resolved.modelProvider ? { modelProvider: resolved.modelProvider } : {},
|
|
711
|
+
personality: CODEX_NATIVE_PERSONALITY_NONE,
|
|
712
|
+
approvalPolicy: resolved.runtime.approvalPolicy,
|
|
695
713
|
approvalsReviewer: resolved.runtime.approvalsReviewer,
|
|
696
|
-
...
|
|
714
|
+
...resolved.runtime.sessionRoot ? { runtimeWorkspaceRoots: [resolved.runtime.sessionRoot] } : {},
|
|
715
|
+
...codexConversationSandboxOrPermissions(resolved.runtime, resolved.runtime.sandbox),
|
|
697
716
|
...serviceTier ? { serviceTier } : {}
|
|
698
717
|
};
|
|
699
718
|
}
|
|
@@ -706,47 +725,34 @@ function codexConversationSandboxOrPermissions(runtime, sandbox) {
|
|
|
706
725
|
config
|
|
707
726
|
};
|
|
708
727
|
}
|
|
709
|
-
async function
|
|
710
|
-
return await withLeasedCodexAppServerClientStartSelectionRetry({
|
|
711
|
-
lease: resolved.clientLease,
|
|
712
|
-
options: resolved.clientOptions,
|
|
713
|
-
run: async (client, requestOptions) => await client.request("thread/start", {
|
|
714
|
-
cwd: params.workspaceDir,
|
|
715
|
-
...resolved.model ? { model: resolved.model } : {},
|
|
716
|
-
...resolved.modelProvider ? { modelProvider: resolved.modelProvider } : {},
|
|
717
|
-
personality: CODEX_NATIVE_PERSONALITY_NONE,
|
|
718
|
-
...buildThreadRequestRuntimeOptions(params, resolved),
|
|
719
|
-
developerInstructions: CODEX_CONVERSATION_THREAD_DEVELOPER_INSTRUCTIONS,
|
|
720
|
-
experimentalRawEvents: true,
|
|
721
|
-
...params.incognito ? { ephemeral: true } : {}
|
|
722
|
-
}, requestOptions),
|
|
723
|
-
onClientChange: (client) => {
|
|
724
|
-
resolved.client = client;
|
|
725
|
-
}
|
|
726
|
-
});
|
|
727
|
-
}
|
|
728
|
-
async function writeThreadBindingFromResponse(params, resolved, response) {
|
|
729
|
-
const current = await params.bindingStore.read(params.identity);
|
|
730
|
-
assertCodexBindingMayBeReplaced(current, "storing a conversation-bound Codex thread");
|
|
731
|
-
const runtimeApprovalPolicy = typeof resolved.runtime.approvalPolicy === "string" ? resolved.runtime.approvalPolicy : void 0;
|
|
732
|
-
const trackSubscription = !params.incognito && isCodexAppServerClientRuntimeLive(resolved.client);
|
|
733
|
-
const sameOwner = isSameCodexAppServerThreadOwner(current, {
|
|
734
|
-
threadId: response.thread.id,
|
|
735
|
-
clientId: resolved.client.getInstanceId()
|
|
736
|
-
});
|
|
728
|
+
async function writeThreadBindingFromResponse(params, resolved, client, response, requestOptions) {
|
|
737
729
|
let retained = false;
|
|
730
|
+
let sameOwner = false;
|
|
738
731
|
try {
|
|
732
|
+
const current = await params.bindingStore.read(params.identity);
|
|
733
|
+
assertCodexBindingMayBeReplaced(current, "storing a conversation-bound Codex thread");
|
|
734
|
+
const trackSubscription = !params.incognito && isCodexAppServerClientRuntimeLive(client);
|
|
735
|
+
sameOwner = isSameCodexAppServerThreadOwner(current, {
|
|
736
|
+
threadId: response.thread.id,
|
|
737
|
+
clientId: client.getInstanceId()
|
|
738
|
+
});
|
|
739
|
+
requestOptions();
|
|
740
|
+
assertCodexThreadAcceptsDirectInput(response.thread);
|
|
739
741
|
if (trackSubscription) {
|
|
740
|
-
retained = await retainCodexAppServerBindingSubscription(
|
|
742
|
+
retained = await retainCodexAppServerBindingSubscription(client, response.thread.id);
|
|
741
743
|
if (!retained) throw new Error("Codex conversation thread lost its native subscription owner.");
|
|
742
744
|
}
|
|
743
|
-
if (current && !sameOwner)
|
|
745
|
+
if (current && !sameOwner) {
|
|
746
|
+
const { assertCurrent } = requestOptions();
|
|
747
|
+
await releaseCodexAppServerBindingSubscription(current, { assertCurrent });
|
|
748
|
+
}
|
|
749
|
+
requestOptions();
|
|
744
750
|
if (!await params.bindingStore.mutate(params.identity, {
|
|
745
751
|
kind: "set",
|
|
746
752
|
binding: {
|
|
747
753
|
threadId: response.thread.id,
|
|
748
|
-
clientId:
|
|
749
|
-
cwd:
|
|
754
|
+
clientId: client.getInstanceId(),
|
|
755
|
+
cwd: resolved.workspaceDir,
|
|
750
756
|
authProfileId: params.authProfileId,
|
|
751
757
|
model: response.model ?? resolved.model ?? params.model,
|
|
752
758
|
modelProvider: normalizeCodexAppServerBindingModelProvider({
|
|
@@ -754,15 +760,13 @@ async function writeThreadBindingFromResponse(params, resolved, response) {
|
|
|
754
760
|
modelProvider: response.modelProvider ?? resolved.modelProvider ?? params.modelProvider,
|
|
755
761
|
...resolved.agentLookup
|
|
756
762
|
}),
|
|
757
|
-
approvalPolicy: resolved.execPolicy?.touched ? runtimeApprovalPolicy : params.approvalPolicy ?? runtimeApprovalPolicy,
|
|
758
|
-
sandbox: resolved.execPolicy?.touched ? resolved.runtime.sandbox : params.sandbox ?? resolved.runtime.sandbox,
|
|
759
763
|
serviceTier: params.serviceTier ?? resolved.runtime.serviceTier ?? void 0,
|
|
760
764
|
networkProxyProfileName: resolved.runtime.networkProxy?.profileName,
|
|
761
765
|
networkProxyConfigFingerprint: resolved.runtime.networkProxy?.configFingerprint
|
|
762
766
|
}
|
|
763
|
-
})) throw new Error("Codex conversation binding changed while storing its thread.");
|
|
767
|
+
}, requestOptions)) throw new Error("Codex conversation binding changed while storing its thread.");
|
|
764
768
|
} catch (error) {
|
|
765
|
-
if (
|
|
769
|
+
if (retained && !sameOwner || !hasCodexAppServerLiveThread(client, response.thread.id)) await rollbackCodexAppServerBindingSubscription(client, response.thread.id, retained);
|
|
766
770
|
throw error;
|
|
767
771
|
}
|
|
768
772
|
}
|
|
@@ -771,44 +775,51 @@ async function attachExistingThread(params) {
|
|
|
771
775
|
bindingStore: params.bindingStore,
|
|
772
776
|
identity: params.identity,
|
|
773
777
|
threadId: params.threadId,
|
|
774
|
-
run:
|
|
775
|
-
assertCodexBindingMayBeReplaced(await params.bindingStore.read(params.identity), "attaching a conversation-bound Codex thread");
|
|
776
|
-
const resolved = await resolveThreadBindingRuntime(params);
|
|
777
|
-
try {
|
|
778
|
-
const response = resolved.runtime.networkProxy ? await requestNewConversationBindingThread(params, resolved) : await withLeasedCodexAppServerClientStartSelectionRetry({
|
|
779
|
-
lease: resolved.clientLease,
|
|
780
|
-
options: resolved.clientOptions,
|
|
781
|
-
run: async (client, requestOptions) => {
|
|
782
|
-
if (isCodexAppServerLiveThreadClaimed(client, params.threadId)) throw new Error(`Codex thread ${params.threadId} has an active run; stop it before binding its conversation.`);
|
|
783
|
-
await releaseCodexAppServerLiveThread(client, params.threadId);
|
|
784
|
-
if (isCodexAppServerLiveThreadClaimed(client, params.threadId)) throw new Error(`Codex thread ${params.threadId} has an active run; stop it before binding its conversation.`);
|
|
785
|
-
return await client.request(CODEX_CONTROL_METHODS.resumeThread, {
|
|
786
|
-
threadId: params.threadId,
|
|
787
|
-
...resolved.model ? { model: resolved.model } : {},
|
|
788
|
-
...resolved.modelProvider ? { modelProvider: resolved.modelProvider } : {},
|
|
789
|
-
personality: CODEX_NATIVE_PERSONALITY_NONE,
|
|
790
|
-
...buildThreadRequestRuntimeOptions(params, resolved)
|
|
791
|
-
}, requestOptions);
|
|
792
|
-
},
|
|
793
|
-
onClientChange: (client) => {
|
|
794
|
-
resolved.client = client;
|
|
795
|
-
}
|
|
796
|
-
});
|
|
797
|
-
if (!resolved.runtime.networkProxy && response.thread.id !== params.threadId) throw new Error(`Codex conversation resume returned ${response.thread.id} for ${params.threadId}.`);
|
|
798
|
-
await writeThreadBindingFromResponse(params, resolved, response);
|
|
799
|
-
} finally {
|
|
800
|
-
releaseCodexAppServerClientLease(resolved.clientLease);
|
|
801
|
-
}
|
|
802
|
-
}
|
|
778
|
+
run: () => bindThread(params, params.threadId)
|
|
803
779
|
});
|
|
804
780
|
}
|
|
805
|
-
async function
|
|
806
|
-
|
|
781
|
+
async function bindThread(params, threadId) {
|
|
782
|
+
const current = await params.bindingStore.read(params.identity);
|
|
783
|
+
assertCodexBindingMayBeReplaced(current, "binding a conversation-bound Codex thread");
|
|
807
784
|
const resolved = await resolveThreadBindingRuntime(params);
|
|
785
|
+
const clientLease = { client: await getLeasedSharedCodexAppServerClient(resolved.clientOptions) };
|
|
808
786
|
try {
|
|
809
|
-
await
|
|
787
|
+
await withLeasedCodexAppServerClientStartSelectionRetry({
|
|
788
|
+
lease: clientLease,
|
|
789
|
+
options: resolved.clientOptions,
|
|
790
|
+
run: async (client, requestOptions) => {
|
|
791
|
+
const request = buildConversationThreadRequest(resolved, params.serviceTier ?? resolved.runtime.serviceTier);
|
|
792
|
+
let response;
|
|
793
|
+
if (threadId && !resolved.runtime.networkProxy) {
|
|
794
|
+
if (isCodexAppServerLiveThreadClaimed(client, threadId)) throw new Error(`Codex thread ${threadId} has an active run; stop it before binding its conversation.`);
|
|
795
|
+
const { thread } = await client.request("thread/read", {
|
|
796
|
+
threadId,
|
|
797
|
+
includeTurns: false
|
|
798
|
+
}, requestOptions());
|
|
799
|
+
assertCodexThreadAcceptsDirectInput(thread);
|
|
800
|
+
const { assertCurrent } = requestOptions();
|
|
801
|
+
await releaseCodexAppServerLiveThread(client, threadId, assertCurrent);
|
|
802
|
+
if (isCodexAppServerLiveThreadClaimed(client, threadId)) throw new Error(`Codex thread ${threadId} has an active run; stop it before binding its conversation.`);
|
|
803
|
+
response = await resumeCodexAppServerThread({
|
|
804
|
+
client,
|
|
805
|
+
abandonClient: () => closeCodexStartupClientBestEffort(client),
|
|
806
|
+
request: {
|
|
807
|
+
...request,
|
|
808
|
+
threadId
|
|
809
|
+
},
|
|
810
|
+
requestResume: (resumeRequest) => client.request("thread/resume", resumeRequest, requestOptions())
|
|
811
|
+
});
|
|
812
|
+
} else response = await client.request("thread/start", {
|
|
813
|
+
...request,
|
|
814
|
+
developerInstructions: CODEX_CONVERSATION_THREAD_DEVELOPER_INSTRUCTIONS,
|
|
815
|
+
experimentalRawEvents: true,
|
|
816
|
+
...params.incognito ? { ephemeral: true } : {}
|
|
817
|
+
}, requestOptions());
|
|
818
|
+
await writeThreadBindingFromResponse(params, resolved, client, response, requestOptions);
|
|
819
|
+
}
|
|
820
|
+
});
|
|
810
821
|
} finally {
|
|
811
|
-
releaseCodexAppServerClientLease(
|
|
822
|
+
releaseCodexAppServerClientLease(clientLease);
|
|
812
823
|
}
|
|
813
824
|
}
|
|
814
825
|
async function runBoundTurn(params) {
|
|
@@ -821,18 +832,19 @@ async function runBoundTurn(params) {
|
|
|
821
832
|
if (!binding?.threadId) throw new Error("bound Codex conversation has no thread binding");
|
|
822
833
|
assertCodexBindingMayBeReplaced(binding, "running a conversation-bound Codex thread");
|
|
823
834
|
let threadId = binding.threadId;
|
|
824
|
-
const
|
|
835
|
+
const requestedWorkspaceDir = binding.cwd || params.data.workspaceDir;
|
|
825
836
|
const reviewerModelProvider = resolveModelBackedReviewerPolicyProvider({
|
|
826
837
|
authProfileId: binding.authProfileId,
|
|
827
838
|
modelProvider: binding.modelProvider,
|
|
828
839
|
...agentLookup
|
|
829
840
|
});
|
|
830
|
-
const {
|
|
841
|
+
const { runtime, workspaceDir } = await resolveConversationAppServerRuntime({
|
|
831
842
|
pluginConfig: params.pluginConfig,
|
|
832
843
|
config: params.config,
|
|
833
|
-
agentId: params.data.agentId,
|
|
834
|
-
sessionKey: params.sessionKey,
|
|
835
|
-
|
|
844
|
+
agentId: params.data.source?.agentId ?? params.data.agentId,
|
|
845
|
+
sessionKey: params.data.legacyBinding ? params.sessionKey : params.data.source?.sessionKey,
|
|
846
|
+
source: params.data.source,
|
|
847
|
+
workspaceDir: requestedWorkspaceDir,
|
|
836
848
|
modelProvider: reviewerModelProvider,
|
|
837
849
|
model: binding.model,
|
|
838
850
|
agentDir: params.data.agentDir
|
|
@@ -845,33 +857,26 @@ async function runBoundTurn(params) {
|
|
|
845
857
|
env: process.env,
|
|
846
858
|
agentDir: params.data.agentDir
|
|
847
859
|
});
|
|
848
|
-
const
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
config: params.config,
|
|
852
|
-
env: process.env,
|
|
853
|
-
agentDir: params.data.agentDir
|
|
854
|
-
});
|
|
855
|
-
const useModelScopedPolicy = execPolicy?.touched === true || modelBackedApprovalsReviewerUnavailable;
|
|
856
|
-
const approvalPolicy = useModelScopedPolicy ? modelScopedRuntime.approvalPolicy : binding.approvalPolicy ?? modelScopedRuntime.approvalPolicy;
|
|
857
|
-
const sandbox = useModelScopedPolicy ? modelScopedRuntime.sandbox : binding.sandbox ?? modelScopedRuntime.sandbox;
|
|
860
|
+
const sessionRoot = modelScopedRuntime.sessionRoot;
|
|
861
|
+
const approvalPolicy = modelScopedRuntime.approvalPolicy;
|
|
862
|
+
const sandbox = modelScopedRuntime.sandbox;
|
|
858
863
|
const permissionProfile = modelScopedRuntime.networkProxy?.profileName;
|
|
859
864
|
const networkProxyConfigFingerprint = modelScopedRuntime.networkProxy?.configFingerprint;
|
|
860
865
|
const networkProxyBindingChanged = binding.networkProxyProfileName !== permissionProfile || binding.networkProxyConfigFingerprint !== networkProxyConfigFingerprint;
|
|
861
866
|
const serviceTier = binding.serviceTier ?? runtime.serviceTier;
|
|
862
867
|
let useStickyNetworkProfile = permissionProfile !== void 0 && binding.networkProxyProfileName === permissionProfile && binding.networkProxyConfigFingerprint === networkProxyConfigFingerprint;
|
|
863
|
-
assertNativeConversationApprovalPolicySupported(
|
|
864
|
-
execPolicy,
|
|
865
|
-
approvalPolicy,
|
|
866
|
-
approvalsReviewer: modelScopedRuntime.approvalsReviewer,
|
|
867
|
-
modelBackedApprovalsReviewerUnavailable
|
|
868
|
-
});
|
|
868
|
+
assertNativeConversationApprovalPolicySupported(modelScopedRuntime);
|
|
869
869
|
const modelSelection = binding.model ? resolveCodexAppServerRequestModelSelection({
|
|
870
870
|
model: binding.model,
|
|
871
871
|
modelProvider: binding.modelProvider,
|
|
872
872
|
authProfileId: binding.authProfileId,
|
|
873
873
|
...agentLookup
|
|
874
874
|
}) : void 0;
|
|
875
|
+
const threadRequestRuntime = {
|
|
876
|
+
runtime: modelScopedRuntime,
|
|
877
|
+
workspaceDir,
|
|
878
|
+
...modelSelection
|
|
879
|
+
};
|
|
875
880
|
const clientOptions = {
|
|
876
881
|
startOptions: runtime.start,
|
|
877
882
|
timeoutMs: runtime.requestTimeoutMs,
|
|
@@ -882,12 +887,20 @@ async function runBoundTurn(params) {
|
|
|
882
887
|
const clientLease = { client };
|
|
883
888
|
let activeTurnId;
|
|
884
889
|
let activeTurnCleanup = () => void 0;
|
|
885
|
-
let
|
|
890
|
+
let isolatedSubscriptionClient;
|
|
886
891
|
let turnRoute;
|
|
887
892
|
let liveThreadOwnership;
|
|
888
893
|
let ownsNativeSubscription = false;
|
|
889
894
|
let turnSucceeded = false;
|
|
895
|
+
const assertResumeInputAllowed = async () => {
|
|
896
|
+
const { thread } = await client.request("thread/read", {
|
|
897
|
+
threadId,
|
|
898
|
+
includeTurns: false
|
|
899
|
+
}, { timeoutMs: runtime.requestTimeoutMs });
|
|
900
|
+
assertCodexThreadAcceptsDirectInput(thread);
|
|
901
|
+
};
|
|
890
902
|
try {
|
|
903
|
+
if (!networkProxyBindingChanged && binding.clientId !== client.getInstanceId()) await assertResumeInputAllowed();
|
|
891
904
|
if (!params.incognito && isCodexAppServerClientRuntimeLive(client)) {
|
|
892
905
|
const ownership = await consumeCodexAppServerLiveThread(client, threadId);
|
|
893
906
|
if (ownership) {
|
|
@@ -904,24 +917,18 @@ async function runBoundTurn(params) {
|
|
|
904
917
|
lease: clientLease,
|
|
905
918
|
options: clientOptions,
|
|
906
919
|
run: async (requestClient, requestOptions) => await requestClient.request("thread/start", {
|
|
907
|
-
|
|
908
|
-
...modelSelection?.model ? { model: modelSelection.model } : {},
|
|
909
|
-
...modelSelection?.modelProvider ? { modelProvider: modelSelection.modelProvider } : {},
|
|
910
|
-
personality: CODEX_NATIVE_PERSONALITY_NONE,
|
|
911
|
-
approvalPolicy,
|
|
912
|
-
approvalsReviewer: modelScopedRuntime.approvalsReviewer,
|
|
913
|
-
...codexConversationSandboxOrPermissions(modelScopedRuntime, sandbox),
|
|
914
|
-
...serviceTier ? { serviceTier } : {},
|
|
920
|
+
...buildConversationThreadRequest(threadRequestRuntime, serviceTier),
|
|
915
921
|
developerInstructions: CODEX_CONVERSATION_THREAD_DEVELOPER_INSTRUCTIONS,
|
|
916
922
|
experimentalRawEvents: true,
|
|
917
923
|
...params.incognito ? { ephemeral: true } : {}
|
|
918
|
-
}, requestOptions),
|
|
924
|
+
}, requestOptions()),
|
|
919
925
|
onClientChange: (nextClient) => {
|
|
920
926
|
client = nextClient;
|
|
921
927
|
}
|
|
922
928
|
}));
|
|
923
929
|
threadId = response.thread.id;
|
|
924
930
|
ownsNativeSubscription = true;
|
|
931
|
+
assertCodexThreadAcceptsDirectInput(response.thread);
|
|
925
932
|
if (liveThreadOwnership && (liveThreadOwnership.threadId !== threadId || liveThreadOwnership.client !== client)) {
|
|
926
933
|
const previousOwnership = liveThreadOwnership;
|
|
927
934
|
try {
|
|
@@ -946,8 +953,6 @@ async function runBoundTurn(params) {
|
|
|
946
953
|
modelProvider: response.modelProvider ?? modelSelection?.modelProvider ?? binding.modelProvider,
|
|
947
954
|
...agentLookup
|
|
948
955
|
}),
|
|
949
|
-
approvalPolicy: typeof approvalPolicy === "string" ? approvalPolicy : void 0,
|
|
950
|
-
sandbox,
|
|
951
956
|
serviceTier: serviceTier ?? void 0,
|
|
952
957
|
networkProxyProfileName: modelScopedRuntime.networkProxy?.profileName,
|
|
953
958
|
networkProxyConfigFingerprint: modelScopedRuntime.networkProxy?.configFingerprint,
|
|
@@ -958,26 +963,24 @@ async function runBoundTurn(params) {
|
|
|
958
963
|
})) throw new Error("Codex conversation binding changed while rotating its thread.");
|
|
959
964
|
useStickyNetworkProfile = modelScopedRuntime.networkProxy !== void 0;
|
|
960
965
|
} else if (binding.clientId !== client.getInstanceId() || isCodexAppServerClientRuntimeLive(client) && !params.incognito && !liveThreadOwnership) {
|
|
966
|
+
if (binding.clientId === client.getInstanceId()) await assertResumeInputAllowed();
|
|
961
967
|
const response = await withLeasedCodexAppServerClientStartSelectionRetry({
|
|
962
968
|
lease: clientLease,
|
|
963
969
|
options: clientOptions,
|
|
964
970
|
run: async (requestClient, requestOptions) => await resumeCodexAppServerThread({
|
|
965
971
|
client: requestClient,
|
|
972
|
+
onSubscriptionReleased: () => {
|
|
973
|
+
isolatedSubscriptionClient = requestClient;
|
|
974
|
+
},
|
|
966
975
|
abandonClient: async () => {
|
|
967
|
-
retiredUnsafeClient = requestClient;
|
|
968
976
|
await closeCodexStartupClientBestEffort(requestClient);
|
|
977
|
+
isolatedSubscriptionClient = requestClient;
|
|
969
978
|
},
|
|
970
979
|
request: {
|
|
971
980
|
threadId,
|
|
972
|
-
...
|
|
973
|
-
...modelSelection?.modelProvider ? { modelProvider: modelSelection.modelProvider } : {},
|
|
974
|
-
personality: CODEX_NATIVE_PERSONALITY_NONE,
|
|
975
|
-
approvalPolicy,
|
|
976
|
-
approvalsReviewer: modelScopedRuntime.approvalsReviewer,
|
|
977
|
-
...codexConversationSandboxOrPermissions(modelScopedRuntime, sandbox),
|
|
978
|
-
...serviceTier ? { serviceTier } : {}
|
|
981
|
+
...buildConversationThreadRequest(threadRequestRuntime, serviceTier)
|
|
979
982
|
},
|
|
980
|
-
|
|
983
|
+
requestResume: (request) => requestClient.request("thread/resume", request, requestOptions())
|
|
981
984
|
}),
|
|
982
985
|
onClientChange: (nextClient) => {
|
|
983
986
|
client = nextClient;
|
|
@@ -985,6 +988,7 @@ async function runBoundTurn(params) {
|
|
|
985
988
|
});
|
|
986
989
|
threadId = response.thread.id;
|
|
987
990
|
ownsNativeSubscription = true;
|
|
991
|
+
assertCodexThreadAcceptsDirectInput(response.thread);
|
|
988
992
|
if (!isSameCodexAppServerThreadOwner(binding, {
|
|
989
993
|
threadId,
|
|
990
994
|
clientId: client.getInstanceId()
|
|
@@ -1017,9 +1021,10 @@ async function runBoundTurn(params) {
|
|
|
1017
1021
|
event: params.event
|
|
1018
1022
|
}),
|
|
1019
1023
|
cwd: workspaceDir,
|
|
1024
|
+
...sessionRoot ? { runtimeWorkspaceRoots: [sessionRoot] } : {},
|
|
1020
1025
|
approvalPolicy,
|
|
1021
1026
|
approvalsReviewer: modelScopedRuntime.approvalsReviewer,
|
|
1022
|
-
...useStickyNetworkProfile ? {} : { sandboxPolicy: codexSandboxPolicyForTurn(sandbox, workspaceDir) },
|
|
1027
|
+
...useStickyNetworkProfile ? {} : { sandboxPolicy: codexSandboxPolicyForTurn(sandbox, sessionRoot ?? workspaceDir) },
|
|
1023
1028
|
...modelSelection?.model ? { model: modelSelection.model } : {},
|
|
1024
1029
|
personality: CODEX_NATIVE_PERSONALITY_NONE,
|
|
1025
1030
|
...serviceTier ? { serviceTier } : {}
|
|
@@ -1036,20 +1041,30 @@ async function runBoundTurn(params) {
|
|
|
1036
1041
|
turnSucceeded = true;
|
|
1037
1042
|
return { reply: { text: replyText || "Codex completed without a text reply." } };
|
|
1038
1043
|
} catch (error) {
|
|
1044
|
+
if (isCodexAppServerOverloadError(error) && error.method === "thread/resume") throw error;
|
|
1045
|
+
if (error instanceof CodexThreadDirectInputError) {
|
|
1046
|
+
if (params.incognito && ownsNativeSubscription) {
|
|
1047
|
+
if (!await unsubscribeCodexThreadBestEffort(client, {
|
|
1048
|
+
threadId,
|
|
1049
|
+
timeoutMs: 5e3
|
|
1050
|
+
})) await retireUnsafeCodexTurnClientBestEffort(client, "parent-owned thread unsubscribe");
|
|
1051
|
+
}
|
|
1052
|
+
throw error;
|
|
1053
|
+
}
|
|
1039
1054
|
if (error instanceof CodexConversationTurnTimeoutError && activeTurnId || turnRoute && isCodexAppServerIndeterminateRequestCancellationError(error)) {
|
|
1040
1055
|
if (!await interruptCodexTurnAndWaitBestEffort(client, {
|
|
1041
1056
|
threadId,
|
|
1042
1057
|
turnId: activeTurnId ?? ""
|
|
1043
1058
|
})) {
|
|
1044
|
-
retiredUnsafeClient = client;
|
|
1045
1059
|
await retireUnsafeCodexTurnClientBestEffort(client, "turn interrupt");
|
|
1060
|
+
isolatedSubscriptionClient = client;
|
|
1046
1061
|
}
|
|
1047
1062
|
}
|
|
1048
1063
|
if (params.incognito) {
|
|
1049
1064
|
if (await params.bindingStore.mutate(identity, {
|
|
1050
1065
|
kind: "clear",
|
|
1051
1066
|
threadId
|
|
1052
|
-
}) &&
|
|
1067
|
+
}) && isolatedSubscriptionClient !== client) {
|
|
1053
1068
|
if (!await unsubscribeCodexThreadBestEffort(client, {
|
|
1054
1069
|
threadId,
|
|
1055
1070
|
timeoutMs: 5e3
|
|
@@ -1061,7 +1076,7 @@ async function runBoundTurn(params) {
|
|
|
1061
1076
|
activeTurnCleanup();
|
|
1062
1077
|
turnRoute?.release();
|
|
1063
1078
|
try {
|
|
1064
|
-
if (ownsNativeSubscription &&
|
|
1079
|
+
if (ownsNativeSubscription && isolatedSubscriptionClient !== client && !params.incognito && isCodexAppServerClientRuntimeLive(client)) {
|
|
1065
1080
|
const currentLiveThreadOwnership = liveThreadOwnership?.client === client && liveThreadOwnership.threadId === threadId ? liveThreadOwnership.ownership : void 0;
|
|
1066
1081
|
let retained = false;
|
|
1067
1082
|
if (turnSucceeded) retained = await params.bindingStore.withLease(identity, async () => {
|
|
@@ -1087,8 +1102,8 @@ async function runBoundTurn(params) {
|
|
|
1087
1102
|
}
|
|
1088
1103
|
}
|
|
1089
1104
|
}
|
|
1090
|
-
function assertNativeConversationApprovalPolicySupported(
|
|
1091
|
-
if (
|
|
1105
|
+
function assertNativeConversationApprovalPolicySupported(runtime) {
|
|
1106
|
+
if (runtime.approvalPolicy !== "never" && runtime.approvalsReviewer === "user") throw new Error(NATIVE_CONVERSATION_INTERACTIVE_APPROVALS_UNAVAILABLE);
|
|
1092
1107
|
}
|
|
1093
1108
|
async function runBoundTurnWithMissingThreadRecovery(params) {
|
|
1094
1109
|
await prepareConversationBinding(params);
|
|
@@ -1116,11 +1131,6 @@ async function prepareConversationBinding(params, options = {}) {
|
|
|
1116
1131
|
assertCodexBindingMayBeReplaced(current, "initializing a conversation-bound Codex thread");
|
|
1117
1132
|
assertCodexBindingMayBeReplaced(sourceBinding, "transferring a session into a conversation-bound Codex thread");
|
|
1118
1133
|
const inherited = current ?? sourceBinding;
|
|
1119
|
-
const execPolicy = resolveConversationExecPolicy({
|
|
1120
|
-
config: params.config,
|
|
1121
|
-
agentId: params.data.agentId,
|
|
1122
|
-
sessionKey: params.sessionKey
|
|
1123
|
-
});
|
|
1124
1134
|
const agentLookup = buildAgentLookup({
|
|
1125
1135
|
agentDir: params.data.agentDir,
|
|
1126
1136
|
config: params.config
|
|
@@ -1134,20 +1144,19 @@ async function prepareConversationBinding(params, options = {}) {
|
|
|
1134
1144
|
model: requested?.model ?? inherited?.model,
|
|
1135
1145
|
modelProvider: requested?.modelProvider ?? inherited?.modelProvider,
|
|
1136
1146
|
authProfileId: requested?.authProfileId ?? inherited?.authProfileId,
|
|
1137
|
-
approvalPolicy: execPolicy.touched ? void 0 : inherited?.approvalPolicy,
|
|
1138
|
-
sandbox: execPolicy.touched ? void 0 : inherited?.sandbox,
|
|
1139
1147
|
serviceTier: inherited?.serviceTier,
|
|
1140
1148
|
config: params.config,
|
|
1141
|
-
sessionKey: params.sessionKey,
|
|
1149
|
+
sessionKey: params.data.legacyBinding ? params.sessionKey : params.data.source?.sessionKey,
|
|
1150
|
+
source: params.data.source,
|
|
1142
1151
|
incognito: params.incognito,
|
|
1143
|
-
agentId: params.data.agentId
|
|
1152
|
+
agentId: params.data.source?.agentId ?? params.data.agentId
|
|
1144
1153
|
};
|
|
1145
1154
|
const threadId = requested?.threadId;
|
|
1146
1155
|
if (threadId && !options.forceNew) await attachExistingThread({
|
|
1147
1156
|
...bindingParams,
|
|
1148
1157
|
threadId
|
|
1149
1158
|
});
|
|
1150
|
-
else await
|
|
1159
|
+
else await bindThread(bindingParams);
|
|
1151
1160
|
const stored = await params.bindingStore.read(identity);
|
|
1152
1161
|
if (!stored) throw new Error("Codex conversation binding disappeared while initializing its thread.");
|
|
1153
1162
|
if (sourceIdentity && params.data.source && !current?.conversationSourceTransferComplete) await params.bindingStore.withLease(sourceIdentity, async () => {
|
|
@@ -1187,12 +1196,13 @@ async function projectConversationSourceHistory(source, target, config) {
|
|
|
1187
1196
|
storePath
|
|
1188
1197
|
});
|
|
1189
1198
|
if (!sessionKey) return;
|
|
1190
|
-
const
|
|
1199
|
+
const entries = await readVisibleSessionTranscriptMessageEntries({
|
|
1191
1200
|
agentId: source.agentId,
|
|
1192
1201
|
sessionId: source.sessionId,
|
|
1193
1202
|
sessionKey,
|
|
1194
1203
|
storePath
|
|
1195
|
-
})
|
|
1204
|
+
});
|
|
1205
|
+
const history = projectBoundedCodexVisibleSessionHistory(entries);
|
|
1196
1206
|
if (history.length === 0) return;
|
|
1197
1207
|
const clientLease = retainSharedCodexAppServerClientByInstanceId(target.clientId);
|
|
1198
1208
|
if (!clientLease) throw new Error("Codex conversation source history lost its bound client owner.");
|
|
@@ -1205,66 +1215,8 @@ async function projectConversationSourceHistory(source, target, config) {
|
|
|
1205
1215
|
clientLease.release();
|
|
1206
1216
|
}
|
|
1207
1217
|
}
|
|
1208
|
-
function resolveConversationExecPolicy(params) {
|
|
1209
|
-
const agentId = params.agentId ?? (params.config ? resolveSessionAgentIds$2({
|
|
1210
|
-
sessionKey: params.sessionKey,
|
|
1211
|
-
config: params.config
|
|
1212
|
-
}).sessionAgentId : void 0);
|
|
1213
|
-
return resolveOpenClawExecPolicyForCodexAppServer({
|
|
1214
|
-
config: params.config,
|
|
1215
|
-
agentId,
|
|
1216
|
-
execOverrides: readSessionExecOverrides({
|
|
1217
|
-
config: params.config,
|
|
1218
|
-
agentId,
|
|
1219
|
-
sessionKey: params.sessionKey
|
|
1220
|
-
}),
|
|
1221
|
-
approvals: loadExecApprovals()
|
|
1222
|
-
});
|
|
1223
|
-
}
|
|
1224
|
-
function readSessionExecOverrides(params) {
|
|
1225
|
-
const sessionKey = params.sessionKey?.trim();
|
|
1226
|
-
if (!params.config || !sessionKey) return;
|
|
1227
|
-
if (!canReadSessionExecOverrides({
|
|
1228
|
-
config: params.config,
|
|
1229
|
-
agentId: params.agentId,
|
|
1230
|
-
sessionKey
|
|
1231
|
-
})) return;
|
|
1232
|
-
const entry = getSessionEntry({
|
|
1233
|
-
storePath: resolveStorePath(params.config.session?.store, { agentId: params.agentId }),
|
|
1234
|
-
sessionKey,
|
|
1235
|
-
readConsistency: "latest"
|
|
1236
|
-
});
|
|
1237
|
-
if (!entry?.execSecurity && !entry?.execAsk) return;
|
|
1238
|
-
return {
|
|
1239
|
-
security: entry.execSecurity,
|
|
1240
|
-
ask: entry.execAsk
|
|
1241
|
-
};
|
|
1242
|
-
}
|
|
1243
|
-
function canReadSessionExecOverrides(params) {
|
|
1244
|
-
const agentId = normalizeAgentIdOrDefault(params.agentId);
|
|
1245
|
-
if (!agentId) return true;
|
|
1246
|
-
const sessionAgentId = parseAgentIdFromSessionKey(params.sessionKey);
|
|
1247
|
-
if (!sessionAgentId) return isDefaultAgentSessionKeyForAgent({
|
|
1248
|
-
config: params.config,
|
|
1249
|
-
agentId
|
|
1250
|
-
});
|
|
1251
|
-
return sessionAgentId === agentId;
|
|
1252
|
-
}
|
|
1253
|
-
function parseAgentIdFromSessionKey(sessionKey) {
|
|
1254
|
-
const raw = sessionKey?.trim();
|
|
1255
|
-
if (!raw) return;
|
|
1256
|
-
const parts = raw.toLowerCase().split(":").filter(Boolean);
|
|
1257
|
-
if (parts.length < 3 || parts[0] !== "agent" || !parts[2]) return;
|
|
1258
|
-
return normalizeAgentIdOrDefault(parts[1]);
|
|
1259
|
-
}
|
|
1260
|
-
function isDefaultAgentSessionKeyForAgent(params) {
|
|
1261
|
-
return normalizeAgentId(params.agentId) === tryResolveDefaultAgentId(params.config);
|
|
1262
|
-
}
|
|
1263
|
-
function normalizeAgentIdOrDefault(value) {
|
|
1264
|
-
const normalized = normalizeAgentId(value);
|
|
1265
|
-
return normalized === "main" && !(value ?? "").trim() ? void 0 : normalized;
|
|
1266
|
-
}
|
|
1267
1218
|
function isCodexThreadNotFoundError(error) {
|
|
1219
|
+
if (isCodexAppServerOverloadError(error) || isCodexAppServerUnsafeSubscriptionError(error)) return false;
|
|
1268
1220
|
const message = formatErrorMessage(error);
|
|
1269
1221
|
return /\bthread not found:/iu.test(message) || /\bbound Codex conversation has no thread binding\b/u.test(message);
|
|
1270
1222
|
}
|
|
@@ -1435,7 +1387,8 @@ async function buildCodexOAuthCredential(source) {
|
|
|
1435
1387
|
} : null;
|
|
1436
1388
|
}
|
|
1437
1389
|
async function buildCodexApiKeyCredential(source) {
|
|
1438
|
-
const
|
|
1390
|
+
const raw = await readJsonObject(source.authPath);
|
|
1391
|
+
const key = normalizeOptionalString(raw.OPENAI_API_KEY);
|
|
1439
1392
|
if (!key) return null;
|
|
1440
1393
|
return {
|
|
1441
1394
|
kind: "api_key",
|
|
@@ -2743,7 +2696,8 @@ async function requestTargetCodexAppServerJson(params) {
|
|
|
2743
2696
|
});
|
|
2744
2697
|
if (hasOpenAiCuratedMarketplace(lastResponse)) return lastResponse;
|
|
2745
2698
|
if (Date.now() >= discoveryDeadline) return lastResponse;
|
|
2746
|
-
|
|
2699
|
+
const waitMs = Math.min(TARGET_CODEX_MARKETPLACE_DISCOVERY_POLL_MS, discoveryDeadline - Date.now());
|
|
2700
|
+
await sleep(waitMs);
|
|
2747
2701
|
} while (Date.now() < discoveryDeadline);
|
|
2748
2702
|
return lastResponse;
|
|
2749
2703
|
}
|
|
@@ -3298,7 +3252,8 @@ function createCodexNodeExecServerCommand() {
|
|
|
3298
3252
|
} catch {
|
|
3299
3253
|
throw new Error("Codex node exec-server requires a valid workspace request.");
|
|
3300
3254
|
}
|
|
3301
|
-
|
|
3255
|
+
if (!isRecord(request) || Object.keys(request).length !== 2 || request.authorization !== "human-approved" && request.authorization !== "session-full") throw new Error("Codex node exec-server requires an authorized managed placement workspace launch.");
|
|
3256
|
+
const placement = parseCodexNodePlacementWorkspace(request.placement);
|
|
3302
3257
|
if (!context?.acquireManagedWorkspace || context.sessionKey !== placement.sessionKey || io.signal.aborted) throw new Error("Codex node exec-server requires active managed placement authority.");
|
|
3303
3258
|
const workspace = context.acquireManagedWorkspace({
|
|
3304
3259
|
workspaceDir: placement.cwd,
|
|
@@ -3310,11 +3265,14 @@ function createCodexNodeExecServerCommand() {
|
|
|
3310
3265
|
const frames = io.frames;
|
|
3311
3266
|
let unsubscribe;
|
|
3312
3267
|
try {
|
|
3313
|
-
|
|
3268
|
+
if (!context.prepareExecAuthorization) throw new Error("Codex node execution requires node-local exec policy support; update the node.");
|
|
3269
|
+
const assertExecAuthorized = context.prepareExecAuthorization(request.authorization);
|
|
3270
|
+
const { runCodexNodeExecServer } = await import("./node-exec-server.runtime-DirKVZ5h.js");
|
|
3314
3271
|
return await runCodexNodeExecServer({
|
|
3315
3272
|
workspaceDir: workspace.workspaceDir,
|
|
3316
3273
|
io,
|
|
3317
3274
|
activeProcesses,
|
|
3275
|
+
assertExecAuthorized,
|
|
3318
3276
|
onFrameReceiver: (receiver) => {
|
|
3319
3277
|
unsubscribe = frames.onMessage(receiver);
|
|
3320
3278
|
}
|
|
@@ -3329,7 +3287,7 @@ function createCodexNodeExecServerCommand() {
|
|
|
3329
3287
|
}
|
|
3330
3288
|
};
|
|
3331
3289
|
}
|
|
3332
|
-
/** Keeps
|
|
3290
|
+
/** Keeps node launch behind command opt-in and a live Full owner or human decision. */
|
|
3333
3291
|
function createCodexNodeExecServerInvokePolicy() {
|
|
3334
3292
|
return {
|
|
3335
3293
|
commands: [CODEX_NODE_EXEC_SERVER_COMMAND],
|
|
@@ -3339,10 +3297,10 @@ function createCodexNodeExecServerInvokePolicy() {
|
|
|
3339
3297
|
family: CODEX_NODE_EXEC_SERVER_CAPABILITY
|
|
3340
3298
|
}),
|
|
3341
3299
|
handle: async (context) => {
|
|
3342
|
-
if (
|
|
3300
|
+
if (context.risk?.level !== "high") return {
|
|
3343
3301
|
ok: false,
|
|
3344
3302
|
code: "CODEX_NODE_EXEC_APPROVAL_REQUIRED",
|
|
3345
|
-
message: "Codex
|
|
3303
|
+
message: "Codex node execution requires an available approval reviewer."
|
|
3346
3304
|
};
|
|
3347
3305
|
let placement;
|
|
3348
3306
|
try {
|
|
@@ -3351,21 +3309,60 @@ function createCodexNodeExecServerInvokePolicy() {
|
|
|
3351
3309
|
return {
|
|
3352
3310
|
ok: false,
|
|
3353
3311
|
code: "CODEX_NODE_EXEC_WORKSPACE_INVALID",
|
|
3354
|
-
message: "Codex
|
|
3312
|
+
message: "Codex node execution requires an exact managed placement workspace."
|
|
3355
3313
|
};
|
|
3356
3314
|
}
|
|
3357
|
-
const
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
}
|
|
3315
|
+
const workspace = {
|
|
3316
|
+
workspaceDir: placement.cwd,
|
|
3317
|
+
environmentId: placement.environmentId,
|
|
3318
|
+
sessionId: placement.sessionId,
|
|
3319
|
+
ownerEpoch: placement.ownerEpoch,
|
|
3320
|
+
sessionKey: placement.sessionKey
|
|
3321
|
+
};
|
|
3322
|
+
const fullLaunch = await context.invokeNodeWithSessionFull?.({
|
|
3323
|
+
workspace,
|
|
3324
|
+
createParams: () => ({
|
|
3325
|
+
placement,
|
|
3326
|
+
authorization: "session-full"
|
|
3327
|
+
})
|
|
3328
|
+
});
|
|
3329
|
+
if (fullLaunch) return fullLaunch;
|
|
3330
|
+
if (!context.approvals) return {
|
|
3364
3331
|
ok: false,
|
|
3365
|
-
code: "
|
|
3366
|
-
message: "Codex
|
|
3332
|
+
code: "CODEX_NODE_EXEC_APPROVAL_REQUIRED",
|
|
3333
|
+
message: "Codex node execution requires an available approval reviewer."
|
|
3367
3334
|
};
|
|
3368
|
-
|
|
3335
|
+
const nodeName = context.node?.displayName ?? context.nodeId;
|
|
3336
|
+
const approval = await context.approvals.request({
|
|
3337
|
+
title: "Run Codex execution on node",
|
|
3338
|
+
description: `Allows arbitrary processes and filesystem access across the node account, not only this workspace. ${nodeName}: ${placement.cwd}`,
|
|
3339
|
+
severity: "critical",
|
|
3340
|
+
allowedDecisions: ["allow-once"]
|
|
3341
|
+
});
|
|
3342
|
+
if (approval.decision !== "allow-once") {
|
|
3343
|
+
if (approval.decision === "deny") return {
|
|
3344
|
+
ok: false,
|
|
3345
|
+
code: "CODEX_NODE_EXEC_APPROVAL_DENIED",
|
|
3346
|
+
message: "Codex node execution was denied. Retry the action and choose Allow once to continue."
|
|
3347
|
+
};
|
|
3348
|
+
if (approval.decision === "allow-always") return {
|
|
3349
|
+
ok: false,
|
|
3350
|
+
code: "CODEX_NODE_EXEC_APPROVAL_INVALID",
|
|
3351
|
+
message: "Codex node execution cannot use permanent approval. Retry the action and choose Allow once."
|
|
3352
|
+
};
|
|
3353
|
+
return {
|
|
3354
|
+
ok: false,
|
|
3355
|
+
code: "CODEX_NODE_EXEC_APPROVAL_EXPIRED",
|
|
3356
|
+
message: "Codex node execution approval expired before a decision. Retry the action and approve the new request."
|
|
3357
|
+
};
|
|
3358
|
+
}
|
|
3359
|
+
return await context.invokeNode({
|
|
3360
|
+
workspace,
|
|
3361
|
+
params: {
|
|
3362
|
+
placement,
|
|
3363
|
+
authorization: "human-approved"
|
|
3364
|
+
}
|
|
3365
|
+
});
|
|
3369
3366
|
}
|
|
3370
3367
|
};
|
|
3371
3368
|
}
|
|
@@ -4151,7 +4148,7 @@ function createCodexSupervisionTools(options) {
|
|
|
4151
4148
|
}
|
|
4152
4149
|
//#endregion
|
|
4153
4150
|
//#region extensions/codex/src/web-search-provider.ts
|
|
4154
|
-
const loadCodexWebSearchRuntime = createLazyRuntimeModule(() => import("./web-search-provider.runtime-
|
|
4151
|
+
const loadCodexWebSearchRuntime = createLazyRuntimeModule(() => import("./web-search-provider.runtime-BEmlE7ov.js"));
|
|
4155
4152
|
const CodexWebSearchSchema = {
|
|
4156
4153
|
type: "object",
|
|
4157
4154
|
properties: { query: {
|
|
@@ -4187,8 +4184,7 @@ const ENDED_SESSION_REASONS = /* @__PURE__ */ new Set([
|
|
|
4187
4184
|
"new",
|
|
4188
4185
|
"reset",
|
|
4189
4186
|
"idle",
|
|
4190
|
-
"daily"
|
|
4191
|
-
"deleted"
|
|
4187
|
+
"daily"
|
|
4192
4188
|
]);
|
|
4193
4189
|
var codex_default = definePluginEntry({
|
|
4194
4190
|
id: "codex",
|
|
@@ -4211,7 +4207,10 @@ var codex_default = definePluginEntry({
|
|
|
4211
4207
|
return livePluginConfig;
|
|
4212
4208
|
};
|
|
4213
4209
|
const resolveCurrentPluginConfig = () => resolvePluginConfig(resolveCurrentConfig);
|
|
4214
|
-
|
|
4210
|
+
const appServerConfig = readCodexPluginConfig(resolveCurrentPluginConfig()).appServer;
|
|
4211
|
+
api.registerService(createCodexDesktopGenerationService({ onGenerationChange: retireSharedCodexAppServerClientsBeforeDesktopGeneration }));
|
|
4212
|
+
api.registerService(createCodexAppServerProcessReaperService());
|
|
4213
|
+
if (appServerConfig?.transport === "websocket") api.registerService(createCodexAppServerConnectionHealthService({
|
|
4215
4214
|
getPluginConfig: resolveCurrentPluginConfig,
|
|
4216
4215
|
getRuntimeConfig: resolveCurrentConfig
|
|
4217
4216
|
}));
|
|
@@ -4223,9 +4222,10 @@ var codex_default = definePluginEntry({
|
|
|
4223
4222
|
overflowPolicy: "reject-new"
|
|
4224
4223
|
});
|
|
4225
4224
|
const lazyBindingStateStore = {
|
|
4226
|
-
|
|
4225
|
+
deleteIf: (key, predicate) => openBindingStateStore().deleteIf(key, predicate),
|
|
4227
4226
|
entries: () => openBindingStateStore().entries(),
|
|
4228
4227
|
lookup: (key) => openBindingStateStore().lookup(key),
|
|
4228
|
+
registerIfAbsent: (key, value, options) => openBindingStateStore().registerIfAbsent(key, value, options),
|
|
4229
4229
|
get update() {
|
|
4230
4230
|
const store = openBindingStateStore();
|
|
4231
4231
|
return store.update?.bind(store);
|
|
@@ -4238,10 +4238,12 @@ var codex_default = definePluginEntry({
|
|
|
4238
4238
|
});
|
|
4239
4239
|
const bindingStore = createLazyCodexAppServerBindingStore(lazyBindingStateStore, {
|
|
4240
4240
|
entries: () => openManagedThreadStateStore().entries(),
|
|
4241
|
+
lookup: (key) => openManagedThreadStateStore().lookup(key),
|
|
4241
4242
|
registerIfAbsent: (key, value) => openManagedThreadStateStore().registerIfAbsent(key, value)
|
|
4242
4243
|
});
|
|
4243
4244
|
registerCodexCliMetadata(api);
|
|
4244
4245
|
const sessionCatalogControlFactory = createCodexSessionCatalogControl({
|
|
4246
|
+
managedThreads: bindingStore.managedThreads,
|
|
4245
4247
|
config: api.config,
|
|
4246
4248
|
getPluginConfig: resolveCurrentPluginConfig,
|
|
4247
4249
|
getRuntimeConfig: resolveCurrentConfig
|
|
@@ -4381,7 +4383,7 @@ var codex_default = definePluginEntry({
|
|
|
4381
4383
|
if (!previousSessionId || !sessionId || previousSessionId === sessionId) return;
|
|
4382
4384
|
const config = resolveCurrentConfig();
|
|
4383
4385
|
const sessionKey = ctx.sessionKey?.trim();
|
|
4384
|
-
const { sessionBindingIdentity } = await import("./session-binding-
|
|
4386
|
+
const { sessionBindingIdentity } = await import("./session-binding-D0zinCP1.js").then((n) => n.f);
|
|
4385
4387
|
const identity = sessionBindingIdentity({
|
|
4386
4388
|
sessionId,
|
|
4387
4389
|
...sessionKey ? { sessionKey } : {},
|
|
@@ -4399,7 +4401,7 @@ var codex_default = definePluginEntry({
|
|
|
4399
4401
|
if (endedSessionKey && nextSessionKey && nextSessionKey !== endedSessionKey) return;
|
|
4400
4402
|
if (event.nextSessionId?.trim() === event.sessionId.trim()) return;
|
|
4401
4403
|
const config = resolveCurrentConfig();
|
|
4402
|
-
const [{ sessionBindingIdentity }, { retireCodexAppServerSessionGeneration }] = await Promise.all([import("./session-binding-
|
|
4404
|
+
const [{ sessionBindingIdentity }, { retireCodexAppServerSessionGeneration }] = await Promise.all([import("./session-binding-D0zinCP1.js").then((n) => n.f), import("./session-retirement-CtUtUTr9.js")]);
|
|
4403
4405
|
await retireCodexAppServerSessionGeneration({
|
|
4404
4406
|
bindingStore,
|
|
4405
4407
|
identity: sessionBindingIdentity({
|