@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
|
@@ -1,27 +1,30 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
import { s as
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import { i as
|
|
16
|
-
import { n as
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
-
import { i as readCodexComputerUseStatus, r as installCodexComputerUse, t as defaultCodexPluginMetadataCache } from "./plugin-metadata-cache-
|
|
1
|
+
import { m as CODEX_PLUGINS_MARKETPLACE_NAME, n as isCodexFastServiceTier } from "./config-utils-C57JiJrU.js";
|
|
2
|
+
import { l as sessionBindingIdentity, t as bindingStoreKey } from "./session-binding-record-CyaXZvTe.js";
|
|
3
|
+
import { B as isJsonObject, i as resolveCodexAppServerRuntimeOptions } from "./config-CyapYSji.js";
|
|
4
|
+
import { Bt as resolveCodexAppServerAuthAccountCacheKey, Et as hasCodexAppServerLiveThread, Ht as resolveCodexAppServerAuthProfileIdForAgent, Q as assertCodexThreadAcceptsDirectInput, Wt as resolveCodexAppServerFallbackApiKeyCacheKey, c as getLeasedSharedCodexAppServerClient, h as releaseLeasedSharedCodexAppServerClient, tt as assertCodexThreadResumeResponse, wt as consumeCodexAppServerLiveThread } from "./shared-client-CKhX2kFt.js";
|
|
5
|
+
import { l as resolveCodexSessionBinding, n as assertCodexBindingMayBeReplaced, o as normalizeCodexAppServerBindingModelProvider, r as createCodexSessionGenerationSupersededError } from "./session-binding-4Ki04sW-.js";
|
|
6
|
+
import { a as closeCodexStartupClientBestEffort } from "./attempt-client-cleanup-Bp1ZOnk2.js";
|
|
7
|
+
import { t as listAllCodexAppServerModels } from "./models-CcrgSMQR.js";
|
|
8
|
+
import { c as defaultCodexAppInventoryCache, i as buildCodexPluginAppCacheKey } from "./thread-resume-BLgqkUc1.js";
|
|
9
|
+
import { At as refreshCodexPluginRuntimeState, Mt as isOpenAiCuratedMarketplaceName } from "./thread-lifecycle-DPK30jad.js";
|
|
10
|
+
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";
|
|
11
|
+
import { r as assertCodexSupervisionThreadLineage, s as resolveCodexBindingAppServerConnection } from "./thread-policy-CTalhWFy.js";
|
|
12
|
+
import { c as resolveCodexNativeSandboxBlock, s as resolveCodexNativeExecutionBlock } from "./request-C8H22rPi.js";
|
|
13
|
+
import { t as CODEX_CONTROL_METHODS } from "./capabilities-B1mgvpP8.js";
|
|
14
|
+
import { s as summarizeCodexAccountUsage } from "./rate-limits-Fx_l4eNa.js";
|
|
15
|
+
import { a as formatCodexDisplayText, c as formatComputerUseStatus, d as formatSkills, f as formatThreads, i as formatAccount, l as formatList, n as buildHelp, o as formatCodexStatus, r as escapeCodexChatText, s as formatCodexTextForDisplay, t as CODEX_RESUME_SAFE_THREAD_ID_PATTERN, u as formatModels } from "./command-formatters-DSbGMXA0.js";
|
|
16
|
+
import { _ as hasCodexAdminScope, a as parseCodexPermissionsModeArg, c as setCodexConversationModel, d as stopCodexConversationTurn, g as canMutateCodexHost, h as CODEX_NATIVE_EXECUTION_AUTH_ERROR, i as parseCodexFastModeArg, l as setCodexConversationPermissions, m as CODEX_HOST_INSPECTION_AUTH_ERROR, n as parseCodexPluginMarketplaceId, o as readCodexConversationActiveTurn, p as CODEX_FULL_PERMISSIONS_AUTH_ERROR, r as formatPermissionsMode, s as setCodexConversationFastMode, t as discoverCodexMarketplacePlugins, u as steerCodexConversationTurn } from "./plugin-marketplace-discovery-B7gHXJ3d.js";
|
|
17
|
+
import { i as readCodexConversationBindingData, n as createCodexCliNodeConversationBindingData, o as resolveCodexDefaultWorkspaceDir, r as createCodexConversationBindingData } from "./conversation-binding-data-BiodpIzq.js";
|
|
18
|
+
import { c as readCodexStatusProbes, l as requestOptions, p as formatCodexCliSessions, s as codexControlRequest, u as safeCodexControlRequest } from "./session-catalog-B47uwekb.js";
|
|
19
|
+
import { i as readCodexComputerUseStatus, r as installCodexComputerUse, t as defaultCodexPluginMetadataCache } from "./plugin-metadata-cache-BwCLTY_U.js";
|
|
20
20
|
import { normalizeOptionalString, normalizeUniqueStringEntries } from "openclaw/plugin-sdk/string-coerce-runtime";
|
|
21
|
-
import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
|
|
22
21
|
import crypto from "node:crypto";
|
|
23
|
-
import {
|
|
22
|
+
import { resolveSessionAgentIdsStrict } from "openclaw/plugin-sdk/agent-scope-runtime";
|
|
24
23
|
import { getSessionEntry, resolveStorePath } from "openclaw/plugin-sdk/session-store-runtime";
|
|
24
|
+
import { parseStrictPositiveInteger } from "openclaw/plugin-sdk/number-runtime";
|
|
25
|
+
import { isDeepStrictEqual } from "node:util";
|
|
26
|
+
import { ensureAuthProfileStore, resolveAgentDir as resolveAgentDir$1, resolveAuthProfileEligibility, resolveProfileUnusableUntilForDisplay } from "openclaw/plugin-sdk/agent-runtime";
|
|
27
|
+
import { findNormalizedProviderValue, resolveAuthProfileOrder } from "openclaw/plugin-sdk/provider-auth";
|
|
25
28
|
import { truncateUtf16Safe } from "openclaw/plugin-sdk/text-utility-runtime";
|
|
26
29
|
import { expectDefined } from "openclaw/plugin-sdk/expect-runtime";
|
|
27
30
|
import { parseAgentSessionKey } from "openclaw/plugin-sdk/routing";
|
|
@@ -591,7 +594,8 @@ function parseCodexCliSessionsArgs(args) {
|
|
|
591
594
|
continue;
|
|
592
595
|
}
|
|
593
596
|
if (arg === "--limit") {
|
|
594
|
-
const
|
|
597
|
+
const value = readRequiredOptionValue(args, index);
|
|
598
|
+
const parsedLimit = parseStrictPositiveInteger(value);
|
|
595
599
|
if (parsedLimit === void 0) {
|
|
596
600
|
parsed.help = true;
|
|
597
601
|
continue;
|
|
@@ -752,11 +756,10 @@ const CODEX_DIAGNOSTICS_COOLDOWN_MS = 6e4;
|
|
|
752
756
|
const CODEX_DIAGNOSTICS_ERROR_MAX_CHARS = 500;
|
|
753
757
|
const CODEX_DIAGNOSTICS_COOLDOWN_MAX_THREADS = 100;
|
|
754
758
|
const CODEX_DIAGNOSTICS_COOLDOWN_MAX_SCOPES = 100;
|
|
755
|
-
const CODEX_DIAGNOSTICS_CONFIRMATION_TTL_MS =
|
|
759
|
+
const CODEX_DIAGNOSTICS_CONFIRMATION_TTL_MS = 3e5;
|
|
756
760
|
const CODEX_DIAGNOSTICS_CONFIRMATION_MAX_REQUESTS_PER_SCOPE = 100;
|
|
757
761
|
const CODEX_DIAGNOSTICS_CONFIRMATION_MAX_SCOPES = 100;
|
|
758
762
|
const CODEX_DIAGNOSTICS_SCOPE_FIELD_MAX_CHARS = 128;
|
|
759
|
-
const CODEX_RESUME_SAFE_THREAD_ID_PATTERN = /^[A-Za-z0-9._:-]+$/;
|
|
760
763
|
const { lastUploadByThread: lastCodexDiagnosticsUploadByThread, lastUploadByScope: lastCodexDiagnosticsUploadByScope, pendingConfirmations: pendingCodexDiagnosticsConfirmations, pendingTokensByScope: pendingCodexDiagnosticsConfirmationTokensByScope } = codexDiagnosticsFeedbackState;
|
|
761
764
|
function normalizeDiagnosticsReason(note) {
|
|
762
765
|
const normalized = normalizeOptionalString(note);
|
|
@@ -909,7 +912,7 @@ function formatCodexDiagnosticsTargetLines(targets) {
|
|
|
909
912
|
}
|
|
910
913
|
function formatCodexDiagnosticsTargetBlock(target, index) {
|
|
911
914
|
const lines = [`Session ${index + 1}`];
|
|
912
|
-
if (target.channel) lines.push(`Channel: ${
|
|
915
|
+
if (target.channel) lines.push(`Channel: ${formatCodexDisplayText(target.channel)}`);
|
|
913
916
|
if (target.sessionKey) lines.push(`OpenClaw session key: ${formatCodexCopyableValueForDisplay(target.sessionKey)}`);
|
|
914
917
|
if (target.sessionId) lines.push(`OpenClaw session id: ${formatCodexCopyableValueForDisplay(target.sessionId)}`);
|
|
915
918
|
lines.push(`Codex thread id: ${formatCodexCopyableValueForDisplay(target.threadId)}`);
|
|
@@ -918,30 +921,18 @@ function formatCodexDiagnosticsTargetBlock(target, index) {
|
|
|
918
921
|
}
|
|
919
922
|
function formatCodexDiagnosticsTargetLine(target) {
|
|
920
923
|
const parts = [];
|
|
921
|
-
if (target.channel) parts.push(`channel ${
|
|
924
|
+
if (target.channel) parts.push(`channel ${formatCodexDisplayText(target.channel)}`);
|
|
922
925
|
const sessionLabel = target.sessionId || target.sessionKey;
|
|
923
|
-
if (sessionLabel) parts.push(`OpenClaw session ${
|
|
924
|
-
parts.push(`Codex thread ${
|
|
926
|
+
if (sessionLabel) parts.push(`OpenClaw session ${formatCodexDisplayText(sessionLabel)}`);
|
|
927
|
+
parts.push(`Codex thread ${formatCodexDisplayText(target.threadId)}`);
|
|
925
928
|
return `- ${parts.join(", ")}`;
|
|
926
929
|
}
|
|
927
|
-
function escapeCodexChatText(value) {
|
|
928
|
-
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll("@", "@").replaceAll("`", "`").replaceAll("[", "[").replaceAll("]", "]").replaceAll("(", "(").replaceAll(")", ")").replaceAll("*", "∗").replaceAll("_", "_").replaceAll("~", "~").replaceAll("|", "|");
|
|
929
|
-
}
|
|
930
|
-
function formatCodexTextForDisplay(value) {
|
|
931
|
-
let safe = "";
|
|
932
|
-
for (const character of value) {
|
|
933
|
-
const codePoint = character.codePointAt(0);
|
|
934
|
-
safe += codePoint != null && isUnsafeDisplayCodePoint(codePoint) ? "?" : character;
|
|
935
|
-
}
|
|
936
|
-
safe = safe.trim();
|
|
937
|
-
return safe || "<unknown>";
|
|
938
|
-
}
|
|
939
930
|
function readCodexDiagnosticsTargetsCooldownMessage(targets, ctx, now, options = {}) {
|
|
940
931
|
for (const target of targets) {
|
|
941
932
|
const cooldownMs = readCodexDiagnosticsCooldownMs(target.threadId, now);
|
|
942
933
|
if (cooldownMs > 0) {
|
|
943
934
|
if (options.includeThreadId === false) return `Codex diagnostics were already sent for one of these Codex threads recently. Try again in ${Math.ceil(cooldownMs / 1e3)}s.`;
|
|
944
|
-
return `Codex diagnostics were already sent for thread ${
|
|
935
|
+
return `Codex diagnostics were already sent for thread ${formatCodexDisplayText(target.threadId)} recently. Try again in ${Math.ceil(cooldownMs / 1e3)}s.`;
|
|
945
936
|
}
|
|
946
937
|
}
|
|
947
938
|
const scopeCooldownMs = readCodexDiagnosticsScopeCooldownMs(options.cooldownScope ?? readCodexDiagnosticsCooldownScope(ctx), now);
|
|
@@ -973,12 +964,6 @@ function buildDiagnosticsTags(ctx) {
|
|
|
973
964
|
function addTag(tags, key, value) {
|
|
974
965
|
if (typeof value === "string" && value.trim()) tags[key] = value.trim();
|
|
975
966
|
}
|
|
976
|
-
function formatCodexThreadIdForDisplay(threadId) {
|
|
977
|
-
return escapeCodexChatText(formatCodexTextForDisplay(threadId));
|
|
978
|
-
}
|
|
979
|
-
function formatCodexValueForDisplay(value) {
|
|
980
|
-
return escapeCodexChatText(formatCodexTextForDisplay(value));
|
|
981
|
-
}
|
|
982
967
|
function formatCodexCopyableValueForDisplay(value) {
|
|
983
968
|
const safe = formatCodexTextForDisplay(value);
|
|
984
969
|
if (CODEX_RESUME_SAFE_THREAD_ID_PATTERN.test(safe)) return `\`${safe}\``;
|
|
@@ -1014,16 +999,14 @@ function pruneCodexDiagnosticsCooldownMap(map, now) {
|
|
|
1014
999
|
for (const [key, lastSentAt] of map) if (now - lastSentAt >= CODEX_DIAGNOSTICS_COOLDOWN_MS) map.delete(key);
|
|
1015
1000
|
}
|
|
1016
1001
|
function formatCodexErrorForDisplay(error) {
|
|
1017
|
-
|
|
1002
|
+
const safe = truncateUtf16Safe(formatCodexTextForDisplay(error), CODEX_DIAGNOSTICS_ERROR_MAX_CHARS);
|
|
1003
|
+
return escapeCodexChatText(safe) || "unknown error";
|
|
1018
1004
|
}
|
|
1019
1005
|
function formatCodexResumeCommandForDisplay(threadId) {
|
|
1020
1006
|
const safeThreadId = formatCodexTextForDisplay(threadId);
|
|
1021
1007
|
if (!CODEX_RESUME_SAFE_THREAD_ID_PATTERN.test(safeThreadId)) return "run codex resume and paste the thread id shown above";
|
|
1022
1008
|
return `\`codex resume ${safeThreadId}\``;
|
|
1023
1009
|
}
|
|
1024
|
-
function isUnsafeDisplayCodePoint(codePoint) {
|
|
1025
|
-
return codePoint <= 31 || codePoint >= 127 && codePoint <= 159 || codePoint === 173 || codePoint === 1564 || codePoint === 6158 || codePoint >= 8203 && codePoint <= 8207 || codePoint >= 8234 && codePoint <= 8238 || codePoint >= 8288 && codePoint <= 8303 || codePoint === 65279 || codePoint >= 65529 && codePoint <= 65531 || codePoint >= 917504 && codePoint <= 917631;
|
|
1026
|
-
}
|
|
1027
1010
|
function normalizeCodexDiagnosticsScopeField(value) {
|
|
1028
1011
|
const normalized = normalizeOptionalString(value);
|
|
1029
1012
|
if (!normalized) return;
|
|
@@ -1063,7 +1046,8 @@ function resolveCodexCommandDeps(overrides) {
|
|
|
1063
1046
|
//#endregion
|
|
1064
1047
|
//#region extensions/codex/src/command-handler-scope.ts
|
|
1065
1048
|
async function resolveControlTarget(ctx) {
|
|
1066
|
-
const
|
|
1049
|
+
const binding = await ctx.getCurrentConversationBinding();
|
|
1050
|
+
const data = readCodexConversationBindingData(binding);
|
|
1067
1051
|
const scope = resolveCodexConversationControlScope(ctx);
|
|
1068
1052
|
if (data?.kind === "codex-app-server-session") return {
|
|
1069
1053
|
identity: conversationBindingIdentity(data.bindingId),
|
|
@@ -1082,18 +1066,64 @@ async function resolveControlTarget(ctx) {
|
|
|
1082
1066
|
agentDir: scope.agentDir
|
|
1083
1067
|
} : void 0;
|
|
1084
1068
|
}
|
|
1085
|
-
async function
|
|
1069
|
+
async function resolvePreparedCodexCommandAuthority(deps, ctx) {
|
|
1086
1070
|
const target = await resolveControlTarget(ctx);
|
|
1087
1071
|
const fallback = resolveCodexConversationControlScope(ctx);
|
|
1072
|
+
const sessionId = ctx.sessionId;
|
|
1073
|
+
const sessionKey = ctx.sessionKey;
|
|
1074
|
+
const sessionAgentId = ctx.sessionTarget?.agentId ?? fallback.agentId;
|
|
1075
|
+
const storePath = ctx.sessionTarget?.storePath ?? (sessionKey ? resolveStorePath(ctx.config.session?.store, { agentId: sessionAgentId }) : void 0);
|
|
1076
|
+
const sessionIdentity = sessionId ? sessionBindingIdentity({
|
|
1077
|
+
sessionId,
|
|
1078
|
+
sessionKey,
|
|
1079
|
+
agentId: sessionAgentId,
|
|
1080
|
+
config: ctx.config
|
|
1081
|
+
}) : void 0;
|
|
1082
|
+
const currentSession = sessionIdentity ? await resolveCodexSessionBinding({
|
|
1083
|
+
reclaimStale: true,
|
|
1084
|
+
bindingStore: deps.bindingStore,
|
|
1085
|
+
identity: sessionIdentity,
|
|
1086
|
+
config: ctx.config,
|
|
1087
|
+
storePath
|
|
1088
|
+
}) : void 0;
|
|
1089
|
+
const assertHostCurrent = currentSession?.assertCurrent ?? (() => {});
|
|
1090
|
+
const binding = (target && (!sessionIdentity || !isDeepStrictEqual(target.identity, sessionIdentity)) ? await resolveCodexSessionBinding({
|
|
1091
|
+
bindingStore: deps.bindingStore,
|
|
1092
|
+
identity: target.identity,
|
|
1093
|
+
config: ctx.config,
|
|
1094
|
+
storePath,
|
|
1095
|
+
assertCurrent: assertHostCurrent
|
|
1096
|
+
}) : currentSession)?.binding;
|
|
1097
|
+
const assertCurrent = () => {
|
|
1098
|
+
assertHostCurrent();
|
|
1099
|
+
if (target && !isDeepStrictEqual(deps.bindingStore.read(target.identity), binding)) throw new Error("Codex command binding changed before dispatch");
|
|
1100
|
+
assertHostCurrent();
|
|
1101
|
+
};
|
|
1102
|
+
assertCurrent();
|
|
1103
|
+
return {
|
|
1104
|
+
target,
|
|
1105
|
+
binding,
|
|
1106
|
+
currentSessionBinding: currentSession?.binding,
|
|
1107
|
+
sessionId,
|
|
1108
|
+
sessionKey,
|
|
1109
|
+
storePath,
|
|
1110
|
+
assertHostCurrent,
|
|
1111
|
+
assertCurrent
|
|
1112
|
+
};
|
|
1113
|
+
}
|
|
1114
|
+
async function resolveCommandAppServerScope(deps, ctx, pluginConfig) {
|
|
1115
|
+
const authority = await resolvePreparedCodexCommandAuthority(deps, ctx);
|
|
1116
|
+
const { target, binding } = authority;
|
|
1117
|
+
const fallback = resolveCodexConversationControlScope(ctx);
|
|
1088
1118
|
const agentDir = target?.agentDir ?? fallback.agentDir;
|
|
1089
|
-
const
|
|
1119
|
+
const authProfileId = binding?.connectionScope === "supervision" ? void 0 : resolveCodexAppServerAuthProfileIdForAgent({
|
|
1120
|
+
authProfileId: binding?.authProfileId ?? target?.requestedAuthProfileId,
|
|
1121
|
+
agentDir,
|
|
1122
|
+
config: ctx.config
|
|
1123
|
+
});
|
|
1090
1124
|
const connection = resolveCodexBindingAppServerConnection({
|
|
1091
1125
|
binding,
|
|
1092
|
-
authProfileId
|
|
1093
|
-
authProfileId: binding?.authProfileId ?? target?.requestedAuthProfileId,
|
|
1094
|
-
agentDir,
|
|
1095
|
-
config: ctx.config
|
|
1096
|
-
}),
|
|
1126
|
+
authProfileId,
|
|
1097
1127
|
pluginConfig
|
|
1098
1128
|
});
|
|
1099
1129
|
return {
|
|
@@ -1101,8 +1131,10 @@ async function resolveCommandAppServerScope(deps, ctx, pluginConfig) {
|
|
|
1101
1131
|
agentDir,
|
|
1102
1132
|
...connection.clientAuthProfileId !== void 0 ? { authProfileId: connection.clientAuthProfileId } : {},
|
|
1103
1133
|
...connection.usesSupervisionConnection ? { startOptions: connection.appServer.start } : {},
|
|
1104
|
-
...
|
|
1105
|
-
...
|
|
1134
|
+
...authority.sessionKey ? { sessionKey: authority.sessionKey } : {},
|
|
1135
|
+
...authority.sessionId ? { sessionId: authority.sessionId } : {},
|
|
1136
|
+
...authority.storePath ? { storePath: authority.storePath } : {},
|
|
1137
|
+
assertCurrent: authority.assertCurrent
|
|
1106
1138
|
};
|
|
1107
1139
|
}
|
|
1108
1140
|
function conversationBindingIdentity(bindingId) {
|
|
@@ -1112,14 +1144,14 @@ function conversationBindingIdentity(bindingId) {
|
|
|
1112
1144
|
};
|
|
1113
1145
|
}
|
|
1114
1146
|
function resolveCodexConversationControlScope(ctx) {
|
|
1115
|
-
const { sessionAgentId } =
|
|
1147
|
+
const { sessionAgentId } = resolveSessionAgentIdsStrict({
|
|
1116
1148
|
sessionKey: ctx.sessionKey,
|
|
1117
1149
|
agentId: ctx.agentId,
|
|
1118
1150
|
config: ctx.config
|
|
1119
1151
|
});
|
|
1120
1152
|
return {
|
|
1121
1153
|
agentId: sessionAgentId,
|
|
1122
|
-
agentDir: resolveAgentDir(ctx.config, sessionAgentId)
|
|
1154
|
+
agentDir: resolveAgentDir$1(ctx.config, sessionAgentId)
|
|
1123
1155
|
};
|
|
1124
1156
|
}
|
|
1125
1157
|
//#endregion
|
|
@@ -1155,7 +1187,7 @@ async function requestCodexDiagnosticsFeedbackApproval(deps, ctx, note, commandP
|
|
|
1155
1187
|
});
|
|
1156
1188
|
const confirmCommand = `${commandPrefix} confirm ${token}`;
|
|
1157
1189
|
const cancelCommand = `${commandPrefix} cancel ${token}`;
|
|
1158
|
-
const displayReason = reason ?
|
|
1190
|
+
const displayReason = reason ? formatCodexDisplayText(reason) : void 0;
|
|
1159
1191
|
return {
|
|
1160
1192
|
text: [
|
|
1161
1193
|
targets.length === 1 ? "Codex runtime thread detected." : "Codex runtime threads detected.",
|
|
@@ -1197,7 +1229,7 @@ async function previewCodexDiagnosticsFeedbackApproval(deps, ctx, note) {
|
|
|
1197
1229
|
const cooldownMessage = readCodexDiagnosticsTargetsCooldownMessage(targets, ctx, Date.now(), { includeThreadId: false });
|
|
1198
1230
|
if (cooldownMessage) return cooldownMessage;
|
|
1199
1231
|
const reason = normalizeDiagnosticsReason(note);
|
|
1200
|
-
const displayReason = reason ?
|
|
1232
|
+
const displayReason = reason ? formatCodexDisplayText(reason) : void 0;
|
|
1201
1233
|
return [
|
|
1202
1234
|
targets.length === 1 ? "Codex runtime thread detected." : "Codex runtime threads detected.",
|
|
1203
1235
|
`Approving diagnostics will also send ${targets.length === 1 ? "this thread's feedback bundle" : "these threads' feedback bundles"} to OpenAI servers.`,
|
|
@@ -1216,7 +1248,7 @@ async function confirmCodexDiagnosticsFeedback(deps, ctx, pluginConfig, token) {
|
|
|
1216
1248
|
if (scopeMismatch) return scopeMismatch.confirmMessage;
|
|
1217
1249
|
deletePendingCodexDiagnosticsConfirmation(token);
|
|
1218
1250
|
if (!pending.privateRouted && !await hasAnyCodexDiagnosticsIdentity(ctx)) return "Cannot send Codex diagnostics because this command did not include a stable session identity.";
|
|
1219
|
-
const currentTargets = pending.privateRouted ?
|
|
1251
|
+
const currentTargets = pending.privateRouted ? resolvePendingCodexDiagnosticsTargets(deps, pending.targets, ctx.config) : await resolveCodexDiagnosticsTargets(deps, ctx);
|
|
1220
1252
|
if (!codexDiagnosticsTargetsMatch(pending.targets, currentTargets)) return "The Codex diagnostics sessions changed before confirmation. Run /diagnostics again for the current threads.";
|
|
1221
1253
|
return await sendCodexDiagnosticsFeedbackForTargets(deps, ctx, pluginConfig, pending.note ?? "", currentTargets, { cooldownScope: pending.scopeKey });
|
|
1222
1254
|
}
|
|
@@ -1323,7 +1355,7 @@ async function resolveCodexDiagnosticsTargets(deps, ctx) {
|
|
|
1323
1355
|
});
|
|
1324
1356
|
candidates.push({
|
|
1325
1357
|
identity,
|
|
1326
|
-
agentDir: resolveAgentDir(ctx.config, identity.agentId),
|
|
1358
|
+
agentDir: resolveAgentDir$1(ctx.config, identity.agentId),
|
|
1327
1359
|
sessionKey: session.sessionKey,
|
|
1328
1360
|
sessionId: session.sessionId,
|
|
1329
1361
|
channel: session.channel,
|
|
@@ -1340,17 +1372,17 @@ async function resolveCodexDiagnosticsTargets(deps, ctx) {
|
|
|
1340
1372
|
const key = bindingStoreKey(candidate.identity);
|
|
1341
1373
|
if (seenBindingKeys.has(key)) continue;
|
|
1342
1374
|
seenBindingKeys.add(key);
|
|
1343
|
-
const binding =
|
|
1375
|
+
const binding = deps.bindingStore.read(candidate.identity);
|
|
1344
1376
|
if (!binding?.threadId || seenThreadIds.has(binding.threadId)) continue;
|
|
1345
1377
|
seenThreadIds.add(binding.threadId);
|
|
1346
1378
|
targets.push(resolveCodexDiagnosticsTarget(candidate, binding, ctx.config));
|
|
1347
1379
|
}
|
|
1348
1380
|
return targets;
|
|
1349
1381
|
}
|
|
1350
|
-
|
|
1382
|
+
function resolvePendingCodexDiagnosticsTargets(deps, targets, config) {
|
|
1351
1383
|
const resolved = [];
|
|
1352
1384
|
for (const target of targets) {
|
|
1353
|
-
const binding =
|
|
1385
|
+
const binding = deps.bindingStore.read(target.identity);
|
|
1354
1386
|
if (!binding?.threadId) continue;
|
|
1355
1387
|
resolved.push(resolveCodexDiagnosticsTarget(target, binding, config));
|
|
1356
1388
|
}
|
|
@@ -1392,8 +1424,9 @@ function isCurrentSessionModelSelectionLocked(ctx) {
|
|
|
1392
1424
|
const sessionKey = ctx.sessionKey?.trim();
|
|
1393
1425
|
if (!sessionKey) return false;
|
|
1394
1426
|
const { agentId } = resolveCodexConversationControlScope(ctx);
|
|
1427
|
+
const storePath = ctx.sessionTarget?.storePath ?? resolveStorePath(ctx.config.session?.store, { agentId });
|
|
1395
1428
|
return isModelSelectionLocked(getSessionEntry({
|
|
1396
|
-
storePath
|
|
1429
|
+
storePath,
|
|
1397
1430
|
sessionKey,
|
|
1398
1431
|
hydrateSkillPromptRefs: false,
|
|
1399
1432
|
readConsistency: "latest"
|
|
@@ -1415,7 +1448,7 @@ async function bindConversation(deps, ctx, pluginConfig, args) {
|
|
|
1415
1448
|
config: ctx.config
|
|
1416
1449
|
}) : void 0;
|
|
1417
1450
|
const currentOwner = currentConversationData?.kind === "codex-app-server-session" ? conversationBindingIdentity(currentConversationData.bindingId) : sessionOwner;
|
|
1418
|
-
const existingBinding = currentOwner ?
|
|
1451
|
+
const existingBinding = currentOwner ? deps.bindingStore.read(currentOwner) : void 0;
|
|
1419
1452
|
assertCodexBindingMayBeReplaced(existingBinding, "binding this conversation to another thread");
|
|
1420
1453
|
const sessionSource = sessionOwner && existingBinding ? {
|
|
1421
1454
|
agentId: sessionOwner.agentId,
|
|
@@ -1450,13 +1483,14 @@ async function bindConversation(deps, ctx, pluginConfig, args) {
|
|
|
1450
1483
|
}
|
|
1451
1484
|
async function detachConversation(deps, ctx) {
|
|
1452
1485
|
if (isCurrentSessionModelSelectionLocked(ctx)) return MODEL_SELECTION_LOCKED_MESSAGE;
|
|
1453
|
-
const
|
|
1486
|
+
const current = await ctx.getCurrentConversationBinding();
|
|
1487
|
+
const data = readCodexConversationBindingData(current);
|
|
1454
1488
|
const identity = data?.kind === "codex-app-server-session" ? conversationBindingIdentity(data.bindingId) : void 0;
|
|
1455
1489
|
const sourceSessionKey = data?.kind === "codex-app-server-session" ? data.source?.sessionKey : void 0;
|
|
1456
1490
|
let expectedThreadId;
|
|
1457
1491
|
let expectedStartId;
|
|
1458
1492
|
if (data?.kind === "codex-app-server-session") {
|
|
1459
|
-
const binding =
|
|
1493
|
+
const binding = deps.bindingStore.read(identity);
|
|
1460
1494
|
assertCodexBindingMayBeReplaced(binding, "detaching its conversation binding");
|
|
1461
1495
|
if (deps.readCodexConversationActiveTurn(identity)) return "This Codex conversation has an active run; use /codex stop before detaching it.";
|
|
1462
1496
|
expectedThreadId = binding?.threadId;
|
|
@@ -1494,13 +1528,13 @@ async function describeConversationBinding(deps, ctx) {
|
|
|
1494
1528
|
"- Active run: not tracked"
|
|
1495
1529
|
].join("\n");
|
|
1496
1530
|
const identity = conversationBindingIdentity(data.bindingId);
|
|
1497
|
-
const threadBinding =
|
|
1531
|
+
const threadBinding = deps.bindingStore.read(identity);
|
|
1498
1532
|
const active = deps.readCodexConversationActiveTurn(identity);
|
|
1499
1533
|
const sessionKey = ctx.sessionKey?.trim();
|
|
1500
1534
|
const { agentId } = resolveCodexConversationControlScope(ctx);
|
|
1501
1535
|
const sessionEntry = sessionKey ? getSessionEntry({
|
|
1502
1536
|
agentId,
|
|
1503
|
-
storePath: resolveStorePath(ctx.config.session?.store, { agentId }),
|
|
1537
|
+
storePath: ctx.sessionTarget?.storePath ?? resolveStorePath(ctx.config.session?.store, { agentId }),
|
|
1504
1538
|
sessionKey,
|
|
1505
1539
|
hydrateSkillPromptRefs: false,
|
|
1506
1540
|
readConsistency: "latest"
|
|
@@ -1519,13 +1553,14 @@ async function describeConversationBinding(deps, ctx) {
|
|
|
1519
1553
|
}
|
|
1520
1554
|
async function buildThreads(deps, ctx, pluginConfig, filter) {
|
|
1521
1555
|
const scope = await resolveCommandAppServerScope(deps, ctx, pluginConfig);
|
|
1522
|
-
|
|
1556
|
+
const response = await deps.codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.listThreads, {
|
|
1523
1557
|
limit: 10,
|
|
1524
1558
|
...filter.trim() ? { searchTerm: filter.trim() } : {}
|
|
1525
1559
|
}, {
|
|
1526
1560
|
config: ctx.config,
|
|
1527
1561
|
...scope
|
|
1528
|
-
})
|
|
1562
|
+
});
|
|
1563
|
+
return formatThreads(response);
|
|
1529
1564
|
}
|
|
1530
1565
|
async function buildCodexCliSessions(deps, args) {
|
|
1531
1566
|
const parsed = parseCodexCliSessionsArgs(args);
|
|
@@ -1551,25 +1586,25 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
|
|
|
1551
1586
|
agentId: scope.agentId,
|
|
1552
1587
|
config: ctx.config
|
|
1553
1588
|
});
|
|
1589
|
+
const { assertCurrent: assertHostGeneration } = await resolveCodexSessionBinding({
|
|
1590
|
+
reclaimStale: true,
|
|
1591
|
+
bindingStore: deps.bindingStore,
|
|
1592
|
+
identity,
|
|
1593
|
+
config: ctx.config,
|
|
1594
|
+
storePath: ctx.sessionTarget?.storePath
|
|
1595
|
+
});
|
|
1554
1596
|
return await withExclusiveCodexAppServerThread({
|
|
1555
1597
|
bindingStore: deps.bindingStore,
|
|
1556
1598
|
identity,
|
|
1557
1599
|
threadId: normalizedThreadId,
|
|
1558
1600
|
run: async () => await deps.bindingStore.withLease(identity, async () => {
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
})) throw createCodexSessionGenerationSupersededError(identity.sessionId);
|
|
1564
|
-
const currentBinding = await deps.bindingStore.read(identity);
|
|
1601
|
+
const generation = await deps.bindingStore.prepareSessionGenerationReclaim(identity);
|
|
1602
|
+
assertHostGeneration();
|
|
1603
|
+
if (generation.kind !== "resolved" || !generation.result) throw createCodexSessionGenerationSupersededError(identity.sessionId);
|
|
1604
|
+
const currentBinding = deps.bindingStore.read(identity);
|
|
1565
1605
|
assertCodexBindingMayBeReplaced(currentBinding, "attaching a different resumed thread");
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
agentDir: scope.agentDir,
|
|
1569
|
-
config: ctx.config
|
|
1570
|
-
});
|
|
1571
|
-
let committedResponse = false;
|
|
1572
|
-
const commitResumedThread = async (value, client) => {
|
|
1606
|
+
let pendingResumeConfiguration = false;
|
|
1607
|
+
const commitResumedThread = async (value, client, { authProfileId, assertCurrent }) => {
|
|
1573
1608
|
const response = assertCodexThreadResumeResponse(value);
|
|
1574
1609
|
const effectiveThreadId = response.thread.id;
|
|
1575
1610
|
if (effectiveThreadId !== normalizedThreadId) throw new Error(`Codex thread/resume returned ${effectiveThreadId} for ${normalizedThreadId}`);
|
|
@@ -1581,52 +1616,75 @@ async function resumeThread(deps, ctx, pluginConfig, args) {
|
|
|
1581
1616
|
agentDir: scope.agentDir,
|
|
1582
1617
|
config: ctx.config
|
|
1583
1618
|
});
|
|
1584
|
-
const
|
|
1585
|
-
assertCodexBindingMayBeReplaced(bindingBeforeCommit, "committing a different resumed thread");
|
|
1586
|
-
const clientId = client?.getInstanceId();
|
|
1587
|
-
const sameOwner = client ? isSameCodexAppServerThreadOwner(bindingBeforeCommit, {
|
|
1588
|
-
threadId: effectiveThreadId,
|
|
1589
|
-
clientId
|
|
1590
|
-
}) : bindingBeforeCommit?.threadId === effectiveThreadId;
|
|
1619
|
+
const clientId = client.getInstanceId();
|
|
1591
1620
|
let retained = false;
|
|
1621
|
+
let sameOwner = false;
|
|
1622
|
+
let knownOwnership;
|
|
1592
1623
|
try {
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1624
|
+
const bindingBeforeCommit = deps.bindingStore.read(identity);
|
|
1625
|
+
assertCodexBindingMayBeReplaced(bindingBeforeCommit, "committing a different resumed thread");
|
|
1626
|
+
sameOwner = isSameCodexAppServerThreadOwner(bindingBeforeCommit, {
|
|
1627
|
+
threadId: effectiveThreadId,
|
|
1628
|
+
clientId
|
|
1629
|
+
});
|
|
1630
|
+
const sameThreadBinding = bindingBeforeCommit?.threadId === effectiveThreadId ? bindingBeforeCommit : void 0;
|
|
1631
|
+
pendingResumeConfiguration = sameThreadBinding?.preserveNativeModel !== true && (!sameThreadBinding?.dynamicToolsFingerprint || !sameThreadBinding.webSearchThreadConfigFingerprint || sameThreadBinding.pendingResumeConfiguration === true);
|
|
1632
|
+
assertCurrent();
|
|
1633
|
+
assertCodexThreadAcceptsDirectInput(response.thread);
|
|
1634
|
+
knownOwnership = sameOwner ? await consumeCodexAppServerLiveThread(client, effectiveThreadId) : void 0;
|
|
1635
|
+
assertCurrent();
|
|
1636
|
+
retained = await retainCodexAppServerBindingSubscription(client, effectiveThreadId, knownOwnership);
|
|
1637
|
+
assertCurrent();
|
|
1638
|
+
if (!retained) throw new Error("Codex resumed thread lost its native subscription owner.");
|
|
1639
|
+
if (bindingBeforeCommit && !sameOwner) await releaseCodexAppServerBindingSubscription(bindingBeforeCommit, { assertCurrent });
|
|
1640
|
+
assertCurrent();
|
|
1598
1641
|
if (!await deps.bindingStore.mutate(identity, {
|
|
1599
1642
|
kind: "set",
|
|
1600
1643
|
binding: {
|
|
1601
|
-
...
|
|
1644
|
+
...sameThreadBinding,
|
|
1602
1645
|
threadId: effectiveThreadId,
|
|
1603
|
-
|
|
1646
|
+
clientId,
|
|
1604
1647
|
cwd: resumedCwd,
|
|
1648
|
+
rolloutPath: response.thread.path ?? sameThreadBinding?.rolloutPath,
|
|
1649
|
+
pendingResumeConfiguration: pendingResumeConfiguration ? true : void 0,
|
|
1605
1650
|
authProfileId,
|
|
1606
1651
|
model: response.model,
|
|
1607
1652
|
modelProvider,
|
|
1608
1653
|
historyCoveredThrough: (/* @__PURE__ */ new Date()).toISOString()
|
|
1609
1654
|
}
|
|
1610
|
-
})) throw new Error("Codex thread binding changed while attaching the resumed thread.");
|
|
1655
|
+
}, assertCurrent)) throw new Error("Codex thread binding changed while attaching the resumed thread.");
|
|
1611
1656
|
} catch (error) {
|
|
1612
|
-
if (
|
|
1657
|
+
if (sameOwner && knownOwnership && !retained) {
|
|
1658
|
+
if (!await retainCodexAppServerBindingSubscription(client, effectiveThreadId, knownOwnership)) await closeCodexStartupClientBestEffort(client);
|
|
1659
|
+
} else if (retained && !sameOwner || !hasCodexAppServerLiveThread(client, effectiveThreadId)) await rollbackCodexAppServerBindingSubscription(client, effectiveThreadId, retained);
|
|
1613
1660
|
throw error;
|
|
1614
1661
|
}
|
|
1615
|
-
committedResponse = true;
|
|
1616
1662
|
};
|
|
1617
|
-
|
|
1663
|
+
await deps.codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.resumeThread, {
|
|
1618
1664
|
threadId: normalizedThreadId,
|
|
1619
1665
|
excludeTurns: true
|
|
1620
1666
|
}, {
|
|
1621
1667
|
config: ctx.config,
|
|
1668
|
+
agentId: scope.agentId,
|
|
1622
1669
|
agentDir: scope.agentDir,
|
|
1623
|
-
authProfileId,
|
|
1670
|
+
authProfileId: currentBinding?.authProfileId,
|
|
1624
1671
|
sessionKey: ctx.sessionKey,
|
|
1625
1672
|
sessionId: ctx.sessionId,
|
|
1673
|
+
storePath: ctx.sessionTarget?.storePath,
|
|
1674
|
+
assertCurrent: assertHostGeneration,
|
|
1675
|
+
beforeRequest: async (request) => {
|
|
1676
|
+
const { thread } = await request({
|
|
1677
|
+
method: "thread/read",
|
|
1678
|
+
requestParams: {
|
|
1679
|
+
threadId: normalizedThreadId,
|
|
1680
|
+
includeTurns: false
|
|
1681
|
+
}
|
|
1682
|
+
});
|
|
1683
|
+
assertCodexThreadAcceptsDirectInput(thread);
|
|
1684
|
+
},
|
|
1626
1685
|
onResponse: commitResumedThread
|
|
1627
1686
|
});
|
|
1628
|
-
|
|
1629
|
-
return `Attached this OpenClaw session to Codex thread ${formatCodexDisplayText(normalizedThreadId)}.`;
|
|
1687
|
+
return `Attached this OpenClaw session to Codex thread ${formatCodexDisplayText(normalizedThreadId)}.${pendingResumeConfiguration ? " The next turn will validate its tools and apply this session's configuration before continuing." : ""}`;
|
|
1630
1688
|
})
|
|
1631
1689
|
});
|
|
1632
1690
|
}
|
|
@@ -1635,12 +1693,13 @@ async function bindCodexCliNodeSession(deps, ctx, parsed) {
|
|
|
1635
1693
|
if (isCurrentSessionModelSelectionLocked(ctx)) return MODEL_SELECTION_LOCKED_MESSAGE;
|
|
1636
1694
|
if (ctx.sessionId) {
|
|
1637
1695
|
const scope = resolveCodexConversationControlScope(ctx);
|
|
1638
|
-
|
|
1696
|
+
const binding = deps.bindingStore.read(sessionBindingIdentity({
|
|
1639
1697
|
sessionId: ctx.sessionId,
|
|
1640
1698
|
sessionKey: ctx.sessionKey,
|
|
1641
1699
|
agentId: scope.agentId,
|
|
1642
1700
|
config: ctx.config
|
|
1643
|
-
}))
|
|
1701
|
+
}));
|
|
1702
|
+
assertCodexBindingMayBeReplaced(binding, "binding a Codex CLI node session");
|
|
1644
1703
|
}
|
|
1645
1704
|
const resolved = await deps.resolveCodexCliSessionForBindingOnNode({
|
|
1646
1705
|
requestedNode: parsed.host,
|
|
@@ -1755,9 +1814,9 @@ async function handleComputerUseCommand(deps, ctx, pluginConfig, args) {
|
|
|
1755
1814
|
async function handleNativeGoal(deps, ctx, pluginConfig, args) {
|
|
1756
1815
|
const action = (args[0] ?? "status").toLowerCase();
|
|
1757
1816
|
const objective = args.slice(1).join(" ").trim();
|
|
1758
|
-
const
|
|
1817
|
+
const authority = await resolvePreparedCodexCommandAuthority(deps, ctx);
|
|
1818
|
+
const { target, binding } = authority;
|
|
1759
1819
|
if (!target) return "Cannot manage the Codex goal because this command has no stable binding identity.";
|
|
1760
|
-
const binding = await deps.bindingStore.read(target.identity);
|
|
1761
1820
|
if (!binding?.threadId) return "No Codex thread is attached to this OpenClaw session yet.";
|
|
1762
1821
|
const connection = resolveCodexBindingAppServerConnection({
|
|
1763
1822
|
binding,
|
|
@@ -1768,6 +1827,10 @@ async function handleNativeGoal(deps, ctx, pluginConfig, args) {
|
|
|
1768
1827
|
agentDir: target.agentDir,
|
|
1769
1828
|
authProfileId: connection.clientAuthProfileId,
|
|
1770
1829
|
config: ctx.config,
|
|
1830
|
+
sessionId: authority.sessionId,
|
|
1831
|
+
sessionKey: authority.sessionKey,
|
|
1832
|
+
storePath: authority.storePath,
|
|
1833
|
+
assertCurrent: authority.assertCurrent,
|
|
1771
1834
|
...connection.usesSupervisionConnection ? { startOptions: connection.appServer.start } : {}
|
|
1772
1835
|
};
|
|
1773
1836
|
if (action === "status" || action === "get") {
|
|
@@ -1783,11 +1846,14 @@ async function handleNativeGoal(deps, ctx, pluginConfig, args) {
|
|
|
1783
1846
|
const isObjectiveUpdate = action === "set";
|
|
1784
1847
|
if (!requestedStatus && !isObjectiveUpdate || isObjectiveUpdate && !objective) return "Usage: /codex goal [status|set <objective>|pause|resume|block|complete|clear]";
|
|
1785
1848
|
if (requestedStatus && args.length > 1) return `Usage: /codex goal ${action}`;
|
|
1786
|
-
return formatNativeGoal(await deps.codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.setThreadGoal, {
|
|
1849
|
+
return formatNativeGoal(await deps.bindingStore.withLease(target.identity, () => deps.codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.setThreadGoal, {
|
|
1787
1850
|
threadId: binding.threadId,
|
|
1788
1851
|
...objective ? { objective } : {},
|
|
1789
1852
|
...requestedStatus ? { status: requestedStatus } : {}
|
|
1790
|
-
},
|
|
1853
|
+
}, {
|
|
1854
|
+
...goalRequestOptions,
|
|
1855
|
+
...(isObjectiveUpdate || requestedStatus === "active") && connection.usesSupervisionConnection ? { beforeRequest: supervisedCommandGuard(deps, target.identity, binding) } : {}
|
|
1856
|
+
})));
|
|
1791
1857
|
}
|
|
1792
1858
|
function formatNativeGoal(response) {
|
|
1793
1859
|
const goal = isJsonObject(response) && isJsonObject(response.goal) ? response.goal : void 0;
|
|
@@ -1803,26 +1869,30 @@ function formatNativeGoal(response) {
|
|
|
1803
1869
|
].join("\n");
|
|
1804
1870
|
}
|
|
1805
1871
|
async function stopConversationTurn(deps, ctx, pluginConfig) {
|
|
1806
|
-
const
|
|
1872
|
+
const authority = await resolvePreparedCodexCommandAuthority(deps, ctx);
|
|
1873
|
+
const { target, binding } = authority;
|
|
1807
1874
|
if (!target) return "Cannot stop Codex because this command did not include a stable binding identity.";
|
|
1808
1875
|
return (await deps.stopCodexConversationTurn({
|
|
1809
1876
|
identity: target.identity,
|
|
1810
|
-
|
|
1877
|
+
binding,
|
|
1811
1878
|
pluginConfig,
|
|
1812
1879
|
agentDir: target.agentDir,
|
|
1813
|
-
config: ctx.config
|
|
1880
|
+
config: ctx.config,
|
|
1881
|
+
assertCurrent: authority.assertCurrent
|
|
1814
1882
|
})).message;
|
|
1815
1883
|
}
|
|
1816
1884
|
async function steerConversationTurn(deps, ctx, pluginConfig, message) {
|
|
1817
|
-
const
|
|
1885
|
+
const authority = await resolvePreparedCodexCommandAuthority(deps, ctx);
|
|
1886
|
+
const { target, binding } = authority;
|
|
1818
1887
|
if (!target) return "Cannot steer Codex because this command did not include a stable binding identity.";
|
|
1819
1888
|
return (await deps.steerCodexConversationTurn({
|
|
1820
1889
|
identity: target.identity,
|
|
1821
|
-
|
|
1890
|
+
binding,
|
|
1822
1891
|
message,
|
|
1823
1892
|
pluginConfig,
|
|
1824
1893
|
agentDir: target.agentDir,
|
|
1825
|
-
config: ctx.config
|
|
1894
|
+
config: ctx.config,
|
|
1895
|
+
assertCurrent: authority.assertCurrent
|
|
1826
1896
|
})).message;
|
|
1827
1897
|
}
|
|
1828
1898
|
async function setConversationModel(deps, ctx, pluginConfig, args) {
|
|
@@ -1830,17 +1900,18 @@ async function setConversationModel(deps, ctx, pluginConfig, args) {
|
|
|
1830
1900
|
const [model = ""] = args;
|
|
1831
1901
|
const normalized = model.trim();
|
|
1832
1902
|
if (normalized && isCurrentSessionModelSelectionLocked(ctx)) return MODEL_SELECTION_LOCKED_MESSAGE;
|
|
1833
|
-
const
|
|
1903
|
+
const authority = await resolvePreparedCodexCommandAuthority(deps, ctx);
|
|
1904
|
+
const { target, binding } = authority;
|
|
1834
1905
|
if (!target) return "Cannot set Codex model because this command did not include a stable binding identity.";
|
|
1835
1906
|
if (!normalized) {
|
|
1836
|
-
const currentSession =
|
|
1837
|
-
storePath:
|
|
1838
|
-
sessionKey:
|
|
1907
|
+
const currentSession = authority.sessionId && authority.sessionKey && authority.storePath ? getSessionEntry({
|
|
1908
|
+
storePath: authority.storePath,
|
|
1909
|
+
sessionKey: authority.sessionKey,
|
|
1839
1910
|
hydrateSkillPromptRefs: false,
|
|
1840
1911
|
readConsistency: "latest"
|
|
1841
1912
|
}) : void 0;
|
|
1842
|
-
const selectedModel = currentSession && currentSession.sessionId ===
|
|
1843
|
-
|
|
1913
|
+
const selectedModel = currentSession && currentSession.sessionId === authority.sessionId ? currentSession.modelOverride ?? currentSession.model : void 0;
|
|
1914
|
+
authority.assertCurrent();
|
|
1844
1915
|
const activeModel = target.identity.kind === "conversation" ? binding?.model : selectedModel ?? binding?.model;
|
|
1845
1916
|
return activeModel ? `Codex model: ${formatCodexDisplayText(activeModel)}` : "Usage: /codex model <model>";
|
|
1846
1917
|
}
|
|
@@ -1850,12 +1921,16 @@ async function setConversationModel(deps, ctx, pluginConfig, args) {
|
|
|
1850
1921
|
pluginConfig,
|
|
1851
1922
|
model: normalized,
|
|
1852
1923
|
agentDir: target.agentDir,
|
|
1853
|
-
config: ctx.config
|
|
1924
|
+
config: ctx.config,
|
|
1925
|
+
binding,
|
|
1926
|
+
storePath: authority.storePath,
|
|
1927
|
+
assertCurrent: authority.assertCurrent
|
|
1854
1928
|
});
|
|
1855
1929
|
}
|
|
1856
1930
|
async function setConversationFastMode(deps, ctx, args) {
|
|
1857
1931
|
if (args.length > 1) return "Usage: /codex fast [on|off|status]";
|
|
1858
|
-
const
|
|
1932
|
+
const authority = await resolvePreparedCodexCommandAuthority(deps, ctx);
|
|
1933
|
+
const { target, binding } = authority;
|
|
1859
1934
|
if (!target) return "Cannot set Codex fast mode because this command did not include a stable binding identity.";
|
|
1860
1935
|
const value = args[0];
|
|
1861
1936
|
const parsed = parseCodexFastModeArg(value);
|
|
@@ -1863,12 +1938,15 @@ async function setConversationFastMode(deps, ctx, args) {
|
|
|
1863
1938
|
return await deps.setCodexConversationFastMode({
|
|
1864
1939
|
identity: target.identity,
|
|
1865
1940
|
bindingStore: deps.bindingStore,
|
|
1866
|
-
|
|
1941
|
+
binding,
|
|
1942
|
+
enabled: parsed,
|
|
1943
|
+
assertCurrent: authority.assertCurrent
|
|
1867
1944
|
});
|
|
1868
1945
|
}
|
|
1869
1946
|
async function setConversationPermissions(deps, ctx, args) {
|
|
1870
1947
|
if (args.length > 1) return "Usage: /codex permissions [default|yolo|status]";
|
|
1871
|
-
const
|
|
1948
|
+
const authority = await resolvePreparedCodexCommandAuthority(deps, ctx);
|
|
1949
|
+
const { target } = authority;
|
|
1872
1950
|
if (!target || !ctx.sessionId || !ctx.sessionKey) return "Cannot set Codex permissions because this command did not include a complete session identity.";
|
|
1873
1951
|
const value = args[0];
|
|
1874
1952
|
const parsed = parseCodexPermissionsModeArg(value);
|
|
@@ -1877,6 +1955,8 @@ async function setConversationPermissions(deps, ctx, args) {
|
|
|
1877
1955
|
return await deps.setCodexConversationPermissions({
|
|
1878
1956
|
mode: parsed,
|
|
1879
1957
|
config: ctx.config,
|
|
1958
|
+
storePath: authority.storePath,
|
|
1959
|
+
assertCurrent: authority.assertHostCurrent,
|
|
1880
1960
|
session: {
|
|
1881
1961
|
agentId: target.agentId,
|
|
1882
1962
|
sessionId: ctx.sessionId,
|
|
@@ -1886,30 +1966,26 @@ async function setConversationPermissions(deps, ctx, args) {
|
|
|
1886
1966
|
}
|
|
1887
1967
|
async function startThreadAction(deps, ctx, pluginConfig, kind, args) {
|
|
1888
1968
|
if (args.length > 0) return `Usage: /codex ${kind}`;
|
|
1889
|
-
const
|
|
1969
|
+
const authority = await resolvePreparedCodexCommandAuthority(deps, ctx);
|
|
1970
|
+
const { target, binding } = authority;
|
|
1890
1971
|
if (!target) return `Cannot start Codex ${kind === "compact" ? "compaction" : "review"} because this command did not include a stable binding identity.`;
|
|
1891
|
-
const binding = await deps.bindingStore.read(target.identity);
|
|
1892
1972
|
if (!binding?.threadId) return `No Codex thread is attached to this OpenClaw session yet.`;
|
|
1893
1973
|
if (kind === "compact") {
|
|
1894
1974
|
const sessionTarget = ctx.sessionTarget;
|
|
1895
1975
|
if (!ctx.sessionId || !ctx.sessionKey || !sessionTarget || sessionTarget.sessionId !== ctx.sessionId || sessionTarget.sessionKey !== ctx.sessionKey) return "Codex compaction is unavailable because this command is not bound to a complete session identity.";
|
|
1896
1976
|
const currentSession = getSessionEntry({
|
|
1897
|
-
storePath: sessionTarget.storePath,
|
|
1977
|
+
storePath: authority.storePath ?? sessionTarget.storePath,
|
|
1898
1978
|
sessionKey: ctx.sessionKey,
|
|
1899
1979
|
hydrateSkillPromptRefs: false,
|
|
1900
1980
|
readConsistency: "latest"
|
|
1901
1981
|
});
|
|
1902
1982
|
if (currentSession?.sessionId !== ctx.sessionId || resolvePersistedSessionRuntimeId(currentSession) !== "codex") return "Codex compaction is unavailable because the current OpenClaw session is not using the Codex runtime.";
|
|
1903
1983
|
if (target.identity.kind === "conversation") {
|
|
1904
|
-
if (!isSameCodexAppServerThreadOwner(binding,
|
|
1905
|
-
sessionId: ctx.sessionId,
|
|
1906
|
-
sessionKey: ctx.sessionKey,
|
|
1907
|
-
agentId: sessionTarget.agentId,
|
|
1908
|
-
config: ctx.config
|
|
1909
|
-
})) : void 0)) return "Codex compaction is unavailable because the conversation-bound thread differs from the current session binding. Resume that thread into the session first.";
|
|
1984
|
+
if (!isSameCodexAppServerThreadOwner(binding, authority.currentSessionBinding)) return "Codex compaction is unavailable because the conversation-bound thread differs from the current session binding. Resume that thread into the session first.";
|
|
1910
1985
|
}
|
|
1911
1986
|
const compactCurrent = ctx.runtimeContext?.compactCurrent;
|
|
1912
1987
|
if (!compactCurrent) return "Codex compaction is unavailable because this command is not bound to a session.";
|
|
1988
|
+
authority.assertCurrent();
|
|
1913
1989
|
const result = await compactCurrent();
|
|
1914
1990
|
return result.compacted ? `Compacted Codex session (${result.tokensAfter ?? "unknown"} tokens after).` : `Codex compaction did not complete: ${formatCodexDisplayText(result.reason ?? "no reason returned")}.`;
|
|
1915
1991
|
}
|
|
@@ -1918,20 +1994,39 @@ async function startThreadAction(deps, ctx, pluginConfig, kind, args) {
|
|
|
1918
1994
|
authProfileId: binding.authProfileId,
|
|
1919
1995
|
pluginConfig
|
|
1920
1996
|
});
|
|
1921
|
-
await deps.codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.review, {
|
|
1997
|
+
await deps.bindingStore.withLease(target.identity, () => deps.codexControlRequest(pluginConfig, CODEX_CONTROL_METHODS.review, {
|
|
1922
1998
|
threadId: binding.threadId,
|
|
1923
1999
|
target: { type: "uncommittedChanges" }
|
|
1924
2000
|
}, {
|
|
1925
2001
|
agentDir: target.agentDir,
|
|
1926
2002
|
authProfileId: connection.clientAuthProfileId,
|
|
1927
2003
|
config: ctx.config,
|
|
1928
|
-
|
|
1929
|
-
|
|
2004
|
+
sessionId: authority.sessionId,
|
|
2005
|
+
sessionKey: authority.sessionKey,
|
|
2006
|
+
storePath: authority.storePath,
|
|
2007
|
+
assertCurrent: authority.assertCurrent,
|
|
2008
|
+
...connection.usesSupervisionConnection ? {
|
|
2009
|
+
startOptions: connection.appServer.start,
|
|
2010
|
+
beforeRequest: supervisedCommandGuard(deps, target.identity, binding)
|
|
2011
|
+
} : {}
|
|
2012
|
+
}));
|
|
1930
2013
|
return `Started Codex review for thread ${formatCodexDisplayText(binding.threadId)}.`;
|
|
1931
2014
|
}
|
|
2015
|
+
function supervisedCommandGuard(deps, identity, binding) {
|
|
2016
|
+
return async (_request, client, scope) => {
|
|
2017
|
+
const { thread } = await client.request("thread/read", {
|
|
2018
|
+
threadId: binding.threadId,
|
|
2019
|
+
includeTurns: false
|
|
2020
|
+
});
|
|
2021
|
+
scope.assertCurrent();
|
|
2022
|
+
if (!isDeepStrictEqual(deps.bindingStore.read(identity), binding)) throw new Error("Codex command binding changed before model execution");
|
|
2023
|
+
scope.assertCurrent();
|
|
2024
|
+
assertCodexSupervisionThreadLineage(binding, thread);
|
|
2025
|
+
};
|
|
2026
|
+
}
|
|
1932
2027
|
//#endregion
|
|
1933
2028
|
//#region extensions/codex/src/command-plugins-management.ts
|
|
1934
|
-
const POLICY_REFRESH_HINT = "
|
|
2029
|
+
const POLICY_REFRESH_HINT = "Takes effect on your next message.";
|
|
1935
2030
|
async function handleCodexPluginsSubcommand(ctx, rest, io, runtime) {
|
|
1936
2031
|
const [verb = "list", ...args] = rest;
|
|
1937
2032
|
const normalized = verb.toLowerCase();
|
|
@@ -2290,7 +2385,7 @@ function formatPluginList(plugins, options = {}) {
|
|
|
2290
2385
|
...rows.map((r) => ` ${r.state} ${r.displayKey.padEnd(keyW)} ${r.pluginName.padEnd(pluginW)} [${r.marketplace}]`),
|
|
2291
2386
|
"",
|
|
2292
2387
|
...globalEnabled ? [] : ["Global codexPlugins.enabled is off; configured sub-plugins are inactive.", ""],
|
|
2293
|
-
|
|
2388
|
+
POLICY_REFRESH_HINT
|
|
2294
2389
|
].join("\n");
|
|
2295
2390
|
}
|
|
2296
2391
|
//#endregion
|