@openclaw/codex 2026.9.1-beta.1 → 2026.9.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 +8 -9
- package/dist/{attempt-client-cleanup-bfsmcQ6m.js → attempt-client-cleanup-Bp1ZOnk2.js} +105 -75
- package/dist/attempt-context-CSazkWns.js +634 -0
- package/dist/{auth-binding-B4FfbcCg.js → auth-binding-Ds_QVm-X.js} +18 -3
- package/dist/{bounded-turn-B7iBUcuP.js → bounded-turn-DxGJRYbY.js} +53 -57
- package/dist/{capabilities-BRMh0aIq.js → capabilities-B1mgvpP8.js} +2 -1
- package/dist/cli-metadata.js +1 -1
- package/dist/{command-formatters-DEsIufkt.js → command-formatters-DSbGMXA0.js} +5 -4
- package/dist/{command-handlers-D_-1_qRp.js → command-handlers-DOJvGv6-.js} +243 -148
- package/dist/{compact-BglNFZrQ.js → compact-Y_xBqrHN.js} +109 -65
- package/dist/{config-giW8X0QA.js → config-CyapYSji.js} +328 -374
- package/dist/config-utils-C57JiJrU.js +69 -0
- package/dist/{context-compaction-activity-BOeJf7yo.js → context-compaction-activity-CMla5FPJ.js} +4 -1
- package/dist/{conversation-binding-data-CW2GuupV.js → conversation-binding-data-BiodpIzq.js} +2 -1
- package/dist/doctor-contract-api.js +144 -14
- package/dist/{dynamic-tools-Dnlfa--w.js → dynamic-tools-BwpvTxaX.js} +1119 -1135
- package/dist/{effective-mcp-catalog-CTeGrnfO.js → effective-mcp-catalog-CY9Jn4bA.js} +4 -3
- package/dist/{event-projector-assistant-message-C5-Ds8mA.js → event-projector-assistant-message-B9kp6iGC.js} +15 -6
- package/dist/event-projector-usage-ZqEVbAEY.js +212 -0
- package/dist/{harness-Csz0F-DK.js → harness-Czh2Sdoc.js} +65 -52
- package/dist/harness.js +1 -1
- package/dist/{image-payload-sanitizer-CnfoUPCE.js → image-payload-sanitizer-tupAr-2o.js} +29 -15
- package/dist/index.js +495 -457
- package/dist/{isolated-completion-Cv6FqygM.js → isolated-completion-CRh-51AK.js} +9 -21
- package/dist/{managed-binary-DFYK4DWq.js → managed-binary-DcpnJF9x.js} +117 -80
- package/dist/media-understanding-provider.js +1 -1
- package/dist/model-catalog-DT5vo6qo.js +101 -0
- package/dist/{models-TS3HBU-q.js → models-CcrgSMQR.js} +26 -29
- package/dist/{native-subagent-monitor-4Mfq2HDs.js → native-subagent-monitor-B3bvQGcg.js} +63 -122
- package/dist/{node-exec-server.runtime-BpWqJO1V.js → node-exec-server.runtime-nfbUOtUB.js} +10 -7
- package/dist/{plugin-approval-roundtrip-bUm777tR.js → plugin-approval-roundtrip-aQVdyL5g.js} +30 -3
- package/dist/{plugin-marketplace-discovery-B9DvaAG-.js → plugin-marketplace-discovery-B7gHXJ3d.js} +44 -30
- package/dist/{plugin-metadata-cache-CTCT3w5L.js → plugin-metadata-cache-BwCLTY_U.js} +6 -6
- package/dist/provider-capabilities-BpG9Ltc5.js +101 -0
- package/dist/{rate-limits-C5_D8Gmb.js → rate-limits-Fx_l4eNa.js} +3 -2
- package/dist/{sandbox-guard-kuWTn9C5.js → request-C8H22rPi.js} +195 -2
- package/dist/{run-attempt-DYc0QCBF.js → run-attempt-BzthFQSM.js} +1616 -2634
- package/dist/{runtime-artifact-BvyT1uyd.js → runtime-artifact-Bh_gf6-t.js} +22 -15
- package/dist/{session-binding-Bcynfd-_.js → session-binding-4Ki04sW-.js} +282 -399
- package/dist/session-binding-record-CyaXZvTe.js +270 -0
- package/dist/{session-catalog-DaLKVtpH.js → session-catalog-B47uwekb.js} +812 -504
- package/dist/{session-cli-DMc4oS2w.js → session-cli-BjLhpmS1.js} +1 -1
- package/dist/session-history-DWmMqiqW.js +93 -0
- package/dist/session-history-read-LHldwvyh.js +36 -0
- package/dist/session-history-worker-runtime.js +48 -0
- package/dist/session-history.worker-zZVcx0ME.js +267 -0
- package/dist/session-history.worker.js +2 -0
- package/dist/session-initialization-BCFVnLL4.js +75 -0
- package/dist/{session-permission-policy-BrNH1bjy.js → session-permission-policy-BaueHmSj.js} +2 -2
- package/dist/session-retirement-DNdmYdFc.js +97 -0
- package/dist/{session-upstream-marker-BIkusb95.js → session-upstream-marker-DReTpGz6.js} +20 -4
- package/dist/settled-turn-context-BOM3Y1pl.js +45 -0
- package/dist/settled-turn-finalizer-BI-b1sry.js +115 -0
- package/dist/{shared-client-DKz23hHY.js → shared-client-CKhX2kFt.js} +3659 -847
- package/dist/{side-question-DjA_jsNe.js → side-question-B6DWAw1A.js} +168 -81
- package/dist/{thread-lifecycle-L7oEkTlq.js → thread-lifecycle-DPK30jad.js} +2412 -2145
- package/dist/{thread-ownership-DZeuKH1j.js → thread-ownership-CbucAmmp.js} +27 -16
- package/dist/thread-policy-CTalhWFy.js +105 -0
- package/dist/{plugin-app-cache-key-C1CAdfcP.js → thread-resume-BLgqkUc1.js} +61 -9
- package/dist/{transcript-mirror-DsCMWBca.js → transcript-mirror-_njEB84z.js} +114 -110
- package/dist/transcript-mirror-attestation-Byl34PC-.js +76 -0
- package/dist/transport-stdio-CzTngV0j.js +728 -0
- package/dist/{upstream-prompt-provenance-CFmsKwr9.js → upstream-prompt-provenance-LphB8slG.js} +8 -4
- package/dist/upstream-session-fork-1fwbNKzQ.js +886 -0
- package/dist/{usage-ROIaW3wo.js → usage-i9fv5-4m.js} +3 -3
- package/dist/{web-search-provider.runtime-ClaNPV7N.js → web-search-provider.runtime-DKQn67A7.js} +3 -3
- package/openclaw.plugin.json +1 -30
- package/package.json +6 -6
- package/dist/binding-connection-BMvPX73o.js +0 -45
- package/dist/command-rpc-CCeCkf_v.js +0 -90
- package/dist/event-projector-usage-Bk1I90Bg.js +0 -328
- package/dist/incognito-session-ET_ufDH-.js +0 -2
- package/dist/model-catalog-i9rNBthX.js +0 -48
- package/dist/protocol-validators-VeJxxJ0U.js +0 -2421
- package/dist/request-DXXGHko0.js +0 -157
- package/dist/session-catalog-home-id-BNwAJ9D7.js +0 -18
- package/dist/session-retirement-CcNC3YSY.js +0 -36
- package/dist/settled-turn-finalizer-Dc3ApjU4.js +0 -328
- package/dist/thread-resume-BE9qNEW0.js +0 -30
- package/dist/transport-stdio-DhoGy33Z.js +0 -99
- package/dist/upstream-session-fork-DlaHxSLC.js +0 -326
package/dist/index.js
CHANGED
|
@@ -1,54 +1,52 @@
|
|
|
1
1
|
import { registerCodexCliMetadata } from "./cli-metadata.js";
|
|
2
|
-
import { n as createCodexAppServerNativeCompaction, t as createCodexAppServerAgentHarness } from "./harness-
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { i as
|
|
2
|
+
import { n as createCodexAppServerNativeCompaction, t as createCodexAppServerAgentHarness } from "./harness-Czh2Sdoc.js";
|
|
3
|
+
import { m as CODEX_PLUGINS_MARKETPLACE_NAME } from "./config-utils-C57JiJrU.js";
|
|
4
|
+
import { l as sessionBindingIdentity, s as readCurrentCodexAppServerBinding } from "./session-binding-record-CyaXZvTe.js";
|
|
5
|
+
import { A as resolveOpenClawExecPolicyForCodexAppServer, B as isJsonObject, L as CODEX_INTERACTIVE_THREAD_SOURCE_KINDS, O as readCodexPluginConfig, c as assertCodexAppServerConnectionSecurity, i as resolveCodexAppServerRuntimeOptions, m as canUseCodexModelBackedApprovalsReviewerForModel, n as codexSandboxPolicyForTurn, s as resolveCodexSupervisionAppServerRuntimeOptions, t as codexAppServerStartOptionsKey, y as readCodexRequirementsToml } from "./config-CyapYSji.js";
|
|
6
|
+
import { B as isCodexAppServerIndeterminateRequestCancellationError, Bt as resolveCodexAppServerAuthAccountCacheKey, C as withLeasedCodexAppServerClientStartSelectionRetry, Dt as isCodexAppServerClientRuntimeLive, Et as hasCodexAppServerLiveThread, G as isUnsupportedCodexAppServerVersionError, H as isCodexAppServerOverloadError, Ht as resolveCodexAppServerAuthProfileIdForAgent, O as createCodexDesktopGenerationService, Ot as isCodexAppServerLiveThreadClaimed, Q as assertCodexThreadAcceptsDirectInput, Wt as resolveCodexAppServerFallbackApiKeyCacheKey, Y as CodexThreadDirectInputError, _ as retainSharedCodexAppServerClientByInstanceId, b as retireSharedCodexAppServerClientsBeforeDesktopGeneration, c as getLeasedSharedCodexAppServerClient, h as releaseLeasedSharedCodexAppServerClient, jt as releaseCodexAppServerLiveThread, m as releaseCodexAppServerClientLease, nt as assertCodexThreadStartResponse, o as clearSharedCodexAppServerClientIfCurrentAndWait, wt as consumeCodexAppServerLiveThread } from "./shared-client-CKhX2kFt.js";
|
|
7
|
+
import { a as setManagedCodexPluginRoot } from "./managed-binary-DcpnJF9x.js";
|
|
6
8
|
import { n as CODEX_APP_SERVER_BINDING_NAMESPACE, t as CODEX_APP_SERVER_BINDING_MAX_ENTRIES } from "./session-binding-meta-B7aEMU7g.js";
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import { s as
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
9
|
+
import { a as isCodexAppServerNativeAuthProfile, n as assertCodexBindingMayBeReplaced, o as normalizeCodexAppServerBindingModelProvider } from "./session-binding-4Ki04sW-.js";
|
|
10
|
+
import { o as createCodexAppServerProcessReaperService } from "./transport-stdio-CzTngV0j.js";
|
|
11
|
+
import { a as closeCodexStartupClientBestEffort, d as unsubscribeCodexThreadBestEffort, h as isCodexNotificationForTurn, l as retireUnsafeCodexTurnClientBestEffort, o as interruptCodexTurnAndWaitBestEffort, p as getCodexAppServerTurnRouter, s as isCodexAppServerUnsafeSubscriptionError } from "./attempt-client-cleanup-Bp1ZOnk2.js";
|
|
12
|
+
import { i as isAssistantCommentaryCompletionNotification } from "./event-projector-usage-ZqEVbAEY.js";
|
|
13
|
+
import { c as defaultCodexAppInventoryCache, i as buildCodexPluginAppCacheKey, t as resumeCodexAppServerThread } from "./thread-resume-BLgqkUc1.js";
|
|
14
|
+
import { E as resolveCodexAppServerRequestModelSelection, Et as mergeCodexThreadConfigs, J as createCodexManagedThreadStore, K as CODEX_MANAGED_THREAD_MAX_ENTRIES, Nt as pluginReadParams, Tt as buildDisabledAppsConfigPatch, jt as isOpenAiCuratedMarketplace, k as buildCodexProjectDocThreadConfig, kt as ensureCodexPluginActivation, q as CODEX_MANAGED_THREAD_NAMESPACE, w as CODEX_NATIVE_PERSONALITY_NONE } from "./thread-lifecycle-DPK30jad.js";
|
|
15
|
+
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-CbucAmmp.js";
|
|
16
|
+
import { s as resolveCodexBindingAppServerConnection } from "./thread-policy-CTalhWFy.js";
|
|
17
|
+
import { c as projectBoundedCodexVisibleSessionHistory } from "./transcript-mirror-_njEB84z.js";
|
|
18
|
+
import { c as resolveCodexNativeSandboxBlock, i as requestCodexAppServerJson, o as withCodexAppServerJsonClient, s as resolveCodexNativeExecutionBlock } from "./request-C8H22rPi.js";
|
|
16
19
|
import { buildCodexMediaUnderstandingProvider } from "./media-understanding-provider.js";
|
|
17
|
-
import { n as describeControlFailure, t as CODEX_CONTROL_METHODS } from "./capabilities-
|
|
18
|
-
import {
|
|
19
|
-
import { a as resolveCodexAppServerForModelProvider, i as resolveCodexSessionPermissionCwd, n as applyCodexSessionPermissionPolicy, t as CODEX_SESSION_PERMISSION_EXEC_MODES } from "./session-permission-policy-
|
|
20
|
-
import {
|
|
21
|
-
import { a as
|
|
22
|
-
import { f as
|
|
23
|
-
import { a as readCodexConversationBindingDataRecord, i as readCodexConversationBindingData, o as resolveCodexDefaultWorkspaceDir, r as createCodexConversationBindingData } from "./conversation-binding-data-CW2GuupV.js";
|
|
24
|
-
import { n as resolveCodexBindingAppServerConnection } from "./binding-connection-BMvPX73o.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-DaLKVtpH.js";
|
|
26
|
-
import { i as withCodexAppServerJsonClient, r as requestCodexAppServerJson } from "./request-DXXGHko0.js";
|
|
27
|
-
import { t as codexControlRequest } from "./command-rpc-CCeCkf_v.js";
|
|
20
|
+
import { n as describeControlFailure, t as CODEX_CONTROL_METHODS } from "./capabilities-B1mgvpP8.js";
|
|
21
|
+
import { a as formatCodexDisplayText } from "./command-formatters-DSbGMXA0.js";
|
|
22
|
+
import { a as resolveCodexAppServerForModelProvider, i as resolveCodexSessionPermissionCwd, n as applyCodexSessionPermissionPolicy, t as CODEX_SESSION_PERMISSION_EXEC_MODES } from "./session-permission-policy-BaueHmSj.js";
|
|
23
|
+
import { f as trackCodexConversationActiveTurn, g as canMutateCodexHost, h as CODEX_NATIVE_EXECUTION_AUTH_ERROR, t as discoverCodexMarketplacePlugins } from "./plugin-marketplace-discovery-B7gHXJ3d.js";
|
|
24
|
+
import { a as readCodexConversationBindingDataRecord, i as readCodexConversationBindingData, o as resolveCodexDefaultWorkspaceDir, r as createCodexConversationBindingData } from "./conversation-binding-data-BiodpIzq.js";
|
|
25
|
+
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-B47uwekb.js";
|
|
28
26
|
import { t as createCodexWebSearchProviderBase } from "./web-search-provider.shared-BrZmlqyR.js";
|
|
29
27
|
import { mutateConfigFile } from "openclaw/plugin-sdk/config-mutation";
|
|
30
28
|
import { normalizePluginsConfig, resolveEffectiveEnableState, resolveLivePluginConfigObject, resolvePluginConfigObject } from "openclaw/plugin-sdk/plugin-config-runtime";
|
|
31
29
|
import { definePluginEntry } from "openclaw/plugin-sdk/plugin-entry";
|
|
32
30
|
import { asBoolean, asOptionalRecord, asSafeIntegerInRange, isRecord, normalizeOptionalString, normalizeSingleOrTrimmedStringList, uniqueStrings } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
31
|
+
import { resolveSessionAgentIdsStrict } from "openclaw/plugin-sdk/agent-scope-runtime";
|
|
32
|
+
import { getSessionEntry, resolveStorePath, resolveTranscriptSessionKeyBySessionId } from "openclaw/plugin-sdk/session-store-runtime";
|
|
33
|
+
import { parseStrictNonNegativeInteger, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
33
34
|
import fs from "node:fs/promises";
|
|
34
35
|
import path from "node:path";
|
|
35
|
-
import { parseStrictNonNegativeInteger, resolveTimerTimeoutMs } from "openclaw/plugin-sdk/number-runtime";
|
|
36
36
|
import { embeddedAgentLog, formatErrorMessage, resolveActiveEmbeddedRunSessionId, resolveSandboxContext } from "openclaw/plugin-sdk/agent-harness-runtime";
|
|
37
|
+
import { canonicalPathFromExistingAncestor, isPathInside } from "openclaw/plugin-sdk/file-access-runtime";
|
|
37
38
|
import os from "node:os";
|
|
38
|
-
import { loadAuthProfileStoreWithoutExternalProfiles, resolveAgentConfig, resolveAgentWorkspaceDir, resolveDefaultAgentDir, resolveDefaultAgentId } from "openclaw/plugin-sdk/agent-runtime";
|
|
39
|
+
import { loadAuthProfileStoreWithoutExternalProfiles, resolveAgentConfig as resolveAgentConfig$1, resolveAgentWorkspaceDir, resolveDefaultAgentDir, resolveDefaultAgentId as resolveDefaultAgentId$1 } from "openclaw/plugin-sdk/agent-runtime";
|
|
39
40
|
import { applyAuthProfileConfig, buildApiKeyCredential, buildOauthProviderAuthResult, buildOpenAICodexCredentialExtra, readCodexCliCredentialsCached, resolveOpenAICodexAuthIdentity, resolveOpenAICodexImportProfileName, updateAuthProfileStoreWithLock } from "openclaw/plugin-sdk/provider-auth";
|
|
40
|
-
import { resolveSessionAgentIds as resolveSessionAgentIds$2 } from "openclaw/plugin-sdk/agent-scope-runtime";
|
|
41
|
-
import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
|
|
42
41
|
import { extractErrorCode, pathExists } from "openclaw/plugin-sdk/security-runtime";
|
|
43
|
-
import {
|
|
42
|
+
import { loadExecApprovals } from "openclaw/plugin-sdk/exec-approvals-runtime";
|
|
44
43
|
import { coerceErrorMessage } from "openclaw/plugin-sdk/error-runtime";
|
|
45
|
-
import { fileURLToPath } from "node:url";
|
|
46
44
|
import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
|
|
47
|
-
import {
|
|
45
|
+
import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
|
|
48
46
|
import { readVisibleSessionTranscriptMessageEntries } from "openclaw/plugin-sdk/session-transcript-runtime";
|
|
49
47
|
import { getSessionBindingService } from "openclaw/plugin-sdk/conversation-binding-runtime";
|
|
50
|
-
import { KeyedAsyncQueue } from "openclaw/plugin-sdk/keyed-async-queue";
|
|
51
48
|
import { ModelSelectionLockedError, isModelSelectionLocked } from "openclaw/plugin-sdk/model-session-runtime";
|
|
49
|
+
import { fileURLToPath } from "node:url";
|
|
52
50
|
import { MIGRATION_REASON_TARGET_EXISTS, applyMigrationManualItem, createMigrationItem, createMigrationManualItem, hasMigrationConfigPatchConflict, markMigrationItemConflict, markMigrationItemError, markMigrationItemSkipped, mergeMigrationConfigValue, readMigrationConfigPath, resolveMigrationConfigRuntime, summarizeMigrationItems, writeMigrationConfigPath } from "openclaw/plugin-sdk/migration";
|
|
53
51
|
import { archiveMigrationItem, copyMemoryMigrationFileItem, copyMigrationFileItem, withCachedMigrationConfigRuntime, writeMigrationReport } from "openclaw/plugin-sdk/migration-runtime";
|
|
54
52
|
import { sleep } from "openclaw/plugin-sdk/runtime-env";
|
|
@@ -181,20 +179,21 @@ function waitForReconnect(delayMs, signal) {
|
|
|
181
179
|
}
|
|
182
180
|
//#endregion
|
|
183
181
|
//#region extensions/codex/src/app-server/session-binding-store.ts
|
|
184
|
-
/**
|
|
182
|
+
/** Keeps lifecycle/auth loading behind mutations while sharing the canonical read codec. */
|
|
185
183
|
function createLazyCodexAppServerBindingStore(state, managedThreadState) {
|
|
186
184
|
let resolved;
|
|
187
|
-
const store = () => resolved ??= import("./session-binding-
|
|
185
|
+
const store = () => resolved ??= import("./session-binding-4Ki04sW-.js").then((n) => n.d).then(({ createCodexAppServerBindingStore }) => createCodexAppServerBindingStore(state));
|
|
188
186
|
const managedThreads = managedThreadState ? createCodexManagedThreadStore(managedThreadState) : void 0;
|
|
189
187
|
return {
|
|
190
188
|
...managedThreads ? { managedThreads } : {},
|
|
191
|
-
read:
|
|
189
|
+
read: (identity) => readCurrentCodexAppServerBinding(state, identity),
|
|
192
190
|
hasOtherThreadOwner: async (threadId, currentIdentity) => (await store()).hasOtherThreadOwner(threadId, currentIdentity),
|
|
193
|
-
mutate: async (identity, mutation) => (await store()).mutate(identity, mutation),
|
|
191
|
+
mutate: async (identity, mutation, assertCurrent) => (await store()).mutate(identity, mutation, assertCurrent),
|
|
194
192
|
prepareSessionGenerationReclaim: async (identity) => (await store()).prepareSessionGenerationReclaim(identity),
|
|
195
|
-
adoptSessionGeneration: async (identity, previousSessionId) => (await store()).adoptSessionGeneration(identity, previousSessionId),
|
|
193
|
+
adoptSessionGeneration: async (identity, previousSessionId, assertCurrent) => (await store()).adoptSessionGeneration(identity, previousSessionId, assertCurrent),
|
|
196
194
|
resetSessionGeneration: async (identity) => (await store()).resetSessionGeneration(identity),
|
|
197
195
|
retireSessionGeneration: async (identity) => (await store()).retireSessionGeneration(identity),
|
|
196
|
+
withSessionDeletion: async (identity, assertCurrent, run) => (await store()).withSessionDeletion(identity, assertCurrent, run),
|
|
198
197
|
withThreadArchiveFence: async (run) => (await store()).withThreadArchiveFence(run),
|
|
199
198
|
withLease: async (identity, run) => (await store()).withLease(identity, run)
|
|
200
199
|
};
|
|
@@ -214,7 +213,7 @@ async function handleCodexCommand(ctx, options) {
|
|
|
214
213
|
}
|
|
215
214
|
}
|
|
216
215
|
async function loadDefaultCodexSubcommandHandler() {
|
|
217
|
-
const { handleCodexSubcommand } = await import("./command-handlers-
|
|
216
|
+
const { handleCodexSubcommand } = await import("./command-handlers-DOJvGv6-.js");
|
|
218
217
|
return handleCodexSubcommand;
|
|
219
218
|
}
|
|
220
219
|
//#endregion
|
|
@@ -396,7 +395,7 @@ function isImageMedia(media) {
|
|
|
396
395
|
return IMAGE_EXTENSIONS.has(path.extname(candidate.split(/[?#]/, 1)[0] ?? "").toLowerCase());
|
|
397
396
|
}
|
|
398
397
|
function normalizeFileUrl(value) {
|
|
399
|
-
if (
|
|
398
|
+
if (!/^file:\/\//iu.test(value)) return value;
|
|
400
399
|
try {
|
|
401
400
|
return fileURLToPath(value);
|
|
402
401
|
} catch {
|
|
@@ -405,18 +404,18 @@ function normalizeFileUrl(value) {
|
|
|
405
404
|
}
|
|
406
405
|
function readLocalMediaPath(value) {
|
|
407
406
|
if (!value) return;
|
|
408
|
-
if (
|
|
407
|
+
if (/^file:\/\//iu.test(value)) return value;
|
|
409
408
|
if (value.startsWith("//")) return;
|
|
410
409
|
if (path.isAbsolute(value) || path.win32.isAbsolute(value)) return value;
|
|
411
410
|
return /^[a-z][a-z0-9+.-]*:/i.test(value) ? void 0 : value;
|
|
412
411
|
}
|
|
413
412
|
//#endregion
|
|
414
413
|
//#region extensions/codex/src/conversation-binding.ts
|
|
415
|
-
const DEFAULT_BOUND_TURN_TIMEOUT_MS =
|
|
414
|
+
const DEFAULT_BOUND_TURN_TIMEOUT_MS = 12e5;
|
|
416
415
|
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.";
|
|
417
416
|
async function resolveConversationAppServerRuntime(params) {
|
|
418
417
|
const source = params.source;
|
|
419
|
-
const agentId = source?.agentId ?? params.agentId ?? (params.config ?
|
|
418
|
+
const agentId = source?.agentId ?? params.agentId ?? (params.config ? resolveSessionAgentIdsStrict({
|
|
420
419
|
sessionKey: params.sessionKey,
|
|
421
420
|
config: params.config
|
|
422
421
|
}).sessionAgentId : void 0);
|
|
@@ -505,18 +504,16 @@ async function startCodexConversationThread(params) {
|
|
|
505
504
|
sessionKey: params.sessionKey,
|
|
506
505
|
config: params.config
|
|
507
506
|
});
|
|
508
|
-
const existingBinding =
|
|
507
|
+
const existingBinding = params.bindingStore.read(identity);
|
|
509
508
|
assertCodexBindingMayBeReplaced(existingBinding, "starting a conversation-bound Codex thread");
|
|
510
509
|
const authProfileId = resolveCodexAppServerAuthProfileIdForAgent({
|
|
511
510
|
authProfileId: params.authProfileId ?? existingBinding?.authProfileId,
|
|
512
511
|
...agentLookup
|
|
513
512
|
});
|
|
514
|
-
const
|
|
515
|
-
if (params.threadId?.trim()) await attachExistingThread({
|
|
513
|
+
const bindingParams = {
|
|
516
514
|
pluginConfig: params.pluginConfig,
|
|
517
515
|
bindingStore: params.bindingStore,
|
|
518
516
|
identity,
|
|
519
|
-
threadId: params.threadId.trim(),
|
|
520
517
|
workspaceDir,
|
|
521
518
|
...agentDir ? { agentDir } : {},
|
|
522
519
|
model: params.model,
|
|
@@ -525,25 +522,20 @@ async function startCodexConversationThread(params) {
|
|
|
525
522
|
serviceTier: params.serviceTier,
|
|
526
523
|
config: params.config,
|
|
527
524
|
sessionKey: params.sessionKey,
|
|
528
|
-
incognito,
|
|
525
|
+
incognito: isIncognitoSessionKey(params.sessionKey),
|
|
529
526
|
agentId: params.agentId
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
|
|
527
|
+
};
|
|
528
|
+
const threadId = params.threadId?.trim();
|
|
529
|
+
const bind = () => params.bindingStore.withLease(identity, () => bindThread(bindingParams, threadId));
|
|
530
|
+
const ownedThreadId = threadId ?? existingBinding?.threadId;
|
|
531
|
+
if (ownedThreadId) await withExclusiveCodexAppServerThread({
|
|
533
532
|
bindingStore: params.bindingStore,
|
|
534
533
|
identity,
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
model: params.model,
|
|
538
|
-
modelProvider: params.modelProvider,
|
|
539
|
-
authProfileId,
|
|
540
|
-
serviceTier: params.serviceTier,
|
|
541
|
-
config: params.config,
|
|
542
|
-
sessionKey: params.sessionKey,
|
|
543
|
-
incognito,
|
|
544
|
-
agentId: params.agentId
|
|
534
|
+
threadId: ownedThreadId,
|
|
535
|
+
run: bind
|
|
545
536
|
});
|
|
546
|
-
|
|
537
|
+
else await bind();
|
|
538
|
+
const storedBinding = params.bindingStore.read(identity);
|
|
547
539
|
if (!storedBinding) throw new Error("Codex session binding disappeared while starting its conversation thread.");
|
|
548
540
|
return createCodexConversationBindingData({
|
|
549
541
|
source: {
|
|
@@ -612,7 +604,7 @@ async function handleCodexConversationInboundClaim(event, ctx, options) {
|
|
|
612
604
|
const identity = conversationBindingIdentity(data);
|
|
613
605
|
const sessionKey = event.sessionKey ?? ctx.sessionKey;
|
|
614
606
|
const incognito = isIncognitoSessionKey(data.source?.sessionKey ?? (data.legacyBinding ? sessionKey : void 0));
|
|
615
|
-
const
|
|
607
|
+
const expected = options.bindingStore.read(identity);
|
|
616
608
|
return {
|
|
617
609
|
handled: true,
|
|
618
610
|
reply: (await withCodexConversationThreadActivity(data.bindingId, async () => {
|
|
@@ -622,8 +614,7 @@ async function handleCodexConversationInboundClaim(event, ctx, options) {
|
|
|
622
614
|
conversationId: publicBinding.conversationId,
|
|
623
615
|
...publicBinding.parentConversationId ? { parentConversationId: publicBinding.parentConversationId } : {}
|
|
624
616
|
});
|
|
625
|
-
const
|
|
626
|
-
const current = await options.bindingStore.read(identity);
|
|
617
|
+
const current = options.bindingStore.read(identity);
|
|
627
618
|
if (currentPublicBinding?.bindingId !== publicBinding.bindingId || expected && (!current || current.threadId !== expected.threadId || current.conversationStartId !== expected.conversationStartId) || !expected && current && data.start?.id && current.conversationStartId !== data.start.id) return { reply: { text: "This Codex conversation was detached or changed before its message could run." } };
|
|
628
619
|
return await runBoundTurnWithMissingThreadRecovery({
|
|
629
620
|
bindingStore: options.bindingStore,
|
|
@@ -650,7 +641,7 @@ async function handleCodexConversationBindingResolved(event, options) {
|
|
|
650
641
|
const data = readCodexConversationBindingDataRecord(event.request.data ?? {});
|
|
651
642
|
if (!data || data.kind !== "codex-app-server-session") return;
|
|
652
643
|
const identity = conversationBindingIdentity(data);
|
|
653
|
-
const binding =
|
|
644
|
+
const binding = options.bindingStore.read(identity);
|
|
654
645
|
assertCodexBindingMayBeReplaced(binding, "clearing a denied conversation binding");
|
|
655
646
|
if (binding && (!data.start?.id || binding.conversationStartId === data.start.id)) await withCodexConversationThreadActivity(identity.bindingId, () => retireCodexConversationThreadBinding({
|
|
656
647
|
bindingStore: options.bindingStore,
|
|
@@ -707,21 +698,21 @@ async function resolveThreadBindingRuntime(params) {
|
|
|
707
698
|
authProfileId: params.authProfileId,
|
|
708
699
|
...agentLookup
|
|
709
700
|
};
|
|
710
|
-
const client = await getLeasedSharedCodexAppServerClient(clientOptions);
|
|
711
701
|
return {
|
|
712
702
|
runtime: modelScopedRuntime,
|
|
713
703
|
workspaceDir,
|
|
714
704
|
agentLookup,
|
|
715
705
|
model: modelSelection?.model,
|
|
716
706
|
modelProvider: modelSelection?.modelProvider ?? modelProvider,
|
|
717
|
-
client,
|
|
718
|
-
clientLease: { client },
|
|
719
707
|
clientOptions
|
|
720
708
|
};
|
|
721
709
|
}
|
|
722
|
-
function
|
|
723
|
-
const serviceTier = params.serviceTier ?? resolved.runtime.serviceTier;
|
|
710
|
+
function buildConversationThreadRequest(resolved, serviceTier) {
|
|
724
711
|
return {
|
|
712
|
+
cwd: resolved.workspaceDir,
|
|
713
|
+
...resolved.model ? { model: resolved.model } : {},
|
|
714
|
+
...resolved.modelProvider ? { modelProvider: resolved.modelProvider } : {},
|
|
715
|
+
personality: CODEX_NATIVE_PERSONALITY_NONE,
|
|
725
716
|
approvalPolicy: resolved.runtime.approvalPolicy,
|
|
726
717
|
approvalsReviewer: resolved.runtime.approvalsReviewer,
|
|
727
718
|
...resolved.runtime.sessionRoot ? { runtimeWorkspaceRoots: [resolved.runtime.sessionRoot] } : {},
|
|
@@ -731,52 +722,39 @@ function buildThreadRequestRuntimeOptions(params, resolved) {
|
|
|
731
722
|
}
|
|
732
723
|
function codexConversationSandboxOrPermissions(runtime, sandbox) {
|
|
733
724
|
const networkProxy = runtime.networkProxy;
|
|
734
|
-
const
|
|
735
|
-
const config = buildCodexProjectDocThreadConfig(mergeCodexThreadConfigs(networkProxy?.configPatch, disabledApps));
|
|
725
|
+
const config = buildCodexProjectDocThreadConfig(mergeCodexThreadConfigs(networkProxy?.configPatch, buildDisabledAppsConfigPatch()));
|
|
736
726
|
return networkProxy ? { config } : {
|
|
737
727
|
sandbox,
|
|
738
728
|
config
|
|
739
729
|
};
|
|
740
730
|
}
|
|
741
|
-
async function
|
|
742
|
-
return await withLeasedCodexAppServerClientStartSelectionRetry({
|
|
743
|
-
lease: resolved.clientLease,
|
|
744
|
-
options: resolved.clientOptions,
|
|
745
|
-
run: async (client, requestOptions) => await client.request("thread/start", {
|
|
746
|
-
cwd: resolved.workspaceDir,
|
|
747
|
-
...resolved.model ? { model: resolved.model } : {},
|
|
748
|
-
...resolved.modelProvider ? { modelProvider: resolved.modelProvider } : {},
|
|
749
|
-
personality: CODEX_NATIVE_PERSONALITY_NONE,
|
|
750
|
-
...buildThreadRequestRuntimeOptions(params, resolved),
|
|
751
|
-
developerInstructions: CODEX_CONVERSATION_THREAD_DEVELOPER_INSTRUCTIONS,
|
|
752
|
-
experimentalRawEvents: true,
|
|
753
|
-
...params.incognito ? { ephemeral: true } : {}
|
|
754
|
-
}, requestOptions),
|
|
755
|
-
onClientChange: (client) => {
|
|
756
|
-
resolved.client = client;
|
|
757
|
-
}
|
|
758
|
-
});
|
|
759
|
-
}
|
|
760
|
-
async function writeThreadBindingFromResponse(params, resolved, response) {
|
|
761
|
-
const current = await params.bindingStore.read(params.identity);
|
|
762
|
-
assertCodexBindingMayBeReplaced(current, "storing a conversation-bound Codex thread");
|
|
763
|
-
const trackSubscription = !params.incognito && isCodexAppServerClientRuntimeLive(resolved.client);
|
|
764
|
-
const sameOwner = isSameCodexAppServerThreadOwner(current, {
|
|
765
|
-
threadId: response.thread.id,
|
|
766
|
-
clientId: resolved.client.getInstanceId()
|
|
767
|
-
});
|
|
731
|
+
async function writeThreadBindingFromResponse(params, resolved, client, response, requestOptions) {
|
|
768
732
|
let retained = false;
|
|
733
|
+
let sameOwner = false;
|
|
769
734
|
try {
|
|
735
|
+
const current = params.bindingStore.read(params.identity);
|
|
736
|
+
assertCodexBindingMayBeReplaced(current, "storing a conversation-bound Codex thread");
|
|
737
|
+
const trackSubscription = !params.incognito && isCodexAppServerClientRuntimeLive(client);
|
|
738
|
+
sameOwner = isSameCodexAppServerThreadOwner(current, {
|
|
739
|
+
threadId: response.thread.id,
|
|
740
|
+
clientId: client.getInstanceId()
|
|
741
|
+
});
|
|
742
|
+
requestOptions();
|
|
743
|
+
assertCodexThreadAcceptsDirectInput(response.thread);
|
|
770
744
|
if (trackSubscription) {
|
|
771
|
-
retained = await retainCodexAppServerBindingSubscription(
|
|
745
|
+
retained = await retainCodexAppServerBindingSubscription(client, response.thread.id);
|
|
772
746
|
if (!retained) throw new Error("Codex conversation thread lost its native subscription owner.");
|
|
773
747
|
}
|
|
774
|
-
if (current && !sameOwner)
|
|
748
|
+
if (current && !sameOwner) {
|
|
749
|
+
const { assertCurrent } = requestOptions();
|
|
750
|
+
await releaseCodexAppServerBindingSubscription(current, { assertCurrent });
|
|
751
|
+
}
|
|
752
|
+
requestOptions();
|
|
775
753
|
if (!await params.bindingStore.mutate(params.identity, {
|
|
776
754
|
kind: "set",
|
|
777
755
|
binding: {
|
|
778
756
|
threadId: response.thread.id,
|
|
779
|
-
clientId:
|
|
757
|
+
clientId: client.getInstanceId(),
|
|
780
758
|
cwd: resolved.workspaceDir,
|
|
781
759
|
authProfileId: params.authProfileId,
|
|
782
760
|
model: response.model ?? resolved.model ?? params.model,
|
|
@@ -789,56 +767,54 @@ async function writeThreadBindingFromResponse(params, resolved, response) {
|
|
|
789
767
|
networkProxyProfileName: resolved.runtime.networkProxy?.profileName,
|
|
790
768
|
networkProxyConfigFingerprint: resolved.runtime.networkProxy?.configFingerprint
|
|
791
769
|
}
|
|
792
|
-
})) throw new Error("Codex conversation binding changed while storing its thread.");
|
|
770
|
+
}, requestOptions)) throw new Error("Codex conversation binding changed while storing its thread.");
|
|
793
771
|
} catch (error) {
|
|
794
|
-
if (
|
|
772
|
+
if (retained && !sameOwner || !hasCodexAppServerLiveThread(client, response.thread.id)) await rollbackCodexAppServerBindingSubscription(client, response.thread.id, retained);
|
|
795
773
|
throw error;
|
|
796
774
|
}
|
|
797
775
|
}
|
|
798
|
-
async function
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
identity: params.identity,
|
|
802
|
-
threadId: params.threadId,
|
|
803
|
-
run: async () => {
|
|
804
|
-
assertCodexBindingMayBeReplaced(await params.bindingStore.read(params.identity), "attaching a conversation-bound Codex thread");
|
|
805
|
-
const resolved = await resolveThreadBindingRuntime(params);
|
|
806
|
-
try {
|
|
807
|
-
const response = resolved.runtime.networkProxy ? await requestNewConversationBindingThread(params, resolved) : await withLeasedCodexAppServerClientStartSelectionRetry({
|
|
808
|
-
lease: resolved.clientLease,
|
|
809
|
-
options: resolved.clientOptions,
|
|
810
|
-
run: async (client, requestOptions) => {
|
|
811
|
-
if (isCodexAppServerLiveThreadClaimed(client, params.threadId)) throw new Error(`Codex thread ${params.threadId} has an active run; stop it before binding its conversation.`);
|
|
812
|
-
await releaseCodexAppServerLiveThread(client, params.threadId);
|
|
813
|
-
if (isCodexAppServerLiveThreadClaimed(client, params.threadId)) throw new Error(`Codex thread ${params.threadId} has an active run; stop it before binding its conversation.`);
|
|
814
|
-
return await client.request(CODEX_CONTROL_METHODS.resumeThread, {
|
|
815
|
-
threadId: params.threadId,
|
|
816
|
-
cwd: resolved.workspaceDir,
|
|
817
|
-
...resolved.model ? { model: resolved.model } : {},
|
|
818
|
-
...resolved.modelProvider ? { modelProvider: resolved.modelProvider } : {},
|
|
819
|
-
personality: CODEX_NATIVE_PERSONALITY_NONE,
|
|
820
|
-
...buildThreadRequestRuntimeOptions(params, resolved)
|
|
821
|
-
}, requestOptions);
|
|
822
|
-
},
|
|
823
|
-
onClientChange: (client) => {
|
|
824
|
-
resolved.client = client;
|
|
825
|
-
}
|
|
826
|
-
});
|
|
827
|
-
if (!resolved.runtime.networkProxy && response.thread.id !== params.threadId) throw new Error(`Codex conversation resume returned ${response.thread.id} for ${params.threadId}.`);
|
|
828
|
-
await writeThreadBindingFromResponse(params, resolved, response);
|
|
829
|
-
} finally {
|
|
830
|
-
releaseCodexAppServerClientLease(resolved.clientLease);
|
|
831
|
-
}
|
|
832
|
-
}
|
|
833
|
-
});
|
|
834
|
-
}
|
|
835
|
-
async function createThread(params) {
|
|
836
|
-
assertCodexBindingMayBeReplaced(await params.bindingStore.read(params.identity), "creating a conversation-bound Codex thread");
|
|
776
|
+
async function bindThread(params, threadId) {
|
|
777
|
+
const current = params.bindingStore.read(params.identity);
|
|
778
|
+
assertCodexBindingMayBeReplaced(current, "binding a conversation-bound Codex thread");
|
|
837
779
|
const resolved = await resolveThreadBindingRuntime(params);
|
|
780
|
+
const clientLease = { client: await getLeasedSharedCodexAppServerClient(resolved.clientOptions) };
|
|
838
781
|
try {
|
|
839
|
-
await
|
|
782
|
+
await withLeasedCodexAppServerClientStartSelectionRetry({
|
|
783
|
+
lease: clientLease,
|
|
784
|
+
options: resolved.clientOptions,
|
|
785
|
+
run: async (client, requestOptions) => {
|
|
786
|
+
const request = buildConversationThreadRequest(resolved, params.serviceTier ?? resolved.runtime.serviceTier);
|
|
787
|
+
let response;
|
|
788
|
+
if (threadId && !resolved.runtime.networkProxy) {
|
|
789
|
+
if (isCodexAppServerLiveThreadClaimed(client, threadId)) throw new Error(`Codex thread ${threadId} has an active run; stop it before binding its conversation.`);
|
|
790
|
+
const { thread } = await client.request("thread/read", {
|
|
791
|
+
threadId,
|
|
792
|
+
includeTurns: false
|
|
793
|
+
}, requestOptions());
|
|
794
|
+
assertCodexThreadAcceptsDirectInput(thread);
|
|
795
|
+
const { assertCurrent } = requestOptions();
|
|
796
|
+
await releaseCodexAppServerLiveThread(client, threadId, assertCurrent);
|
|
797
|
+
if (isCodexAppServerLiveThreadClaimed(client, threadId)) throw new Error(`Codex thread ${threadId} has an active run; stop it before binding its conversation.`);
|
|
798
|
+
response = await resumeCodexAppServerThread({
|
|
799
|
+
client,
|
|
800
|
+
abandonClient: () => closeCodexStartupClientBestEffort(client),
|
|
801
|
+
request: {
|
|
802
|
+
...request,
|
|
803
|
+
threadId
|
|
804
|
+
},
|
|
805
|
+
requestResume: (resumeRequest) => client.request("thread/resume", resumeRequest, requestOptions())
|
|
806
|
+
});
|
|
807
|
+
} else response = await client.request("thread/start", {
|
|
808
|
+
...request,
|
|
809
|
+
developerInstructions: CODEX_CONVERSATION_THREAD_DEVELOPER_INSTRUCTIONS,
|
|
810
|
+
experimentalRawEvents: true,
|
|
811
|
+
...params.incognito ? { ephemeral: true } : {}
|
|
812
|
+
}, requestOptions());
|
|
813
|
+
await writeThreadBindingFromResponse(params, resolved, client, response, requestOptions);
|
|
814
|
+
}
|
|
815
|
+
});
|
|
840
816
|
} finally {
|
|
841
|
-
releaseCodexAppServerClientLease(
|
|
817
|
+
releaseCodexAppServerClientLease(clientLease);
|
|
842
818
|
}
|
|
843
819
|
}
|
|
844
820
|
async function runBoundTurn(params) {
|
|
@@ -847,266 +823,288 @@ async function runBoundTurn(params) {
|
|
|
847
823
|
config: params.config
|
|
848
824
|
});
|
|
849
825
|
const identity = conversationBindingIdentity(params.data);
|
|
850
|
-
const binding =
|
|
826
|
+
const binding = params.bindingStore.read(identity);
|
|
851
827
|
if (!binding?.threadId) throw new Error("bound Codex conversation has no thread binding");
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
828
|
+
return await withExclusiveCodexAppServerThread({
|
|
829
|
+
bindingStore: params.bindingStore,
|
|
830
|
+
identity,
|
|
831
|
+
threadId: binding.threadId,
|
|
832
|
+
run: async () => {
|
|
833
|
+
const current = params.bindingStore.read(identity);
|
|
834
|
+
if (!isSameCodexAppServerThreadOwner(current, binding)) throw new Error("Codex conversation binding changed before its turn.");
|
|
835
|
+
assertCodexBindingMayBeReplaced(binding, "running a conversation-bound Codex thread");
|
|
836
|
+
let threadId = binding.threadId;
|
|
837
|
+
const requestedWorkspaceDir = binding.cwd || params.data.workspaceDir;
|
|
838
|
+
const reviewerModelProvider = resolveModelBackedReviewerPolicyProvider({
|
|
839
|
+
authProfileId: binding.authProfileId,
|
|
840
|
+
modelProvider: binding.modelProvider,
|
|
841
|
+
...agentLookup
|
|
842
|
+
});
|
|
843
|
+
const { runtime, workspaceDir } = await resolveConversationAppServerRuntime({
|
|
844
|
+
pluginConfig: params.pluginConfig,
|
|
845
|
+
config: params.config,
|
|
846
|
+
agentId: params.data.source?.agentId ?? params.data.agentId,
|
|
847
|
+
sessionKey: params.data.legacyBinding ? params.sessionKey : params.data.source?.sessionKey,
|
|
848
|
+
source: params.data.source,
|
|
849
|
+
workspaceDir: requestedWorkspaceDir,
|
|
850
|
+
modelProvider: reviewerModelProvider,
|
|
851
|
+
model: binding.model,
|
|
852
|
+
agentDir: params.data.agentDir
|
|
853
|
+
});
|
|
854
|
+
const modelScopedRuntime = resolveCodexAppServerForModelProvider({
|
|
855
|
+
appServer: runtime,
|
|
856
|
+
provider: reviewerModelProvider,
|
|
857
|
+
model: binding.model,
|
|
858
|
+
config: params.config,
|
|
859
|
+
env: process.env,
|
|
860
|
+
agentDir: params.data.agentDir
|
|
861
|
+
});
|
|
862
|
+
const sessionRoot = modelScopedRuntime.sessionRoot;
|
|
863
|
+
const approvalPolicy = modelScopedRuntime.approvalPolicy;
|
|
864
|
+
const sandbox = modelScopedRuntime.sandbox;
|
|
865
|
+
const permissionProfile = modelScopedRuntime.networkProxy?.profileName;
|
|
866
|
+
const networkProxyConfigFingerprint = modelScopedRuntime.networkProxy?.configFingerprint;
|
|
867
|
+
const networkProxyBindingChanged = binding.networkProxyProfileName !== permissionProfile || binding.networkProxyConfigFingerprint !== networkProxyConfigFingerprint;
|
|
868
|
+
const serviceTier = binding.serviceTier ?? runtime.serviceTier;
|
|
869
|
+
let useStickyNetworkProfile = permissionProfile !== void 0 && binding.networkProxyProfileName === permissionProfile && binding.networkProxyConfigFingerprint === networkProxyConfigFingerprint;
|
|
870
|
+
assertNativeConversationApprovalPolicySupported(modelScopedRuntime);
|
|
871
|
+
const modelSelection = binding.model ? resolveCodexAppServerRequestModelSelection({
|
|
872
|
+
model: binding.model,
|
|
873
|
+
modelProvider: binding.modelProvider,
|
|
874
|
+
authProfileId: binding.authProfileId,
|
|
875
|
+
...agentLookup
|
|
876
|
+
}) : void 0;
|
|
877
|
+
const threadRequestRuntime = {
|
|
878
|
+
runtime: modelScopedRuntime,
|
|
879
|
+
workspaceDir,
|
|
880
|
+
...modelSelection
|
|
881
|
+
};
|
|
882
|
+
const clientOptions = {
|
|
883
|
+
startOptions: runtime.start,
|
|
884
|
+
timeoutMs: runtime.requestTimeoutMs,
|
|
885
|
+
authProfileId: binding.authProfileId,
|
|
886
|
+
...agentLookup
|
|
887
|
+
};
|
|
888
|
+
let client = await getLeasedSharedCodexAppServerClient(clientOptions);
|
|
889
|
+
const clientLease = { client };
|
|
890
|
+
let activeTurnId;
|
|
891
|
+
let activeTurnCleanup = () => void 0;
|
|
892
|
+
let isolatedSubscriptionClient;
|
|
893
|
+
let turnRoute;
|
|
894
|
+
let liveThreadOwnership;
|
|
895
|
+
let ownsNativeSubscription = false;
|
|
896
|
+
let turnSucceeded = false;
|
|
897
|
+
const assertResumeInputAllowed = async () => {
|
|
898
|
+
const { thread } = await client.request("thread/read", {
|
|
915
899
|
threadId,
|
|
916
|
-
|
|
917
|
-
};
|
|
918
|
-
|
|
919
|
-
}
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
900
|
+
includeTurns: false
|
|
901
|
+
}, { timeoutMs: runtime.requestTimeoutMs });
|
|
902
|
+
assertCodexThreadAcceptsDirectInput(thread);
|
|
903
|
+
};
|
|
904
|
+
try {
|
|
905
|
+
if (!networkProxyBindingChanged && binding.clientId !== client.getInstanceId()) await assertResumeInputAllowed();
|
|
906
|
+
if (!params.incognito && isCodexAppServerClientRuntimeLive(client)) {
|
|
907
|
+
const ownership = await consumeCodexAppServerLiveThread(client, threadId);
|
|
908
|
+
if (ownership) {
|
|
909
|
+
liveThreadOwnership = {
|
|
910
|
+
client,
|
|
911
|
+
threadId,
|
|
912
|
+
ownership
|
|
913
|
+
};
|
|
914
|
+
ownsNativeSubscription = true;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
if (networkProxyBindingChanged) {
|
|
918
|
+
const response = assertCodexThreadStartResponse(await withLeasedCodexAppServerClientStartSelectionRetry({
|
|
919
|
+
lease: clientLease,
|
|
920
|
+
options: clientOptions,
|
|
921
|
+
run: async (requestClient, requestOptions) => await requestClient.request("thread/start", {
|
|
922
|
+
...buildConversationThreadRequest(threadRequestRuntime, serviceTier),
|
|
923
|
+
developerInstructions: CODEX_CONVERSATION_THREAD_DEVELOPER_INSTRUCTIONS,
|
|
924
|
+
experimentalRawEvents: true,
|
|
925
|
+
...params.incognito ? { ephemeral: true } : {}
|
|
926
|
+
}, requestOptions()),
|
|
927
|
+
onClientChange: (nextClient) => {
|
|
928
|
+
client = nextClient;
|
|
929
|
+
}
|
|
930
|
+
}));
|
|
931
|
+
threadId = response.thread.id;
|
|
932
|
+
ownsNativeSubscription = true;
|
|
933
|
+
assertCodexThreadAcceptsDirectInput(response.thread);
|
|
934
|
+
if (liveThreadOwnership && (liveThreadOwnership.threadId !== threadId || liveThreadOwnership.client !== client)) {
|
|
935
|
+
const previousOwnership = liveThreadOwnership;
|
|
936
|
+
try {
|
|
937
|
+
await previousOwnership.ownership.release(previousOwnership.threadId);
|
|
938
|
+
} catch (error) {
|
|
939
|
+
if (!(isCodexAppServerClientRuntimeLive(previousOwnership.client) && await retainCodexAppServerBindingSubscription(previousOwnership.client, previousOwnership.threadId, previousOwnership.ownership).catch(() => false))) await closeCodexStartupClientBestEffort(previousOwnership.client);
|
|
940
|
+
liveThreadOwnership = void 0;
|
|
941
|
+
throw error;
|
|
942
|
+
}
|
|
943
|
+
liveThreadOwnership = void 0;
|
|
944
|
+
} else if (binding.threadId !== threadId) await releaseCodexAppServerBindingSubscription(binding);
|
|
945
|
+
if (!await params.bindingStore.mutate(identity, {
|
|
946
|
+
kind: "set",
|
|
947
|
+
binding: {
|
|
948
|
+
threadId,
|
|
949
|
+
clientId: client.getInstanceId(),
|
|
950
|
+
cwd: response.thread.cwd ?? workspaceDir,
|
|
951
|
+
authProfileId: binding.authProfileId,
|
|
952
|
+
model: response.model ?? modelSelection?.model ?? binding.model,
|
|
953
|
+
modelProvider: normalizeCodexAppServerBindingModelProvider({
|
|
954
|
+
authProfileId: binding.authProfileId,
|
|
955
|
+
modelProvider: response.modelProvider ?? modelSelection?.modelProvider ?? binding.modelProvider,
|
|
956
|
+
...agentLookup
|
|
957
|
+
}),
|
|
958
|
+
serviceTier: serviceTier ?? void 0,
|
|
959
|
+
networkProxyProfileName: modelScopedRuntime.networkProxy?.profileName,
|
|
960
|
+
networkProxyConfigFingerprint: modelScopedRuntime.networkProxy?.configFingerprint,
|
|
961
|
+
conversationStartId: binding.conversationStartId,
|
|
962
|
+
conversationSourceTransferComplete: binding.conversationSourceTransferComplete,
|
|
963
|
+
historyCoveredThrough: binding.historyCoveredThrough
|
|
964
|
+
}
|
|
965
|
+
})) throw new Error("Codex conversation binding changed while rotating its thread.");
|
|
966
|
+
useStickyNetworkProfile = modelScopedRuntime.networkProxy !== void 0;
|
|
967
|
+
} else if (binding.clientId !== client.getInstanceId() || isCodexAppServerClientRuntimeLive(client) && !params.incognito && !liveThreadOwnership) {
|
|
968
|
+
if (binding.clientId === client.getInstanceId()) await assertResumeInputAllowed();
|
|
969
|
+
const response = await withLeasedCodexAppServerClientStartSelectionRetry({
|
|
970
|
+
lease: clientLease,
|
|
971
|
+
options: clientOptions,
|
|
972
|
+
run: async (requestClient, requestOptions) => await resumeCodexAppServerThread({
|
|
973
|
+
client: requestClient,
|
|
974
|
+
onSubscriptionReleased: () => {
|
|
975
|
+
isolatedSubscriptionClient = requestClient;
|
|
976
|
+
},
|
|
977
|
+
abandonClient: async () => {
|
|
978
|
+
await closeCodexStartupClientBestEffort(requestClient);
|
|
979
|
+
isolatedSubscriptionClient = requestClient;
|
|
980
|
+
},
|
|
981
|
+
request: {
|
|
982
|
+
threadId,
|
|
983
|
+
...buildConversationThreadRequest(threadRequestRuntime, serviceTier)
|
|
984
|
+
},
|
|
985
|
+
requestResume: (request) => requestClient.request("thread/resume", request, requestOptions())
|
|
986
|
+
}),
|
|
987
|
+
onClientChange: (nextClient) => {
|
|
988
|
+
client = nextClient;
|
|
989
|
+
}
|
|
990
|
+
});
|
|
991
|
+
threadId = response.thread.id;
|
|
992
|
+
ownsNativeSubscription = true;
|
|
993
|
+
assertCodexThreadAcceptsDirectInput(response.thread);
|
|
994
|
+
if (!isSameCodexAppServerThreadOwner(binding, {
|
|
995
|
+
threadId,
|
|
996
|
+
clientId: client.getInstanceId()
|
|
997
|
+
})) await releaseCodexAppServerBindingSubscription(binding);
|
|
998
|
+
if (!await params.bindingStore.mutate(identity, {
|
|
999
|
+
kind: "patch",
|
|
1000
|
+
threadId: binding.threadId,
|
|
1001
|
+
patch: {
|
|
1002
|
+
clientId: client.getInstanceId(),
|
|
1003
|
+
cwd: response.thread.cwd ?? binding.cwd,
|
|
1004
|
+
model: response.model ?? modelSelection?.model ?? binding.model,
|
|
1005
|
+
modelProvider: normalizeCodexAppServerBindingModelProvider({
|
|
1006
|
+
authProfileId: binding.authProfileId,
|
|
1007
|
+
modelProvider: response.modelProvider ?? modelSelection?.modelProvider ?? binding.modelProvider,
|
|
1008
|
+
...agentLookup
|
|
1009
|
+
})
|
|
1010
|
+
}
|
|
1011
|
+
})) throw new Error("Codex conversation binding changed while resuming on a new client.");
|
|
1012
|
+
}
|
|
1013
|
+
const turnCollector = createCodexConversationTurnCollector(threadId);
|
|
1014
|
+
turnRoute = getCodexAppServerTurnRouter(client).reserveThread({
|
|
1015
|
+
threadId,
|
|
1016
|
+
onNotification: turnCollector.handleNotification
|
|
1017
|
+
});
|
|
1018
|
+
turnRoute.armTurn();
|
|
1019
|
+
activeTurnId = (await client.request("turn/start", {
|
|
1020
|
+
threadId,
|
|
1021
|
+
input: buildCodexConversationTurnInput({
|
|
1022
|
+
prompt: params.prompt,
|
|
1023
|
+
event: params.event
|
|
1024
|
+
}),
|
|
926
1025
|
cwd: workspaceDir,
|
|
927
1026
|
...sessionRoot ? { runtimeWorkspaceRoots: [sessionRoot] } : {},
|
|
928
|
-
...modelSelection?.model ? { model: modelSelection.model } : {},
|
|
929
|
-
...modelSelection?.modelProvider ? { modelProvider: modelSelection.modelProvider } : {},
|
|
930
|
-
personality: CODEX_NATIVE_PERSONALITY_NONE,
|
|
931
1027
|
approvalPolicy,
|
|
932
1028
|
approvalsReviewer: modelScopedRuntime.approvalsReviewer,
|
|
933
|
-
...
|
|
934
|
-
...
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
client
|
|
941
|
-
}
|
|
942
|
-
}));
|
|
943
|
-
threadId = response.thread.id;
|
|
944
|
-
ownsNativeSubscription = true;
|
|
945
|
-
if (liveThreadOwnership && (liveThreadOwnership.threadId !== threadId || liveThreadOwnership.client !== client)) {
|
|
946
|
-
const previousOwnership = liveThreadOwnership;
|
|
947
|
-
try {
|
|
948
|
-
await previousOwnership.ownership.release(previousOwnership.threadId);
|
|
949
|
-
} catch (error) {
|
|
950
|
-
if (!(isCodexAppServerClientRuntimeLive(previousOwnership.client) && await retainCodexAppServerBindingSubscription(previousOwnership.client, previousOwnership.threadId, previousOwnership.ownership).catch(() => false))) await closeCodexStartupClientBestEffort(previousOwnership.client);
|
|
951
|
-
liveThreadOwnership = void 0;
|
|
952
|
-
throw error;
|
|
953
|
-
}
|
|
954
|
-
liveThreadOwnership = void 0;
|
|
955
|
-
} else if (binding.threadId !== threadId) await releaseCodexAppServerBindingSubscription(binding);
|
|
956
|
-
if (!await params.bindingStore.mutate(identity, {
|
|
957
|
-
kind: "set",
|
|
958
|
-
binding: {
|
|
1029
|
+
...useStickyNetworkProfile ? {} : { sandboxPolicy: codexSandboxPolicyForTurn(sandbox, sessionRoot ?? workspaceDir) },
|
|
1030
|
+
...modelSelection?.model ? { model: modelSelection.model } : {},
|
|
1031
|
+
personality: CODEX_NATIVE_PERSONALITY_NONE,
|
|
1032
|
+
...serviceTier ? { serviceTier } : {}
|
|
1033
|
+
}, { timeoutMs: runtime.requestTimeoutMs })).turn.id;
|
|
1034
|
+
activeTurnCleanup = trackCodexConversationActiveTurn({
|
|
1035
|
+
identity,
|
|
1036
|
+
client,
|
|
959
1037
|
threadId,
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
1038
|
+
turnId: activeTurnId
|
|
1039
|
+
});
|
|
1040
|
+
turnCollector.setTurnId(activeTurnId);
|
|
1041
|
+
await turnRoute.bindTurn(activeTurnId);
|
|
1042
|
+
const replyText = (await turnCollector.wait({ timeoutMs: params.timeoutMs ?? DEFAULT_BOUND_TURN_TIMEOUT_MS })).replyText.trim();
|
|
1043
|
+
turnSucceeded = true;
|
|
1044
|
+
return { reply: { text: replyText || "Codex completed without a text reply." } };
|
|
1045
|
+
} catch (error) {
|
|
1046
|
+
if (isCodexAppServerOverloadError(error) && error.method === "thread/resume") throw error;
|
|
1047
|
+
if (error instanceof CodexThreadDirectInputError) {
|
|
1048
|
+
if (params.incognito && ownsNativeSubscription) {
|
|
1049
|
+
if (!await unsubscribeCodexThreadBestEffort(client, {
|
|
1050
|
+
threadId,
|
|
1051
|
+
timeoutMs: 5e3
|
|
1052
|
+
})) await retireUnsafeCodexTurnClientBestEffort(client, "parent-owned thread unsubscribe");
|
|
1053
|
+
}
|
|
1054
|
+
throw error;
|
|
975
1055
|
}
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
} else if (binding.clientId !== client.getInstanceId() || isCodexAppServerClientRuntimeLive(client) && !params.incognito && !liveThreadOwnership) {
|
|
979
|
-
const response = await withLeasedCodexAppServerClientStartSelectionRetry({
|
|
980
|
-
lease: clientLease,
|
|
981
|
-
options: clientOptions,
|
|
982
|
-
run: async (requestClient, requestOptions) => await resumeCodexAppServerThread({
|
|
983
|
-
client: requestClient,
|
|
984
|
-
abandonClient: async () => {
|
|
985
|
-
retiredUnsafeClient = requestClient;
|
|
986
|
-
await closeCodexStartupClientBestEffort(requestClient);
|
|
987
|
-
},
|
|
988
|
-
request: {
|
|
1056
|
+
if (error instanceof CodexConversationTurnTimeoutError && activeTurnId || turnRoute && isCodexAppServerIndeterminateRequestCancellationError(error)) {
|
|
1057
|
+
if (!await interruptCodexTurnAndWaitBestEffort(client, {
|
|
989
1058
|
threadId,
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
approvalPolicy,
|
|
996
|
-
approvalsReviewer: modelScopedRuntime.approvalsReviewer,
|
|
997
|
-
...codexConversationSandboxOrPermissions(modelScopedRuntime, sandbox),
|
|
998
|
-
...serviceTier ? { serviceTier } : {}
|
|
999
|
-
},
|
|
1000
|
-
...requestOptions
|
|
1001
|
-
}),
|
|
1002
|
-
onClientChange: (nextClient) => {
|
|
1003
|
-
client = nextClient;
|
|
1059
|
+
turnId: activeTurnId ?? ""
|
|
1060
|
+
})) {
|
|
1061
|
+
await retireUnsafeCodexTurnClientBestEffort(client, "turn interrupt");
|
|
1062
|
+
isolatedSubscriptionClient = client;
|
|
1063
|
+
}
|
|
1004
1064
|
}
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
patch: {
|
|
1016
|
-
clientId: client.getInstanceId(),
|
|
1017
|
-
cwd: response.thread.cwd ?? binding.cwd,
|
|
1018
|
-
model: response.model ?? modelSelection?.model ?? binding.model,
|
|
1019
|
-
modelProvider: normalizeCodexAppServerBindingModelProvider({
|
|
1020
|
-
authProfileId: binding.authProfileId,
|
|
1021
|
-
modelProvider: response.modelProvider ?? modelSelection?.modelProvider ?? binding.modelProvider,
|
|
1022
|
-
...agentLookup
|
|
1023
|
-
})
|
|
1065
|
+
if (params.incognito) {
|
|
1066
|
+
if (await params.bindingStore.mutate(identity, {
|
|
1067
|
+
kind: "clear",
|
|
1068
|
+
threadId
|
|
1069
|
+
}) && isolatedSubscriptionClient !== client) {
|
|
1070
|
+
if (!await unsubscribeCodexThreadBestEffort(client, {
|
|
1071
|
+
threadId,
|
|
1072
|
+
timeoutMs: 5e3
|
|
1073
|
+
})) await retireUnsafeCodexTurnClientBestEffort(client, "thread unsubscribe");
|
|
1074
|
+
}
|
|
1024
1075
|
}
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
}, { timeoutMs: runtime.requestTimeoutMs })).turn.id;
|
|
1048
|
-
activeTurnCleanup = trackCodexConversationActiveTurn({
|
|
1049
|
-
identity,
|
|
1050
|
-
client,
|
|
1051
|
-
threadId,
|
|
1052
|
-
turnId: activeTurnId
|
|
1053
|
-
});
|
|
1054
|
-
turnCollector.setTurnId(activeTurnId);
|
|
1055
|
-
await turnRoute.bindTurn(activeTurnId);
|
|
1056
|
-
const replyText = (await turnCollector.wait({ timeoutMs: params.timeoutMs ?? DEFAULT_BOUND_TURN_TIMEOUT_MS })).replyText.trim();
|
|
1057
|
-
turnSucceeded = true;
|
|
1058
|
-
return { reply: { text: replyText || "Codex completed without a text reply." } };
|
|
1059
|
-
} catch (error) {
|
|
1060
|
-
if (error instanceof CodexConversationTurnTimeoutError && activeTurnId || turnRoute && isCodexAppServerIndeterminateRequestCancellationError(error)) {
|
|
1061
|
-
if (!await interruptCodexTurnAndWaitBestEffort(client, {
|
|
1062
|
-
threadId,
|
|
1063
|
-
turnId: activeTurnId ?? ""
|
|
1064
|
-
})) {
|
|
1065
|
-
retiredUnsafeClient = client;
|
|
1066
|
-
await retireUnsafeCodexTurnClientBestEffort(client, "turn interrupt");
|
|
1067
|
-
}
|
|
1068
|
-
}
|
|
1069
|
-
if (params.incognito) {
|
|
1070
|
-
if (await params.bindingStore.mutate(identity, {
|
|
1071
|
-
kind: "clear",
|
|
1072
|
-
threadId
|
|
1073
|
-
}) && retiredUnsafeClient !== client) {
|
|
1074
|
-
if (!await unsubscribeCodexThreadBestEffort(client, {
|
|
1075
|
-
threadId,
|
|
1076
|
-
timeoutMs: 5e3
|
|
1077
|
-
})) await retireUnsafeCodexTurnClientBestEffort(client, "thread unsubscribe");
|
|
1078
|
-
}
|
|
1079
|
-
}
|
|
1080
|
-
throw error;
|
|
1081
|
-
} finally {
|
|
1082
|
-
activeTurnCleanup();
|
|
1083
|
-
turnRoute?.release();
|
|
1084
|
-
try {
|
|
1085
|
-
if (ownsNativeSubscription && retiredUnsafeClient !== client && !params.incognito && isCodexAppServerClientRuntimeLive(client)) {
|
|
1086
|
-
const currentLiveThreadOwnership = liveThreadOwnership?.client === client && liveThreadOwnership.threadId === threadId ? liveThreadOwnership.ownership : void 0;
|
|
1087
|
-
let retained = false;
|
|
1088
|
-
if (turnSucceeded) retained = await params.bindingStore.withLease(identity, async () => {
|
|
1089
|
-
const current = await params.bindingStore.read(identity);
|
|
1090
|
-
if (current?.threadId !== threadId || current.clientId !== client.getInstanceId()) return false;
|
|
1091
|
-
return await retainCodexAppServerBindingSubscription(client, threadId, currentLiveThreadOwnership);
|
|
1092
|
-
});
|
|
1093
|
-
if (!retained) {
|
|
1094
|
-
if (!(currentLiveThreadOwnership ? await currentLiveThreadOwnership.release(threadId).then(() => true) : await unsubscribeCodexThreadBestEffort(client, {
|
|
1076
|
+
throw error;
|
|
1077
|
+
} finally {
|
|
1078
|
+
activeTurnCleanup();
|
|
1079
|
+
turnRoute?.release();
|
|
1080
|
+
try {
|
|
1081
|
+
if (ownsNativeSubscription && isolatedSubscriptionClient !== client && !params.incognito && isCodexAppServerClientRuntimeLive(client)) {
|
|
1082
|
+
const currentLiveThreadOwnership = liveThreadOwnership?.client === client && liveThreadOwnership.threadId === threadId ? liveThreadOwnership.ownership : void 0;
|
|
1083
|
+
let retained = false;
|
|
1084
|
+
if (turnSucceeded) retained = await params.bindingStore.withLease(identity, async () => {
|
|
1085
|
+
const latest = params.bindingStore.read(identity);
|
|
1086
|
+
if (latest?.threadId !== threadId || latest.clientId !== client.getInstanceId()) return false;
|
|
1087
|
+
return await retainCodexAppServerBindingSubscription(client, threadId, currentLiveThreadOwnership);
|
|
1088
|
+
});
|
|
1089
|
+
if (!retained) {
|
|
1090
|
+
if (!(currentLiveThreadOwnership ? await currentLiveThreadOwnership.release(threadId).then(() => true) : await unsubscribeCodexThreadBestEffort(client, {
|
|
1091
|
+
threadId,
|
|
1092
|
+
timeoutMs: 5e3
|
|
1093
|
+
}))) await closeCodexStartupClientBestEffort(client);
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
} catch (error) {
|
|
1097
|
+
embeddedAgentLog.warn("codex conversation subscription cleanup failed", {
|
|
1095
1098
|
threadId,
|
|
1096
|
-
|
|
1097
|
-
})
|
|
1099
|
+
reason: formatErrorMessage(error)
|
|
1100
|
+
});
|
|
1101
|
+
await closeCodexStartupClientBestEffort(client);
|
|
1102
|
+
} finally {
|
|
1103
|
+
releaseCodexAppServerClientLease(clientLease);
|
|
1098
1104
|
}
|
|
1099
1105
|
}
|
|
1100
|
-
} catch (error) {
|
|
1101
|
-
embeddedAgentLog.warn("codex conversation subscription cleanup failed", {
|
|
1102
|
-
threadId,
|
|
1103
|
-
reason: formatErrorMessage(error)
|
|
1104
|
-
});
|
|
1105
|
-
await closeCodexStartupClientBestEffort(client);
|
|
1106
|
-
} finally {
|
|
1107
|
-
releaseCodexAppServerClientLease(clientLease);
|
|
1108
1106
|
}
|
|
1109
|
-
}
|
|
1107
|
+
});
|
|
1110
1108
|
}
|
|
1111
1109
|
function assertNativeConversationApprovalPolicySupported(runtime) {
|
|
1112
1110
|
if (runtime.approvalPolicy !== "never" && runtime.approvalsReviewer === "user") throw new Error(NATIVE_CONVERSATION_INTERACTIVE_APPROVALS_UNAVAILABLE);
|
|
@@ -1123,8 +1121,10 @@ async function runBoundTurnWithMissingThreadRecovery(params) {
|
|
|
1123
1121
|
}
|
|
1124
1122
|
async function prepareConversationBinding(params, options = {}) {
|
|
1125
1123
|
const identity = conversationBindingIdentity(params.data);
|
|
1126
|
-
|
|
1127
|
-
|
|
1124
|
+
const snapshot = params.bindingStore.read(identity);
|
|
1125
|
+
const run = () => params.bindingStore.withLease(identity, async () => {
|
|
1126
|
+
const current = params.bindingStore.read(identity);
|
|
1127
|
+
if (current?.threadId !== snapshot?.threadId || current?.clientId !== snapshot?.clientId) throw new Error("Codex conversation binding changed before preparation.");
|
|
1128
1128
|
const requested = params.data.start && current?.conversationStartId !== params.data.start.id ? params.data.start : void 0;
|
|
1129
1129
|
if (current && !requested && !options.forceNew) return;
|
|
1130
1130
|
const sourceIdentity = params.data.source ? sessionBindingIdentity({
|
|
@@ -1133,7 +1133,7 @@ async function prepareConversationBinding(params, options = {}) {
|
|
|
1133
1133
|
sessionKey: params.data.source.sessionKey,
|
|
1134
1134
|
config: params.config
|
|
1135
1135
|
}) : void 0;
|
|
1136
|
-
const sourceBinding = sourceIdentity ?
|
|
1136
|
+
const sourceBinding = sourceIdentity ? params.bindingStore.read(sourceIdentity) : void 0;
|
|
1137
1137
|
assertCodexBindingMayBeReplaced(current, "initializing a conversation-bound Codex thread");
|
|
1138
1138
|
assertCodexBindingMayBeReplaced(sourceBinding, "transferring a session into a conversation-bound Codex thread");
|
|
1139
1139
|
const inherited = current ?? sourceBinding;
|
|
@@ -1158,15 +1158,11 @@ async function prepareConversationBinding(params, options = {}) {
|
|
|
1158
1158
|
agentId: params.data.source?.agentId ?? params.data.agentId
|
|
1159
1159
|
};
|
|
1160
1160
|
const threadId = requested?.threadId;
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
threadId
|
|
1164
|
-
});
|
|
1165
|
-
else await createThread(bindingParams);
|
|
1166
|
-
const stored = await params.bindingStore.read(identity);
|
|
1161
|
+
await bindThread(bindingParams, options.forceNew ? void 0 : threadId);
|
|
1162
|
+
const stored = params.bindingStore.read(identity);
|
|
1167
1163
|
if (!stored) throw new Error("Codex conversation binding disappeared while initializing its thread.");
|
|
1168
1164
|
if (sourceIdentity && params.data.source && !current?.conversationSourceTransferComplete) await params.bindingStore.withLease(sourceIdentity, async () => {
|
|
1169
|
-
const source =
|
|
1165
|
+
const source = params.bindingStore.read(sourceIdentity);
|
|
1170
1166
|
if (source && source.threadId === params.data.source?.threadId) {
|
|
1171
1167
|
const sourceSessionKey = sourceIdentity.sessionKey ?? resolveTranscriptSessionKeyBySessionId({
|
|
1172
1168
|
agentId: sourceIdentity.agentId,
|
|
@@ -1193,6 +1189,14 @@ async function prepareConversationBinding(params, options = {}) {
|
|
|
1193
1189
|
}
|
|
1194
1190
|
})) throw new Error("Codex conversation binding changed while initializing its thread.");
|
|
1195
1191
|
});
|
|
1192
|
+
const threadId = params.data.start?.threadId ?? snapshot?.threadId;
|
|
1193
|
+
if (threadId) await withExclusiveCodexAppServerThread({
|
|
1194
|
+
bindingStore: params.bindingStore,
|
|
1195
|
+
identity,
|
|
1196
|
+
threadId,
|
|
1197
|
+
run
|
|
1198
|
+
});
|
|
1199
|
+
else await run();
|
|
1196
1200
|
}
|
|
1197
1201
|
async function projectConversationSourceHistory(source, target, config) {
|
|
1198
1202
|
const storePath = resolveStorePath(config?.session?.store, { agentId: source.agentId });
|
|
@@ -1202,12 +1206,13 @@ async function projectConversationSourceHistory(source, target, config) {
|
|
|
1202
1206
|
storePath
|
|
1203
1207
|
});
|
|
1204
1208
|
if (!sessionKey) return;
|
|
1205
|
-
const
|
|
1209
|
+
const entries = await readVisibleSessionTranscriptMessageEntries({
|
|
1206
1210
|
agentId: source.agentId,
|
|
1207
1211
|
sessionId: source.sessionId,
|
|
1208
1212
|
sessionKey,
|
|
1209
1213
|
storePath
|
|
1210
|
-
})
|
|
1214
|
+
});
|
|
1215
|
+
const history = projectBoundedCodexVisibleSessionHistory(entries);
|
|
1211
1216
|
if (history.length === 0) return;
|
|
1212
1217
|
const clientLease = retainSharedCodexAppServerClientByInstanceId(target.clientId);
|
|
1213
1218
|
if (!clientLease) throw new Error("Codex conversation source history lost its bound client owner.");
|
|
@@ -1221,6 +1226,7 @@ async function projectConversationSourceHistory(source, target, config) {
|
|
|
1221
1226
|
}
|
|
1222
1227
|
}
|
|
1223
1228
|
function isCodexThreadNotFoundError(error) {
|
|
1229
|
+
if (isCodexAppServerOverloadError(error) || isCodexAppServerUnsafeSubscriptionError(error)) return false;
|
|
1224
1230
|
const message = formatErrorMessage(error);
|
|
1225
1231
|
return /\bthread not found:/iu.test(message) || /\bbound Codex conversation has no thread binding\b/u.test(message);
|
|
1226
1232
|
}
|
|
@@ -1391,7 +1397,8 @@ async function buildCodexOAuthCredential(source) {
|
|
|
1391
1397
|
} : null;
|
|
1392
1398
|
}
|
|
1393
1399
|
async function buildCodexApiKeyCredential(source) {
|
|
1394
|
-
const
|
|
1400
|
+
const raw = await readJsonObject(source.authPath);
|
|
1401
|
+
const key = normalizeOptionalString(raw.OPENAI_API_KEY);
|
|
1395
1402
|
if (!key) return null;
|
|
1396
1403
|
return {
|
|
1397
1404
|
kind: "api_key",
|
|
@@ -2123,9 +2130,9 @@ function sanitizePluginName(value) {
|
|
|
2123
2130
|
//#region extensions/codex/src/migration/targets.ts
|
|
2124
2131
|
function resolveCodexMigrationTargets(ctx) {
|
|
2125
2132
|
const cfg = ctx.config;
|
|
2126
|
-
const agentId = ctx.targetAgentId ?? resolveDefaultAgentId(cfg);
|
|
2133
|
+
const agentId = ctx.targetAgentId ?? resolveDefaultAgentId$1(cfg);
|
|
2127
2134
|
const workspaceDir = resolveAgentWorkspaceDir(cfg, agentId);
|
|
2128
|
-
const configuredAgentDir = resolveAgentConfig(cfg, agentId)?.agentDir?.trim();
|
|
2135
|
+
const configuredAgentDir = resolveAgentConfig$1(cfg, agentId)?.agentDir?.trim();
|
|
2129
2136
|
return {
|
|
2130
2137
|
workspaceDir,
|
|
2131
2138
|
agentDir: ctx.runtime?.agent?.resolveAgentDir(cfg, agentId) ?? (configuredAgentDir ? resolveHomePath(configuredAgentDir) : void 0) ?? path.join(ctx.stateDir, "agents", agentId, "agent")
|
|
@@ -2699,7 +2706,8 @@ async function requestTargetCodexAppServerJson(params) {
|
|
|
2699
2706
|
});
|
|
2700
2707
|
if (hasOpenAiCuratedMarketplace(lastResponse)) return lastResponse;
|
|
2701
2708
|
if (Date.now() >= discoveryDeadline) return lastResponse;
|
|
2702
|
-
|
|
2709
|
+
const waitMs = Math.min(TARGET_CODEX_MARKETPLACE_DISCOVERY_POLL_MS, discoveryDeadline - Date.now());
|
|
2710
|
+
await sleep(waitMs);
|
|
2703
2711
|
} while (Date.now() < discoveryDeadline);
|
|
2704
2712
|
return lastResponse;
|
|
2705
2713
|
}
|
|
@@ -2866,7 +2874,7 @@ function createCodexPluginsTool(options) {
|
|
|
2866
2874
|
const marketplace = typeof params.marketplace === "string" ? params.marketplace.trim() : void 0;
|
|
2867
2875
|
const limit = typeof params.limit === "number" && Number.isInteger(params.limit) ? Math.max(1, Math.min(params.limit, 20)) : 12;
|
|
2868
2876
|
const pluginConfig = options.getPluginConfig();
|
|
2869
|
-
const binding = options.context.sessionId ?
|
|
2877
|
+
const binding = options.context.sessionId ? options.bindingStore.read(sessionBindingIdentity({
|
|
2870
2878
|
sessionId: options.context.sessionId,
|
|
2871
2879
|
sessionKey: options.context.sessionKey,
|
|
2872
2880
|
agentId: options.context.agentId,
|
|
@@ -3041,11 +3049,11 @@ function createCodexThreadsTool(options) {
|
|
|
3041
3049
|
agentId: options.context.agentId,
|
|
3042
3050
|
config: runtimeConfig()
|
|
3043
3051
|
});
|
|
3044
|
-
const currentBinding =
|
|
3045
|
-
const requestOptions =
|
|
3052
|
+
const currentBinding = (session) => session ? options.bindingStore.read(currentIdentity(session.sessionId)) : void 0;
|
|
3053
|
+
const requestOptions = (pluginConfig) => {
|
|
3046
3054
|
const plugin = readCodexPluginConfig(pluginConfig);
|
|
3047
3055
|
const session = currentSession();
|
|
3048
|
-
const binding =
|
|
3056
|
+
const binding = currentBinding(session);
|
|
3049
3057
|
if (binding?.connectionScope === "supervision") {
|
|
3050
3058
|
const connection = resolveCodexBindingAppServerConnection({
|
|
3051
3059
|
binding,
|
|
@@ -3106,7 +3114,7 @@ function createCodexThreadsTool(options) {
|
|
|
3106
3114
|
sourceKinds: [...CODEX_INTERACTIVE_THREAD_SOURCE_KINDS],
|
|
3107
3115
|
...cursor ? { cursor } : {},
|
|
3108
3116
|
...searchTerm ? { searchTerm } : {}
|
|
3109
|
-
},
|
|
3117
|
+
}, requestOptions(pluginConfig));
|
|
3110
3118
|
return jsonResult(mayReadRawTranscripts ? response : redactNativeThreadResponse(response));
|
|
3111
3119
|
}
|
|
3112
3120
|
const threadId = readThreadId(params);
|
|
@@ -3116,7 +3124,7 @@ function createCodexThreadsTool(options) {
|
|
|
3116
3124
|
const response = await request(pluginConfig, CODEX_CONTROL_METHODS.readThread, {
|
|
3117
3125
|
threadId,
|
|
3118
3126
|
includeTurns
|
|
3119
|
-
},
|
|
3127
|
+
}, requestOptions(pluginConfig));
|
|
3120
3128
|
return jsonResult(mayReadRawTranscripts ? response : redactNativeThreadResponse(response));
|
|
3121
3129
|
}
|
|
3122
3130
|
if ((action === "fork" || action === "rename" || action === "archive" || action === "unarchive") && supervision?.enabled === true && supervision.allowWriteControls !== true) throw new Error("Codex native thread mutations are disabled for this codex plugin supervision config.");
|
|
@@ -3128,7 +3136,7 @@ function createCodexThreadsTool(options) {
|
|
|
3128
3136
|
await request(pluginConfig, CODEX_CONTROL_METHODS.renameThread, {
|
|
3129
3137
|
threadId,
|
|
3130
3138
|
name
|
|
3131
|
-
},
|
|
3139
|
+
}, requestOptions(pluginConfig));
|
|
3132
3140
|
return jsonResult({
|
|
3133
3141
|
action,
|
|
3134
3142
|
threadId,
|
|
@@ -3136,17 +3144,17 @@ function createCodexThreadsTool(options) {
|
|
|
3136
3144
|
});
|
|
3137
3145
|
}
|
|
3138
3146
|
if (action === "unarchive") {
|
|
3139
|
-
const response = await request(pluginConfig, CODEX_CONTROL_METHODS.unarchiveThread, { threadId },
|
|
3147
|
+
const response = await request(pluginConfig, CODEX_CONTROL_METHODS.unarchiveThread, { threadId }, requestOptions(pluginConfig));
|
|
3140
3148
|
return jsonResult(mayReadRawTranscripts ? response : redactNativeThreadResponse(response));
|
|
3141
3149
|
}
|
|
3142
3150
|
const session = currentSession();
|
|
3143
|
-
const binding =
|
|
3151
|
+
const binding = currentBinding(session);
|
|
3144
3152
|
if (action === "archive") {
|
|
3145
3153
|
if (params.confirm !== true) throw new Error("confirm=true is required to archive a native Codex thread");
|
|
3146
3154
|
if (!session) throw new Error("cannot safely archive a native Codex thread without a session identity");
|
|
3147
3155
|
const identity = currentIdentity(session.sessionId);
|
|
3148
3156
|
await options.bindingStore.withThreadArchiveFence(async () => {
|
|
3149
|
-
const archivedBinding =
|
|
3157
|
+
const archivedBinding = currentBinding(session);
|
|
3150
3158
|
if (archivedBinding?.threadId === threadId) {
|
|
3151
3159
|
if (session.modelSelectionLocked) throw new ModelSelectionLockedError();
|
|
3152
3160
|
assertCodexBindingMayBeReplaced(archivedBinding, "archiving its bound native thread");
|
|
@@ -3154,20 +3162,20 @@ function createCodexThreadsTool(options) {
|
|
|
3154
3162
|
assertThreadMayBeArchived(await request(pluginConfig, CODEX_CONTROL_METHODS.readThread, {
|
|
3155
3163
|
threadId,
|
|
3156
3164
|
includeTurns: false
|
|
3157
|
-
},
|
|
3165
|
+
}, requestOptions(pluginConfig)), threadId);
|
|
3158
3166
|
if (await options.bindingStore.hasOtherThreadOwner(threadId, identity)) throw new Error("cannot archive a native Codex thread owned by another OpenClaw session");
|
|
3159
3167
|
await assertCodexArchiveDescendantsUnowned({
|
|
3160
3168
|
bindingStore: options.bindingStore,
|
|
3161
3169
|
threadId,
|
|
3162
|
-
listPage: async (listParams) => await request(pluginConfig, CODEX_CONTROL_METHODS.listThreads, listParams,
|
|
3170
|
+
listPage: async (listParams) => await request(pluginConfig, CODEX_CONTROL_METHODS.listThreads, listParams, requestOptions(pluginConfig)),
|
|
3163
3171
|
assertDescendantIdle: async (descendantThreadId) => {
|
|
3164
3172
|
assertThreadMayBeArchived(await request(pluginConfig, CODEX_CONTROL_METHODS.readThread, {
|
|
3165
3173
|
threadId: descendantThreadId,
|
|
3166
3174
|
includeTurns: false
|
|
3167
|
-
},
|
|
3175
|
+
}, requestOptions(pluginConfig)), descendantThreadId);
|
|
3168
3176
|
}
|
|
3169
3177
|
});
|
|
3170
|
-
await request(pluginConfig, CODEX_CONTROL_METHODS.archiveThread, { threadId },
|
|
3178
|
+
await request(pluginConfig, CODEX_CONTROL_METHODS.archiveThread, { threadId }, requestOptions(pluginConfig));
|
|
3171
3179
|
if (archivedBinding?.threadId === threadId) await options.bindingStore.mutate(identity, {
|
|
3172
3180
|
kind: "clear",
|
|
3173
3181
|
threadId
|
|
@@ -3189,13 +3197,13 @@ function createCodexThreadsTool(options) {
|
|
|
3189
3197
|
assertThreadMayBeForked(await request(pluginConfig, CODEX_CONTROL_METHODS.readThread, {
|
|
3190
3198
|
threadId,
|
|
3191
3199
|
includeTurns: false
|
|
3192
|
-
},
|
|
3200
|
+
}, requestOptions(pluginConfig)), threadId);
|
|
3193
3201
|
}
|
|
3194
3202
|
const response = await request(pluginConfig, CODEX_CONTROL_METHODS.forkThread, {
|
|
3195
3203
|
threadId,
|
|
3196
3204
|
threadSource: "user",
|
|
3197
3205
|
excludeTurns: true
|
|
3198
|
-
},
|
|
3206
|
+
}, requestOptions(pluginConfig));
|
|
3199
3207
|
if (!isJsonObject(response) || !isJsonObject(response.thread)) throw new Error("Codex app-server returned an invalid thread/fork response");
|
|
3200
3208
|
const forkThreadId = typeof response.thread.id === "string" && response.thread.id.trim() ? response.thread.id : void 0;
|
|
3201
3209
|
if (!forkThreadId) throw new Error("Codex app-server thread/fork response did not include a thread id");
|
|
@@ -3254,7 +3262,8 @@ function createCodexNodeExecServerCommand() {
|
|
|
3254
3262
|
} catch {
|
|
3255
3263
|
throw new Error("Codex node exec-server requires a valid workspace request.");
|
|
3256
3264
|
}
|
|
3257
|
-
|
|
3265
|
+
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.");
|
|
3266
|
+
const placement = parseCodexNodePlacementWorkspace(request.placement);
|
|
3258
3267
|
if (!context?.acquireManagedWorkspace || context.sessionKey !== placement.sessionKey || io.signal.aborted) throw new Error("Codex node exec-server requires active managed placement authority.");
|
|
3259
3268
|
const workspace = context.acquireManagedWorkspace({
|
|
3260
3269
|
workspaceDir: placement.cwd,
|
|
@@ -3266,11 +3275,14 @@ function createCodexNodeExecServerCommand() {
|
|
|
3266
3275
|
const frames = io.frames;
|
|
3267
3276
|
let unsubscribe;
|
|
3268
3277
|
try {
|
|
3269
|
-
|
|
3278
|
+
if (!context.prepareExecAuthorization) throw new Error("Codex node execution requires node-local exec policy support; update the node.");
|
|
3279
|
+
const assertExecAuthorized = context.prepareExecAuthorization(request.authorization);
|
|
3280
|
+
const { runCodexNodeExecServer } = await import("./node-exec-server.runtime-nfbUOtUB.js");
|
|
3270
3281
|
return await runCodexNodeExecServer({
|
|
3271
3282
|
workspaceDir: workspace.workspaceDir,
|
|
3272
3283
|
io,
|
|
3273
3284
|
activeProcesses,
|
|
3285
|
+
assertExecAuthorized,
|
|
3274
3286
|
onFrameReceiver: (receiver) => {
|
|
3275
3287
|
unsubscribe = frames.onMessage(receiver);
|
|
3276
3288
|
}
|
|
@@ -3285,17 +3297,21 @@ function createCodexNodeExecServerCommand() {
|
|
|
3285
3297
|
}
|
|
3286
3298
|
};
|
|
3287
3299
|
}
|
|
3288
|
-
/** Keeps node
|
|
3300
|
+
/** Keeps node launch behind command opt-in and a live Full owner or human decision. */
|
|
3289
3301
|
function createCodexNodeExecServerInvokePolicy() {
|
|
3290
3302
|
return {
|
|
3291
3303
|
commands: [CODEX_NODE_EXEC_SERVER_COMMAND],
|
|
3292
3304
|
dangerous: true,
|
|
3305
|
+
standingApproval: {
|
|
3306
|
+
kind: "placement",
|
|
3307
|
+
scope: CODEX_NODE_EXEC_SERVER_CAPABILITY
|
|
3308
|
+
},
|
|
3293
3309
|
classifyRisk: () => ({
|
|
3294
3310
|
level: "high",
|
|
3295
3311
|
family: CODEX_NODE_EXEC_SERVER_CAPABILITY
|
|
3296
3312
|
}),
|
|
3297
3313
|
handle: async (context) => {
|
|
3298
|
-
if (
|
|
3314
|
+
if (context.risk?.level !== "high") return {
|
|
3299
3315
|
ok: false,
|
|
3300
3316
|
code: "CODEX_NODE_EXEC_APPROVAL_REQUIRED",
|
|
3301
3317
|
message: "Codex node execution requires an available approval reviewer."
|
|
@@ -3310,18 +3326,52 @@ function createCodexNodeExecServerInvokePolicy() {
|
|
|
3310
3326
|
message: "Codex node execution requires an exact managed placement workspace."
|
|
3311
3327
|
};
|
|
3312
3328
|
}
|
|
3313
|
-
const
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
}
|
|
3329
|
+
const workspace = {
|
|
3330
|
+
workspaceDir: placement.cwd,
|
|
3331
|
+
environmentId: placement.environmentId,
|
|
3332
|
+
sessionId: placement.sessionId,
|
|
3333
|
+
ownerEpoch: placement.ownerEpoch,
|
|
3334
|
+
sessionKey: placement.sessionKey
|
|
3335
|
+
};
|
|
3336
|
+
const fullLaunch = await context.invokeNodeWithSessionFull?.({
|
|
3337
|
+
workspace,
|
|
3338
|
+
createParams: () => ({
|
|
3339
|
+
placement,
|
|
3340
|
+
authorization: "session-full"
|
|
3341
|
+
})
|
|
3342
|
+
});
|
|
3343
|
+
if (fullLaunch) return fullLaunch;
|
|
3344
|
+
if (!context.approvals) return {
|
|
3320
3345
|
ok: false,
|
|
3321
|
-
code: "
|
|
3322
|
-
message: "Codex node execution requires
|
|
3346
|
+
code: "CODEX_NODE_EXEC_APPROVAL_REQUIRED",
|
|
3347
|
+
message: "Codex node execution requires an available approval reviewer."
|
|
3323
3348
|
};
|
|
3324
|
-
|
|
3349
|
+
const nodeName = context.node?.displayName ?? context.nodeId;
|
|
3350
|
+
const approval = await context.approvals.request({
|
|
3351
|
+
title: "Run Codex on this node placement",
|
|
3352
|
+
description: `Allows arbitrary processes and filesystem access across the node account, not only this workspace. Allow always applies only while this exact placement remains active. ${nodeName}: ${placement.cwd}`,
|
|
3353
|
+
severity: "critical",
|
|
3354
|
+
allowedDecisions: ["allow-once", "allow-always"]
|
|
3355
|
+
});
|
|
3356
|
+
if (approval.decision !== "allow-once" && approval.decision !== "allow-always") {
|
|
3357
|
+
if (approval.decision === "deny") return {
|
|
3358
|
+
ok: false,
|
|
3359
|
+
code: "CODEX_NODE_EXEC_APPROVAL_DENIED",
|
|
3360
|
+
message: "Codex node execution was denied. Retry the action and choose Allow once or Allow always to continue."
|
|
3361
|
+
};
|
|
3362
|
+
return {
|
|
3363
|
+
ok: false,
|
|
3364
|
+
code: "CODEX_NODE_EXEC_APPROVAL_EXPIRED",
|
|
3365
|
+
message: "Codex node execution approval expired before a decision. Retry the action and approve the new request."
|
|
3366
|
+
};
|
|
3367
|
+
}
|
|
3368
|
+
return await context.invokeNode({
|
|
3369
|
+
workspace,
|
|
3370
|
+
params: {
|
|
3371
|
+
placement,
|
|
3372
|
+
authorization: "human-approved"
|
|
3373
|
+
}
|
|
3374
|
+
});
|
|
3325
3375
|
}
|
|
3326
3376
|
};
|
|
3327
3377
|
}
|
|
@@ -4107,7 +4157,7 @@ function createCodexSupervisionTools(options) {
|
|
|
4107
4157
|
}
|
|
4108
4158
|
//#endregion
|
|
4109
4159
|
//#region extensions/codex/src/web-search-provider.ts
|
|
4110
|
-
const loadCodexWebSearchRuntime = createLazyRuntimeModule(() => import("./web-search-provider.runtime-
|
|
4160
|
+
const loadCodexWebSearchRuntime = createLazyRuntimeModule(() => import("./web-search-provider.runtime-DKQn67A7.js"));
|
|
4111
4161
|
const CodexWebSearchSchema = {
|
|
4112
4162
|
type: "object",
|
|
4113
4163
|
properties: { query: {
|
|
@@ -4143,13 +4193,13 @@ const ENDED_SESSION_REASONS = /* @__PURE__ */ new Set([
|
|
|
4143
4193
|
"new",
|
|
4144
4194
|
"reset",
|
|
4145
4195
|
"idle",
|
|
4146
|
-
"daily"
|
|
4147
|
-
"deleted"
|
|
4196
|
+
"daily"
|
|
4148
4197
|
]);
|
|
4149
4198
|
var codex_default = definePluginEntry({
|
|
4150
4199
|
id: "codex",
|
|
4151
4200
|
name: "Codex",
|
|
4152
4201
|
description: "Codex app-server harness and native session supervision.",
|
|
4202
|
+
reload: { noopPrefixes: ["plugins.entries.codex.config.codexPlugins"] },
|
|
4153
4203
|
register(api) {
|
|
4154
4204
|
setManagedCodexPluginRoot(api.rootDir);
|
|
4155
4205
|
const resolveCurrentConfig = () => api.runtime.config?.current ? api.runtime.config.current() : void 0;
|
|
@@ -4169,6 +4219,7 @@ var codex_default = definePluginEntry({
|
|
|
4169
4219
|
const resolveCurrentPluginConfig = () => resolvePluginConfig(resolveCurrentConfig);
|
|
4170
4220
|
const appServerConfig = readCodexPluginConfig(resolveCurrentPluginConfig()).appServer;
|
|
4171
4221
|
api.registerService(createCodexDesktopGenerationService({ onGenerationChange: retireSharedCodexAppServerClientsBeforeDesktopGeneration }));
|
|
4222
|
+
api.registerService(createCodexAppServerProcessReaperService());
|
|
4172
4223
|
if (appServerConfig?.transport === "websocket") api.registerService(createCodexAppServerConnectionHealthService({
|
|
4173
4224
|
getPluginConfig: resolveCurrentPluginConfig,
|
|
4174
4225
|
getRuntimeConfig: resolveCurrentConfig
|
|
@@ -4181,9 +4232,10 @@ var codex_default = definePluginEntry({
|
|
|
4181
4232
|
overflowPolicy: "reject-new"
|
|
4182
4233
|
});
|
|
4183
4234
|
const lazyBindingStateStore = {
|
|
4184
|
-
|
|
4235
|
+
deleteIf: (key, predicate) => openBindingStateStore().deleteIf(key, predicate),
|
|
4185
4236
|
entries: () => openBindingStateStore().entries(),
|
|
4186
4237
|
lookup: (key) => openBindingStateStore().lookup(key),
|
|
4238
|
+
registerIfAbsent: (key, value, options) => openBindingStateStore().registerIfAbsent(key, value, options),
|
|
4187
4239
|
get update() {
|
|
4188
4240
|
const store = openBindingStateStore();
|
|
4189
4241
|
return store.update?.bind(store);
|
|
@@ -4196,10 +4248,12 @@ var codex_default = definePluginEntry({
|
|
|
4196
4248
|
});
|
|
4197
4249
|
const bindingStore = createLazyCodexAppServerBindingStore(lazyBindingStateStore, {
|
|
4198
4250
|
entries: () => openManagedThreadStateStore().entries(),
|
|
4251
|
+
lookup: (key) => openManagedThreadStateStore().lookup(key),
|
|
4199
4252
|
registerIfAbsent: (key, value) => openManagedThreadStateStore().registerIfAbsent(key, value)
|
|
4200
4253
|
});
|
|
4201
4254
|
registerCodexCliMetadata(api);
|
|
4202
4255
|
const sessionCatalogControlFactory = createCodexSessionCatalogControl({
|
|
4256
|
+
managedThreads: bindingStore.managedThreads,
|
|
4203
4257
|
config: api.config,
|
|
4204
4258
|
getPluginConfig: resolveCurrentPluginConfig,
|
|
4205
4259
|
getRuntimeConfig: resolveCurrentConfig
|
|
@@ -4333,22 +4387,6 @@ var codex_default = definePluginEntry({
|
|
|
4333
4387
|
})
|
|
4334
4388
|
}));
|
|
4335
4389
|
api.onConversationBindingResolved?.((event) => codexConversationBindingRuntime.handleBindingResolved(event, { bindingStore }));
|
|
4336
|
-
api.on("after_compaction", async (event, ctx) => {
|
|
4337
|
-
const previousSessionId = event.previousSessionId?.trim();
|
|
4338
|
-
const sessionId = ctx.sessionId?.trim();
|
|
4339
|
-
if (!previousSessionId || !sessionId || previousSessionId === sessionId) return;
|
|
4340
|
-
const config = resolveCurrentConfig();
|
|
4341
|
-
const sessionKey = ctx.sessionKey?.trim();
|
|
4342
|
-
const { sessionBindingIdentity } = await import("./session-binding-Bcynfd-_.js").then((n) => n.f);
|
|
4343
|
-
const identity = sessionBindingIdentity({
|
|
4344
|
-
sessionId,
|
|
4345
|
-
...sessionKey ? { sessionKey } : {},
|
|
4346
|
-
...ctx.agentId ? { agentId: ctx.agentId } : {},
|
|
4347
|
-
...config ? { config } : {}
|
|
4348
|
-
});
|
|
4349
|
-
const adopted = await bindingStore.adoptSessionGeneration(identity, previousSessionId);
|
|
4350
|
-
if (adopted === "conflict") api.logger.warn?.(`codex: could not adopt compacted session generation ${sessionId} (${adopted}); secondary native compaction will skip`);
|
|
4351
|
-
});
|
|
4352
4390
|
api.on("session_end", async (event, ctx) => {
|
|
4353
4391
|
if (!event.reason || !ENDED_SESSION_REASONS.has(event.reason)) return;
|
|
4354
4392
|
const sessionKey = event.sessionKey ?? ctx.sessionKey;
|
|
@@ -4357,7 +4395,7 @@ var codex_default = definePluginEntry({
|
|
|
4357
4395
|
if (endedSessionKey && nextSessionKey && nextSessionKey !== endedSessionKey) return;
|
|
4358
4396
|
if (event.nextSessionId?.trim() === event.sessionId.trim()) return;
|
|
4359
4397
|
const config = resolveCurrentConfig();
|
|
4360
|
-
const [{ sessionBindingIdentity }, { retireCodexAppServerSessionGeneration }] = await Promise.all([import("./session-binding-
|
|
4398
|
+
const [{ sessionBindingIdentity }, { retireCodexAppServerSessionGeneration }] = await Promise.all([import("./session-binding-4Ki04sW-.js").then((n) => n.d), import("./session-retirement-DNdmYdFc.js")]);
|
|
4361
4399
|
await retireCodexAppServerSessionGeneration({
|
|
4362
4400
|
bindingStore,
|
|
4363
4401
|
identity: sessionBindingIdentity({
|